Consider the following Basic program for the C64.
10 OPEN 15,8,15
20 PRINT#15, "I"
30 CLOSE 15
This classic gem simply opens the 'command channel' and sends the DOS 'init' command to the disk drive. The purpose of the 'init' command is to refresh the disk id and block allocation map (BAM). Not very exciting, but I am just trying to get my feet on terra firma.
I have tried to perform the same operation in assembly. I think I am really close, but there is something wrong with my implementation. Note, this probably isn't the prettiest code or the most robust (I am ignoring errors, etc) - but it should work nonetheless.
I have two subroutines here, the first sends the 'init' over the command channel and the second reads the 'status' from the command channel. Both subroutines use a common 'open_15' and 'close_15' to do the setup and teardown for the command channel. I am reasonably sure the 'status' works - but the 'init' fails with a 31,syntax error,00,00. This leads me to conclude there is something wrong with how I am sending the init command over the command channel.
I tried some permutations on the data I am sending - just the character I, the character I in quotes, the I followed by a CR, the I followed by a null, I even tried sending a correctly formatted rename command string like this "R:NEW=OLD" - but nothing seems to change that I always get back a syntax error. The fact I get the same error for both an init and a rename command also reinforces my suspicion I am not sending the data correctly.
It shouldn't matter, but all my tests have been conducted inside the VICE emulator x64sc.exe 3.4 r37296M (GTK3 3.22.30, GLib 2.58.3) running in Winders 10 Pro.
Can someone please tell me where I have gone off the rails?
*=$C000
READST = $FFB7 ; read I/O status word
SETLFS = $FFBA ; set logical file parameters
SETNAM = $FFBD ; set filename parameters
OPEN = $FFC0 ; open a logical file
CLOSE = $FFC3 ; close a logical file
CHKIN = $FFC6 ; define an input channel
CHKOUT = $FFC9 ; define an output channel
CLRCHN = $FFCC ; restore default devices
CHRIN = $FFCF ; input a character
CHROUT = $FFD2 ; output a character
start jsr init ; attempt the "init"
jsr status ; read the command channel status
rts
init jsr open_15
ldx #$0F ; use file number 15 for output
jsr CHKOUT
lda #$49 ; send the letter "I" thru the
jsr CHROUT ; command channel
jsr close_15
rts
status jsr open_15 ; open file number 15
ldx #$0F ; use file number 15 for input
jsr CHKIN
@read jsr READST ; read status byte
bne @done ; either EOF or read error
jsr CHRIN ; get a byte from file
jsr CHROUT ; print byte to screen
jmp @read
@done jsr close_15
rts
open_15 lda #$00 ; set no filename
tax
tay
jsr SETNAM
lda #$0F ; logical file number 15
tay ; command channel 15
ldx #$08 ; default to device 8
jsr SETLFS
jsr OPEN ; open file number 15
rts
close_15 lda #$0F ; close file number 15
jsr CLOSE
jsr CLRCHN ; restore default devices
rts