2019-11-18 13:40:23 -05:00
|
|
|
; *** Constants ***
|
|
|
|
.equ BAS_SCRATCHPAD_SIZE 0x20
|
2019-11-13 15:28:16 -05:00
|
|
|
; *** Variables ***
|
|
|
|
; Value of `SP` when basic was first invoked. This is where SP is going back to
|
|
|
|
; on restarts.
|
|
|
|
.equ BAS_INITSP BAS_RAMSTART
|
|
|
|
; **Pointer** to current line number
|
|
|
|
.equ BAS_PCURLN @+2
|
2019-11-18 13:40:23 -05:00
|
|
|
.equ BAS_SCRATCHPAD @+2
|
|
|
|
.equ BAS_RAMEND @+BAS_SCRATCHPAD_SIZE
|
2019-11-13 15:28:16 -05:00
|
|
|
|
|
|
|
; *** Code ***
|
|
|
|
basStart:
|
|
|
|
ld (BAS_INITSP), sp
|
|
|
|
xor a
|
|
|
|
ld hl, .welcome
|
|
|
|
call printstr
|
|
|
|
call printcrlf
|
|
|
|
ld hl, .welcome+2 ; points to a zero word
|
|
|
|
ld (BAS_PCURLN), hl
|
|
|
|
jr basPrompt
|
|
|
|
|
|
|
|
.welcome:
|
|
|
|
.db "OK", 0, 0
|
|
|
|
|
|
|
|
basPrompt:
|
|
|
|
ld hl, .sPrompt
|
|
|
|
call printstr
|
|
|
|
call stdioReadLine
|
|
|
|
call parseDecimal
|
|
|
|
jr z, .number
|
|
|
|
call basDirect
|
|
|
|
jr basPrompt
|
|
|
|
.number:
|
|
|
|
; do nothing for now, we only support direct mode.
|
|
|
|
ld hl, .sNumber
|
|
|
|
call basPrintLn
|
|
|
|
jr basPrompt
|
|
|
|
.sNumber:
|
|
|
|
.db "A number!", 0
|
|
|
|
.sPrompt:
|
|
|
|
.db "> ", 0
|
|
|
|
|
|
|
|
basDirect:
|
2019-11-18 13:40:23 -05:00
|
|
|
; First, get cmd length
|
|
|
|
call fnWSIdx
|
|
|
|
cp 7
|
|
|
|
jr nc, .unknown ; Too long, can't possibly fit anything.
|
|
|
|
; A contains whitespace IDX, save it in B
|
|
|
|
ld b, a
|
2019-11-13 15:28:16 -05:00
|
|
|
ex de, hl
|
2019-11-18 13:40:23 -05:00
|
|
|
ld hl, basCmds1+2
|
2019-11-13 15:28:16 -05:00
|
|
|
.loop:
|
2019-11-18 13:40:23 -05:00
|
|
|
ld a, b ; whitespace IDX
|
2019-11-13 15:28:16 -05:00
|
|
|
call strncmp
|
|
|
|
jr z, .found
|
2019-11-18 13:40:23 -05:00
|
|
|
ld a, 8
|
2019-11-13 15:28:16 -05:00
|
|
|
call addHL
|
|
|
|
ld a, (hl)
|
|
|
|
cp 0xff
|
|
|
|
jr nz, .loop
|
2019-11-18 13:40:23 -05:00
|
|
|
.unknown:
|
2019-11-13 15:28:16 -05:00
|
|
|
ld hl, .sUnknown
|
|
|
|
jr basPrintLn
|
|
|
|
|
|
|
|
.found:
|
2019-11-18 13:40:23 -05:00
|
|
|
dec hl \ dec hl
|
2019-11-13 15:28:16 -05:00
|
|
|
call intoHL
|
2019-11-18 13:40:23 -05:00
|
|
|
push hl \ pop ix
|
|
|
|
; Bring back command string from DE to HL
|
|
|
|
ex de, hl
|
|
|
|
ld a, b ; cmd's length
|
|
|
|
call addHL
|
|
|
|
call rdWS
|
|
|
|
jp (ix)
|
2019-11-13 15:28:16 -05:00
|
|
|
|
|
|
|
.sUnknown:
|
|
|
|
.db "Unknown command", 0
|
|
|
|
|
|
|
|
basPrintLn:
|
|
|
|
call printcrlf
|
|
|
|
call printstr
|
|
|
|
jp printcrlf
|
|
|
|
|
2019-11-18 13:40:23 -05:00
|
|
|
basERR:
|
|
|
|
ld hl, .sErr
|
|
|
|
jr basPrintLn
|
|
|
|
.sErr:
|
|
|
|
.db "ERR", 0
|
|
|
|
|
2019-11-13 15:28:16 -05:00
|
|
|
; *** Commands ***
|
2019-11-18 13:40:23 -05:00
|
|
|
; A command receives its argument through (HL), which is already placed to
|
|
|
|
; either:
|
|
|
|
; 1 - the end of the string if the command has no arg.
|
|
|
|
; 2 - the beginning of the arg, with whitespace properly skipped.
|
2019-11-13 15:28:16 -05:00
|
|
|
basBYE:
|
|
|
|
ld hl, .sBye
|
|
|
|
call basPrintLn
|
|
|
|
; To quit the loop, let's return the stack to its initial value and
|
|
|
|
; then return.
|
|
|
|
xor a
|
|
|
|
ld sp, (BAS_INITSP)
|
|
|
|
ret
|
|
|
|
.sBye:
|
|
|
|
.db "Goodbye!", 0
|
|
|
|
|
2019-11-18 13:40:23 -05:00
|
|
|
basPRINT:
|
2019-11-18 15:52:07 -05:00
|
|
|
call parseExpr
|
2019-11-18 13:40:23 -05:00
|
|
|
jp nz, basERR
|
|
|
|
push ix \ pop de
|
|
|
|
ld hl, BAS_SCRATCHPAD
|
|
|
|
call fmtDecimal
|
|
|
|
jp basPrintLn
|
|
|
|
|
2019-11-13 15:28:16 -05:00
|
|
|
; direct only
|
|
|
|
basCmds1:
|
|
|
|
.dw basBYE
|
2019-11-18 13:40:23 -05:00
|
|
|
.db "bye", 0, 0, 0
|
2019-11-13 15:28:16 -05:00
|
|
|
; statements
|
|
|
|
basCmds2:
|
2019-11-18 13:40:23 -05:00
|
|
|
.dw basPRINT
|
|
|
|
.db "print", 0
|
|
|
|
.db 0xff, 0xff, 0xff ; end of table
|