Files
open-roms/src/dos_m65/dev_sdcard/fs_hvsr_util_nextdirentry.s
T

243 lines
4.8 KiB
ArmAsm

;
; 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
cpx #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 #$06
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 #$18
+beq fs_hvsr_util_nextdirentry ; file extension 'DIR' does not mean this is a directory
tya
clc
ror
clc
ror
cmp #$07 ; mark some file types (not SEQ/PRG/USR/REL/CBM/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