diff --git a/parts/shell.asm b/parts/shell.asm index 8afc349..56d2b10 100644 --- a/parts/shell.asm +++ b/parts/shell.asm @@ -4,34 +4,59 @@ ; for now, this unit is tightly coupled to acia.asm, but it will eventually be ; more general than that. -; Incomplete. For now, this outputs a welcome prompt and then waits for input. -; Whenever input is CR or LF, we echo back what we've received and empty the -; input buffer. This also happen when the buffer is full. +; 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, d_welcome + 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? - ret z ; if yes, we're finished + jr z, .end ; if yes, we're finished call aciaPutC inc hl - jr printstr - ; no ret because our only way out is ret z above + jr .loop + +.end: + pop hl + pop af + ret printcrlf: ld a, CR @@ -73,9 +98,124 @@ chkbuf: ; alright, let's go! ld hl, ACIA_BUF - call printstr - call printcrlf + call shellParse ret -; *** DATA *** -d_welcome: .byte "Welcome to Collapse OS", 0 +; 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 +