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

257 lines
4.7 KiB
ArmAsm

;
; Hypervisor virtual filesystem - reading directory
;
fs_hvsr_read_dir_open:
; Open the directory
lda #$12 ; dos_opendir
sta HTRAP00
+nop
; XXX handle read errors
sta SD_DIR_DESC ; store directory descriptor XXX invent better name
; Reset status to OK
lda #$00
jsr dos_status_00
; Provide pointer to the header
lda #$20
sta SD_ACPTR_LEN+0
lda #$00
sta SD_ACPTR_LEN+1
lda #<dir_hdr_sd
sta SD_ACPTR_PTR+0
lda #>dir_hdr_sd
sta SD_ACPTR_PTR+1
; Set directory phase to 'file name'
lda #$01
sta SD_DIR_PHASE
; End
jmp dos_EXIT
fs_hvsr_read_dir:
; Read dirent structure into $1000 and then copy it to SD_DIRENT
; Starting at $1000 VIC sees chargen, so this should be a safe place
; Content of the original memory location will be preserved
jsr fs_hvsr_dirent_prepare
ldx SD_DIR_DESC ; directory descriptor
ldy #$10 ; target page number
lda #$13 ; dos_readdir
sta HTRAP00
+nop
php
jsr fs_hvsr_dirent_swap
plp
; If nothing to read, output 'blocks free'
+bcc fs_hvsr_read_dir_blocksfree
; Dirent structure - important fields:
; - $00-$3F - file name
; - $40 - file name length
; - $51-$54 - file length
; - $55 - file type and attributes
; Validate/fix characters in file name
ldx SD_DIRENT+$40
@lp1:
lda SD_DIRENT,x
cmp #$22
beq fs_hvsr_read_dir ; quotation mark is illegal
cmp #$2A
beq fs_hvsr_read_dir ; asterisk is illegal, it is used for filtering
cmp #$20
bcc fs_hvsr_read_dir ; control characters are not allowed
cmp #$5B
bcc @lp1_next ; up to PETSCII 'Z' is OK
cmp #$61
bcc fs_hvsr_read_dir ; some characters are not allowed
cmp #$7B
bcs fs_hvsr_read_dir ; PETSCII-art and control characters are illegal
clc
sbc #$20 ; make everything the same case
sta SD_DIRENT,x
@lp1_next:
dex
bpl @lp1
inc $D020
; Validate file name length
; XXX check for directory!
lda SD_DIRENT+$40
sec
sbc #$04 ; strip 4 bytes - for dot and extension
sta SD_DIRENT+$40
bmi fs_hvsr_read_dir ; if name too short, try next entry
beq fs_hvsr_read_dir ; if name too short, try next entry
cmp #$11
bcs fs_hvsr_read_dir ; if stripped name is 17 characters or longer, try the next entry
sta SD_DIRENT+$40 ; store corrected file name length
tax
; Detect file type (+64 for read-only, +128 = damaged)
lda SD_DIRENT, x
cmp #$2E
bne fs_hvsr_read_dir ; 3-character extension is required!
; XXX temporary; detect file type by extension instead
; Try to prepare output row, starting from SD_DIRENT+$80
lda #$01 ; link to the next line - dummy, will be regenerated by BASIC
sta SD_DIRENT+$80
sta SD_DIRENT+$81
lda #$00 ; XXX calculate length in blocks instead
sta SD_DIRENT+$82
sta SD_DIRENT+$83
ldx #$04 ; XXX put correct amount of spaces instead
lda #' '
sta SD_DIRENT+$80, x
inx
sta SD_DIRENT+$80, x
lda #$22 ; opening quote
sta SD_DIRENT+$80, x
ldy #$FF ; put file name
@lp2:
inx
iny
lda SD_DIRENT, y
sta SD_DIRENT+$80,x
bne @lp2
inx
lda #$22 ; closing quote
sta SD_DIRENT+$80, x
inx
lda #' ' ; XXX put correct amount of spaces instead
sta SD_DIRENT+$80, x
inx
sta SD_DIRENT+$80, x
inx
; XXX put read-only mark if needed
ldy #$03 ; XXX select proper file type instead
lda dir_ext_01+0, y
sta SD_DIRENT+$80, x
inx
lda dir_ext_01+1, y
sta SD_DIRENT+$80, x
inx
lda dir_ext_01+2, y
sta SD_DIRENT+$80, x
inx
; No 'damaged' mark is needed here; put ending 0 and provide pointer
lda #$00
sta SD_DIRENT+$80, x
inx
stx SD_ACPTR_LEN+0
sta SD_ACPTR_LEN+1
lda #<(SD_DIRENT+$80)
sta SD_ACPTR_PTR+0
lda #>(SD_DIRENT+$80)
sta SD_ACPTR_PTR+1
clc
rts
fs_hvsr_read_dir_blocksfree:
; Set pointer to '0 BLOCKS FREE.' line
lda #$13
sta SD_ACPTR_LEN+0
lda #$00
sta SD_ACPTR_LEN+1
lda #<dir_end
sta SD_ACPTR_PTR+0
lda #>dir_end
sta SD_ACPTR_PTR+1
; Mark end of directory
lda #$00
sta SD_DIR_PHASE
; Close the directory within the hypervisor XXX maybe move it to close routine
ldx SD_DIR_DESC
lda #$14 ; dos_closedir
sta HTRAP00
+nop
clc
rts
;
; Helper routines
;
fs_hvsr_dirent_prepare:
ldx #$00
txa
@1:
ldy $1000, x
sty SD_DIRENT, x
sta $1000, x
inx
bne @1
rts
fs_hvsr_dirent_swap:
php
ldx #$00
@1:
lda $1000, x
ldy SD_DIRENT, x
sta SD_DIRENT, x
sty $1000, x
inx
bne @1
plp
rts