Page 1 of 1

Getting the Current Directory

Posted: Sun Oct 20, 2024 1:14 pm
by Yazwho
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.

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

cwd.png
cwd.png (89.87 KiB) Viewed 428 times

Re: Getting the Current Directory

Posted: Mon Oct 21, 2024 3:03 am
by jaydg
This is an item on my to-do list. Thanks for sharing, I'll see how it works for my situation soon.