Skip to content

Instantly share code, notes, and snippets.

@DavidSM64
Created November 18, 2020 13:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DavidSM64/a036a622f4b7a2d8364c355e72766eb7 to your computer and use it in GitHub Desktop.
Save DavidSM64/a036a622f4b7a2d8364c355e72766eb7 to your computer and use it in GitHub Desktop.
; execute_dos_command
; Processes a CMDR-DOS channel 15 command.
; Arguments:
; r0 = Pointer to a null-terminated string that is a valid DOS command.
; Command Examples:
; "MD:FOO" creates a new directory called FOO
; "CD:FOO" will enter the FOO directory
; "CD:.." will enter the parent directory
; "RD:FOO" will delete the FOO directory
; Assumptions:
; * SD Card is being used and is set to device #8
; * String in r0 is less than 256 characters.
execute_dos_command:
!zone {
lda (r0)
bne .setup ; Checking for the null-terminator
rts ; End early if the input is an empty string.
.setup:
ldx #15 ; Open Channel 15 to send DOS commands.
jsr CHKIN
lda #8 ; SD Card in device #8
jsr LISTEN
lda #$6F ; $6X = LISTEN to channel X, so $6F = LISTEN to channel 15
jsr SECOND
.loop_init:
ldy #0 ; Start at the first character.
.send_char:
lda (r0),Y ; Read the current character
beq .cleanup_and_exit ; Exit if the byte is the null terminator
jsr IECOUT ; Send character to the serial bus
iny ; Move to the next character
bra .send_char ; Keep looping
.cleanup_and_exit:
jsr UNLSN ; Stop listening and send the command.
jmp CLRCHN ; Close the channel and return
}
; get_dos_directory
; Reads the current directory of CMDR-DOS to an output RAM address.
; Arguments:
; r0 = Pointer to a string that has valid directory syntax.
; .A = Length of the string at r0
; r1 = Pointer to the output location
; Directory Syntax Examples:
; "$" will list everything in the current directory
; "$:*=P" will only list files
; "$:*=D" will only list directories
; "$:FOO*=D" will only list directories the start with FOO
; "$=T" will list everything with ISO timestamps
; Assumptions:
; * SD Card is being used and is set to device #8
; * String in r0 is less than 256 characters.
get_dos_directory:
!zone {
bne .setup
rts ; End early if the length of the input string is 0
.setup:
ldx r0L
ldy r0H
jsr SETNAM
ldx #8 ; SD Card in device #8
lda #15
ldy #$60
jsr SETLFS
jsr OPEN ; open directory channel
ldx #15
jsr CHKIN
.loop:
jsr BASIN
tay
jsr READST
bne .cleanup_and_exit ; Branch if end-of-file (or an error) occured.
tya
sta (r1) ; Store the byte to the address at r1
inc r1L ; Increment r1 and then keep looping
bne .loop
inc r1H
bra .loop
.cleanup_and_exit:
jsr CLRCHN
lda #15
sec
jmp CLOSE
}
; get_dos_dir_entries
; Gets the entry names of the current directory, and then
; outputs them to a RAM address.
; Arguments:
; r0 = Pointer to a string that has valid directory syntax.
; .A = Length of the string at r0
; r1 = Pointer to the output location
; Returns:
; .A = Number of entries
; Directory Syntax Examples:
; "$" will list everything in the current directory
; "$:*=P" will only list files
; "$:*=D" will only list directories
; "$:FOO*=D" will only list directories the start with FOO
; "$=T" will list everything with ISO timestamps
; Assumptions:
; * SD Card is being used and is set to device #8
; * String in r0 is less than 256 characters.
get_dos_dir_entries:
!zone {
bne .setup
rts ; End early if the length of the input string is 0
.setup:
ldx r0L
ldy r0H
jsr SETNAM
ldx #8 ; SD Card in device #8
lda #15
ldy #$60
jsr SETLFS
jsr OPEN ; open directory channel
ldx #15
jsr CHKIN
.loop_init:
ldx #0 ; Use .X to keep track of writing to output
lda #0 ; Number of entries
pha ; Keep 'Number of entries' on the stack.
jsr BASIN
jsr BASIN ; Skip the $0801 word
.loop_entry:
jsr BASIN ; Skip the block size
jsr BASIN
.loop_char:
jsr BASIN
tay
jsr READST
bne .cleanup_and_exit ; Branch if end-of-file (or an error) occured.
tya
cmp #$22 ; Look for the double-quote ascii character
beq .loop_double_quote
cpx #1
bne .loop_char ; Only write bytes to output when .X == 1
.loop_write_byte:
sta (r1) ; Store the byte to the address at r1
inc r1L ; Increment r1 and then keep looping
bne .loop_char
inc r1H
bra .loop_char
.loop_double_quote:
cpx #0
bne .loop_double_quote_close
ldx #2 ; .X == 2 only on the first double-quote entry.
pla
inc
pha ; number of entries += 1
cmp #1 ; Skip writing the first double-quotes, since it's always "X16 DISK"
beq .loop_char
ldx #1 ; enable writing bytes to output
bra .loop_char
.loop_double_quote_close:
txa
ldx #0 ; disable writing bytes to output
cmp #2 ; Was .X == 2? If so, then skip writing null-terminator
beq .loop_char
lda #0
bra .loop_write_byte ; Store a null-terminator to seperate the entries.
.cleanup_and_exit:
jsr CLRCHN
lda #15
sec
jsr CLOSE
pla ; .A = Number of entries
dec ; Subtract 1 because we didn't write the first double-quotes entry.
rts
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment