mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-26 05:28:06 +11:00
Compare commits
No commits in common. "1f26879cd33b8a9e3fd1ca424ccf50135c7bd303" and "38333e9e0764c10097aec93b85ad6a1c9e9393df" have entirely different histories.
1f26879cd3
...
38333e9e07
@ -1,2 +0,0 @@
|
||||
language: c
|
||||
script: ./runtests.sh
|
15
TRICKS.txt
15
TRICKS.txt
@ -1,15 +0,0 @@
|
||||
This file describe tricks that are used throughout the code and might need
|
||||
explanation.
|
||||
|
||||
or a: Equivalent to "cp 0", but results in a shorter opcode.
|
||||
|
||||
xor a: sets A to 0 more efficiently than ld a, 0
|
||||
|
||||
and 0xbf: Given a letter in the a-z range, changes it to its uppercase value
|
||||
if it's already uppercased, then it stays that way.
|
||||
|
||||
Z if almost always used as a success indicator for routines. Set for success,
|
||||
Reset for failure. "xor a" (destroys A) and "cp a" (preserves A) are used to
|
||||
ensure Z is set. To ensure that it is reset, it's a bit more complicated and
|
||||
"unsetZ" routine exists for that, although that in certain circumstances,
|
||||
"inc a \ dec a" or "or a" can work.
|
@ -9,7 +9,7 @@
|
||||
; is reached on the block device.
|
||||
|
||||
; *** Requirements ***
|
||||
; blkGetB
|
||||
; blkGetC
|
||||
; parseArgs
|
||||
;
|
||||
; *** Includes ***
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
; *** Variables ***
|
||||
.equ AT28W_MAXBYTES AT28W_RAMSTART
|
||||
.equ AT28W_RAMEND @+2
|
||||
.equ AT28W_RAMEND AT28W_MAXBYTES+2
|
||||
; *** Code ***
|
||||
|
||||
at28wMain:
|
||||
@ -33,7 +33,7 @@ at28wInner:
|
||||
; BC is zero, default to 0x2000 (8k, the size of the AT28)
|
||||
ld bc, 0x2000
|
||||
.loop:
|
||||
call blkGetB
|
||||
call blkGetC
|
||||
jr nz, .loopend
|
||||
ld (hl), a
|
||||
ld e, a ; save expected data for verification
|
||||
|
@ -4,14 +4,14 @@
|
||||
; Number of lines currently in the buffer
|
||||
.equ BUF_LINECNT BUF_RAMSTART
|
||||
; List of pointers to strings in scratchpad
|
||||
.equ BUF_LINES @+2
|
||||
.equ BUF_LINES BUF_LINECNT+2
|
||||
; Points to the end of the scratchpad, that is, one byte after the last written
|
||||
; char in it.
|
||||
.equ BUF_PADEND @+ED_BUF_MAXLINES*2
|
||||
.equ BUF_PADEND BUF_LINES+ED_BUF_MAXLINES*2
|
||||
; The in-memory scratchpad
|
||||
.equ BUF_PAD @+2
|
||||
.equ BUF_PAD BUF_PADEND+2
|
||||
|
||||
.equ BUF_RAMEND @+ED_BUF_PADMAXLEN
|
||||
.equ BUF_RAMEND BUF_PAD+ED_BUF_PADMAXLEN
|
||||
|
||||
; *** Code ***
|
||||
|
||||
@ -25,7 +25,7 @@ bufInit:
|
||||
; init pad end in case we have an empty file.
|
||||
ld (BUF_PADEND), hl
|
||||
.loop:
|
||||
call ioGetB
|
||||
call ioGetC
|
||||
jr nz, .loopend
|
||||
or a ; null? hum, weird. same as LF
|
||||
jr z, .lineend
|
||||
|
@ -13,9 +13,9 @@
|
||||
|
||||
; 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
|
||||
.equ CMD_ADDR2 CMD_ADDR1+3
|
||||
.equ CMD_TYPE CMD_ADDR2+3
|
||||
.equ CMD_RAMEND CMD_TYPE+1
|
||||
|
||||
; *** Code ***
|
||||
|
||||
@ -89,11 +89,11 @@ cmdParse:
|
||||
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
|
||||
@ -125,11 +125,11 @@ cmdParse:
|
||||
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:
|
||||
@ -157,11 +157,11 @@ cmdParse:
|
||||
.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.
|
||||
|
@ -9,10 +9,10 @@
|
||||
; Handle of the target file
|
||||
.equ IO_FILE_HDL IO_RAMSTART
|
||||
; block device targeting IO_FILE_HDL
|
||||
.equ IO_BLK @+FS_HANDLE_SIZE
|
||||
.equ IO_BLK IO_FILE_HDL+FS_HANDLE_SIZE
|
||||
; Buffer for lines read from I/O.
|
||||
.equ IO_LINE @+BLOCKDEV_SIZE
|
||||
.equ IO_RAMEND @+IO_MAXLEN+1 ; +1 for null
|
||||
.equ IO_LINE IO_BLK+BLOCKDEV_SIZE
|
||||
.equ IO_RAMEND IO_LINE+IO_MAXLEN+1 ; +1 for null
|
||||
; *** Code ***
|
||||
|
||||
; Given a file name in (HL), open that file in (IO_FILE_HDL) and open a blkdev
|
||||
@ -25,26 +25,26 @@ ioInit:
|
||||
ld de, IO_BLK
|
||||
ld hl, .blkdev
|
||||
jp blkSet
|
||||
.fsGetB:
|
||||
.fsGetC:
|
||||
ld ix, IO_FILE_HDL
|
||||
jp fsGetB
|
||||
.fsPutB:
|
||||
jp fsGetC
|
||||
.fsPutC:
|
||||
ld ix, IO_FILE_HDL
|
||||
jp fsPutB
|
||||
jp fsPutC
|
||||
.blkdev:
|
||||
.dw .fsGetB, .fsPutB
|
||||
.dw .fsGetC, .fsPutC
|
||||
|
||||
ioGetB:
|
||||
ioGetC:
|
||||
push ix
|
||||
ld ix, IO_BLK
|
||||
call _blkGetB
|
||||
call _blkGetC
|
||||
pop ix
|
||||
ret
|
||||
|
||||
ioPutB:
|
||||
ioPutC:
|
||||
push ix
|
||||
ld ix, IO_BLK
|
||||
call _blkPutB
|
||||
call _blkPutC
|
||||
pop ix
|
||||
ret
|
||||
|
||||
@ -76,14 +76,14 @@ ioPutLine:
|
||||
ld a, (hl)
|
||||
or a
|
||||
jr z, .loopend ; null, we're finished
|
||||
call ioPutB
|
||||
call ioPutC
|
||||
jr nz, .error
|
||||
inc hl
|
||||
jr .loop
|
||||
.loopend:
|
||||
; Wrote the whole line, write ending LF
|
||||
ld a, 0x0a
|
||||
call ioPutB
|
||||
call ioPutC
|
||||
jr z, .end ; success
|
||||
; continue to error
|
||||
.error:
|
||||
|
@ -25,16 +25,16 @@
|
||||
; *** Requirements ***
|
||||
; BLOCKDEV_SIZE
|
||||
; FS_HANDLE_SIZE
|
||||
; _blkGetB
|
||||
; _blkPutB
|
||||
; _blkGetC
|
||||
; _blkPutC
|
||||
; _blkSeek
|
||||
; _blkTell
|
||||
; addHL
|
||||
; cpHLDE
|
||||
; fsFindFN
|
||||
; fsOpen
|
||||
; fsGetB
|
||||
; fsPutB
|
||||
; fsGetC
|
||||
; fsPutC
|
||||
; fsSetSize
|
||||
; intoHL
|
||||
; printstr
|
||||
@ -46,7 +46,7 @@
|
||||
; *** Variables ***
|
||||
;
|
||||
.equ ED_CURLINE ED_RAMSTART
|
||||
.equ ED_RAMEND @+2
|
||||
.equ ED_RAMEND ED_CURLINE+2
|
||||
|
||||
edMain:
|
||||
; because ed only takes a single string arg, we can use HL directly
|
||||
|
@ -4,15 +4,15 @@
|
||||
; sectors. Collapse OS doesn't have a random number generator, so we'll simply
|
||||
; rely on initial SRAM value, which tend is random enough for our purpose.
|
||||
;
|
||||
; How it works is simple. From its designated RAMSTART, it calls PutB until it
|
||||
; How it works is simple. From its designated RAMSTART, it calls PutC until it
|
||||
; reaches the end of RAM (0xffff). Then, it starts over and this time it reads
|
||||
; every byte and compares.
|
||||
;
|
||||
; If there's an error, prints out where.
|
||||
;
|
||||
; *** Requirements ***
|
||||
; sdcPutB
|
||||
; sdcGetB
|
||||
; sdcPutC
|
||||
; sdcGetC
|
||||
; printstr
|
||||
; printHexPair
|
||||
;
|
||||
|
@ -9,7 +9,7 @@ sdctMain:
|
||||
; we set DE to 12 instead of zero
|
||||
push de ; <|
|
||||
ld de, 12 ; |
|
||||
call sdcPutB ; |
|
||||
call sdcPutC ; |
|
||||
pop de ; <|
|
||||
jr nz, .error
|
||||
inc hl
|
||||
@ -30,7 +30,7 @@ sdctMain:
|
||||
.rLoop:
|
||||
push de ; <|
|
||||
ld de, 12 ; |
|
||||
call sdcGetB ; |
|
||||
call sdcGetC ; |
|
||||
pop de ; <|
|
||||
jr nz, .error
|
||||
ex de, hl
|
||||
|
@ -54,7 +54,7 @@ handleDB:
|
||||
or a ; cp 0
|
||||
jr nz, .overflow ; not zero? overflow
|
||||
ld a, l
|
||||
call ioPutB
|
||||
call ioPutC
|
||||
jr nz, .ioError
|
||||
.stopStrLit:
|
||||
call readComma
|
||||
@ -84,7 +84,7 @@ handleDB:
|
||||
or a ; when we encounter 0, that was what used to
|
||||
jr z, .stopStrLit ; be our closing quote. Stop.
|
||||
; Normal character, output
|
||||
call ioPutB
|
||||
call ioPutC
|
||||
jr nz, .ioError
|
||||
jr .stringLiteral
|
||||
|
||||
@ -98,10 +98,10 @@ handleDW:
|
||||
jr nz, .badarg
|
||||
push ix \ pop hl
|
||||
ld a, l
|
||||
call ioPutB
|
||||
call ioPutC
|
||||
jr nz, .ioError
|
||||
ld a, h
|
||||
call ioPutB
|
||||
call ioPutC
|
||||
jr nz, .ioError
|
||||
call readComma
|
||||
jr z, .loop
|
||||
@ -208,7 +208,7 @@ handleFIL:
|
||||
or c
|
||||
jr z, .loopend
|
||||
xor a
|
||||
call ioPutB
|
||||
call ioPutC
|
||||
jr nz, .ioError
|
||||
dec bc
|
||||
jr .loop
|
||||
@ -314,7 +314,7 @@ getDirectiveID:
|
||||
|
||||
; Parse directive specified in A (D_* const) with args in I/O and act in
|
||||
; an appropriate manner. If the directive results in writing data at its
|
||||
; current location, that data is directly written through ioPutB.
|
||||
; current location, that data is directly written through ioPutC.
|
||||
; Each directive has the same return value pattern: Z on success, not-Z on
|
||||
; error, A contains the error number (ERR_*).
|
||||
parseDirective:
|
||||
|
@ -5,9 +5,9 @@
|
||||
;
|
||||
; We don't buffer the whole source in memory, so we need our input blkdev to
|
||||
; support Seek so we can read the file a second time. So, for input, we need
|
||||
; GetB and Seek.
|
||||
; GetC and Seek.
|
||||
;
|
||||
; For output, we only need PutB. Output doesn't start until the second pass.
|
||||
; For output, we only need PutC. Output doesn't start until the second pass.
|
||||
;
|
||||
; The goal of the second pass is to assign values to all symbols so that we
|
||||
; can have forward references (instructions referencing a label that happens
|
||||
@ -33,11 +33,11 @@
|
||||
; blkSet
|
||||
; fsFindFN
|
||||
; fsOpen
|
||||
; fsGetB
|
||||
; fsGetC
|
||||
; cpHLDE
|
||||
; parseArgs
|
||||
; _blkGetB
|
||||
; _blkPutB
|
||||
; _blkGetC
|
||||
; _blkPutC
|
||||
; _blkSeek
|
||||
; _blkTell
|
||||
; printstr
|
||||
|
@ -888,7 +888,7 @@ parseInstruction:
|
||||
ld hl, INS_UPCODE
|
||||
.loopWrite:
|
||||
ld a, (hl)
|
||||
call ioPutB
|
||||
call ioPutC
|
||||
jr nz, .ioError
|
||||
inc hl
|
||||
djnz .loopWrite
|
||||
|
@ -8,7 +8,7 @@
|
||||
; maintaining IO_PC and of properly disabling output on first pass.
|
||||
;
|
||||
; On top of that, this unit has the responsibility of keeping track of the
|
||||
; current lineno. Whenever GetB is called, we check if the fetched byte is a
|
||||
; current lineno. Whenever GetC is called, we check if the fetched char is a
|
||||
; newline. If it is, we increase our lineno. This unit is the best place to
|
||||
; keep track of this because we have to handle ioRecallPos.
|
||||
;
|
||||
@ -17,7 +17,7 @@
|
||||
; mechanism, that is, a way to say "you see that character I've just read? that
|
||||
; was out of my bounds. Could you make it as if I had never read it?". That
|
||||
; buffer is one character big and is made with the expectation that ioPutBack
|
||||
; is always called right after a ioGetB (when it's called).
|
||||
; is always called right after a ioGetC (when it's called).
|
||||
;
|
||||
; ioPutBack will mess up seek and tell offsets, so thath "put back" should be
|
||||
; consumed before having to seek and tell.
|
||||
@ -25,7 +25,7 @@
|
||||
; That's for the general rules.
|
||||
;
|
||||
; Now, let's enter includes. To simplify processing, we make include mostly
|
||||
; transparent to all other units. They always read from ioGetB and a include
|
||||
; transparent to all other units. They always read from ioGetC and a include
|
||||
; directive should have the exact same effect as copy/pasting the contents of
|
||||
; the included file in the caller.
|
||||
;
|
||||
@ -33,7 +33,7 @@
|
||||
; can include.
|
||||
;
|
||||
; When we include, all we do here is open the file with fsOpen and set a flag
|
||||
; indicating that we're inside an include. When that flag is on, GetB, Seek and
|
||||
; indicating that we're inside an include. When that flag is on, GetC, Seek and
|
||||
; Tell are transparently redirected to their fs* counterpart.
|
||||
;
|
||||
; When we reach EOF in an included file, we transparently unset the "in include"
|
||||
@ -73,7 +73,7 @@ ioInit:
|
||||
call blkSet
|
||||
jp ioResetCounters
|
||||
|
||||
ioGetB:
|
||||
ioGetC:
|
||||
ld a, (IO_PUTBACK_BUF)
|
||||
or a ; cp 0
|
||||
jr nz, .getback
|
||||
@ -81,7 +81,7 @@ ioGetB:
|
||||
jr z, .normalmode
|
||||
; We're in "include mode", read from FS
|
||||
ld ix, IO_INCLUDE_BLK
|
||||
call _blkGetB
|
||||
call _blkGetC
|
||||
jr nz, .includeEOF
|
||||
cp 0x0a ; newline
|
||||
ret nz ; not newline? nothing to do
|
||||
@ -111,7 +111,7 @@ ioGetB:
|
||||
.normalmode:
|
||||
; normal mode, read from IN stream
|
||||
ld ix, IO_IN_BLK
|
||||
call _blkGetB
|
||||
call _blkGetC
|
||||
cp 0x0a ; newline
|
||||
ret nz ; not newline? return
|
||||
; inc current lineno
|
||||
@ -133,14 +133,14 @@ _callIX:
|
||||
jp (ix)
|
||||
ret
|
||||
|
||||
; Put back non-zero character A into the "ioGetB stack". The next ioGetB call,
|
||||
; Put back non-zero character A into the "ioGetC stack". The next ioGetC call,
|
||||
; instead of reading from IO_IN_BLK, will return that character. That's the
|
||||
; easiest way I found to handle the readWord/gotoNextLine problem.
|
||||
ioPutBack:
|
||||
ld (IO_PUTBACK_BUF), a
|
||||
ret
|
||||
|
||||
ioPutB:
|
||||
ioPutC:
|
||||
push hl
|
||||
ld hl, (IO_PC)
|
||||
inc hl
|
||||
@ -151,7 +151,7 @@ ioPutB:
|
||||
jr z, .skip
|
||||
pop af
|
||||
ld ix, IO_OUT_BLK
|
||||
jp _blkPutB
|
||||
jp _blkPutC
|
||||
.skip:
|
||||
pop af
|
||||
cp a ; ensure Z
|
||||
@ -240,7 +240,7 @@ ioOpenInclude:
|
||||
cp a ; ensure Z
|
||||
ret
|
||||
|
||||
; Open file specified in (HL) and spit its contents through ioPutB
|
||||
; Open file specified in (HL) and spit its contents through ioPutC
|
||||
; Sets Z on success.
|
||||
ioSpitBin:
|
||||
call fsFindFN
|
||||
@ -251,9 +251,9 @@ ioSpitBin:
|
||||
ld hl, 0
|
||||
.loop:
|
||||
ld ix, IO_BIN_HDL
|
||||
call fsGetB
|
||||
call fsGetC
|
||||
jr nz, .loopend
|
||||
call ioPutB
|
||||
call ioPutC
|
||||
inc hl
|
||||
jr .loop
|
||||
.loopend:
|
||||
@ -274,12 +274,12 @@ ioLineNo:
|
||||
pop af
|
||||
ret
|
||||
|
||||
_ioIncGetB:
|
||||
_ioIncGetC:
|
||||
ld ix, IO_INCLUDE_HDL
|
||||
jp fsGetB
|
||||
jp fsGetC
|
||||
|
||||
_ioIncBlk:
|
||||
.dw _ioIncGetB, unsetZ
|
||||
.dw _ioIncGetC, unsetZ
|
||||
|
||||
; call printstr followed by newline
|
||||
ioPrintLN:
|
||||
|
@ -128,7 +128,7 @@ zasmParseFile:
|
||||
ret
|
||||
|
||||
; Parse next token and accompanying args (when relevant) in I/O, write the
|
||||
; resulting opcode(s) through ioPutB and increases (IO_PC) by the number of
|
||||
; resulting opcode(s) through ioPutC and increases (IO_PC) by the number of
|
||||
; bytes written. BC is set to the result of the call to tokenize.
|
||||
; Sets Z if parse was successful, unset if there was an error. EOF is not an
|
||||
; error. If there is an error, A is set to the corresponding error code (ERR_*).
|
||||
|
@ -74,12 +74,12 @@ isLabel:
|
||||
; Read I/O as long as it's whitespace. When it's not, stop and return the last
|
||||
; read char in A
|
||||
_eatWhitespace:
|
||||
call ioGetB
|
||||
call ioGetC
|
||||
call isSep
|
||||
ret nz
|
||||
jr _eatWhitespace
|
||||
|
||||
; Read ioGetB until a word starts, then read ioGetB as long as there is no
|
||||
; Read ioGetC until a word starts, then read ioGetC as long as there is no
|
||||
; separator and put that contents in (scratchpad), null terminated, for a
|
||||
; maximum of SCRATCHPAD_SIZE-1 characters.
|
||||
; If EOL (\n, \r or comment) or EOF is hit before we could read a word, we stop
|
||||
@ -104,7 +104,7 @@ readWord:
|
||||
.loop:
|
||||
ld (hl), a
|
||||
inc hl
|
||||
call ioGetB
|
||||
call ioGetC
|
||||
call isSepOrLineEnd
|
||||
jr z, .success
|
||||
cp ','
|
||||
@ -130,7 +130,7 @@ readWord:
|
||||
; inside quotes, we accept literal whitespaces, but not line ends.
|
||||
ld (hl), a
|
||||
inc hl
|
||||
call ioGetB
|
||||
call ioGetC
|
||||
cp '"'
|
||||
jr z, .loop ; ending the quote ends the word
|
||||
call isLineEnd
|
||||
@ -143,12 +143,12 @@ readWord:
|
||||
; single quote is more straightforward: we have 3 chars and we put them
|
||||
; right in scratchpad
|
||||
ld (hl), a
|
||||
call ioGetB
|
||||
call ioGetC
|
||||
or a
|
||||
jr z, .error
|
||||
inc hl
|
||||
ld (hl), a
|
||||
call ioGetB
|
||||
call ioGetC
|
||||
cp 0x27 ; '
|
||||
jr nz, .error
|
||||
inc hl
|
||||
@ -165,7 +165,7 @@ readComma:
|
||||
call unsetZ
|
||||
ret
|
||||
|
||||
; Read ioGetB until we reach the beginning of next line, skipping comments if
|
||||
; Read ioGetC until we reach the beginning of next line, skipping comments if
|
||||
; necessary. This skips all whitespace, \n, \r, comments until we reach the
|
||||
; first non-comment character. Then, we put it back (ioPutBack) and return.
|
||||
;
|
||||
@ -176,7 +176,7 @@ readComma:
|
||||
gotoNextLine:
|
||||
.loop1:
|
||||
; first loop is "strict", that is: we error out on non-whitespace.
|
||||
call ioGetB
|
||||
call ioGetC
|
||||
call isSepOrLineEnd
|
||||
ret nz ; error
|
||||
or a ; cp 0
|
||||
@ -189,7 +189,7 @@ gotoNextLine:
|
||||
.loop2:
|
||||
; second loop is the "comment loop": anything is valid and we just run
|
||||
; until EOL.
|
||||
call ioGetB
|
||||
call ioGetC
|
||||
or a ; cp 0
|
||||
jr z, .eof
|
||||
cp '\' ; special case: '\' doesn't count as a line end
|
||||
@ -201,7 +201,7 @@ gotoNextLine:
|
||||
.loop3:
|
||||
; Loop 3 happens after we reach our first line sep. This means that we
|
||||
; wade through whitespace until we reach a non-whitespace character.
|
||||
call ioGetB
|
||||
call ioGetC
|
||||
or a ; cp 0
|
||||
jr z, .eof
|
||||
cp 0x3b ; ';'
|
||||
|
@ -13,11 +13,11 @@ Definition of block devices happen at include time. It would look like:
|
||||
BLOCKDEV_COUNT .equ 1
|
||||
#include "blockdev.asm"
|
||||
; List of devices
|
||||
.dw sdcGetB, sdcPutB
|
||||
.dw aciaGetC, aciaPutC
|
||||
[...]
|
||||
|
||||
That tells `blockdev` that we're going to set up one device, that its GetB and
|
||||
PutB are the ones defined by `sdc.asm`.
|
||||
That tells `blockdev` that we're going to set up one device, that its GetC and
|
||||
PutC are the ones defined by `acia.asm`.
|
||||
|
||||
If your block device is read-only or write-only, use dummy routines. `unsetZ`
|
||||
is a good choice since it will return with the `Z` flag unset, indicating an
|
||||
@ -28,16 +28,16 @@ seek pointer. This seek pointer is used in shell commands described below.
|
||||
|
||||
## Routine definitions
|
||||
|
||||
Parts that implement GetB and PutB do so in a loosely-coupled manner, but
|
||||
Parts that implement GetC and PutC do so in a loosely-coupled manner, but
|
||||
they should try to adhere to the convention, that is:
|
||||
|
||||
**GetB**: Get the byte at position specified by `HL`. If it supports 32-bit
|
||||
**GetC**: Get the character at position specified by `HL`. If it supports 32-bit
|
||||
addressing, `DE` contains the high-order bytes. Return the result in
|
||||
`A`. If there's an error (for example, address out of range), unset
|
||||
`Z`. This routine is not expected to block. We expect the result to be
|
||||
immediate.
|
||||
|
||||
**PutB**: The opposite of GetB. Write the character in `A` at specified
|
||||
**PutC**: The opposite of GetC. Write the character in `A` at specified
|
||||
position. `Z` unset on error.
|
||||
|
||||
## Shell usage
|
||||
|
@ -2,34 +2,34 @@
|
||||
;
|
||||
; A block device is an abstraction over something we can read from, write to.
|
||||
;
|
||||
; A device that fits this abstraction puts the proper hook into itself, and then
|
||||
; the glue code assigns a blockdev ID to that device. It then becomes easy to
|
||||
; access arbitrary devices in a convenient manner.
|
||||
; A device that fits this abstraction puts the properly hook into itself, and
|
||||
; then the glue code assigns a blockdev ID to that device. It then becomes easy
|
||||
; to access arbitrary devices in a convenient manner.
|
||||
;
|
||||
; This module exposes a seek/tell/getb/putb API that is then re-routed to
|
||||
; This module exposes a seek/tell/getc/putc API that is then re-routed to
|
||||
; underlying drivers. There will eventually be more than one driver type, but
|
||||
; for now we sit on only one type of driver: random access driver.
|
||||
;
|
||||
; *** Random access drivers ***
|
||||
;
|
||||
; Random access drivers are expected to supply two routines: GetB and PutB.
|
||||
; Random access drivers are expected to supply two routines: GetC and PutC.
|
||||
;
|
||||
; GetB:
|
||||
; Reads one byte at address specified in DE/HL and returns its value in A.
|
||||
; GetC:
|
||||
; Reads one character at address specified in DE/HL and returns its value in A.
|
||||
; Sets Z according to whether read was successful: Set if successful, unset
|
||||
; if not.
|
||||
;
|
||||
; Unsuccessful reads generally mean that requested addr is out of bounds (we
|
||||
; reached EOF).
|
||||
;
|
||||
; PutB:
|
||||
; Writes byte in A at address specified in DE/HL. Sets Z according to whether
|
||||
; the operation was successful.
|
||||
; PutC:
|
||||
; Writes character in A at address specified in DE/HL. Sets Z according to
|
||||
; whether the operation was successful.
|
||||
;
|
||||
; Unsuccessful writes generally mean that we're out of bounds for writing.
|
||||
;
|
||||
; All routines are expected to preserve unused registers except IX which is
|
||||
; explicitly protected during GetB/PutB calls. This makes quick "handle+jump"
|
||||
; explicitly protected during GetC/PutC calls. This makes quick "handle+jump"
|
||||
; definitions possible.
|
||||
|
||||
|
||||
@ -46,9 +46,9 @@
|
||||
.equ BLOCKDEV_SIZE 8
|
||||
; *** VARIABLES ***
|
||||
; Pointer to the selected block device. A block device is a 8 bytes block of
|
||||
; memory with pointers to GetB, PutB, and a 32-bit counter, in that order.
|
||||
; memory with pointers to GetC, PutC, and a 32-bit counter, in that order.
|
||||
.equ BLOCKDEV_SEL BLOCKDEV_RAMSTART
|
||||
.equ BLOCKDEV_RAMEND @+BLOCKDEV_SIZE
|
||||
.equ BLOCKDEV_RAMEND BLOCKDEV_SEL+BLOCKDEV_SIZE
|
||||
|
||||
; *** CODE ***
|
||||
; Select block index specified in A and place them in routine pointers at (DE).
|
||||
@ -121,16 +121,16 @@ _blkInc:
|
||||
pop af
|
||||
ret
|
||||
|
||||
; Reads one byte from selected device and returns its value in A.
|
||||
; Reads one character from selected device and returns its value in A.
|
||||
; Sets Z according to whether read was successful: Set if successful, unset
|
||||
; if not.
|
||||
blkGetB:
|
||||
blkGetC:
|
||||
push ix
|
||||
ld ix, BLOCKDEV_SEL
|
||||
call _blkGetB
|
||||
call _blkGetC
|
||||
pop ix
|
||||
ret
|
||||
_blkGetB:
|
||||
_blkGetC:
|
||||
push hl
|
||||
push de
|
||||
call _blkTell
|
||||
@ -139,20 +139,20 @@ _blkGetB:
|
||||
pop hl
|
||||
jr _blkInc ; advance and return
|
||||
|
||||
; Writes byte in A in current position in the selected device. Sets Z according
|
||||
; to whether the operation was successful.
|
||||
blkPutB:
|
||||
; Writes character in A in current position in the selected device. Sets Z
|
||||
; according to whether the operation was successful.
|
||||
blkPutC:
|
||||
push ix
|
||||
ld ix, BLOCKDEV_SEL
|
||||
call _blkPutB
|
||||
call _blkPutC
|
||||
pop ix
|
||||
ret
|
||||
_blkPutB:
|
||||
_blkPutC:
|
||||
push ix
|
||||
push hl
|
||||
push de
|
||||
call _blkTell
|
||||
inc ix ; make IX point to PutB
|
||||
inc ix ; make IX point to PutC
|
||||
inc ix
|
||||
call callIXI
|
||||
pop de
|
||||
@ -160,7 +160,7 @@ _blkPutB:
|
||||
pop ix
|
||||
jr _blkInc ; advance and return
|
||||
|
||||
; Reads B chars from blkGetB and copy them in (HL).
|
||||
; Reads B chars from blkGetC and copy them in (HL).
|
||||
; Sets Z if successful, unset Z if there was an error.
|
||||
blkRead:
|
||||
push ix
|
||||
@ -172,7 +172,7 @@ _blkRead:
|
||||
push hl
|
||||
push bc
|
||||
.loop:
|
||||
call _blkGetB
|
||||
call _blkGetC
|
||||
jr nz, .end ; Z already unset
|
||||
ld (hl), a
|
||||
inc hl
|
||||
@ -183,7 +183,7 @@ _blkRead:
|
||||
pop hl
|
||||
ret
|
||||
|
||||
; Writes B chars to blkPutB from (HL).
|
||||
; Writes B chars to blkPutC from (HL).
|
||||
; Sets Z if successful, unset Z if there was an error.
|
||||
blkWrite:
|
||||
push ix
|
||||
@ -196,7 +196,7 @@ _blkWrite:
|
||||
push bc
|
||||
.loop:
|
||||
ld a, (hl)
|
||||
call _blkPutB
|
||||
call _blkPutC
|
||||
jr nz, .end ; Z already unset
|
||||
inc hl
|
||||
djnz .loop
|
||||
@ -217,11 +217,11 @@ _blkWrite:
|
||||
; (high). DE is only used for mode 0.
|
||||
;
|
||||
; When seeking to an out-of-bounds position, the resulting position will be
|
||||
; one position ahead of the last valid position. Therefore, GetB after a seek
|
||||
; one position ahead of the last valid position. Therefore, GetC after a seek
|
||||
; to end would always fail.
|
||||
;
|
||||
; If the device is "growable", it's possible that seeking to end when calling
|
||||
; PutB doesn't necessarily result in a failure.
|
||||
; PutC doesn't necessarily result in a failure.
|
||||
blkSeek:
|
||||
push ix
|
||||
ld ix, BLOCKDEV_SEL
|
||||
@ -309,6 +309,6 @@ _blkTell:
|
||||
|
||||
; This label is at the end of the file on purpose: the glue file should include
|
||||
; a list of device routine table entries just after the include. Each line
|
||||
; has 2 word addresses: GetB and PutB. An entry could look like:
|
||||
; .dw mmapGetB, mmapPutB
|
||||
; has 4 word addresses: GetC, PutC and Seek, Tell. An entry could look like:
|
||||
; .dw mmapGetC, mmapPutC, mmapSeek, mmapTell
|
||||
blkDevTbl:
|
||||
|
@ -50,7 +50,7 @@ blkSeekCmd:
|
||||
; stop loading.
|
||||
;
|
||||
; Returns a SHELL_ERR_IO_ERROR only if we couldn't read any byte (if the first
|
||||
; call to GetB failed)
|
||||
; call to GetC failed)
|
||||
;
|
||||
; Example: load 42
|
||||
blkLoadCmd:
|
||||
@ -62,12 +62,12 @@ blkLoad:
|
||||
ld a, (hl)
|
||||
ld b, a
|
||||
ld hl, (SHELL_MEM_PTR)
|
||||
call blkGetB
|
||||
call blkGetC
|
||||
jr nz, .ioError
|
||||
jr .intoLoop ; we'v already called blkGetB. don't call it
|
||||
jr .intoLoop ; we'v already called blkGetC. don't call it
|
||||
; again.
|
||||
.loop:
|
||||
call blkGetB
|
||||
call blkGetC
|
||||
.intoLoop:
|
||||
ld (hl), a
|
||||
inc hl
|
||||
@ -86,7 +86,7 @@ blkLoad:
|
||||
|
||||
; Load the specified number of bytes (max 0x100, 0 means 0x100) from the current
|
||||
; memory pointer and write them to I/O. Memory pointer doesn't move. This puts
|
||||
; chars to blkPutB. Raises error if not all bytes could be written.
|
||||
; chars to blkPutC. Raises error if not all bytes could be written.
|
||||
;
|
||||
; Example: save 42
|
||||
blkSaveCmd:
|
||||
@ -101,7 +101,7 @@ blkSave:
|
||||
.loop:
|
||||
ld a, (hl)
|
||||
inc hl
|
||||
call blkPutB
|
||||
call blkPutC
|
||||
jr nz, .ioError
|
||||
djnz .loop
|
||||
.loopend:
|
||||
|
@ -9,6 +9,6 @@
|
||||
.equ BLOCKDEV_ERR_OUT_OF_BOUNDS 0x03
|
||||
.equ BLOCKDEV_ERR_UNSUPPORTED 0x04
|
||||
|
||||
; IO routines (GetB, PutB) returned an error in a load/save command
|
||||
; IO routines (GetC, PutC) returned an error in a load/save command
|
||||
.equ SHELL_ERR_IO_ERROR 0x05
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
; Collapse OS filesystem (CFS) is not made to be convenient, but to be simple.
|
||||
; This is little more than "named storage blocks". Characteristics:
|
||||
;
|
||||
; * a filesystem sits upon a blockdev. It needs GetB, PutB, Seek.
|
||||
; * a filesystem sits upon a blockdev. It needs GetC, PutC, Seek.
|
||||
; * No directory. Use filename prefix to group.
|
||||
; * First block of each file has metadata. Others are raw data.
|
||||
; * No FAT. Files are a chain of blocks of a predefined size. To enumerate
|
||||
@ -98,12 +98,12 @@
|
||||
; This pointer is 32 bits. 32 bits pointers are a bit awkward: first two bytes
|
||||
; are high bytes *low byte first*, and then the low two bytes, same order.
|
||||
; When loaded in HL/DE, the four bytes are loaded in this order: E, D, L, H
|
||||
.equ FS_START @+BLOCKDEV_SIZE
|
||||
.equ FS_START FS_BLK+BLOCKDEV_SIZE
|
||||
; This variable below contain the metadata of the last block we moved
|
||||
; to. We read this data in memory to avoid constant seek+read operations.
|
||||
.equ FS_META @+4
|
||||
.equ FS_HANDLES @+FS_METASIZE
|
||||
.equ FS_RAMEND @+FS_HANDLE_COUNT*FS_HANDLE_SIZE
|
||||
.equ FS_META FS_START+4
|
||||
.equ FS_HANDLES FS_META+FS_METASIZE
|
||||
.equ FS_RAMEND FS_HANDLES+FS_HANDLE_COUNT*FS_HANDLE_SIZE
|
||||
|
||||
; *** DATA ***
|
||||
P_FS_MAGIC:
|
||||
@ -333,10 +333,10 @@ fsIsDeleted:
|
||||
; we can still access the FS even if blkdev selection changes. These routines
|
||||
; below mimic blkdev's methods, but for our private mount.
|
||||
|
||||
fsblkGetB:
|
||||
fsblkGetC:
|
||||
push ix
|
||||
ld ix, FS_BLK
|
||||
call _blkGetB
|
||||
call _blkGetC
|
||||
pop ix
|
||||
ret
|
||||
|
||||
@ -347,10 +347,10 @@ fsblkRead:
|
||||
pop ix
|
||||
ret
|
||||
|
||||
fsblkPutB:
|
||||
fsblkPutC:
|
||||
push ix
|
||||
ld ix, FS_BLK
|
||||
call _blkPutB
|
||||
call _blkPutC
|
||||
pop ix
|
||||
ret
|
||||
|
||||
@ -458,27 +458,27 @@ fsSetSize:
|
||||
; cache.
|
||||
ld a, l
|
||||
ld (ix+4), a
|
||||
call fsblkPutB
|
||||
call fsblkPutC
|
||||
ld a, h
|
||||
ld (ix+5), a
|
||||
call fsblkPutB
|
||||
call fsblkPutC
|
||||
pop hl ; <-- lvl 1
|
||||
xor a ; ensure Z
|
||||
ret
|
||||
|
||||
; Read a byte in handle at (IX) at position HL and put it into A.
|
||||
; Z is set on success, unset if handle is at the end of the file.
|
||||
fsGetB:
|
||||
fsGetC:
|
||||
call fsWithinBounds
|
||||
jr z, .proceed
|
||||
; We want to unset Z, but also return 0 to ensure that a GetB that
|
||||
; We want to unset Z, but also return 0 to ensure that a GetC that
|
||||
; doesn't check Z doesn't end up with false data.
|
||||
xor a
|
||||
jp unsetZ ; returns
|
||||
.proceed:
|
||||
push hl
|
||||
call fsPlaceH
|
||||
call fsblkGetB
|
||||
call fsblkGetC
|
||||
cp a ; ensure Z
|
||||
pop hl
|
||||
ret
|
||||
@ -486,10 +486,10 @@ fsGetB:
|
||||
; Write byte A in handle (IX) at position HL.
|
||||
; Z is set on success, unset if handle is at the end of the file.
|
||||
; TODO: detect end of block alloc
|
||||
fsPutB:
|
||||
fsPutC:
|
||||
push hl
|
||||
call fsPlaceH
|
||||
call fsblkPutB
|
||||
call fsblkPutC
|
||||
pop hl
|
||||
; if HL is out of bounds, increase bounds
|
||||
call fsWithinBounds
|
||||
|
@ -24,7 +24,7 @@ _mmapAddr:
|
||||
pop de
|
||||
jp unsetZ
|
||||
|
||||
mmapGetB:
|
||||
mmapGetC:
|
||||
push hl
|
||||
call _mmapAddr
|
||||
jr nz, .end
|
||||
@ -35,7 +35,7 @@ mmapGetB:
|
||||
ret
|
||||
|
||||
|
||||
mmapPutB:
|
||||
mmapPutC:
|
||||
push hl
|
||||
call _mmapAddr
|
||||
jr nz, .end
|
||||
|
@ -16,7 +16,7 @@
|
||||
;
|
||||
; *** Variables ***
|
||||
.equ PGM_HANDLE PGM_RAMSTART
|
||||
.equ PGM_RAMEND @+FS_HANDLE_SIZE
|
||||
.equ PGM_RAMEND PGM_HANDLE+FS_HANDLE_SIZE
|
||||
|
||||
; Routine suitable to plug into SHELL_CMDHOOK. HL points to the full cmdline.
|
||||
; which has been processed to replace the first ' ' with a null char.
|
||||
@ -48,7 +48,7 @@ pgmRun:
|
||||
ld hl, 0 ; addr that we read in file handle
|
||||
ld de, PGM_CODEADDR ; addr in mem we write to
|
||||
.loop:
|
||||
call fsGetB ; we use Z at end of loop
|
||||
call fsGetC ; we use Z at end of loop
|
||||
ld (de), a ; Z preserved
|
||||
inc hl ; Z preserved in 16-bit
|
||||
inc de ; Z preserved in 16-bit
|
||||
|
@ -20,14 +20,14 @@
|
||||
;
|
||||
; SD card's lowest common denominator in terms of block size is 512 bytes, so
|
||||
; that's what we deal with. To avoid wastefully reading entire blocks from the
|
||||
; card for one byte read ops, we buffer the last read block. If a GetB or PutB
|
||||
; card for one byte read ops, we buffer the last read block. If a GetC or PutC
|
||||
; operation is within that buffer, then no interaction with the SD card is
|
||||
; necessary.
|
||||
;
|
||||
; As soon as a GetB or PutB operation is made that is outside the current
|
||||
; As soon as a GetC or PutC operation is made that is outside the current
|
||||
; buffer, we load a new block.
|
||||
;
|
||||
; When we PutB, we flag the buffer as "dirty". On the next buffer change (during
|
||||
; When we PutC, we flag the buffer as "dirty". On the next buffer change (during
|
||||
; an out-of-buffer request or during an explicit "flush" operation), bytes
|
||||
; currently in the buffer will be written to the SD card.
|
||||
;
|
||||
@ -37,10 +37,10 @@
|
||||
; right away, in another file on the same card (zasm), on a different sector.
|
||||
;
|
||||
; If we only have one buffer in this scenario, we'll end up loading a new sector
|
||||
; at each GetB/PutB operation and, more importantly, writing a whole block for
|
||||
; at each GetC/PutC operation and, more importantly, writing a whole block for
|
||||
; a few bytes each time. This will wear the card prematurely (and be very slow).
|
||||
;
|
||||
; With 2 buffers, we solve the problem. Whenever GetB/PutB is called, we first
|
||||
; With 2 buffers, we solve the problem. Whenever GetC/PutC is called, we first
|
||||
; look if one of the buffer holds our sector. If not, we see if one of the
|
||||
; buffer is clean (not dirty). If yes, we use this one. If both are dirty or
|
||||
; clean, we use any. This way, as long as writing isn't made to random
|
||||
@ -721,7 +721,7 @@ _sdcPlaceBuf:
|
||||
xor a ; ensure Z
|
||||
ret
|
||||
|
||||
sdcGetB:
|
||||
sdcGetC:
|
||||
push hl
|
||||
call _sdcPlaceBuf
|
||||
jr nz, .error
|
||||
@ -736,7 +736,7 @@ sdcGetB:
|
||||
pop hl
|
||||
ret
|
||||
|
||||
sdcPutB:
|
||||
sdcPutC:
|
||||
push hl
|
||||
push af ; let's remember the char we put, _sdcPlaceBuf
|
||||
; destroys A.
|
||||
|
@ -24,7 +24,7 @@ jp aciaInt
|
||||
.equ BLOCKDEV_COUNT 1
|
||||
.inc "blockdev.asm"
|
||||
; List of devices
|
||||
.dw mmapGetB, mmapPutB
|
||||
.dw mmapGetC, mmapPutC
|
||||
|
||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
||||
.inc "stdio.asm"
|
||||
|
@ -29,8 +29,8 @@ jp aciaInt
|
||||
.equ BLOCKDEV_COUNT 2
|
||||
.inc "blockdev.asm"
|
||||
; List of devices
|
||||
.dw sdcGetB, sdcPutB
|
||||
.dw blk2GetB, blk2PutB
|
||||
.dw sdcGetC, sdcPutC
|
||||
.dw blk2GetC, blk2PutC
|
||||
|
||||
|
||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
||||
@ -83,10 +83,10 @@ init:
|
||||
|
||||
; *** blkdev 2: file handle 0 ***
|
||||
|
||||
blk2GetB:
|
||||
blk2GetC:
|
||||
ld ix, FS_HANDLES
|
||||
jp fsGetB
|
||||
jp fsGetC
|
||||
|
||||
blk2PutB:
|
||||
blk2PutC:
|
||||
ld ix, FS_HANDLES
|
||||
jp fsPutB
|
||||
jp fsPutC
|
||||
|
@ -27,7 +27,7 @@
|
||||
jp blkSet
|
||||
jp fsFindFN
|
||||
jp fsOpen
|
||||
jp fsGetB
|
||||
jp fsGetC
|
||||
jp cpHLDE ; approaching 0x38...
|
||||
|
||||
; interrupt hook
|
||||
@ -37,14 +37,14 @@ jp aciaInt
|
||||
; *** Jump Table (cont.) ***
|
||||
jp parseArgs
|
||||
jp printstr
|
||||
jp _blkGetB
|
||||
jp _blkPutB
|
||||
jp _blkGetC
|
||||
jp _blkPutC
|
||||
jp _blkSeek
|
||||
jp _blkTell
|
||||
jp printHexPair
|
||||
jp sdcGetB
|
||||
jp sdcPutB
|
||||
jp blkGetB
|
||||
jp sdcGetC
|
||||
jp sdcPutC
|
||||
jp blkGetC
|
||||
|
||||
.inc "err.h"
|
||||
.inc "core.asm"
|
||||
@ -55,10 +55,10 @@ jp aciaInt
|
||||
.equ BLOCKDEV_COUNT 4
|
||||
.inc "blockdev.asm"
|
||||
; List of devices
|
||||
.dw sdcGetB, sdcPutB
|
||||
.dw blk1GetB, blk1PutB
|
||||
.dw blk2GetB, blk2PutB
|
||||
.dw mmapGetB, mmapPutB
|
||||
.dw sdcGetC, sdcPutC
|
||||
.dw blk1GetC, blk1PutC
|
||||
.dw blk2GetC, blk2PutC
|
||||
.dw mmapGetC, mmapPutC
|
||||
|
||||
|
||||
.equ MMAP_START 0xe000
|
||||
@ -116,20 +116,20 @@ init:
|
||||
|
||||
; *** blkdev 1: file handle 0 ***
|
||||
|
||||
blk1GetB:
|
||||
blk1GetC:
|
||||
ld ix, FS_HANDLES
|
||||
jp fsGetB
|
||||
jp fsGetC
|
||||
|
||||
blk1PutB:
|
||||
blk1PutC:
|
||||
ld ix, FS_HANDLES
|
||||
jp fsPutB
|
||||
jp fsPutC
|
||||
|
||||
; *** blkdev 2: file handle 1 ***
|
||||
|
||||
blk2GetB:
|
||||
blk2GetC:
|
||||
ld ix, FS_HANDLES+FS_HANDLE_SIZE
|
||||
jp fsGetB
|
||||
jp fsGetC
|
||||
|
||||
blk2PutB:
|
||||
blk2PutC:
|
||||
ld ix, FS_HANDLES+FS_HANDLE_SIZE
|
||||
jp fsPutB
|
||||
jp fsPutC
|
||||
|
@ -5,31 +5,30 @@
|
||||
|
||||
; *** JUMP TABLE ***
|
||||
.equ strncmp 0x03
|
||||
.equ addDE @+3
|
||||
.equ addHL @+3
|
||||
.equ upcase @+3
|
||||
.equ unsetZ @+3
|
||||
.equ intoDE @+3
|
||||
.equ intoHL @+3
|
||||
.equ writeHLinDE @+3
|
||||
.equ findchar @+3
|
||||
.equ parseHex @+3
|
||||
.equ parseHexPair @+3
|
||||
.equ blkSel @+3
|
||||
.equ blkSet @+3
|
||||
.equ fsFindFN @+3
|
||||
.equ fsOpen @+3
|
||||
.equ fsGetB @+3
|
||||
.equ cpHLDE @+3
|
||||
; now at 0x36
|
||||
.equ addDE 0x06
|
||||
.equ addHL 0x09
|
||||
.equ upcase 0x0c
|
||||
.equ unsetZ 0x0f
|
||||
.equ intoDE 0x12
|
||||
.equ intoHL 0x15
|
||||
.equ writeHLinDE 0x18
|
||||
.equ findchar 0x1b
|
||||
.equ parseHex 0x1e
|
||||
.equ parseHexPair 0x21
|
||||
.equ blkSel 0x24
|
||||
.equ blkSet 0x27
|
||||
.equ fsFindFN 0x2a
|
||||
.equ fsOpen 0x2d
|
||||
.equ fsGetC 0x30
|
||||
.equ cpHLDE 0x33
|
||||
|
||||
.equ parseArgs 0x3b
|
||||
.equ printstr @+3
|
||||
.equ _blkGetB @+3
|
||||
.equ _blkPutB @+3
|
||||
.equ _blkSeek @+3
|
||||
.equ _blkTell @+3
|
||||
.equ printHexPair @+3
|
||||
.equ sdcGetB @+3
|
||||
.equ sdcPutB @+3
|
||||
.equ blkGetB @+3
|
||||
.equ printstr 0x3e
|
||||
.equ _blkGetC 0x41
|
||||
.equ _blkPutC 0x44
|
||||
.equ _blkSeek 0x47
|
||||
.equ _blkTell 0x4a
|
||||
.equ printHexPair 0x4d
|
||||
.equ sdcGetC 0x50
|
||||
.equ sdcPutC 0x53
|
||||
.equ blkGetC 0x56
|
||||
|
@ -22,14 +22,14 @@
|
||||
jp blkSet
|
||||
jp fsFindFN
|
||||
jp fsOpen
|
||||
jp fsGetB
|
||||
jp fsPutB
|
||||
jp fsGetC
|
||||
jp fsPutC
|
||||
jp fsSetSize
|
||||
jp cpHLDE
|
||||
jp parseArgs
|
||||
jp printstr
|
||||
jp _blkGetB
|
||||
jp _blkPutB
|
||||
jp _blkGetC
|
||||
jp _blkPutC
|
||||
jp _blkSeek
|
||||
jp _blkTell
|
||||
jp printcrlf
|
||||
@ -63,9 +63,9 @@
|
||||
.equ BLOCKDEV_COUNT 3
|
||||
.inc "blockdev.asm"
|
||||
; List of devices
|
||||
.dw mmapGetB, mmapPutB
|
||||
.dw f0GetB, f0PutB
|
||||
.dw f1GetB, f1PutB
|
||||
.dw mmapGetC, mmapPutC
|
||||
.dw f0GetC, f0PutC
|
||||
.dw f1GetC, f1PutC
|
||||
|
||||
|
||||
.equ FS_RAMSTART BLOCKDEV_RAMEND
|
||||
@ -121,21 +121,21 @@ init:
|
||||
ld (SHELL_CMDHOOK), hl
|
||||
jp shellLoop
|
||||
|
||||
f0GetB:
|
||||
f0GetC:
|
||||
ld ix, FS_HANDLES
|
||||
jp fsGetB
|
||||
jp fsGetC
|
||||
|
||||
f0PutB:
|
||||
f0PutC:
|
||||
ld ix, FS_HANDLES
|
||||
jp fsPutB
|
||||
jp fsPutC
|
||||
|
||||
f1GetB:
|
||||
f1GetC:
|
||||
ld ix, FS_HANDLES+FS_HANDLE_SIZE
|
||||
jp fsGetB
|
||||
jp fsGetC
|
||||
|
||||
f1PutB:
|
||||
f1PutC:
|
||||
ld ix, FS_HANDLES+FS_HANDLE_SIZE
|
||||
jp fsPutB
|
||||
jp fsPutC
|
||||
|
||||
edCmd:
|
||||
.db "ed", 0, 0, 0b1001, 0, 0
|
||||
|
@ -30,14 +30,14 @@
|
||||
.equ blkSet 0x27
|
||||
.equ fsFindFN 0x2a
|
||||
.equ fsOpen 0x2d
|
||||
.equ fsGetB 0x30
|
||||
.equ fsPutB 0x33
|
||||
.equ fsGetC 0x30
|
||||
.equ fsPutC 0x33
|
||||
.equ fsSetSize 0x36
|
||||
.equ cpHLDE 0x39
|
||||
.equ parseArgs 0x3c
|
||||
.equ printstr 0x3f
|
||||
.equ _blkGetB 0x42
|
||||
.equ _blkPutB 0x45
|
||||
.equ _blkGetC 0x42
|
||||
.equ _blkPutC 0x45
|
||||
.equ _blkSeek 0x48
|
||||
.equ _blkTell 0x4b
|
||||
.equ printcrlf 0x4e
|
||||
|
20
runtests.sh
20
runtests.sh
@ -1,20 +0,0 @@
|
||||
#/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
git clean -fxd
|
||||
|
||||
cd tools/emul
|
||||
make
|
||||
|
||||
cd ../tests
|
||||
make
|
||||
|
||||
# let's try again with an updated zasm
|
||||
cd ../emul
|
||||
make updatebootstrap all
|
||||
|
||||
cd ../tests
|
||||
make
|
@ -26,14 +26,14 @@
|
||||
jp blkSet
|
||||
jp fsFindFN
|
||||
jp fsOpen
|
||||
jp fsGetB
|
||||
jp fsPutB
|
||||
jp fsGetC
|
||||
jp fsPutC
|
||||
jp fsSetSize
|
||||
jp cpHLDE
|
||||
jp parseArgs
|
||||
jp printstr
|
||||
jp _blkGetB
|
||||
jp _blkPutB
|
||||
jp _blkGetC
|
||||
jp _blkPutC
|
||||
jp _blkSeek
|
||||
jp _blkTell
|
||||
jp printcrlf
|
||||
@ -48,10 +48,10 @@
|
||||
.equ BLOCKDEV_COUNT 4
|
||||
.inc "blockdev.asm"
|
||||
; List of devices
|
||||
.dw fsdevGetB, fsdevPutB
|
||||
.dw stdoutGetB, stdoutPutB
|
||||
.dw stdinGetB, stdinPutB
|
||||
.dw mmapGetB, mmapPutB
|
||||
.dw fsdevGetC, fsdevPutC
|
||||
.dw stdoutGetC, stdoutPutC
|
||||
.dw stdinGetC, stdinPutC
|
||||
.dw mmapGetC, mmapPutC
|
||||
|
||||
|
||||
.equ MMAP_START 0xe000
|
||||
@ -84,8 +84,8 @@ init:
|
||||
; setup stack
|
||||
ld hl, KERNEL_RAMEND
|
||||
ld sp, hl
|
||||
ld hl, emulGetB
|
||||
ld de, emulPutB
|
||||
ld hl, emulGetC
|
||||
ld de, emulPutC
|
||||
call stdioInit
|
||||
call fsInit
|
||||
ld a, 0 ; select fsdev
|
||||
@ -97,17 +97,17 @@ init:
|
||||
ld (SHELL_CMDHOOK), hl
|
||||
jp shellLoop
|
||||
|
||||
emulGetB:
|
||||
emulGetC:
|
||||
; Blocks until a char is returned
|
||||
in a, (STDIO_PORT)
|
||||
cp a ; ensure Z
|
||||
ret
|
||||
|
||||
emulPutB:
|
||||
emulPutC:
|
||||
out (STDIO_PORT), a
|
||||
ret
|
||||
|
||||
fsdevGetB:
|
||||
fsdevGetC:
|
||||
ld a, e
|
||||
out (FS_ADDR_PORT), a
|
||||
ld a, h
|
||||
@ -121,7 +121,7 @@ fsdevGetB:
|
||||
cp a ; ensure Z
|
||||
ret
|
||||
|
||||
fsdevPutB:
|
||||
fsdevPutC:
|
||||
push af
|
||||
ld a, e
|
||||
out (FS_ADDR_PORT), a
|
||||
@ -142,21 +142,21 @@ fsdevPutB:
|
||||
|
||||
.equ STDOUT_HANDLE FS_HANDLES
|
||||
|
||||
stdoutGetB:
|
||||
stdoutGetC:
|
||||
ld ix, STDOUT_HANDLE
|
||||
jp fsGetB
|
||||
jp fsGetC
|
||||
|
||||
stdoutPutB:
|
||||
stdoutPutC:
|
||||
ld ix, STDOUT_HANDLE
|
||||
jp fsPutB
|
||||
jp fsPutC
|
||||
|
||||
.equ STDIN_HANDLE FS_HANDLES+FS_HANDLE_SIZE
|
||||
|
||||
stdinGetB:
|
||||
stdinGetC:
|
||||
ld ix, STDIN_HANDLE
|
||||
jp fsGetB
|
||||
jp fsGetC
|
||||
|
||||
stdinPutB:
|
||||
stdinPutC:
|
||||
ld ix, STDIN_HANDLE
|
||||
jp fsPutB
|
||||
jp fsPutC
|
||||
|
||||
|
@ -19,14 +19,14 @@
|
||||
.equ blkSet @+3
|
||||
.equ fsFindFN @+3
|
||||
.equ fsOpen @+3
|
||||
.equ fsGetB @+3
|
||||
.equ fsPutB @+3
|
||||
.equ fsGetC @+3
|
||||
.equ fsPutC @+3
|
||||
.equ fsSetSize @+3
|
||||
.equ cpHLDE @+3
|
||||
.equ parseArgs @+3
|
||||
.equ printstr @+3
|
||||
.equ _blkGetB @+3
|
||||
.equ _blkPutB @+3
|
||||
.equ _blkGetC @+3
|
||||
.equ _blkPutC @+3
|
||||
.equ _blkSeek @+3
|
||||
.equ _blkTell @+3
|
||||
.equ printcrlf @+3
|
||||
|
@ -24,11 +24,11 @@ jp blkSel
|
||||
jp blkSet
|
||||
jp fsFindFN
|
||||
jp fsOpen
|
||||
jp fsGetB
|
||||
jp fsGetC
|
||||
jp cpHLDE
|
||||
jp parseArgs
|
||||
jp _blkGetB
|
||||
jp _blkPutB
|
||||
jp _blkGetC
|
||||
jp _blkPutC
|
||||
jp _blkSeek
|
||||
jp _blkTell
|
||||
jp printstr
|
||||
@ -40,9 +40,9 @@ jp printstr
|
||||
.equ BLOCKDEV_COUNT 3
|
||||
.inc "blockdev.asm"
|
||||
; List of devices
|
||||
.dw emulGetB, unsetZ
|
||||
.dw unsetZ, emulPutB
|
||||
.dw fsdevGetB, fsdevPutB
|
||||
.dw emulGetC, unsetZ
|
||||
.dw unsetZ, emulPutC
|
||||
.dw fsdevGetC, fsdevPutC
|
||||
|
||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
||||
.inc "stdio.asm"
|
||||
@ -71,7 +71,7 @@ init:
|
||||
.db "0 1", 0
|
||||
|
||||
; *** I/O ***
|
||||
emulGetB:
|
||||
emulGetC:
|
||||
; the STDIN_SEEK port works by poking it twice. First poke is for high
|
||||
; byte, second poke is for low one.
|
||||
ld a, h
|
||||
@ -87,7 +87,7 @@ emulGetB:
|
||||
call unsetZ
|
||||
ret
|
||||
|
||||
emulPutB:
|
||||
emulPutC:
|
||||
out (STDIO_PORT), a
|
||||
cp a ; ensure Z
|
||||
ret
|
||||
@ -97,7 +97,7 @@ stderrPutC:
|
||||
cp a ; ensure Z
|
||||
ret
|
||||
|
||||
fsdevGetB:
|
||||
fsdevGetC:
|
||||
ld a, e
|
||||
out (FS_SEEK_PORT), a
|
||||
ld a, h
|
||||
@ -111,7 +111,7 @@ fsdevGetB:
|
||||
cp a ; ensure Z
|
||||
ret
|
||||
|
||||
fsdevPutB:
|
||||
fsdevPutC:
|
||||
push af
|
||||
ld a, e
|
||||
out (FS_SEEK_PORT), a
|
||||
|
@ -5,25 +5,25 @@
|
||||
|
||||
; *** JUMP TABLE ***
|
||||
.equ strncmp 0x03
|
||||
.equ addDE @+3
|
||||
.equ addHL @+3
|
||||
.equ upcase @+3
|
||||
.equ unsetZ @+3
|
||||
.equ intoDE @+3
|
||||
.equ intoHL @+3
|
||||
.equ writeHLinDE @+3
|
||||
.equ findchar @+3
|
||||
.equ parseHex @+3
|
||||
.equ parseHexPair @+3
|
||||
.equ blkSel @+3
|
||||
.equ blkSet @+3
|
||||
.equ fsFindFN @+3
|
||||
.equ fsOpen @+3
|
||||
.equ fsGetB @+3
|
||||
.equ cpHLDE @+3
|
||||
.equ parseArgs @+3
|
||||
.equ _blkGetB @+3
|
||||
.equ _blkPutB @+3
|
||||
.equ _blkSeek @+3
|
||||
.equ _blkTell @+3
|
||||
.equ printstr @+3
|
||||
.equ addDE 0x06
|
||||
.equ addHL 0x09
|
||||
.equ upcase 0x0c
|
||||
.equ unsetZ 0x0f
|
||||
.equ intoDE 0x12
|
||||
.equ intoHL 0x15
|
||||
.equ writeHLinDE 0x18
|
||||
.equ findchar 0x1b
|
||||
.equ parseHex 0x1e
|
||||
.equ parseHexPair 0x21
|
||||
.equ blkSel 0x24
|
||||
.equ blkSet 0x27
|
||||
.equ fsFindFN 0x2a
|
||||
.equ fsOpen 0x2d
|
||||
.equ fsGetC 0x30
|
||||
.equ cpHLDE 0x33
|
||||
.equ parseArgs 0x36
|
||||
.equ _blkGetC 0x39
|
||||
.equ _blkPutC 0x3c
|
||||
.equ _blkSeek 0x3f
|
||||
.equ _blkTell 0x42
|
||||
.equ printstr 0x45
|
||||
|
@ -9,7 +9,7 @@
|
||||
.equ BLOCKDEV_ERR_OUT_OF_BOUNDS 0x03
|
||||
.equ BLOCKDEV_ERR_UNSUPPORTED 0x04
|
||||
|
||||
; IO routines (GetB, PutB) returned an error in a load/save command
|
||||
; IO routines (GetC, PutC) returned an error in a load/save command
|
||||
.equ SHELL_ERR_IO_ERROR 0x05
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user