shell/stdio: decouple from blkdev (again)
Move load/save to blkdev_cmds and add a new "poke" builtin shell cmd that is the mirror of "peek" and strictly uses stdio (no blkdev involved). This allows us to slim the minimal OS size but, more importantly, change the behavior of "load" so that we don't expect GetC to block until Z is set. This way, using "load X" with X being larger than the blkdev size won't block forever. This also brings our RC2014 minimal kernel below the 1K mark again.
This commit is contained in:
parent
88bf98321e
commit
73c3fc7947
@ -150,7 +150,9 @@ blkGetC:
|
||||
blkGetCW:
|
||||
ld ix, (BLOCKDEV_GETC)
|
||||
.loop:
|
||||
push ix ; fs messes with IX a lot
|
||||
call callIX
|
||||
pop ix
|
||||
jr nz, .loop
|
||||
ret
|
||||
|
||||
|
@ -44,3 +44,60 @@ blkSeekCmd:
|
||||
xor a
|
||||
ret
|
||||
|
||||
; Load the specified number of bytes (max 0xff) from IO and write them in the
|
||||
; current memory pointer (which doesn't change). This gets chars from
|
||||
; blkGetCW.
|
||||
; Control is returned to the shell only after all bytes are read.
|
||||
;
|
||||
; Example: load 42
|
||||
blkLoadCmd:
|
||||
.db "load", 0b001, 0, 0
|
||||
blkLoad:
|
||||
push bc
|
||||
push hl
|
||||
|
||||
ld a, (hl)
|
||||
ld b, a
|
||||
ld hl, (SHELL_MEM_PTR)
|
||||
.loop: call blkGetCW
|
||||
jr nz, .ioError
|
||||
ld (hl), a
|
||||
inc hl
|
||||
djnz .loop
|
||||
; success
|
||||
xor a
|
||||
jr .end
|
||||
.ioError:
|
||||
ld a, SHELL_ERR_IO_ERROR
|
||||
.end:
|
||||
pop hl
|
||||
pop bc
|
||||
ret
|
||||
|
||||
; Load the specified number of bytes (max 0xff) from the current memory pointer
|
||||
; and write them to I/O. Memory pointer doesn't move. This puts chars to
|
||||
; blkPutC.
|
||||
; Control is returned to the shell only after all bytes are written.
|
||||
;
|
||||
; Example: save 42
|
||||
blkSaveCmd:
|
||||
.db "save", 0b001, 0, 0
|
||||
blkSave:
|
||||
push bc
|
||||
push hl
|
||||
|
||||
ld a, (hl)
|
||||
ld b, a
|
||||
ld hl, (SHELL_MEM_PTR)
|
||||
.loop:
|
||||
ld a, (hl)
|
||||
inc hl
|
||||
call blkPutC
|
||||
djnz .loop
|
||||
|
||||
.end:
|
||||
pop hl
|
||||
pop bc
|
||||
xor a
|
||||
ret
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
; *** REQUIREMENTS ***
|
||||
; parse
|
||||
; stdio
|
||||
; blkdev
|
||||
|
||||
; *** DEFINES ***
|
||||
; SHELL_EXTRA_CMD_COUNT: Number of extra cmds to be expected after the regular
|
||||
@ -32,7 +31,7 @@
|
||||
; *** CONSTS ***
|
||||
|
||||
; number of entries in shellCmdTbl
|
||||
.equ SHELL_CMD_COUNT 7+SHELL_EXTRA_CMD_COUNT
|
||||
.equ SHELL_CMD_COUNT 6+SHELL_EXTRA_CMD_COUNT
|
||||
|
||||
; maximum number of bytes to receive as args in all commands. Determines the
|
||||
; size of the args variable.
|
||||
@ -411,58 +410,29 @@ shellPeek:
|
||||
xor a
|
||||
ret
|
||||
|
||||
; Load the specified number of bytes (max 0xff) from IO and write them in the
|
||||
; current memory pointer (which doesn't change). This gets chars from
|
||||
; blkGetCW.
|
||||
; Control is returned to the shell only after all bytes are read.
|
||||
;
|
||||
; Example: load 42
|
||||
shellLoadCmd:
|
||||
.db "load", 0b001, 0, 0
|
||||
shellLoad:
|
||||
; poke byte where memory pointer points and set them to bytes types through
|
||||
; stdioGetC. If the optional numerical byte arg is supplied, this number of
|
||||
; bytes will be expected from stdioGetC. Blocks until all bytes have been
|
||||
; fetched.
|
||||
shellPokeCmd:
|
||||
.db "poke", 0b101, 0, 0
|
||||
shellPoke:
|
||||
push bc
|
||||
push hl
|
||||
|
||||
ld a, (hl)
|
||||
or a ; cp 0
|
||||
jr nz, .arg1isset ; if arg1 is set, no need for a default
|
||||
ld a, 1 ; default for arg1
|
||||
.arg1isset:
|
||||
ld b, a
|
||||
ld hl, (SHELL_MEM_PTR)
|
||||
.loop: call blkGetCW
|
||||
jr nz, .ioError
|
||||
.loop: call stdioGetC
|
||||
jr nz, .loop ; nothing typed? loop
|
||||
ld (hl), a
|
||||
inc hl
|
||||
djnz .loop
|
||||
; success
|
||||
xor a
|
||||
jr .end
|
||||
.ioError:
|
||||
ld a, SHELL_ERR_IO_ERROR
|
||||
.end:
|
||||
pop hl
|
||||
pop bc
|
||||
ret
|
||||
|
||||
; Load the specified number of bytes (max 0xff) from the current memory pointer
|
||||
; and write them to I/O. Memory pointer doesn't move. This puts chars to
|
||||
; blkPutC.
|
||||
; Control is returned to the shell only after all bytes are written.
|
||||
;
|
||||
; Example: save 42
|
||||
shellSaveCmd:
|
||||
.db "save", 0b001, 0, 0
|
||||
shellSave:
|
||||
push bc
|
||||
push hl
|
||||
|
||||
ld a, (hl)
|
||||
ld b, a
|
||||
ld hl, (SHELL_MEM_PTR)
|
||||
.loop:
|
||||
ld a, (hl)
|
||||
inc hl
|
||||
call blkPutC
|
||||
djnz .loop
|
||||
|
||||
.end:
|
||||
pop hl
|
||||
pop bc
|
||||
xor a
|
||||
@ -530,6 +500,6 @@ shellIOWRCmd:
|
||||
; This table is at the very end of the file on purpose. The idea is to be able
|
||||
; to graft extra commands easily after an include in the glue file.
|
||||
shellCmdTbl:
|
||||
.dw shellMptrCmd, shellPeekCmd, shellLoadCmd, shellSaveCmd, shellCallCmd
|
||||
.dw shellMptrCmd, shellPeekCmd, shellPokeCmd, shellCallCmd
|
||||
.dw shellIORDCmd, shellIOWRCmd
|
||||
|
||||
|
@ -1,12 +1,9 @@
|
||||
; stdio
|
||||
;
|
||||
; Allows other modules to print to "standard out", that is, the console through
|
||||
; which the user is connected in a decoupled manner.
|
||||
; Allows other modules to print to "standard out", and get data from "stamdard
|
||||
; in", that is, the console through which the user is connected in a decoupled
|
||||
; manner.
|
||||
;
|
||||
; *** REQUIREMENTS ***
|
||||
; blkdev. select the block device you want to use as stdio just before you call
|
||||
; stdioInit.
|
||||
|
||||
; *** VARIABLES ***
|
||||
; Used to store formatted hex values just before printing it.
|
||||
.equ STDIO_HEX_FMT STDIO_RAMSTART
|
||||
@ -14,14 +11,10 @@
|
||||
.equ STDIO_PUTC STDIO_GETC+2
|
||||
.equ STDIO_RAMEND STDIO_PUTC+2
|
||||
|
||||
; Select the blockdev to use as stdio before calling this.
|
||||
; Sets GetC to the routine where HL points to and PutC to DE.
|
||||
stdioInit:
|
||||
push hl
|
||||
ld hl, (BLOCKDEV_GETC)
|
||||
ld (STDIO_GETC), hl
|
||||
ld hl, (BLOCKDEV_PUTC)
|
||||
ld (STDIO_PUTC), hl
|
||||
pop hl
|
||||
ld (STDIO_PUTC), de
|
||||
ret
|
||||
|
||||
stdioGetC:
|
||||
|
@ -16,13 +16,7 @@ jp aciaInt
|
||||
.equ ACIA_RAMSTART RAMSTART
|
||||
#include "acia.asm"
|
||||
|
||||
.equ BLOCKDEV_RAMSTART ACIA_RAMEND
|
||||
.equ BLOCKDEV_COUNT 1
|
||||
#include "blockdev.asm"
|
||||
; List of devices
|
||||
.dw aciaGetC, aciaPutC, 0, 0
|
||||
|
||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
||||
.equ STDIO_RAMSTART ACIA_RAMEND
|
||||
#include "stdio.asm"
|
||||
|
||||
.equ SHELL_RAMSTART STDIO_RAMEND
|
||||
@ -37,9 +31,8 @@ init:
|
||||
im 1
|
||||
|
||||
call aciaInit
|
||||
xor a
|
||||
ld de, BLOCKDEV_GETC
|
||||
call blkSel
|
||||
ld hl, aciaGetC
|
||||
ld de, aciaPutC
|
||||
call stdioInit
|
||||
call shellInit
|
||||
ei
|
||||
|
@ -17,10 +17,9 @@
|
||||
#include "parse.asm"
|
||||
|
||||
.equ BLOCKDEV_RAMSTART RAMSTART
|
||||
.equ BLOCKDEV_COUNT 4
|
||||
.equ BLOCKDEV_COUNT 3
|
||||
#include "blockdev.asm"
|
||||
; List of devices
|
||||
.dw emulGetC, emulPutC, 0, 0
|
||||
.dw fsdevGetC, fsdevPutC, fsdevSeek, fsdevTell
|
||||
.dw stdoutGetC, stdoutPutC, stdoutSeek, stdoutTell
|
||||
.dw stdinGetC, stdinPutC, stdinSeek, stdinTell
|
||||
@ -36,9 +35,10 @@
|
||||
#include "fs_cmds.asm"
|
||||
|
||||
.equ SHELL_RAMSTART FS_RAMEND
|
||||
.equ SHELL_EXTRA_CMD_COUNT 7
|
||||
.equ SHELL_EXTRA_CMD_COUNT 9
|
||||
#include "shell.asm"
|
||||
.dw blkBselCmd, blkSeekCmd, fsOnCmd, flsCmd, fnewCmd, fdelCmd, fopnCmd
|
||||
.dw blkBselCmd, blkSeekCmd, blkLoadCmd, blkSaveCmd
|
||||
.dw fsOnCmd, flsCmd, fnewCmd, fdelCmd, fopnCmd
|
||||
|
||||
.equ PGM_CODEADDR USERCODE
|
||||
#include "pgm.asm"
|
||||
@ -48,18 +48,14 @@ init:
|
||||
; setup stack
|
||||
ld hl, KERNEL_RAMEND
|
||||
ld sp, hl
|
||||
xor a
|
||||
ld de, BLOCKDEV_GETC
|
||||
call blkSel
|
||||
ld hl, emulGetC
|
||||
ld de, emulPutC
|
||||
call stdioInit
|
||||
call fsInit
|
||||
ld a, 1 ; select fsdev
|
||||
ld a, 0 ; select fsdev
|
||||
ld de, BLOCKDEV_GETC
|
||||
call blkSel
|
||||
call fsOn
|
||||
xor a ; select ACIA
|
||||
ld de, BLOCKDEV_GETC
|
||||
call blkSel
|
||||
call shellInit
|
||||
ld hl, pgmShellHook
|
||||
ld (SHELL_CMDHOOK), hl
|
||||
|
@ -32,8 +32,8 @@ def main():
|
||||
print("File too big. 0xff bytes max")
|
||||
return 1
|
||||
fd = os.open(args.device, os.O_RDWR)
|
||||
sendcmd(fd, 'load {:x}'.format(st.st_size).encode())
|
||||
print("Loading...")
|
||||
sendcmd(fd, 'poke {:x}'.format(st.st_size).encode())
|
||||
print("Poking...")
|
||||
with open(args.filename, 'rb') as fp:
|
||||
fcontents = fp.read()
|
||||
for c in fcontents:
|
||||
@ -41,7 +41,7 @@ def main():
|
||||
# Let's give the machine a bit of time to breathe. We ain't in a
|
||||
# hurry now, are we?
|
||||
time.sleep(0.0001)
|
||||
print("Loaded")
|
||||
print("Poked")
|
||||
os.read(fd, 5)
|
||||
print("Peeking back...")
|
||||
sendcmd(fd, 'peek {:x}'.format(st.st_size).encode())
|
||||
|
Loading…
Reference in New Issue
Block a user