243 lines
4.8 KiB
ArmAsm
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
|