aboutsummaryrefslogtreecommitdiffstats
path: root/src/fs.asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs.asm')
-rw-r--r--src/fs.asm804
1 files changed, 599 insertions, 205 deletions
diff --git a/src/fs.asm b/src/fs.asm
index 692fb45..7e59f3e 100644
--- a/src/fs.asm
+++ b/src/fs.asm
@@ -1,193 +1,568 @@
; =============================================================================
-; fs.asm - a tiny RAM filesystem in WRAMX ($D000-$DFFF, 4 KiB).
+; fs.asm - a small block-based filesystem (inodes + a root directory) on the
+; persistent block device (blk.asm). Same syscall interface as before
+; (open/close/getb/putb/list/remove) so the tools and libc are unchanged.
;
-; 8 fixed slots of 512 bytes: name[8] (first byte 0 = free) + len[2] + data[502].
-; Slot i base = $D000 + i*512 -> high = $D0 + i*2, low = $00.
-; Because WRAMX is always mapped (DMG) and the caller's buffers live in the
-; mapped $A000 window, the kernel can copy between them directly.
+; Bitmaps (block 1) and the inode table (blocks 2-3) are cached in WRAMX; file
+; and directory data stream through fs_datbuf / fs_dirbuf. Metadata bitmap
+; writes are write-through; inode writes are flushed on close.
; =============================================================================
INCLUDE "include/gbos.inc"
SECTION "fs", ROM0
; -----------------------------------------------------------------------------
-; FsSlotBase - in: A = slot (0..7) out: HL = slot base. (A clobbered)
+; small helpers
; -----------------------------------------------------------------------------
-FsSlotBase::
- add a ; slot*2
- add HIGH(FS_BASE) ; + $D0
+zero256: ; HL = buffer; zero 256 bytes
+ ld b, 0
+ xor a
+.z
+ ld [hl+], a
+ dec b
+ jr nz, .z
+ ret
+
+; inode_ptr - A = inode -> HL = &inode in fs_inobuf (= fs_inobuf + inode*16)
+inode_ptr::
+ ld c, a
+ and $0F
+ swap a
+ ld l, a ; (inode & 15) << 4
+ ld a, c
+ swap a
+ and $0F ; inode >> 4
+ add HIGH(fs_inobuf)
ld h, a
- ld l, 0
+ ret
+
+; write_inode - A = inode ; flush the inode's block (2 or 3) to disk
+write_inode::
+ cp 16
+ jr nc, .hi
+ ld hl, fs_inobuf
+ ld a, BLK_INODE0
+ jp write_block
+.hi
+ ld hl, fs_inobuf + 256
+ ld a, BLK_INODE0 + 1
+ jp write_block
+
+; bit_addr - A = index, HL = bitmap base -> HL = &byte, E = mask(1<<bit)
+bit_addr:
+ ld c, a
+ srl a
+ srl a
+ srl a ; index/8
+ add l
+ ld l, a
+ ld a, h
+ adc 0
+ ld h, a
+ ld a, c
+ and 7
+ ld e, 1
+.sh
+ or a
+ jr z, .done
+ sla e
+ dec a
+ jr .sh
+.done
ret
; -----------------------------------------------------------------------------
-; FsNameEq - compare the <=8-byte NUL-terminated names at DE and HL.
-; out: Z set if equal. preserves DE, HL.
+; block / inode allocators (bitmaps live in fs_bmbuf, write-through to block 1)
; -----------------------------------------------------------------------------
-FsNameEq::
- push de
+write_bitmap:
+ ld hl, fs_bmbuf
+ ld a, BLK_BITMAP
+ jp write_block
+
+; alloc_block -> A = block# (>=4) or 0 if the disk is full
+alloc_block::
+ ld c, BLK_DATA0
+.l
+ ld a, c
+ ld hl, fs_bmbuf + BM_BLOCKS
+ call bit_addr ; HL=&byte, E=mask
+ ld a, [hl]
+ and e
+ jr z, .found
+ inc c
+ ld a, c
+ cp FS_NBLOCKS
+ jr c, .l
+ xor a
+ ret
+.found
+ ld a, [hl]
+ or e
+ ld [hl], a
+ ld a, c ; save block# (write_bitmap clobbers C)
+ push af
+ call write_bitmap
+ pop af
+ ret
+
+; free_block - A = block#
+free_block::
+ ld hl, fs_bmbuf + BM_BLOCKS
+ call bit_addr
+ ld a, e
+ cpl
+ ld e, a
+ ld a, [hl]
+ and e
+ ld [hl], a
+ jp write_bitmap
+
+; alloc_inode -> A = inode# (>=2) or 0
+alloc_inode::
+ ld c, 2
+.l
+ ld a, c
+ ld hl, fs_bmbuf + BM_INODES
+ call bit_addr
+ ld a, [hl]
+ and e
+ jr z, .found
+ inc c
+ ld a, c
+ cp NINODES
+ jr c, .l
+ xor a
+ ret
+.found
+ ld a, [hl]
+ or e
+ ld [hl], a
+ ld a, c ; save inode# (write_bitmap clobbers C)
+ push af
+ call write_bitmap
+ pop af
+ ret
+
+; free_inode - A = inode#
+free_inode::
+ ld hl, fs_bmbuf + BM_INODES
+ call bit_addr
+ ld a, e
+ cpl
+ ld e, a
+ ld a, [hl]
+ and e
+ ld [hl], a
+ jp write_bitmap
+
+; -----------------------------------------------------------------------------
+; data-block cache (one block in fs_datbuf; wFsCurBlk / wFsDirty)
+; -----------------------------------------------------------------------------
+db_flush::
+ ld a, [wFsDirty]
+ or a
+ ret z
+ xor a
+ ld [wFsDirty], a
+ ld a, [wFsCurBlk]
+ cp $FF
+ ret z
+ ld hl, fs_datbuf
+ jp write_block
+
+; db_use - A = block ; ensure that block is loaded in fs_datbuf
+db_use::
+ ld c, a
+ ld a, [wFsCurBlk]
+ cp c
+ ret z
+ push bc ; db_flush clobbers C (write_block does ld c,a)
+ call db_flush
+ pop bc
+ ld a, c
+ ld [wFsCurBlk], a
+ ld hl, fs_datbuf
+ jp read_block
+
+; -----------------------------------------------------------------------------
+; name compare: [HL] vs wFsNameBuf, <=15 bytes NUL-terminated -> Z if equal.
+; preserves HL.
+; -----------------------------------------------------------------------------
+name_eq:
push hl
- ld b, 8
-.cmp
+ ld de, wFsNameBuf
+ ld b, 15
+.c
ld a, [de]
cp [hl]
jr nz, .ne
- or a ; equal byte; if NUL, strings ended equal
+ or a
jr z, .eq
- inc de
inc hl
+ inc de
dec b
- jr nz, .cmp
+ jr nz, .c
.eq
pop hl
- pop de
- xor a ; Z set
+ xor a
ret
.ne
pop hl
- pop de
ld a, 1
- and a ; Z clear
+ and a
ret
+; entry_ptr - C = entry index -> HL = &fs_dirbuf[C*16]
+entry_ptr:
+ ld a, c
+ swap a ; C*16 (C < 16)
+ ld hl, fs_dirbuf
+ add l
+ ld l, a
+ ret ; (fs_dirbuf is page-aligned, no carry)
+
+; load_rootdir - read the root directory's data block into fs_dirbuf
+load_rootdir:
+ ld a, [fs_inobuf + 16 + I_BLOCKS] ; root inode (1) blocks[0]
+ ld hl, fs_dirbuf
+ jp read_block
+
+; write_rootdir - write fs_dirbuf back to the root directory's data block
+write_rootdir:
+ ld a, [fs_inobuf + 16 + I_BLOCKS]
+ ld hl, fs_dirbuf
+ jp write_block
+
; -----------------------------------------------------------------------------
-; FsFind - in: DE = name out: A = slot (0..7) or $FF.
+; dir_find - name in wFsNameBuf -> A = inode (0 if not found)
; -----------------------------------------------------------------------------
-FsFind::
+dir_find::
+ call load_rootdir
ld c, 0
.l
- ld a, c
- call FsSlotBase ; HL = base
- ld a, [hl] ; name[0]
+ call entry_ptr ; HL = &entry
+ ld a, [hl] ; entry.inode
or a
- jr z, .next ; free slot
- call FsNameEq ; DE vs HL
+ jr z, .next
+ inc hl ; &name
+ call name_eq
jr z, .found
.next
inc c
ld a, c
- cp FS_MAX_FILES
+ cp DIRENTS
jr c, .l
- ld a, $FF
+ xor a
ret
.found
- ld a, c
+ dec hl ; back to entry base
+ ld a, [hl]
ret
; -----------------------------------------------------------------------------
-; FsAllocSlot - out: A = free slot or $FF.
+; dir_add - A = inode to link (name in wFsNameBuf) -> A = 1 ok / 0 dir full
; -----------------------------------------------------------------------------
-FsAllocSlot::
+dir_add::
+ ld [wFsInode], a
+ call load_rootdir
ld c, 0
.l
+ call entry_ptr
+ ld a, [hl]
+ or a
+ jr z, .free
+ inc c
ld a, c
- call FsSlotBase
+ cp DIRENTS
+ jr c, .l
+ xor a
+ ret
+.free
+ ld a, [wFsInode]
+ ld [hl+], a ; entry.inode
+ ld de, wFsNameBuf ; copy the name
+ ld b, 15
+.cp
+ ld a, [de]
+ ld [hl+], a
+ inc de
+ dec b
+ jr nz, .cp
+ call write_rootdir
+ ld a, 1
+ ret
+
+; -----------------------------------------------------------------------------
+; dir_remove - name in wFsNameBuf -> A = inode removed (0 if not found)
+; -----------------------------------------------------------------------------
+dir_remove::
+ call load_rootdir
+ ld c, 0
+.l
+ call entry_ptr
ld a, [hl]
or a
+ jr z, .next
+ inc hl
+ call name_eq
jr z, .found
+.next
inc c
ld a, c
- cp FS_MAX_FILES
+ cp DIRENTS
jr c, .l
- ld a, $FF
+ xor a
ret
.found
- ld a, c
+ dec hl ; entry base
+ ld a, [hl]
+ ld [wFsInode], a
+ xor a
+ ld [hl], a ; clear entry.inode
+ call write_rootdir
+ ld a, [wFsInode]
ret
; -----------------------------------------------------------------------------
-; FsSetName - copy the name at DE into slot wFsSlot (<=8 bytes, incl. NUL).
+; file_truncate - A = inode ; free all data blocks, size = 0 (cached inode)
; -----------------------------------------------------------------------------
-FsSetName::
- ld a, [wFsSlot]
- call FsSlotBase ; HL = base (= name)
- push de
- ld b, 8
-.cp
- ld a, [de]
- ld [hl+], a
+file_truncate::
+ ld [wFsInode], a
+ call inode_ptr
+ ld a, l
+ add I_BLOCKS
+ ld l, a ; HL = &blocks[0] (fs_inobuf, no page cross)
+ ld b, NDIRECT
+.fb
+ ld a, [hl]
or a
- jr z, .done
- inc de
+ jr z, .skip
+ push bc
+ push hl
+ call free_block
+ pop hl
+ pop bc
+ xor a
+ ld [hl], a
+.skip
+ inc hl
dec b
- jr nz, .cp
-.done
- pop de
+ jr nz, .fb
+ ; size = 0
+ ld a, [wFsInode]
+ call inode_ptr
+ ld a, l
+ add I_SIZE
+ ld l, a
+ xor a
+ ld [hl+], a
+ ld [hl], a
+ ld a, [wFsInode]
+ jp write_inode
+
+; -----------------------------------------------------------------------------
+; format + mount
+; -----------------------------------------------------------------------------
+fs_format::
+ ; superblock (block 0)
+ ld hl, fs_datbuf
+ call zero256
+ ld hl, fs_datbuf
+ ld a, SUPER_MAG0
+ ld [hl+], a
+ ld a, SUPER_MAG1
+ ld [hl+], a
+ ld a, SUPER_MAG2
+ ld [hl+], a
+ ld a, SUPER_MAG3
+ ld [hl+], a
+ ld a, FS_VERSION
+ ld [hl], a
+ ld a, BLK_SUPER
+ ld hl, fs_datbuf
+ call write_block
+ ; bitmaps (block 1): blocks 0-4 used, inodes 0-1 used
+ ld hl, fs_bmbuf
+ call zero256
+ ld a, $1F
+ ld [fs_bmbuf + BM_BLOCKS], a
+ ld a, $03
+ ld [fs_bmbuf + BM_INODES], a
+ call write_bitmap
+ ; inode table (blocks 2-3): zero, then inode 1 = root dir
+ ld hl, fs_inobuf
+ call zero256
+ ld hl, fs_inobuf + 256
+ call zero256
+ ld hl, fs_inobuf + 16 ; inode 1
+ ld a, IT_DIR
+ ld [hl], a ; I_TYPE
+ ld a, 1
+ ld [fs_inobuf + 16 + I_NLINK], a
+ xor a
+ ld [fs_inobuf + 16 + I_SIZE], a ; size lo
+ ld a, 1
+ ld [fs_inobuf + 16 + I_SIZE + 1], a ; size hi = 256 (one dir block)
+ ld a, BLK_DATA0
+ ld [fs_inobuf + 16 + I_BLOCKS], a ; blocks[0] = block 4
+ ld a, BLK_INODE0
+ ld hl, fs_inobuf
+ call write_block
+ ld a, BLK_INODE0 + 1
+ ld hl, fs_inobuf + 256
+ call write_block
+ ; root dir data block (block 4): empty
+ ld hl, fs_dirbuf
+ call zero256
+ ld a, BLK_DATA0
+ ld hl, fs_dirbuf
+ jp write_block
+
+; fs_init - mount: format on first boot (magic/version check), load caches.
+fs_init::
+ ld a, $FF
+ ld [wFsCurBlk], a
+ xor a
+ ld [wFsDirty], a
+ ; check superblock
+ ld a, BLK_SUPER
+ ld hl, fs_datbuf
+ call read_block
+ ld hl, fs_datbuf
+ ld a, [hl+]
+ cp SUPER_MAG0
+ jr nz, .fmt
+ ld a, [hl+]
+ cp SUPER_MAG1
+ jr nz, .fmt
+ ld a, [hl+]
+ cp SUPER_MAG2
+ jr nz, .fmt
+ ld a, [hl+]
+ cp SUPER_MAG3
+ jr nz, .fmt
+ ld a, [hl]
+ cp FS_VERSION
+ jr z, .load
+.fmt
+ call fs_format
+.load
+ ld a, BLK_BITMAP
+ ld hl, fs_bmbuf
+ call read_block
+ ld a, BLK_INODE0
+ ld hl, fs_inobuf
+ call read_block
+ ld a, BLK_INODE0 + 1
+ ld hl, fs_inobuf + 256
+ call read_block
+ ld a, $FF
+ ld [wFsCurBlk], a
ret
; -----------------------------------------------------------------------------
-; OFPtr - in: A = fd out: HL = &open-file entry. preserves DE.
+; OFPtr - A = fd -> HL = &open-file entry. preserves DE.
; -----------------------------------------------------------------------------
OFPtr::
push de
ld h, 0
ld l, a
ld d, h
- ld e, l ; DE = fd
- add hl, hl ; 2
- add hl, hl ; 4
+ ld e, l
+ add hl, hl
+ add hl, hl
add hl, de ; 5*fd
ld de, wOFTable
add hl, de
pop de
ret
+; copy the NUL-terminated name at DE (process memory) into wFsNameBuf.
+copy_name:
+ ld hl, wFsNameBuf
+ ld b, 15
+.c
+ ld a, [de]
+ ld [hl+], a
+ or a
+ ret z
+ inc de
+ dec b
+ jr nz, .c
+ xor a
+ ld [hl], a
+ ret
+
; =============================================================================
; sys_open(DE = name, B = mode 0=read/1=write) -> A = fd or $FF
; =============================================================================
sys_open::
ld a, b
ld [wFsMode], a
- call FsFind ; A = slot or $FF (DE = name)
- ld [wFsSlot], a
+ call copy_name ; name -> wFsNameBuf (before any block I/O)
+ call dir_find ; A = inode or 0
+ ld [wFsInode], a
ld a, [wFsMode]
or a
jr nz, .write
- ; --- read mode: must exist ---
- ld a, [wFsSlot]
- cp $FF
+ ; --- read ---
+ ld a, [wFsInode]
+ or a
jr z, .fail
- jr .alloc
+ jr .allocof
.write
- ; --- write mode: create or truncate ---
- ld a, [wFsSlot]
- cp $FF
+ ld a, [wFsInode]
+ or a
jr nz, .trunc
- call FsAllocSlot
- cp $FF
+ ; --- create ---
+ call alloc_inode
+ or a
jr z, .fail
- ld [wFsSlot], a
- call FsSetName ; DE still = name
-.trunc
- ld a, [wFsSlot]
- call FsSlotBase
- ld a, l
- add FS_LEN
- ld l, a ; HL = &len
+ ld [wFsInode], a
+ call inode_ptr ; HL = &inode
+ push hl
+ ld b, 16
xor a
+.zi
ld [hl+], a
- ld [hl], a ; len = 0
-.alloc
- ; --- allocate an open-file entry ---
+ dec b
+ jr nz, .zi
+ pop hl
+ ld a, IT_FILE
+ ld [hl], a
+ inc hl
+ ld a, 1
+ ld [hl], a ; nlink
+ ld a, [wFsInode]
+ call write_inode
+ ld a, [wFsInode]
+ call dir_add
+ or a
+ jr z, .fail
+ jr .allocof
+.trunc
+ ld a, [wFsInode]
+ call file_truncate
+.allocof
ld c, 0
-.of
+.ofl
ld a, c
- call OFPtr ; HL = &OF[c]
+ call OFPtr
ld a, [hl]
or a
jr z, .gotof
inc c
ld a, c
cp OF_MAX
- jr c, .of
+ jr c, .ofl
.fail
ld a, $FF
ret
.gotof
ld a, 1
ld [hl+], a ; inuse
- ld a, [wFsSlot]
- ld [hl+], a ; slot
+ ld a, [wFsInode]
+ ld [hl+], a ; inode
ld a, [wFsMode]
ld [hl+], a ; mode
xor a
@@ -197,12 +572,24 @@ sys_open::
ret
; =============================================================================
-; sys_close(B = fd)
+; sys_close(B = fd) - flush data + inode, free the descriptor
; =============================================================================
sys_close::
ld a, b
cp OF_MAX
jr nc, .done
+ ld [wFsSlot], a ; save fd
+ call OFPtr
+ ld a, [hl]
+ or a
+ jr z, .done
+ inc hl
+ ld a, [hl]
+ ld [wFsInode], a
+ call db_flush
+ ld a, [wFsInode]
+ call write_inode
+ ld a, [wFsSlot]
call OFPtr
xor a
ld [hl], a ; inuse = 0
@@ -217,7 +604,7 @@ sys_getb::
ld a, b
cp OF_MAX
jr nc, .eof
- call OFPtr ; HL = OF entry
+ call OFPtr
ld a, [hl]
or a
jr z, .eof
@@ -225,44 +612,54 @@ sys_getb::
ld [wFsOFPtr], a
ld a, h
ld [wFsOFPtr+1], a
- inc hl ; OF_SLOT
+ inc hl
ld a, [hl]
- ld [wFsSlot], a
- inc hl ; OF_MODE
+ ld [wFsInode], a
+ inc hl
inc hl ; OF_POS lo
ld a, [hl+]
ld e, a
ld a, [hl]
ld d, a ; DE = pos
- ; file length -> BC
- ld a, [wFsSlot]
- call FsSlotBase ; HL = base
+ ; pos < size ?
+ ld a, [wFsInode]
+ call inode_ptr
ld a, l
- add FS_LEN
+ add I_SIZE
ld l, a
ld a, [hl+]
ld c, a
ld a, [hl]
- ld b, a ; BC = len
- ; pos >= len ? EOF
+ ld b, a ; BC = size
ld a, e
sub c
ld a, d
sbc b
- jr nc, .eof
- ; addr = base + FS_DATA + pos
- ld a, [wFsSlot]
- call FsSlotBase ; HL = base (low = 0)
- ld a, FS_DATA
- add e
+ jr nc, .eof ; pos >= size
+ ; data block = inode.blocks[pos/256 = D]
+ ld a, [wFsInode]
+ call inode_ptr
+ ld a, l
+ add I_BLOCKS
+ ld l, a
+ ld a, d
+ add l
+ ld l, a ; &blocks[blkidx]
+ ld a, [hl]
+ push de
+ call db_use
+ pop de
+ ; byte = fs_datbuf[E]
+ ld hl, fs_datbuf
+ ld a, e
+ add l
ld l, a
ld a, h
- adc d
- ld h, a ; HL = &data[pos]
+ adc 0
+ ld h, a
ld a, [hl]
ld [wFsByte], a
inc de ; pos++
- ; store pos back
ld a, [wFsOFPtr]
add OF_POS
ld l, a
@@ -274,15 +671,14 @@ sys_getb::
ld a, d
ld [hl], a
ld a, [wFsByte]
- and a ; CF = 0 (success)
+ and a ; CF = 0
ret
.eof
scf
ret
; =============================================================================
-; sys_putb(B = fd, E = byte) -- byte is in E, not A: the syscall dispatch
-; clobbers A (it indexes the jump table with it).
+; sys_putb(B = fd, E = byte)
; =============================================================================
sys_putb::
ld a, e
@@ -300,42 +696,50 @@ sys_putb::
ld [wFsOFPtr+1], a
inc hl
ld a, [hl]
- ld [wFsSlot], a
+ ld [wFsInode], a
+ inc hl
inc hl
- inc hl ; OF_POS lo
ld a, [hl+]
ld e, a
ld a, [hl]
ld d, a ; DE = pos
- ; pos >= FS_MAX_DATA ? full
- ld a, e
- sub LOW(FS_MAX_DATA)
+ ; ensure inode.blocks[pos/256] is allocated
+ ld a, [wFsInode]
+ call inode_ptr
+ ld a, l
+ add I_BLOCKS
+ ld l, a
ld a, d
- sbc HIGH(FS_MAX_DATA)
- jr nc, .done
- ; addr = base + FS_DATA + pos
- ld a, [wFsSlot]
- call FsSlotBase
- ld a, FS_DATA
- add e
+ add l
+ ld l, a ; HL = &blocks[blkidx]
+ ld a, [hl]
+ or a
+ jr nz, .haveblk
+ push hl
+ push de
+ call alloc_block
+ pop de
+ pop hl
+ or a
+ jr z, .done ; disk full
+ ld [hl], a
+.haveblk
+ ld a, [hl] ; data block#
+ push de
+ call db_use
+ pop de
+ ld hl, fs_datbuf
+ ld a, e
+ add l
ld l, a
ld a, h
- adc d
+ adc 0
ld h, a
ld a, [wFsByte]
- ld [hl], a ; write byte
- inc de ; pos++
- ; len = pos (sequential append)
- ld a, [wFsSlot]
- call FsSlotBase
- ld a, l
- add FS_LEN
- ld l, a
- ld a, e
- ld [hl+], a
- ld a, d
ld [hl], a
- ; store pos back
+ ld a, 1
+ ld [wFsDirty], a
+ inc de ; pos++
ld a, [wFsOFPtr]
add OF_POS
ld l, a
@@ -346,22 +750,67 @@ sys_putb::
ld [hl+], a
ld a, d
ld [hl], a
+ ; size = max(size, pos) (cached inode; flushed on close)
+ ld a, [wFsInode]
+ call inode_ptr
+ ld a, l
+ add I_SIZE
+ ld l, a
+ ld a, [hl+]
+ ld c, a
+ ld a, [hl]
+ ld b, a ; BC = size, HL at size+1
+ ld a, c
+ sub e
+ ld a, b
+ sbc d
+ jr nc, .done ; size >= pos
+ dec hl ; size lo
+ ld a, e
+ ld [hl+], a
+ ld a, d
+ ld [hl], a
.done
xor a
ret
; =============================================================================
-; sys_list(B = slot, DE = namebuf[8]) -> A = 1 if used (name copied), else 0
+; sys_list(B = index, DE = namebuf) -> A = 1 (name copied) / 0 (no more)
+; index selects the index-th *used* entry in the root directory.
; =============================================================================
sys_list::
+ ld a, e
+ ld [wFsOFPtr], a
+ ld a, d
+ ld [wFsOFPtr+1], a
ld a, b
- cp FS_MAX_FILES
- jr nc, .no
- call FsSlotBase ; HL = base (name)
+ ld [wFsSlot], a ; wanted index
+ call load_rootdir
+ ld c, 0 ; entry cursor
+ ld b, 0 ; used counter
+.l
+ call entry_ptr ; HL = &entry
ld a, [hl]
or a
- jr z, .no
- ld b, 8
+ jr z, .next
+ ld a, [wFsSlot]
+ cp b
+ jr z, .found
+ inc b
+.next
+ inc c
+ ld a, c
+ cp DIRENTS
+ jr c, .l
+ xor a
+ ret
+.found
+ inc hl ; &name (fs_dirbuf)
+ ld a, [wFsOFPtr]
+ ld e, a
+ ld a, [wFsOFPtr+1]
+ ld d, a ; DE = namebuf (process memory)
+ ld b, 15
.cp
ld a, [hl+]
ld [de], a
@@ -370,82 +819,27 @@ sys_list::
jr nz, .cp
ld a, 1
ret
-.no
- xor a
- ret
; =============================================================================
; sys_remove(DE = name) -> A = 0 ok / $FF not found
; =============================================================================
sys_remove::
- call FsFind
- cp $FF
+ call copy_name
+ call dir_remove ; A = inode or 0
+ or a
jr z, .no
- call FsSlotBase
+ ld [wFsInode], a
+ call file_truncate ; A = inode (frees data blocks)
+ ld a, [wFsInode]
+ call inode_ptr
xor a
- ld [hl], a ; name[0] = 0 -> free
+ ld [hl], a ; I_TYPE = free
+ ld a, [wFsInode]
+ call write_inode
+ ld a, [wFsInode]
+ call free_inode
xor a
ret
.no
ld a, $FF
ret
-
-; =============================================================================
-; fs_init - mark all slots free, clear the OF table, seed a "readme" file.
-; =============================================================================
-fs_init::
- ld c, 0
-.clr
- ld a, c
- call FsSlotBase
- xor a
- ld [hl], a ; name[0] = 0
- inc c
- ld a, c
- cp FS_MAX_FILES
- jr c, .clr
- ; zero the open-file table
- ld hl, wOFTable
- ld b, OF_MAX * OF_SIZE
- xor a
-.zof
- ld [hl+], a
- dec b
- jr nz, .zof
- ; seed slot 0 = "readme"
- xor a
- ld [wFsSlot], a
- ld de, .rname
- call FsSetName
- ; copy content -> data
- xor a
- call FsSlotBase ; HL = base
- ld a, FS_DATA
- ld l, a ; HL = &data (base low = 0)
- ld de, .rtext
- ld bc, .rtext_end - .rtext
-.ccpy
- ld a, [de]
- ld [hl+], a
- inc de
- dec bc
- ld a, b
- or c
- jr nz, .ccpy
- ; set len
- xor a
- call FsSlotBase
- ld a, l
- add FS_LEN
- ld l, a
- ld a, LOW(.rtext_end - .rtext)
- ld [hl+], a
- ld a, HIGH(.rtext_end - .rtext)
- ld [hl], a
- ret
-.rname
- db "readme", 0
-.rtext
- db "welcome to gbos!", $0D, $0A
- db "files live in RAM.", $0D, $0A
-.rtext_end