diff --git a/parts/blockdev.asm b/parts/blockdev.asm index d672f63..9b0d262 100644 --- a/parts/blockdev.asm +++ b/parts/blockdev.asm @@ -108,9 +108,11 @@ blkGetCW: ; Reads B chars from blkGetC and copy them in (HL). ; Sets Z if successful, unset Z if there was an error. blkRead: + ld ix, (BLOCKDEV_GETC) +_blkRead: push hl .loop: - call blkGetC + call _blkCall jr nz, .end ; Z already unset ld (hl), a inc hl @@ -129,10 +131,12 @@ blkPutC: ; Writes B chars to blkPutC from (HL). ; Sets Z if successful, unset Z if there was an error. blkWrite: + ld ix, (BLOCKDEV_PUTC) +_blkWrite: push hl .loop: ld a, (hl) - call blkPutC + call _blkCall jr nz, .end ; Z already unset inc hl djnz .loop @@ -149,6 +153,9 @@ blkWrite: ; 4 : Move to the beginning ; Set position of selected device to the value specified in HL blkSeek: + ld ix, (BLOCKDEV_SEEK) + ld iy, (BLOCKDEV_TELL) +_blkSeek: push de cp BLOCKDEV_SEEK_FORWARD jr z, .forward @@ -162,7 +169,10 @@ blkSeek: jr .seek ; for absolute mode, HL is already correct .forward: ex hl, de ; DE has our offset - call blkTell ; HL has our curpos + ; We want to be able to plug our own TELL function, which is why we + ; don't call blkTell directly here. + ; Calling TELL + call callIY ; HL has our curpos add hl, de jr nc, .seek ; no carry? alright! ; we have carry? out of bounds, set to maximum @@ -176,7 +186,6 @@ blkSeek: ld hl, 0xffff .seek: pop de - ld ix, (BLOCKDEV_SEEK) jr _blkCall ; Returns the current position of the selected device in HL. diff --git a/parts/core.asm b/parts/core.asm index 6c3b960..3825db2 100644 --- a/parts/core.asm +++ b/parts/core.asm @@ -71,6 +71,10 @@ callIX: jp (ix) ret +callIY: + jp (iy) + ret + ; Ensures that Z is unset (more complicated than it sounds...) unsetZ: push bc diff --git a/parts/fs.asm b/parts/fs.asm index 40841f6..7b45332 100644 --- a/parts/fs.asm +++ b/parts/fs.asm @@ -95,13 +95,16 @@ FS_ERR_NO_FS .equ 0x5 FS_ERR_NOT_FOUND .equ 0x6 ; *** VARIABLES *** -; A copy of BLOCKDEV_SEL when the FS was mounted. 0 if no FS is mounted. -FS_BLKSEL .equ FS_RAMSTART +; A copy of BLOCKDEV routines when the FS was mounted. 0 if no FS is mounted. +FS_GETC .equ FS_RAMSTART +FS_PUTC .equ FS_GETC+2 +FS_SEEK .equ FS_PUTC+2 +FS_TELL .equ FS_SEEK+2 ; Offset at which our FS start on mounted device -FS_START .equ FS_BLKSEL+2 +FS_START .equ FS_TELL+2 ; Offset at which we are currently pointing to with regards to our routines ; below, which all assume this offset as a context. This offset is not relative -; to FS_START. It can be used directly with blkSeek. +; to FS_START. It can be used directly with fsblkSeek. 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. @@ -117,8 +120,8 @@ P_FS_MAGIC: fsInit: xor a - ld hl, FS_BLKSEL - ld b, FS_RAMEND-FS_BLKSEL + ld hl, FS_GETC + ld b, FS_RAMEND-FS_GETC call fill ret @@ -150,10 +153,10 @@ fsNext: ld a, BLOCKDEV_SEEK_FORWARD ld hl, FS_BLOCKSIZE .loop: - call blkSeek + call fsblkSeek djnz .loop ; Good, were here. We're going to read meta from our current position. - call blkTell ; --> HL + call fsblkTell ; --> HL ld (FS_PTR), hl call fsReadMeta jr nz, .createChainEnd @@ -178,27 +181,27 @@ fsNext: ret ; Reads metadata at current FS_PTR and place it in FS_META. -; Returns Z according to whether the blkRead operation succeeded. +; Returns Z according to whether the fsblkRead operation succeeded. fsReadMeta: call fsPlace push bc push hl ld b, 0x20 ld hl, FS_META - call blkRead ; Sets Z + call fsblkRead ; Sets Z pop hl pop bc ret ; Writes metadata in FS_META at current FS_PTR. -; Returns Z according to whether the blkWrite operation succeeded. +; Returns Z according to whether the fsblkWrite operation succeeded. fsWriteMeta: call fsPlace push bc push hl ld b, 0x20 ld hl, FS_META - call blkWrite ; Sets Z + call fsblkWrite ; Sets Z pop hl pop bc ret @@ -228,7 +231,7 @@ fsPlace: push hl xor a ld hl, (FS_PTR) - call blkSeek + call fsblkSeek pop hl pop af ret @@ -279,7 +282,7 @@ fsAlloc: ldir ; Good, FS_META ready. Now, let's update FS_PTR because it hasn't been ; changed yet. - call blkTell + call fsblkTell ld (FS_PTR), hl ; Ok, now we can write our metadata call fsWriteMeta @@ -311,6 +314,28 @@ fsIsDeleted: cp 0 ; Z flag is our answer ret +; *** blkdev methods *** +; When "mounting" a FS, we copy the current blkdev's routine privately so that +; we can still access the FS even if blkdev selection changes. These routines +; below mimic blkdev's methods, but for our private mount. + +fsblkRead: + ld ix, (FS_GETC) + jp _blkRead + +fsblkWrite: + ld ix, (FS_PUTC) + jp _blkWrite + +fsblkSeek: + ld ix, (FS_SEEK) + ld iy, (FS_TELL) + jp _blkSeek + +fsblkTell: + ld ix, (FS_TELL) + jp _blkCall + ; *** Handling *** ; Open file at current position into handle at (HL) @@ -341,23 +366,40 @@ fsSeek: ; *** SHELL COMMANDS *** ; Mount the fs subsystem upon the currently selected blockdev at current offset. ; Verify is block is valid and error out if its not, mounting nothing. -; Upon mounting, copy currently selected device in FS_BLKSEL. +; Upon mounting, copy currently selected device in FS_GETC/PUTC/SEEK/TELL. fsOnCmd: .db "fson", 0, 0, 0 push hl - call blkTell + push de + push bc + ; We have to set blkdev routines early before knowing whether the + ; mounting succeeds because methods like fsReadMeta uses fsblk* methods. + ld hl, BLOCKDEV_GETC + ld de, FS_GETC + ld bc, 8 ; we have 8 bytes to copy + ldir ; copy! + call fsblkTell + ld (FS_START), hl ld (FS_PTR), hl call fsReadMeta jr nz, .error call fsIsValid jr nz, .error ; success - ld (FS_START), hl xor a jr .end .error: + ; couldn't mount. Let's reset our variables. + xor a + ld b, 10 ; blkdev routines + FS_START which is just + ; after. + ld hl, FS_GETC + call fill + ld a, FS_ERR_NO_FS .end: + pop bc + pop de pop hl ret