fs: implement GetC, PutC, Seek and Tell on file handle

Very coarse, but I got them to work.
This commit is contained in:
Virgil Dupras 2019-04-23 19:42:10 -04:00
parent f00334ec89
commit a391f85c00
3 changed files with 106 additions and 17 deletions

View File

@ -111,6 +111,7 @@ blkRead:
ld ix, (BLOCKDEV_GETC)
_blkRead:
push hl
push bc
.loop:
call _blkCall
jr nz, .end ; Z already unset
@ -119,6 +120,7 @@ _blkRead:
djnz .loop
cp a ; ensure Z
.end:
pop bc
pop hl
ret
@ -134,6 +136,7 @@ blkWrite:
ld ix, (BLOCKDEV_PUTC)
_blkWrite:
push hl
push bc
.loop:
ld a, (hl)
call _blkCall
@ -142,6 +145,7 @@ _blkWrite:
djnz .loop
cp a ; ensure Z
.end:
pop bc
pop hl
ret
@ -152,6 +156,13 @@ _blkWrite:
; 3 : Move to the end
; 4 : Move to the beginning
; Set position of selected device to the value specified in HL
;
; When seeking to an out-of-bounds position, the resulting position will be
; 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
; PutC doesn't necessarily result in a failure.
blkSeek:
ld ix, (BLOCKDEV_SEEK)
ld iy, (BLOCKDEV_TELL)

View File

@ -62,6 +62,7 @@ writeHLinDE:
inc de
ld a, h
ld (de), a
dec de
pop af
ret

View File

@ -79,18 +79,18 @@
; *** CONSTS ***
FS_MAX_NAME_SIZE .equ 0x1a
FS_BLOCKSIZE .equ 0x100
FS_METASIZE .equ 0x20
FS_META_ALLOC_OFFSET .equ 3
FS_META_FSIZE_OFFSET .equ 4
FS_META_FNAME_OFFSET .equ 6
; Size in bytes of a FS handle:
; * 2 bytes for starting offset
; * 2 bytes for current position. (absolute)
; * 2 bytes for starting offset, after metadata
; * 2 bytes for maximum offset
; * 2 bytes for file size (we could fetch it from metadata all the time, but it
; could be time consuming depending on the underlying device).
; * 2 bytes for current position.
; Starting offset is the *metadata* offset. We need, when we write to a handle,
; to change the size of the file.
FS_HANDLE_SIZE .equ 6
FS_HANDLE_SIZE .equ 8
FS_ERR_NO_FS .equ 0x5
FS_ERR_NOT_FOUND .equ 0x6
@ -109,7 +109,7 @@ FS_PTR .equ FS_START+2
; This variable below contain the metadata of the last block FS_PTR was moved
; to. We read this data in memory to avoid constant seek+read operations.
FS_META .equ FS_PTR+2
FS_HANDLES .equ FS_META+0x20
FS_HANDLES .equ FS_META+FS_METASIZE
FS_RAMEND .equ FS_HANDLES+(FS_HANDLE_COUNT*FS_HANDLE_SIZE)
; *** DATA ***
@ -186,7 +186,7 @@ fsReadMeta:
call fsPlace
push bc
push hl
ld b, 0x20
ld b, FS_METASIZE
ld hl, FS_META
call fsblkRead ; Sets Z
pop hl
@ -199,7 +199,7 @@ fsWriteMeta:
call fsPlace
push bc
push hl
ld b, 0x20
ld b, FS_METASIZE
ld hl, FS_META
call fsblkWrite ; Sets Z
pop hl
@ -217,7 +217,7 @@ fsInitMeta:
ld bc, 3
ldir
xor a
ld b, 0x20-3
ld b, FS_METASIZE-3
call fill
pop hl
pop de
@ -319,10 +319,18 @@ fsIsDeleted:
; we can still access the FS even if blkdev selection changes. These routines
; below mimic blkdev's methods, but for our private mount.
fsblkGetC:
ld ix, (FS_GETC)
jp _blkCall
fsblkRead:
ld ix, (FS_GETC)
jp _blkRead
fsblkPutC:
ld ix, (FS_PUTC)
jp _blkCall
fsblkWrite:
ld ix, (FS_PUTC)
jp _blkWrite
@ -340,27 +348,95 @@ fsblkTell:
; Open file at current position into handle at (HL)
fsOpen:
push hl
push de
push af
ex hl, de
ld hl, (FS_PTR)
ld a, FS_METASIZE
call addHL
call writeHLinDE
inc de
inc de
call writeHLinDE
inc de
inc de
; Maximum offset is starting offset + (numblocks * 0x100) - 1
ld a, (FS_META+FS_META_ALLOC_OFFSET)
; Because our blocks are exactly 0x100 in size, we simple have to
; increase the H in HL to have our result.
add a, h
ld h, a
call writeHLinDE
inc de
inc de
ld hl, (FS_META+FS_META_FSIZE_OFFSET)
call writeHLinDE
pop af
pop de
pop hl
ret
; Ensures that file size in metadata corresponds to file size in handle as (HL).
fsCommit:
fsPlaceH:
push af
push hl
ld ixh, d
ld ixl, e
push ix
ld l, (ix)
ld h, (ix+1)
ld a, BLOCKDEV_SEEK_ABSOLUTE
call fsblkSeek
pop ix
pop hl
pop af
ret
; Read a byte in handle at (HL), put it into A and advance the handle's
fsAdvanceH:
inc (ix)
ld a, (ix)
ret nc ; no carry
inc (ix+1)
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.
fsRead:
fsGetC:
call fsPlaceH
push ix
call fsblkGetC
; increase current pos
pop ix ; recall
call fsAdvanceH
ret
; Write byte A in handle at (HL) and advance the handle's position.
; Z is set on success, unset if handle is at the end of the allocated space.
fsWrite:
; Write byte A in handle (DE) and advance the handle's position.
; Z is set on success, unset if handle is at the end of the file.
fsPutC:
call fsPlaceH
push ix
call fsblkPutC
; increase current pos
pop ix ; recall
call fsAdvanceH
ret
; Sets position of handle (HL) to DE. This position does *not* include metadata.
; Sets position of handle (DE) to HL. This position does *not* include metadata.
; It is an offset that starts at actual data.
; Sets Z if offset is within bounds, unsets Z if it isn't.
fsSeek:
ld ixh, d
ld ixl, e
ld (ix), l
ld (ix+1), h
ret
fsTell:
ld ixh, d
ld ixl, e
ld l, (ix)
ld h, (ix+1)
ret
; *** SHELL COMMANDS ***
@ -369,6 +445,7 @@ fsSeek:
; Upon mounting, copy currently selected device in FS_GETC/PUTC/SEEK/TELL.
fsOnCmd:
.db "fson", 0, 0, 0
fsOn:
push hl
push de
push bc