From 8eb40537ab944cea56459877a5dc5fca49b2f71b Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 18 Feb 2021 16:28:48 +0100 Subject: [PATCH] work towards wildcard support and file loading in CBDOS --- src/dos_m65/,aliases_dos.s | 27 +- src/dos_m65/dev_sdcard/fs_hvsr_read_dir.s | 2 +- .../dev_sdcard/fs_hvsr_util_nextdirentry.s | 241 ++++++++++++++++++ 3 files changed, 263 insertions(+), 7 deletions(-) create mode 100644 src/dos_m65/dev_sdcard/fs_hvsr_util_nextdirentry.s diff --git a/src/dos_m65/,aliases_dos.s b/src/dos_m65/,aliases_dos.s index 63254ee4..dc3512f1 100644 --- a/src/dos_m65/,aliases_dos.s +++ b/src/dos_m65/,aliases_dos.s @@ -7,6 +7,13 @@ ; - additional 16KB RAM is reserved for DOS too ($14000-$17FFF), and can be banked-in if needed + ; + ; Temporary storage locations + ; + + !addr FS_HVSR_DIRENT = $1000 + + ; ; Page start+0 ; @@ -41,7 +48,7 @@ !addr par_LDA_nnnn_Y = $8015 ; - 2 bytes; address in buffer, ram disk !addr code_RTS_04 = $8017 ; - RTS instruction - ; Parameters for utilities + ; Parameters for utilities/helkpers !addr PAR_TRACK = $8018 ; track number for status/error !addr PAR_SECTOR = $8019 ; sector number for status/error @@ -49,14 +56,18 @@ !addr PAR_FSIZE_BYTES = $801A ; 4 bytes - file size in bytes !addr PAR_FSIZE_BLOCKS = $801E ; 2 bytes - file size in blocks + !addr PAR_FTYPE = $801F ; bits 0-5 - type, bits 6-7 - protected, closed + !addr PAR_FNAME = $8020 ; 16 bytes - filename, filled with $A0 + !addr PAR_FPATTERN = $8030 ; 16 bytes - pattern to match, filled with $A0 + ; Various temporary data - !addr XX_DIR_PHASE = $8020 ; directory output phase, values deponds on device driver, but 0 = not reading - !addr SD_DIR_PHASE = $8020 ; - SD card - !addr FD_DIR_PHASE = $8021 ; - floppy - !addr RD_DIR_PHASE = $8022 ; - ram disk + !addr XX_DIR_PHASE = $8040 ; directory output phase, values deponds on device driver, but 0 = not reading + !addr SD_DIR_PHASE = $8040 ; - SD card + !addr FD_DIR_PHASE = $8041 ; - floppy + !addr RD_DIR_PHASE = $8042 ; - ram disk - ; Free space: $8023-$8063 + ; Free space: $8043-$8063 !addr SD_ACPTR_helper = $8052 ; subroutine in RAM to read a byte !addr code_LDA_01 = $8052 ; - LDA instruction @@ -103,6 +114,10 @@ !addr FD_STATUS_STR = $80A0 ; status string for floppy drive, terminated by 0 !addr RD_STATUS_STR = $80D0 ; status string for ram disk, terminated by 0 + ; + ; Further pages + ; + !addr SD_CMDFN_BUF = $8100 ; buffer for command and/or file name, 128 bytes, SD card !addr FD_CMDFN_BUF = $8180 ; buffer for command and/or file name, 128 bytes, floppy !addr RD_CMDFN_BUF = $8200 ; buffer for command and/or file name, 128 bytes, ram disk diff --git a/src/dos_m65/dev_sdcard/fs_hvsr_read_dir.s b/src/dos_m65/dev_sdcard/fs_hvsr_read_dir.s index f13fe773..762f7f42 100644 --- a/src/dos_m65/dev_sdcard/fs_hvsr_read_dir.s +++ b/src/dos_m65/dev_sdcard/fs_hvsr_read_dir.s @@ -322,7 +322,7 @@ fs_hvsr_read_dir: fs_hvsr_read_dir_blocksfree: - ; Set pointer to '65535 BLOCKS FREE.' line + ; Set pointer to 'BLOCKS FREE.' line ; XXX determine free space diff --git a/src/dos_m65/dev_sdcard/fs_hvsr_util_nextdirentry.s b/src/dos_m65/dev_sdcard/fs_hvsr_util_nextdirentry.s new file mode 100644 index 00000000..b2b1eb1e --- /dev/null +++ b/src/dos_m65/dev_sdcard/fs_hvsr_util_nextdirentry.s @@ -0,0 +1,241 @@ + +; +; Hypervisor virtual filesystem - helper routine to get the next directory entry +; + + +; Fills-in: PAR_FNAME, PAR_FTYPE, PAR_FSIZE_BYTES + +; NOTE: overrides page pointed by FS_HVSR_DIRENT! + + +; XXX work-in-progress, this should be used within directory reading code + +fs_hvsr_util_nextdirentry: + + ; Clear the page which will be used + + ldx #$00 + txa + +@lpclear: + + sta FS_HVSR_DIRENT, x + inx + bne @lpclear + + ; Ask the hypervisor to read the next dirent structure + + ldx SD_DESC ; directory descriptor XXX rename to FS_HVSR_DESC + ldy #>FS_HVSR_DIRENT ; target page number + + lda #$14 ; dos_readdir + sta HTRAP00 + +nop + + +bcc @fail + + ; Reading entry succeeded, try to decode it. Important dirent fileds: + + ; - $00-$3F - file name + ; - $40 - file name length + ; - $52-$55 - file length + ; - $56-$57 - file type ($10 = dir, $20 = regular) and attributes ($01 for read-only) + + ; + ; Preprocess/validate the filename + ; + + ldx FS_HVSR_DIRENT+$40 ; file name length + beq fs_hvsr_util_nextdirentry ; do not even try for empty file name + cmp #20 + bcs fs_hvsr_util_nextdirentry ; if longer than 16 characters + dot + extension - also skip this one + dex + +@lpname: + + lda FS_HVSR_DIRENT,x + cmp #$22 + beq fs_hvsr_util_nextdirentry ; quotation mark is illegal + cmp #$2A + beq fs_hvsr_util_nextdirentry ; asterisk is illegal, it is used for filtering + cmp #$3F + beq fs_hvsr_util_nextdirentry ; the question mark - in the MS-DOS world it is illegal + cmp #$20 + bcc fs_hvsr_util_nextdirentry ; control characters are not allowed + cmp #$5B + bcc @lpname_next ; up to PETSCII 'Z' is OK + cmp #$61 + bcc fs_hvsr_util_nextdirentry ; some characters are not allowed + cmp #$7E + bne @lpname_1 + lda #$A6 ; replace tilde / pi with something more sane + bra @lpname_store_next + +@lpname_1: + + cmp #$7B + bcs fs_hvsr_util_nextdirentry ; PETSCII-art and control characters are illegal + clc + sbc #$20 ; make everything the same case + +@lpname_store_next: + + sta FS_HVSR_DIRENT,x ; use this when file name has to be adapted + +@lpname_next: + + dex + bpl @lpname + + ; + ; Determine type (file/directory) + ; + + lda FS_HVSR_DIRENT+$56 + tax + and #$FE + beq @entity_file ; workaround for older hypervisors + + and #$20 + bne @entity_file ; branch on file + + txa + and #$10 + beq fs_hvsr_util_nextdirentry ; this type is unknown + +@entity_dir: + + ; Once again validate the name length, with more precise information + + lda FS_HVSR_DIRENT+$40 + cmp #$11 + bcs fs_hvsr_util_nextdirentry ; skip entry if file name longer than 16 characters + + ; Set the type to directory + + lda #$05 + bra @detect_attributes + +@entity_file: + + ; Once again validate the name length, with more precise information + + lda FS_HVSR_DIRENT+$40 + sec + sbc #$04 ; strip 4 bytes - for dot and extension + bmi fs_hvsr_util_nextdirentry ; if name too short, try next entry + beq fs_hvsr_util_nextdirentry ; if name too short, try next entry + sta FS_HVSR_DIRENT+$40 ; store corrected file name length + tax + + ; Make sure there is a dot marking the start of a 3-byte extension + + lda FS_HVSR_DIRENT, x + cmp #$2E + +bne fs_hvsr_util_nextdirentry + + ; + ; Detect file type by extension + ; + + inx + ldy #$00 + +@lpext: + + lda FS_HVSR_DIRENT+0, x + cmp dir_types+0, y + bne @lpext_next + + lda FS_HVSR_DIRENT+1, x + cmp dir_types+1, y + bne @lpext_next + + lda FS_HVSR_DIRENT+2, x + cmp dir_types+2, y + beq @lpext_found + +@lpext_next: + + iny + iny + iny + iny + cpy #(dir_types__end - dir_types) + bcc @lpext + + jmp fs_hvsr_util_nextdirentry ; file extension not detected + +@lpext_found: + + cpy #$10 + +beq fs_hvsr_util_nextdirentry ; file extension 'DIR' does not mean this is a directory + tya + + asr ; convert the result to CBM-compatible value + asr + inc + + cmp #$06 ; mark some file types (not SEQ/PRG/USR/REL/DIR) as read-only + bcc @detect_attributes + ora #$40 + +@detect_attributes: + + ora #$80 ; mark the file as closed, FAT32 does not have a 'not closed' attribute + sta PAR_FTYPE + + lda FS_HVSR_DIRENT+$56 ; also apply read-only attribute from FAT32 + and #$01 + beq @copy_size + + lda PAR_FTYPE + ora #$40 + sta PAR_FTYPE + +@copy_size: + + ; Copy the file size + + ldx #$03 + +@lpsize: + + lda FS_HVSR_DIRENT+$52,x ; copy file size in byytes + sta PAR_FSIZE_BYTES,x + dex + bpl @lpsize + +@copy_name: + + ; Last, but not least - copy file name + + lda #$A0 ; fill-in empty bytes with $A0, to simulate CBM file system + ldx #$0F + +@lpname_cpy: + + cpx FS_HVSR_DIRENT+$40 + bcs @lpname_fill + lda FS_HVSR_DIRENT, x + +@lpname_fill: + + sta PAR_FNAME,x + dex + bpl @lpname_cpy + + ; All done + + clc + rts + +@fail: + + ; Reading next entry failed, this is the end + + ; XXX check error code + + sec + rts