From 4f44d3de63b592f237dcb2bc664d3e927f44d688 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sun, 12 May 2019 15:38:58 -0400 Subject: [PATCH] parts/z80/fs: add "fopn" command --- doc/shell.md | 1 + parts/z80/fs.asm | 79 +++++++++++++++++++++++++++++++++---------- parts/z80/shell.asm | 11 ++++-- tools/emul/shell_.asm | 52 +++++++++++++++++++++++++--- 4 files changed, 120 insertions(+), 23 deletions(-) diff --git a/doc/shell.md b/doc/shell.md index 2d15997..656e3a2 100644 --- a/doc/shell.md +++ b/doc/shell.md @@ -33,6 +33,7 @@ table describes those codes: | `02` | Badly formatted arguments | | `03` | Out of bounds | | `04` | Unsupported command | +| `05` | I/O error | ## mptr diff --git a/parts/z80/fs.asm b/parts/z80/fs.asm index f37a127..39a7c50 100644 --- a/parts/z80/fs.asm +++ b/parts/z80/fs.asm @@ -292,6 +292,25 @@ fsAlloc: pop bc ret +; Place FS_PTR to the filename with the name in (HL). +; Sets Z on success, unset when not found. +fsFindFN: + push de + call fsBegin + jr nz, .end ; nothing to find, Z is unset + ld a, FS_MAX_NAME_SIZE +.loop: + ld de, FS_META+FS_META_FNAME_OFFSET + call strncmp + jr z, .end ; Z is set + call fsNext + jr z, .loop + ; End of the chain, not found + call unsetZ +.end: + pop de + ret + ; *** Metadata *** ; Sets Z according to whether the current block in FS_META is valid. @@ -378,6 +397,7 @@ fsOpen: pop hl ret +; Place FS blockdev at proper position for file handle in (DE). fsPlaceH: push af push hl @@ -393,23 +413,31 @@ fsPlaceH: pop af ret +; Advance file handle in (IX) by one byte fsAdvanceH: + push af inc (ix) ld a, (ix) - ret nc ; no carry + jr nc, .end inc (ix+1) +.end: + pop af ret ; Read a byte in handle at (DE), put it into A and advance the handle's ; position. ; Z is set on success, unset if handle is at the end of the file. fsGetC: - call fsPlaceH push ix + call fsPlaceH + push ix ; Save handle in IX for fsAdvanceH call fsblkGetC ; increase current pos - pop ix ; recall + pop ix ; recall handle in IX + jr nz, .end ; error, don't advance call fsAdvanceH +.end: + pop ix ret ; Write byte A in handle (DE) and advance the handle's position. @@ -494,7 +522,7 @@ flsCmd: call printcrlf .skip: call fsNext - jr z, .loop ; Z set? fsNext was successfull + jr z, .loop ; Z set? fsNext was successful xor a jr .end .error: @@ -520,20 +548,10 @@ fdelCmd: .db "fdel", 0b1001, 0b001, 0 push hl push de - ex hl, de - call intoDE ; DE now holds the string we look for - call fsBegin + call intoHL ; HL now holds the string we look for + call fsFindFN jr nz, .notfound - ld a, FS_MAX_NAME_SIZE -.loop: - ld hl, FS_META+FS_META_FNAME_OFFSET - call strncmp - jr z, .found - call fsNext - jr z, .loop - ; End of chain, not found - jr .notfound -.found: + ; Found! delete xor a ; Set filename to zero to flag it as deleted ld (FS_META+FS_META_FNAME_OFFSET), a @@ -546,3 +564,30 @@ fdelCmd: pop de pop hl ret + + +; Opens specified filename in specified file handle. +; First argument is file handle, second one is file name. +; Example: fopn 0 foo.txt +fopnCmd: + .db "fopn", 0b001, 0b1001, 0b001 + push hl + push de + ld a, (hl) ; file handle index + ld de, FS_HANDLES + call addDE ; DE now stores pointer to file handle + inc hl + call intoHL ; HL now holds the string we look for + call fsFindFN + jr nz, .notfound + ; Found! + ; FS_PTR points to the file we want to open + ex hl, de ; HL now points to the file handle. + call fsOpen + jr .end +.notfound: + ld a, FS_ERR_NOT_FOUND +.end: + pop de + pop hl + ret diff --git a/parts/z80/shell.asm b/parts/z80/shell.asm index c1c3d90..ca994ac 100644 --- a/parts/z80/shell.asm +++ b/parts/z80/shell.asm @@ -38,6 +38,9 @@ SHELL_ERR_UNKNOWN_CMD .equ 0x01 ; Arguments for the command weren't properly formatted SHELL_ERR_BAD_ARGS .equ 0x02 +; IO routines (GetC, PutC) returned an error in a load/save command +SHELL_ERR_IO_ERROR .equ 0x05 + ; Size of the shell command buffer. If a typed command reaches this size, the ; command is flushed immediately (same as pressing return). SHELL_BUFSIZE .equ 0x20 @@ -409,14 +412,18 @@ shellLoad: ld b, a ld hl, (SHELL_MEM_PTR) .loop: SHELL_IO_GETC + 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 - xor a ret ; Load the specified number of bytes (max 0xff) from the current memory pointer diff --git a/tools/emul/shell_.asm b/tools/emul/shell_.asm index ac286c6..f58ca8c 100644 --- a/tools/emul/shell_.asm +++ b/tools/emul/shell_.asm @@ -15,11 +15,13 @@ STDIO_RAMSTART .equ RAMEND #include "stdio.asm" BLOCKDEV_RAMSTART .equ STDIO_RAMEND -BLOCKDEV_COUNT .equ 2 +BLOCKDEV_COUNT .equ 4 #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 #include "blockdev_cmds.asm" @@ -28,11 +30,11 @@ BLOCKDEV_COUNT .equ 2 #include "fs.asm" SHELL_RAMSTART .equ FS_RAMEND -.define SHELL_IO_GETC call blkGetCW +.define SHELL_IO_GETC call blkGetC .define SHELL_IO_PUTC call blkPutC -SHELL_EXTRA_CMD_COUNT .equ 6 +SHELL_EXTRA_CMD_COUNT .equ 7 #include "shell.asm" -.dw blkBselCmd, blkSeekCmd, fsOnCmd, flsCmd, fnewCmd, fdelCmd +.dw blkBselCmd, blkSeekCmd, fsOnCmd, flsCmd, fnewCmd, fdelCmd, fopnCmd init: di @@ -62,6 +64,7 @@ emulPutC: fsdevGetC: in a, (FS_DATA_PORT) + cp a ; ensure Z ret fsdevPutC: @@ -69,15 +72,56 @@ fsdevPutC: ret fsdevSeek: + push af ld a, l out (FS_SEEKL_PORT), a ld a, h out (FS_SEEKH_PORT), a + pop af ret fsdevTell: + push af in a, (FS_SEEKL_PORT) ld l, a in a, (FS_SEEKH_PORT) ld h, a + pop af ret + +.equ STDOUT_HANDLE FS_HANDLES + +stdoutGetC: + ld de, STDOUT_HANDLE + jp fsGetC + +stdoutPutC: + ld de, STDOUT_HANDLE + jp fsPutC + +stdoutSeek: + ld de, STDOUT_HANDLE + jp fsSeek + +stdoutTell: + ld de, STDOUT_HANDLE + jp fsTell + +.equ STDIN_HANDLE FS_HANDLES+FS_HANDLE_SIZE + +stdinGetC: + ld de, STDIN_HANDLE + jp fsGetC + +stdinPutC: + ld de, STDIN_HANDLE + jp fsPutC + +stdinSeek: + ld de, STDIN_HANDLE + jp fsSeek + +stdinTell: + ld de, STDIN_HANDLE + jp fsTell +