Getting the Current Directory
Posted: Sun Oct 20, 2024 1:14 pm
I needed to get the current directory, but found the command `$=C` difficult to use as it returns the data as displayed in the BASIC prompt. So to make this more 'machine readable' I've written the code below which will return a pointer to a string in $yyxx which is null terminated in the form that is easier to use.
I thought it might help someone else in a similar endeavour.
While tested, please do shout if there are any issues as string parsing the output of the kernel can be difficult to test every scenario.
I thought it might help someone else in a similar endeavour.
While tested, please do shout if there are any issues as string parsing the output of the kernel can be difficult to test every scenario.
Code: Select all
import BM="BM.bmasm";
BM.X16Header();
.segment ZP, $02, scope:Main
.padvar byte depth
.segment Main
.constvar string current_directory $a000
.constvar byte temp_bank $02
jsr get_current_directory
.loop:
jmp -loop
.proc get_current_directory
; $=C returns
; 2 : header (eg 0x801)
; 2 : unsure, 0x01 0x01
; 2 : size in bytes
; 1 : inverse petscii code 0x12
; x : quote enclosed string for the volume name (null terminated)
; directory entries from present to root
; 2 : unsure 0x01 0x01
; 2 : size
; x : untrimmed quote enclosed string for the name
; 5 : DIR + 0x20 + 0x00
; next dir entry unless name is '/', if so then stop
var GetCurrentDirectory = "$=C";
lda #@(GetCurrentDirectory.Length)
ldx #<get_directory
ldy #>get_directory
jsr SETNAM
lda #15
ldx #8
ldy #0
jsr SETLFS
jsr OPEN
ldx #15
jsr CHKIN
lda #temp_bank
sta RAM_BANK
stz depth
; discard volume
ldx #6 ; remove header
.loop:
jsr GETIN
dex
bne -loop
.loop:
jsr GETIN
cmp #$22
bne -loop
.loop:
jsr GETIN
cmp #$00
bne -loop
ldx #4 ; remove header
.loop:
jsr GETIN
dex
bne -loop
.line_start:
; read and discard to a quote mark
lda store_location + 1
pha
lda store_location + 2
pha
inc depth
.loop:
jsr GETIN
cmp #$22
bne -loop
; read and store to a quote mark
.loop:
jsr GETIN
cmp #$22 ; quote mark
beq +line_done
cmp #$2f ; /
beq +read_done
jsr store_location
inx
jmp -loop
.line_done:
lda #$2f
jsr store_location
jmp -line_start
.store_location:
sta current_directory
inc store_location + 1
bne +skip
inc store_location + 2
.skip:
rts
.read_done:
lda #15
jsr CLOSE
; now reverse the strings
; return pointer in $yyxx
lda store_location + 1
tax
lda store_location + 2
tay
pla ; remove last entry
pla
dec depth
beq all_done ; in case we're at root
.line_start:
pla
sta read_location + 2
pla
sta read_location + 1
.read_location:
lda current_directory
inc read_location + 1
bne +skip
inc read_location + 2
.skip:
cmp #$2f
beq +line_done
jsr store_location
jmp -read_location
.line_done:
dec depth
beq all_done
lda #$2f
jsr store_location
jmp -line_start
.all_done:
lda #0 ; null terminated
jsr store_location
rts
.get_directory:
BM.Bytes(BM.StringToPetscii(GetCurrentDirectory, false));
.endproc