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:
|
blkGetCW:
|
||||||
ld ix, (BLOCKDEV_GETC)
|
ld ix, (BLOCKDEV_GETC)
|
||||||
.loop:
|
.loop:
|
||||||
|
push ix ; fs messes with IX a lot
|
||||||
call callIX
|
call callIX
|
||||||
|
pop ix
|
||||||
jr nz, .loop
|
jr nz, .loop
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -44,3 +44,60 @@ blkSeekCmd:
|
|||||||
xor a
|
xor a
|
||||||
ret
|
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 ***
|
; *** REQUIREMENTS ***
|
||||||
; parse
|
; parse
|
||||||
; stdio
|
; stdio
|
||||||
; blkdev
|
|
||||||
|
|
||||||
; *** DEFINES ***
|
; *** DEFINES ***
|
||||||
; SHELL_EXTRA_CMD_COUNT: Number of extra cmds to be expected after the regular
|
; SHELL_EXTRA_CMD_COUNT: Number of extra cmds to be expected after the regular
|
||||||
@ -32,7 +31,7 @@
|
|||||||
; *** CONSTS ***
|
; *** CONSTS ***
|
||||||
|
|
||||||
; number of entries in shellCmdTbl
|
; 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
|
; maximum number of bytes to receive as args in all commands. Determines the
|
||||||
; size of the args variable.
|
; size of the args variable.
|
||||||
@ -411,58 +410,29 @@ shellPeek:
|
|||||||
xor a
|
xor a
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Load the specified number of bytes (max 0xff) from IO and write them in the
|
; poke byte where memory pointer points and set them to bytes types through
|
||||||
; current memory pointer (which doesn't change). This gets chars from
|
; stdioGetC. If the optional numerical byte arg is supplied, this number of
|
||||||
; blkGetCW.
|
; bytes will be expected from stdioGetC. Blocks until all bytes have been
|
||||||
; Control is returned to the shell only after all bytes are read.
|
; fetched.
|
||||||
;
|
shellPokeCmd:
|
||||||
; Example: load 42
|
.db "poke", 0b101, 0, 0
|
||||||
shellLoadCmd:
|
shellPoke:
|
||||||
.db "load", 0b001, 0, 0
|
|
||||||
shellLoad:
|
|
||||||
push bc
|
push bc
|
||||||
push hl
|
push hl
|
||||||
|
|
||||||
ld a, (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 b, a
|
||||||
ld hl, (SHELL_MEM_PTR)
|
ld hl, (SHELL_MEM_PTR)
|
||||||
.loop: call blkGetCW
|
.loop: call stdioGetC
|
||||||
jr nz, .ioError
|
jr nz, .loop ; nothing typed? loop
|
||||||
ld (hl), a
|
ld (hl), a
|
||||||
inc hl
|
inc hl
|
||||||
djnz .loop
|
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 hl
|
||||||
pop bc
|
pop bc
|
||||||
xor a
|
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
|
; 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.
|
; to graft extra commands easily after an include in the glue file.
|
||||||
shellCmdTbl:
|
shellCmdTbl:
|
||||||
.dw shellMptrCmd, shellPeekCmd, shellLoadCmd, shellSaveCmd, shellCallCmd
|
.dw shellMptrCmd, shellPeekCmd, shellPokeCmd, shellCallCmd
|
||||||
.dw shellIORDCmd, shellIOWRCmd
|
.dw shellIORDCmd, shellIOWRCmd
|
||||||
|
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
; stdio
|
; stdio
|
||||||
;
|
;
|
||||||
; Allows other modules to print to "standard out", that is, the console through
|
; Allows other modules to print to "standard out", and get data from "stamdard
|
||||||
; which the user is connected in a decoupled manner.
|
; 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 ***
|
; *** VARIABLES ***
|
||||||
; Used to store formatted hex values just before printing it.
|
; Used to store formatted hex values just before printing it.
|
||||||
.equ STDIO_HEX_FMT STDIO_RAMSTART
|
.equ STDIO_HEX_FMT STDIO_RAMSTART
|
||||||
@ -14,14 +11,10 @@
|
|||||||
.equ STDIO_PUTC STDIO_GETC+2
|
.equ STDIO_PUTC STDIO_GETC+2
|
||||||
.equ STDIO_RAMEND STDIO_PUTC+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:
|
stdioInit:
|
||||||
push hl
|
|
||||||
ld hl, (BLOCKDEV_GETC)
|
|
||||||
ld (STDIO_GETC), hl
|
ld (STDIO_GETC), hl
|
||||||
ld hl, (BLOCKDEV_PUTC)
|
ld (STDIO_PUTC), de
|
||||||
ld (STDIO_PUTC), hl
|
|
||||||
pop hl
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
stdioGetC:
|
stdioGetC:
|
||||||
|
@ -16,13 +16,7 @@ jp aciaInt
|
|||||||
.equ ACIA_RAMSTART RAMSTART
|
.equ ACIA_RAMSTART RAMSTART
|
||||||
#include "acia.asm"
|
#include "acia.asm"
|
||||||
|
|
||||||
.equ BLOCKDEV_RAMSTART ACIA_RAMEND
|
.equ STDIO_RAMSTART ACIA_RAMEND
|
||||||
.equ BLOCKDEV_COUNT 1
|
|
||||||
#include "blockdev.asm"
|
|
||||||
; List of devices
|
|
||||||
.dw aciaGetC, aciaPutC, 0, 0
|
|
||||||
|
|
||||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
|
||||||
#include "stdio.asm"
|
#include "stdio.asm"
|
||||||
|
|
||||||
.equ SHELL_RAMSTART STDIO_RAMEND
|
.equ SHELL_RAMSTART STDIO_RAMEND
|
||||||
@ -37,9 +31,8 @@ init:
|
|||||||
im 1
|
im 1
|
||||||
|
|
||||||
call aciaInit
|
call aciaInit
|
||||||
xor a
|
ld hl, aciaGetC
|
||||||
ld de, BLOCKDEV_GETC
|
ld de, aciaPutC
|
||||||
call blkSel
|
|
||||||
call stdioInit
|
call stdioInit
|
||||||
call shellInit
|
call shellInit
|
||||||
ei
|
ei
|
||||||
|
@ -17,10 +17,9 @@
|
|||||||
#include "parse.asm"
|
#include "parse.asm"
|
||||||
|
|
||||||
.equ BLOCKDEV_RAMSTART RAMSTART
|
.equ BLOCKDEV_RAMSTART RAMSTART
|
||||||
.equ BLOCKDEV_COUNT 4
|
.equ BLOCKDEV_COUNT 3
|
||||||
#include "blockdev.asm"
|
#include "blockdev.asm"
|
||||||
; List of devices
|
; List of devices
|
||||||
.dw emulGetC, emulPutC, 0, 0
|
|
||||||
.dw fsdevGetC, fsdevPutC, fsdevSeek, fsdevTell
|
.dw fsdevGetC, fsdevPutC, fsdevSeek, fsdevTell
|
||||||
.dw stdoutGetC, stdoutPutC, stdoutSeek, stdoutTell
|
.dw stdoutGetC, stdoutPutC, stdoutSeek, stdoutTell
|
||||||
.dw stdinGetC, stdinPutC, stdinSeek, stdinTell
|
.dw stdinGetC, stdinPutC, stdinSeek, stdinTell
|
||||||
@ -36,9 +35,10 @@
|
|||||||
#include "fs_cmds.asm"
|
#include "fs_cmds.asm"
|
||||||
|
|
||||||
.equ SHELL_RAMSTART FS_RAMEND
|
.equ SHELL_RAMSTART FS_RAMEND
|
||||||
.equ SHELL_EXTRA_CMD_COUNT 7
|
.equ SHELL_EXTRA_CMD_COUNT 9
|
||||||
#include "shell.asm"
|
#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
|
.equ PGM_CODEADDR USERCODE
|
||||||
#include "pgm.asm"
|
#include "pgm.asm"
|
||||||
@ -48,18 +48,14 @@ init:
|
|||||||
; setup stack
|
; setup stack
|
||||||
ld hl, KERNEL_RAMEND
|
ld hl, KERNEL_RAMEND
|
||||||
ld sp, hl
|
ld sp, hl
|
||||||
xor a
|
ld hl, emulGetC
|
||||||
ld de, BLOCKDEV_GETC
|
ld de, emulPutC
|
||||||
call blkSel
|
|
||||||
call stdioInit
|
call stdioInit
|
||||||
call fsInit
|
call fsInit
|
||||||
ld a, 1 ; select fsdev
|
ld a, 0 ; select fsdev
|
||||||
ld de, BLOCKDEV_GETC
|
ld de, BLOCKDEV_GETC
|
||||||
call blkSel
|
call blkSel
|
||||||
call fsOn
|
call fsOn
|
||||||
xor a ; select ACIA
|
|
||||||
ld de, BLOCKDEV_GETC
|
|
||||||
call blkSel
|
|
||||||
call shellInit
|
call shellInit
|
||||||
ld hl, pgmShellHook
|
ld hl, pgmShellHook
|
||||||
ld (SHELL_CMDHOOK), hl
|
ld (SHELL_CMDHOOK), hl
|
||||||
|
@ -32,8 +32,8 @@ def main():
|
|||||||
print("File too big. 0xff bytes max")
|
print("File too big. 0xff bytes max")
|
||||||
return 1
|
return 1
|
||||||
fd = os.open(args.device, os.O_RDWR)
|
fd = os.open(args.device, os.O_RDWR)
|
||||||
sendcmd(fd, 'load {:x}'.format(st.st_size).encode())
|
sendcmd(fd, 'poke {:x}'.format(st.st_size).encode())
|
||||||
print("Loading...")
|
print("Poking...")
|
||||||
with open(args.filename, 'rb') as fp:
|
with open(args.filename, 'rb') as fp:
|
||||||
fcontents = fp.read()
|
fcontents = fp.read()
|
||||||
for c in fcontents:
|
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
|
# Let's give the machine a bit of time to breathe. We ain't in a
|
||||||
# hurry now, are we?
|
# hurry now, are we?
|
||||||
time.sleep(0.0001)
|
time.sleep(0.0001)
|
||||||
print("Loaded")
|
print("Poked")
|
||||||
os.read(fd, 5)
|
os.read(fd, 5)
|
||||||
print("Peeking back...")
|
print("Peeking back...")
|
||||||
sendcmd(fd, 'peek {:x}'.format(st.st_size).encode())
|
sendcmd(fd, 'peek {:x}'.format(st.st_size).encode())
|
||||||
|
Loading…
Reference in New Issue
Block a user