|
- ; shell
- ;
- ; Runs a shell over an asynchronous communication interface adapter (ACIA).
- ; for now, this unit is tightly coupled to acia.asm, but it will eventually be
- ; more general than that.
-
- ; Status: incomplete. As it is now, it spits a welcome prompt, wait for input
- ; and compare the first 4 chars of the input with a command table and call the
- ; appropriate routine if it's found, an error if it's not.
- ;
- ; Commands, for now, are dummy.
- ;
- ; See constants below for error codes.
-
- ; *** CONSTS ***
- CR .equ 0x0d
- LF .equ 0x0a
-
- ; number of entries in shellCmdTbl
- SHELL_CMD_COUNT .equ 2
-
- ; The command that was type isn't known to the shell
- SHELL_ERR_UNKNOWN_CMD .equ 0x01
-
- ; Arguments for the command weren't properly formatted
- SHELL_ERR_BAD_ARGS .equ 0x02
-
- ; *** CODE ***
- shellInit:
- ; print prompt
- ld hl, .prompt
- call printstr
- call printcrlf
- ret
-
- .prompt:
- .db "Collapse OS", 0
-
- shellLoop:
- call chkbuf
- jr shellLoop
-
- ; print null-terminated string pointed to by HL
- printstr:
- push af
- push hl
-
- .loop:
- ld a, (hl) ; load character to send
- or a ; is it zero?
- jr z, .end ; if yes, we're finished
- call aciaPutC
- inc hl
- jr .loop
-
- .end:
- pop hl
- pop af
- ret
-
- printcrlf:
- ld a, CR
- call aciaPutC
- ld a, LF
- call aciaPutC
- ret
-
-
- ; check if the input buffer is full or ends in CR or LF. If it does, prints it
- ; back and empty it.
- chkbuf:
- call aciaBufPtr
- cp 0
- ret z ; BUFIDX is zero? nothing to check.
-
- cp ACIA_BUFSIZE
- jr z, .do ; if BUFIDX == BUFSIZE? do!
-
- ; our previous char is in BUFIDX - 1. Fetch this
- dec hl
- ld a, (hl) ; now, that's our char we have in A
- inc hl ; put HL back where it was
-
- cp CR
- jr z, .do ; char is CR? do!
- cp LF
- jr z, .do ; char is LF? do!
-
- ; nothing matched? don't do anything
- ret
-
- .do:
- ; terminate our string with 0
- xor a
- ld (hl), a
- ; reset buffer index
- ld (ACIA_BUFIDX), a
-
- ; alright, let's go!
- ld hl, ACIA_BUF
- call shellParse
- ret
-
- ; Compares strings pointed to by HL and DE up to A count of characters. If
- ; equal, Z is set. If not equal, Z is reset.
- strncmp:
- push bc
- push hl
- push de
-
- ld b, a
- .loop:
- ld a, (de)
- cp (hl)
- jr nz, .end ; not equal? break early
- inc hl
- inc de
- djnz .loop
-
- .end:
- pop de
- pop hl
- pop bc
- ; Because we don't call anything else than CP that modify the Z flag,
- ; our Z value will be that of the last cp (reset if we broke the loop
- ; early, set otherwise)
- ret
-
- ; add the value of A into DE
- addDE:
- add a, e
- jr nc, .end ; no carry? skip inc
- inc d
- .end:
- ld e, a
- ret
-
- ; jump to the location pointed to by HL. This allows us to call HL instead of
- ; just jumping it.
- jumpHL:
- jp hl
- ret
-
- ; Parse command (null terminated) at HL and calls it
- shellParse:
- push af
- push bc
- push de
-
- ld de, shellCmdTbl
- ld a, SHELL_CMD_COUNT
- ld b, a
-
- .loop:
- ld a, 4 ; 4 chars to compare
- call strncmp
- jr z, .found
- ld a, 6
- call addDE
- djnz .loop
-
- ; exhausted loop? not found
- ld a, SHELL_ERR_UNKNOWN_CMD
- call shellPrintErr
- jr .end
-
- .found:
- ld a, 4
- call addDE
- ex hl, de
- call jumpHL
- ex hl, de
-
- .end:
- pop de
- pop bc
- pop af
- ret
-
- ; Print the error code set in A (doesn't work for codes > 9 yet...)
- shellPrintErr:
- push af
- push hl
-
- ld hl, .str
- call printstr
-
- ; ascii for '0' is 0x30
- add a, 0x30
- call aciaPutC
- call printcrlf
-
- pop hl
- pop af
- ret
-
- .str:
- .db "ERR ", 0
-
- ; *** COMMANDS ***
- shellSeek:
- ld hl, .str
- call printstr
- ret
- .str:
- .db "seek called", CR, LF, 0
-
- shellPeek:
- ld hl, .str
- call printstr
- ret
- .str:
- .db "peek called", CR, LF, 0
-
- ; Format: 4 bytes name followed by 2 bytes jump. fill names with zeroes
- shellCmdTbl:
- .db "seek"
- jr shellSeek
- .db "peek"
- jr shellPeek
|