mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-27 23:18:06 +11:00
b745f49186
The goal is to avoid mixing those routines with "character devices" (acia, vpd, kbd) which aren't block devices and have routines that have different expectations. This is a first step to fixing #64.
187 lines
3.8 KiB
NASM
187 lines
3.8 KiB
NASM
; cmd - parse and interpret command
|
|
;
|
|
; *** Consts ***
|
|
|
|
; address type
|
|
|
|
.equ ABSOLUTE 0
|
|
; handles +, - and ".". For +, easy. For -, addr is negative. For ., it's 0.
|
|
.equ RELATIVE 1
|
|
.equ EOF 2
|
|
|
|
; *** Variables ***
|
|
|
|
; An address is a one byte type and a two bytes line number (0-indexed)
|
|
.equ CMD_ADDR1 CMD_RAMSTART
|
|
.equ CMD_ADDR2 @+3
|
|
.equ CMD_TYPE @+3
|
|
.equ CMD_RAMEND @+1
|
|
|
|
; *** Code ***
|
|
|
|
; Parse command line that HL points to and set unit's variables
|
|
; Sets Z on success, unset on error.
|
|
cmdParse:
|
|
ld a, (hl)
|
|
cp 'q'
|
|
jr z, .simpleCmd
|
|
cp 'w'
|
|
jr z, .simpleCmd
|
|
ld ix, CMD_ADDR1
|
|
call .readAddr
|
|
ret nz
|
|
; Before we check for the existence of a second addr, let's set that
|
|
; second addr to the same value as the first. That's going to be its
|
|
; value if we have to ",".
|
|
ld a, (ix)
|
|
ld (CMD_ADDR2), a
|
|
ld a, (ix+1)
|
|
ld (CMD_ADDR2+1), a
|
|
ld a, (ix+2)
|
|
ld (CMD_ADDR2+2), a
|
|
ld a, (hl)
|
|
cp ','
|
|
jr nz, .noaddr2
|
|
inc hl
|
|
ld ix, CMD_ADDR2
|
|
call .readAddr
|
|
ret nz
|
|
.noaddr2:
|
|
; We expect HL (rest of the cmdline) to be a null char or an accepted
|
|
; cmd, otherwise it's garbage
|
|
ld a, (hl)
|
|
or a
|
|
jr z, .nullCmd
|
|
cp 'p'
|
|
jr z, .okCmd
|
|
cp 'd'
|
|
jr z, .okCmd
|
|
cp 'a'
|
|
jr z, .okCmd
|
|
cp 'i'
|
|
jr z, .okCmd
|
|
; unsupported cmd
|
|
ret ; Z unset
|
|
.nullCmd:
|
|
ld a, 'p'
|
|
.okCmd:
|
|
ld (CMD_TYPE), a
|
|
ret ; Z already set
|
|
|
|
.simpleCmd:
|
|
; Z already set
|
|
ld (CMD_TYPE), a
|
|
ret
|
|
|
|
; Parse the string at (HL) and sets its corresponding address in IX, properly
|
|
; considering implicit values (current address when nothing is specified).
|
|
; advances HL to the char next to the last parsed char.
|
|
; It handles "+" and "-" addresses such as "+3", "-2", "+", "-".
|
|
; Sets Z on success, unset on error. Line out of bounds isn't an error. Only
|
|
; overflows.
|
|
.readAddr:
|
|
ld a, (hl)
|
|
cp '+'
|
|
jr z, .plusOrMinus
|
|
cp '-'
|
|
jr z, .plusOrMinus
|
|
cp '.'
|
|
jr z, .dot
|
|
cp '$'
|
|
jr z, .eof
|
|
|
|
; inline parseDecimalDigit
|
|
add a, 0xff-'9' ; maps '0'-'9' onto 0xf6-0xff
|
|
sub 0xff-9 ; maps to 0-9 and carries if not a digit
|
|
|
|
jr c, .notHandled
|
|
; straight number
|
|
ld a, ABSOLUTE
|
|
ld (ix), a
|
|
call .parseDecimalM
|
|
ret nz
|
|
dec de ; from 1-based to 0-base
|
|
jr .end
|
|
.dot:
|
|
inc hl ; advance cmd cursor
|
|
; the rest is the same as .notHandled
|
|
.notHandled:
|
|
; something else. It's probably our command. Our addr is therefore "."
|
|
ld a, RELATIVE
|
|
ld (ix), a
|
|
xor a ; sets Z
|
|
ld (ix+1), a
|
|
ld (ix+2), a
|
|
ret
|
|
.eof:
|
|
inc hl ; advance cmd cursor
|
|
ld a, EOF
|
|
ld (ix), a
|
|
ret ; Z set during earlier CP
|
|
.plusOrMinus:
|
|
push af ; preserve that + or -
|
|
ld a, RELATIVE
|
|
ld (ix), a
|
|
inc hl ; advance cmd cursor
|
|
ld a, (hl)
|
|
ld de, 1 ; if .pmNoSuffix
|
|
|
|
; inline parseDecimalDigit
|
|
add a, 0xff-'9' ; maps '0'-'9' onto 0xf6-0xff
|
|
sub 0xff-9 ; maps to 0-9 and carries if not a digit
|
|
|
|
jr c, .pmNoSuffix
|
|
call .parseDecimalM ; --> DE
|
|
.pmNoSuffix:
|
|
pop af ; bring back that +/-
|
|
cp '-'
|
|
jr nz, .end
|
|
; we had a "-". Negate DE
|
|
push hl
|
|
ld hl, 0
|
|
sbc hl, de
|
|
ex de, hl
|
|
pop hl
|
|
.end:
|
|
; we still have to save DE in memory
|
|
ld (ix+1), e
|
|
ld (ix+2), d
|
|
cp a ; ensure Z
|
|
ret
|
|
|
|
; call parseDecimal and set HL to the character following the last digit
|
|
.parseDecimalM:
|
|
push bc
|
|
push ix
|
|
push hl
|
|
.loop:
|
|
inc hl
|
|
ld a, (hl)
|
|
|
|
; inline parseDecimalDigit
|
|
add a, 0xff-'9' ; maps '0'-'9' onto 0xf6-0xff
|
|
sub 0xff-9 ; maps to 0-9 and carries if not a digit
|
|
|
|
jr nc, .loop
|
|
; We're at the first non-digit char. Let's save it because we're going
|
|
; to temporarily replace it with a null.
|
|
ld b, (hl) ; refetch (HL), A has been mucked with in
|
|
; parseDecimalDigit
|
|
xor a
|
|
ld (hl), a
|
|
; Now, let's go back to the beginning of the string and parse it.
|
|
; but before we do this, let's save the end of string in DE
|
|
ex de, hl
|
|
pop hl
|
|
call parseDecimal
|
|
; Z is set properly at this point. nothing touches Z below.
|
|
ld a, b
|
|
ld (de), a
|
|
ex de, hl ; put end of string back from DE to HL
|
|
; Put addr in its final register, DE
|
|
push ix \ pop de
|
|
pop ix
|
|
pop bc
|
|
ret
|
|
|