2021-01-07 00:56:31 +00:00
; C64 and Cx16 disk drive I/O routines.
2020-10-13 23:17:18 +00:00
%import textio
2021-01-07 19:01:11 +00:00
%import string
2020-10-13 23:17:18 +00:00
%import syslib
diskio {
2022-07-08 19:50:32 +00:00
sub directory(ubyte drivenumber) -> bool {
2020-12-09 23:02:21 +00:00
; -- Prints the directory contents of disk drive 8-11 to the screen. Returns success.
2020-10-13 23:17:18 +00:00
c64.SETNAM(1, "$")
2020-12-11 21:36:14 +00:00
c64.SETLFS(13, drivenumber, 0)
2022-07-30 11:17:20 +00:00
ubyte status = 1
2020-12-11 21:36:14 +00:00
void c64.OPEN() ; open 13,8,0,"$"
2020-10-13 23:17:18 +00:00
if_cs
goto io_error
2020-12-11 21:36:14 +00:00
void c64.CHKIN(13) ; use #13 as input channel
2020-10-13 23:17:18 +00:00
if_cs
goto io_error
repeat 4 {
void c64.CHRIN() ; skip the 4 prologue bytes
}
; while not key pressed / EOF encountered, read data.
2022-07-30 11:17:20 +00:00
status = c64.READST()
if status!=0 {
status = 1
goto io_error
}
while status==0 {
2020-12-08 00:02:38 +00:00
ubyte low = c64.CHRIN()
ubyte high = c64.CHRIN()
txt.print_uw(mkword(high, low))
2021-01-14 21:51:09 +00:00
txt.spc()
2020-10-13 23:17:18 +00:00
ubyte @zp char
2020-12-22 02:35:00 +00:00
repeat {
2020-10-13 23:17:18 +00:00
char = c64.CHRIN()
2020-12-22 04:54:28 +00:00
if char==0
2020-12-22 02:35:00 +00:00
break
2020-10-13 23:17:18 +00:00
txt.chrout(char)
2020-12-22 02:35:00 +00:00
}
2021-01-08 15:56:17 +00:00
txt.nl()
2020-10-13 23:17:18 +00:00
void c64.CHRIN() ; skip 2 bytes
void c64.CHRIN()
status = c64.READST()
2020-12-22 02:35:00 +00:00
if c64.STOP2()
2020-10-13 23:17:18 +00:00
break
}
2022-07-30 11:17:20 +00:00
status = c64.READST()
2020-10-13 23:17:18 +00:00
io_error:
c64.CLRCHN() ; restore default i/o devices
2020-12-11 21:36:14 +00:00
c64.CLOSE(13)
2020-10-13 23:17:18 +00:00
2021-01-10 13:29:51 +00:00
if status and status & $40 == 0 { ; bit 6=end of file
2020-10-13 23:17:18 +00:00
txt.print("\ni/o error, status: ")
txt.print_ub(status)
2021-01-08 15:56:17 +00:00
txt.nl()
2020-10-13 23:17:18 +00:00
return false
}
return true
}
2022-07-30 11:17:20 +00:00
sub diskname(ubyte drivenumber) -> uword {
; -- Returns pointer to disk name string or 0 if failure.
c64.SETNAM(1, "$")
c64.SETLFS(13, drivenumber, 0)
ubyte okay = false
void c64.OPEN() ; open 13,8,0,"$"
if_cs
goto io_error
void c64.CHKIN(13) ; use #13 as input channel
if_cs
goto io_error
repeat 6 {
void c64.CHRIN() ; skip the 6 prologue bytes
}
if c64.READST()!=0
goto io_error
; while not key pressed / EOF encountered, read data.
cx16.r0 = &list_filename
repeat {
@(cx16.r0) = c64.CHRIN()
if @(cx16.r0)==0
break
cx16.r0++
}
okay = true
io_error:
c64.CLRCHN() ; restore default i/o devices
c64.CLOSE(13)
if okay
return &list_filename
return 0
}
2020-10-13 23:17:18 +00:00
2020-12-09 23:58:59 +00:00
; internal variables for the iterative file lister / loader
2022-07-08 19:50:32 +00:00
bool list_skip_disk_name
2020-12-08 02:28:29 +00:00
uword list_pattern
uword list_blocks
2022-07-08 19:50:32 +00:00
bool iteration_in_progress = false
2020-12-31 18:27:34 +00:00
ubyte @zp first_byte
2022-07-08 19:50:32 +00:00
bool have_first_byte
2022-08-01 20:58:03 +00:00
str list_filename = "?" * 40
const uword filenames_buf_size = 800
uword filenames_buffer = memory("filenames", filenames_buf_size, 0) ; note: if you know what you're doing (=doesn't call list_files()) your user code may reuse this buffer if required.
2020-12-11 21:36:14 +00:00
2021-01-18 00:38:33 +00:00
; ----- get a list of files (uses iteration functions internally) -----
2020-12-11 21:36:14 +00:00
2020-12-30 22:34:00 +00:00
sub list_files(ubyte drivenumber, uword pattern_ptr, uword name_ptrs, ubyte max_names) -> ubyte {
2022-07-30 11:17:20 +00:00
; -- fill the array 'name_ptrs' with (pointers to) the names of the files requested. Returns number of files.
2022-08-01 20:58:03 +00:00
uword buffer_start = filenames_buffer
2020-12-11 21:36:14 +00:00
ubyte files_found = 0
2020-12-30 22:34:00 +00:00
if lf_start_list(drivenumber, pattern_ptr) {
2020-12-11 21:36:14 +00:00
while lf_next_entry() {
2022-08-01 20:58:03 +00:00
@(name_ptrs) = lsb(filenames_buffer)
2020-12-11 21:36:14 +00:00
name_ptrs++
2022-08-01 20:58:03 +00:00
@(name_ptrs) = msb(filenames_buffer)
2020-12-11 21:36:14 +00:00
name_ptrs++
2022-08-01 20:58:03 +00:00
filenames_buffer += string.copy(diskio.list_filename, filenames_buffer) + 1
2020-12-11 21:36:14 +00:00
files_found++
2022-08-01 20:58:03 +00:00
if filenames_buffer - buffer_start > filenames_buf_size-18
2020-12-11 21:36:14 +00:00
break
if files_found == max_names
break
}
lf_end_list()
}
return files_found
}
2020-12-09 23:58:59 +00:00
2021-01-10 04:04:56 +00:00
; ----- iterative file lister functions (uses io channel 12) -----
2020-12-09 23:58:59 +00:00
2022-07-08 19:50:32 +00:00
sub lf_start_list(ubyte drivenumber, uword pattern_ptr) -> bool {
2020-12-30 22:34:00 +00:00
; -- start an iterative file listing with optional pattern matching.
2020-12-11 21:36:14 +00:00
; note: only a single iteration loop can be active at a time!
2020-12-08 02:28:29 +00:00
lf_end_list()
2020-12-30 22:34:00 +00:00
list_pattern = pattern_ptr
2020-12-08 02:28:29 +00:00
list_skip_disk_name = true
2020-12-09 23:02:21 +00:00
iteration_in_progress = true
2020-12-07 22:29:34 +00:00
c64.SETNAM(1, "$")
2020-12-11 21:36:14 +00:00
c64.SETLFS(12, drivenumber, 0)
void c64.OPEN() ; open 12,8,0,"$"
2020-12-07 22:29:34 +00:00
if_cs
2020-12-08 02:28:29 +00:00
goto io_error
2020-12-11 21:36:14 +00:00
void c64.CHKIN(12) ; use #12 as input channel
2020-12-07 22:29:34 +00:00
if_cs
2020-12-08 02:28:29 +00:00
goto io_error
2020-12-07 22:29:34 +00:00
repeat 4 {
void c64.CHRIN() ; skip the 4 prologue bytes
}
2020-12-08 02:28:29 +00:00
if c64.READST()==0
return true
io_error:
lf_end_list()
return false
}
2022-07-08 19:50:32 +00:00
sub lf_next_entry() -> bool {
2020-12-08 02:28:29 +00:00
; -- retrieve the next entry from an iterative file listing session.
; results will be found in list_blocks and list_filename.
; if it returns false though, there are no more entries (or an error occurred).
2020-12-09 23:02:21 +00:00
if not iteration_in_progress
2020-12-08 02:28:29 +00:00
return false
2020-12-08 00:02:38 +00:00
2020-12-11 21:36:14 +00:00
repeat {
void c64.CHKIN(12) ; use #12 as input channel again
2020-12-08 02:28:29 +00:00
uword nameptr = &list_filename
ubyte blocks_lsb = c64.CHRIN()
ubyte blocks_msb = c64.CHRIN()
2020-12-11 21:36:14 +00:00
if c64.READST()
goto close_end
2020-12-08 02:28:29 +00:00
list_blocks = mkword(blocks_msb, blocks_lsb)
2020-12-07 22:29:34 +00:00
; read until the filename starts after the first "
while c64.CHRIN()!='\"' {
if c64.READST()
2020-12-08 00:34:08 +00:00
goto close_end
2020-12-07 22:29:34 +00:00
}
2020-12-08 02:28:29 +00:00
; read the filename
2020-12-08 00:02:38 +00:00
repeat {
ubyte char = c64.CHRIN()
2020-12-22 02:35:00 +00:00
if char==0
2020-12-08 00:34:08 +00:00
break
2020-12-08 00:02:38 +00:00
if char=='\"'
break
2020-12-08 02:28:29 +00:00
@(nameptr) = char
nameptr++
2020-12-08 00:02:38 +00:00
}
2020-12-08 02:28:29 +00:00
@(nameptr) = 0
2020-12-08 00:02:38 +00:00
2020-12-08 21:10:12 +00:00
while c64.CHRIN() {
; read the rest of the entry until the end
}
2020-12-08 00:02:38 +00:00
2020-12-07 22:29:34 +00:00
void c64.CHRIN() ; skip 2 bytes
void c64.CHRIN()
2020-12-08 02:28:29 +00:00
if not list_skip_disk_name {
2020-12-30 22:34:00 +00:00
if not list_pattern
return true
2022-03-21 20:19:32 +00:00
if string.pattern_match(list_filename, list_pattern)
2020-12-08 02:28:29 +00:00
return true
}
list_skip_disk_name = false
2020-12-07 22:29:34 +00:00
}
2020-12-08 00:34:08 +00:00
close_end:
2020-12-08 02:28:29 +00:00
lf_end_list()
return false
2020-12-07 22:29:34 +00:00
}
2020-12-08 02:28:29 +00:00
sub lf_end_list() {
; -- end an iterative file listing session (close channels).
2020-12-09 23:02:21 +00:00
if iteration_in_progress {
2020-12-08 02:28:29 +00:00
c64.CLRCHN()
2020-12-11 21:36:14 +00:00
c64.CLOSE(12)
2020-12-09 23:02:21 +00:00
iteration_in_progress = false
2020-12-08 02:28:29 +00:00
}
}
2021-01-10 04:04:56 +00:00
; ----- iterative file loader functions (uses io channel 11) -----
2020-12-09 23:58:59 +00:00
2022-07-08 19:50:32 +00:00
sub f_open(ubyte drivenumber, uword filenameptr) -> bool {
2020-12-11 21:36:14 +00:00
; -- open a file for iterative reading with f_read
; note: only a single iteration loop can be active at a time!
2020-12-09 23:58:59 +00:00
f_close()
2021-01-07 19:01:11 +00:00
c64.SETNAM(string.length(filenameptr), filenameptr)
2021-01-13 21:11:51 +00:00
c64.SETLFS(11, drivenumber, 0)
2020-12-09 23:58:59 +00:00
void c64.OPEN() ; open 11,8,0,"filename"
if_cc {
2022-07-15 20:21:34 +00:00
if c64.READST()==0 {
iteration_in_progress = true
have_first_byte = false
void c64.CHKIN(11) ; use #11 as input channel
if_cc {
first_byte = c64.CHRIN() ; read first byte to test for file not found
if not c64.READST() {
have_first_byte = true
return true
}
2020-12-31 18:27:34 +00:00
}
}
2020-12-09 23:58:59 +00:00
}
f_close()
return false
}
2020-12-24 05:24:52 +00:00
sub f_read(uword bufferpointer, uword num_bytes) -> uword {
; -- read from the currently open file, up to the given number of bytes.
; returns the actual number of bytes read. (checks for End-of-file and error conditions)
2022-06-26 19:42:56 +00:00
; NOTE: on systems with banked ram (such as Commander X16) this routine DOES NOT
; automatically load into subsequent banks if it reaches a bank boundary!
2020-12-31 18:27:34 +00:00
if not iteration_in_progress or not num_bytes
2020-12-09 23:58:59 +00:00
return 0
2020-12-31 18:27:34 +00:00
list_blocks = 0 ; we reuse this variable for the total number of bytes read
if have_first_byte {
have_first_byte=false
@(bufferpointer) = first_byte
bufferpointer++
list_blocks++
num_bytes--
}
2020-12-11 21:36:14 +00:00
void c64.CHKIN(11) ; use #11 as input channel again
2022-06-01 22:37:18 +00:00
2020-12-31 15:46:24 +00:00
%asm {{
lda bufferpointer
2022-01-17 21:03:53 +00:00
sta m_in_buffer+1
2020-12-31 15:46:24 +00:00
lda bufferpointer+1
2022-01-17 21:03:53 +00:00
sta m_in_buffer+2
2020-12-31 15:46:24 +00:00
}}
2020-12-24 05:24:52 +00:00
repeat num_bytes {
2020-12-31 15:46:24 +00:00
%asm {{
jsr c64.CHRIN
2021-01-10 13:29:51 +00:00
sta cx16.r5
2022-01-17 21:03:53 +00:00
m_in_buffer sta $ffff
inc m_in_buffer+1
2020-12-31 15:46:24 +00:00
bne +
2022-01-17 21:03:53 +00:00
inc m_in_buffer+2
2020-12-31 18:27:34 +00:00
+ inc list_blocks
2020-12-31 15:46:24 +00:00
bne +
2020-12-31 18:27:34 +00:00
inc list_blocks+1
2020-12-31 15:46:24 +00:00
+
}}
2020-12-24 05:24:52 +00:00
2021-01-10 13:29:51 +00:00
if cx16.r5==$0d { ; chance on I/o error status?
first_byte = c64.READST()
2022-05-31 23:09:37 +00:00
if first_byte & $40 {
2021-01-10 13:29:51 +00:00
f_close() ; end of file, close it
2022-05-31 23:09:37 +00:00
list_blocks-- ; don't count that last CHRIN read
}
2021-01-10 13:29:51 +00:00
if first_byte
2022-05-31 23:09:37 +00:00
return list_blocks ; number of bytes read
2021-01-10 13:29:51 +00:00
}
2020-12-31 18:27:34 +00:00
}
2022-05-31 23:09:37 +00:00
return list_blocks ; number of bytes read
2020-12-31 15:46:24 +00:00
}
sub f_read_all(uword bufferpointer) -> uword {
; -- read the full contents of the file, returns number of bytes read.
if not iteration_in_progress
return 0
2022-05-31 23:09:37 +00:00
uword total_read = 0
2020-12-31 18:27:34 +00:00
if have_first_byte {
have_first_byte=false
@(bufferpointer) = first_byte
bufferpointer++
2022-05-31 23:09:37 +00:00
total_read = 1
2020-12-31 18:27:34 +00:00
}
2020-12-31 15:46:24 +00:00
while not c64.READST() {
2022-05-31 23:09:37 +00:00
uword size = f_read(bufferpointer, 256)
total_read += size
bufferpointer += size
2020-12-24 05:24:52 +00:00
}
2022-05-31 23:09:37 +00:00
return total_read
2020-12-24 05:24:52 +00:00
}
2021-01-10 04:04:56 +00:00
asmsub f_readline(uword bufptr @AY) clobbers(X) -> ubyte @Y {
; Routine to read text lines from a text file. Lines must be less than 255 characters.
2021-01-10 15:00:22 +00:00
; Reads characters from the input file UNTIL a newline or return character (or EOF).
; The line read will be 0-terminated in the buffer (and not contain the end of line character).
2021-01-14 21:51:09 +00:00
; The length of the line is returned in Y. Note that an empty line is okay and is length 0!
; I/O error status should be checked by the caller itself via READST() routine.
2021-01-10 04:04:56 +00:00
%asm {{
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldx #11
jsr c64.CHKIN ; use channel 11 again for input
ldy #0
2021-01-10 15:00:22 +00:00
lda have_first_byte
beq _loop
lda #0
sta have_first_byte
lda first_byte
sta (P8ZP_SCRATCH_W1),y
iny
2021-01-10 04:04:56 +00:00
_loop jsr c64.CHRIN
sta (P8ZP_SCRATCH_W1),y
beq _end
iny
cmp #$0a
2021-01-10 15:00:22 +00:00
beq _line_end
2021-01-10 04:04:56 +00:00
cmp #$0d
bne _loop
2021-01-10 15:00:22 +00:00
_line_end dey ; get rid of the trailing end-of-line char
lda #0
2021-01-10 04:04:56 +00:00
sta (P8ZP_SCRATCH_W1),y
_end rts
}}
}
2020-12-31 15:46:24 +00:00
2020-12-09 23:58:59 +00:00
sub f_close() {
; -- end an iterative file loading session (close channels).
if iteration_in_progress {
c64.CLRCHN()
c64.CLOSE(11)
iteration_in_progress = false
}
}
2021-05-01 17:13:56 +00:00
; ----- iterative file saver functions (uses io channel 14) -----
2022-07-08 19:50:32 +00:00
sub f_open_w(ubyte drivenumber, uword filenameptr) -> bool {
2021-05-01 17:13:56 +00:00
; -- open a file for iterative writing with f_write
f_close_w()
c64.SETNAM(string.length(filenameptr), filenameptr)
c64.SETLFS(14, drivenumber, 1)
void c64.OPEN() ; open 14,8,1,"filename"
if_cc {
void c64.CHKOUT(14) ; use #14 as input channel
return not c64.READST()
}
f_close_w()
return false
}
2022-07-08 19:50:32 +00:00
sub f_write(uword bufferpointer, uword num_bytes) -> bool {
2021-05-01 17:13:56 +00:00
; -- write the given umber of bytes to the currently open file
if num_bytes!=0 {
void c64.CHKOUT(14) ; use #14 as input channel again
repeat num_bytes {
c64.CHROUT(@(bufferpointer))
bufferpointer++
}
return not c64.READST()
}
return true
}
sub f_close_w() {
; -- end an iterative file writing session (close channels).
c64.CLRCHN()
c64.CLOSE(14)
}
; ---- other functions ----
2020-12-09 23:02:21 +00:00
sub status(ubyte drivenumber) -> uword {
; -- retrieve the disk drive's current status message
2022-08-01 20:58:03 +00:00
uword messageptr = filenames_buffer
c64.SETNAM(0, filenames_buffer)
2020-10-13 23:17:18 +00:00
c64.SETLFS(15, drivenumber, 15)
void c64.OPEN() ; open 15,8,15
if_cs
goto io_error
void c64.CHKIN(15) ; use #15 as input channel
if_cs
goto io_error
2020-12-09 23:02:21 +00:00
while not c64.READST() {
2022-07-17 19:56:52 +00:00
first_byte = c64.CHRIN()
if first_byte=='\r' or first_byte=='\n'
2022-07-15 20:21:34 +00:00
break
2022-07-17 19:56:52 +00:00
@(messageptr) = first_byte
2020-12-09 23:02:21 +00:00
messageptr++
}
@(messageptr) = 0
2022-07-15 20:21:34 +00:00
2021-05-01 13:20:11 +00:00
done:
2020-10-13 23:17:18 +00:00
c64.CLRCHN() ; restore default i/o devices
c64.CLOSE(15)
2022-08-01 20:58:03 +00:00
return filenames_buffer
2021-05-01 13:20:11 +00:00
io_error:
2022-08-01 20:58:03 +00:00
void string.copy("?disk error", filenames_buffer)
2021-05-01 13:20:11 +00:00
goto done
2020-10-13 23:17:18 +00:00
}
2022-07-08 19:50:32 +00:00
sub save(ubyte drivenumber, uword filenameptr, uword address, uword size) -> bool {
2021-01-07 19:01:11 +00:00
c64.SETNAM(string.length(filenameptr), filenameptr)
2020-10-14 20:33:49 +00:00
c64.SETLFS(1, drivenumber, 0)
2022-02-10 02:10:47 +00:00
uword @shared end_address = address + size
2021-04-06 21:55:20 +00:00
first_byte = 0 ; result var reuse
2020-10-14 20:33:49 +00:00
%asm {{
lda address
sta P8ZP_SCRATCH_W1
lda address+1
sta P8ZP_SCRATCH_W1+1
stx P8ZP_SCRATCH_REG
lda #<P8ZP_SCRATCH_W1
ldx end_address
ldy end_address+1
jsr c64.SAVE
php
ldx P8ZP_SCRATCH_REG
plp
}}
if_cc
2020-12-31 18:27:34 +00:00
first_byte = c64.READST()==0
2020-10-14 20:33:49 +00:00
2020-12-03 15:01:58 +00:00
c64.CLRCHN()
c64.CLOSE(1)
2020-12-31 18:27:34 +00:00
return first_byte
2020-10-13 23:17:18 +00:00
}
2021-12-03 23:07:21 +00:00
; Use kernal LOAD routine to load the given program file in memory.
2022-01-03 21:44:27 +00:00
; This is similar to Basic's LOAD "filename",drive / LOAD "filename",drive,1
2021-12-03 23:07:21 +00:00
; If you don't give an address_override, the location in memory is taken from the 2-byte file header.
; If you specify a custom address_override, the first 2 bytes in the file are ignored
; and the rest is loaded at the given location in memory.
2021-12-14 22:54:42 +00:00
; Returns the end load address+1 if successful or 0 if a load error occurred.
2021-12-03 23:07:21 +00:00
; NOTE: when the load is larger than 64Kb and/or spans multiple RAM banks
2021-12-04 22:23:10 +00:00
; (which is possible on the Commander X16), the returned size is not correct,
; because it doesn't take the number of ram banks into account.
; Consider using cx16diskio.load() instead.
2020-10-14 20:33:49 +00:00
sub load(ubyte drivenumber, uword filenameptr, uword address_override) -> uword {
2022-04-02 01:26:48 +00:00
return load_headerless_cx16(drivenumber, filenameptr, address_override, false)
}
; Use kernal LOAD routine to load the given file in memory.
; INCLUDING the first 2 bytes in the file: no program header is assumed in the file.
; This is different from Basic's LOAD instruction which always skips the first two bytes.
; The load address is mandatory.
; Returns the end load address+1 if successful or 0 if a load error occurred.
; NOTE: when the load is larger than 64Kb and/or spans multiple RAM banks
; (which is possible on the Commander X16), the returned size is not correct,
; because it doesn't take the number of ram banks into account.
; Consider using cx16diskio.load_raw() instead on the Commander X16.
sub load_raw(ubyte drivenumber, uword filenameptr, uword address) -> uword {
if sys.target==16 ; are we on commander X16?
return load_headerless_cx16(drivenumber, filenameptr, address, true)
; fallback to reading the 2 header bytes separately
if not f_open(drivenumber, filenameptr)
return 0
cx16.r1 = f_read(address, 2)
f_close()
if cx16.r1!=2
return 0
address += 2
return load(drivenumber, filenameptr, address)
}
; Internal routine, only to be used on Commander X16 platform if headerless=true,
; because this routine uses kernal support for that to load headerless files.
2022-07-08 19:50:32 +00:00
sub load_headerless_cx16(ubyte drivenumber, uword filenameptr, uword address_override, bool headerless) -> uword {
2021-01-07 19:01:11 +00:00
c64.SETNAM(string.length(filenameptr), filenameptr)
2020-10-14 20:33:49 +00:00
ubyte secondary = 1
2021-12-14 22:54:42 +00:00
cx16.r1 = 0
2020-10-14 20:33:49 +00:00
if address_override
secondary = 0
2022-04-02 01:26:48 +00:00
if headerless
secondary |= %00000010 ; activate cx16 kernal headerless load support
2020-10-14 20:33:49 +00:00
c64.SETLFS(1, drivenumber, secondary)
%asm {{
stx P8ZP_SCRATCH_REG
lda #0
ldx address_override
ldy address_override+1
jsr c64.LOAD
bcs +
2021-12-14 22:54:42 +00:00
stx cx16.r1
sty cx16.r1+1
2020-10-14 20:33:49 +00:00
+ ldx P8ZP_SCRATCH_REG
}}
2020-12-03 15:01:58 +00:00
c64.CLRCHN()
c64.CLOSE(1)
2021-12-14 22:54:42 +00:00
return cx16.r1
2020-10-14 20:33:49 +00:00
}
2020-10-13 23:17:18 +00:00
sub delete(ubyte drivenumber, uword filenameptr) {
; -- delete a file on the drive
2022-08-01 20:58:03 +00:00
filenames_buffer[0] = 's'
filenames_buffer[1] = ':'
ubyte flen = string.copy(filenameptr, filenames_buffer+2)
c64.SETNAM(flen+2, filenames_buffer)
2020-10-13 23:17:18 +00:00
c64.SETLFS(1, drivenumber, 15)
void c64.OPEN()
c64.CLRCHN()
c64.CLOSE(1)
}
sub rename(ubyte drivenumber, uword oldfileptr, uword newfileptr) {
; -- rename a file on the drive
2022-08-01 20:58:03 +00:00
filenames_buffer[0] = 'r'
filenames_buffer[1] = ':'
ubyte flen_new = string.copy(newfileptr, filenames_buffer+2)
filenames_buffer[flen_new+2] = '='
ubyte flen_old = string.copy(oldfileptr, filenames_buffer+3+flen_new)
c64.SETNAM(3+flen_new+flen_old, filenames_buffer)
2020-10-13 23:17:18 +00:00
c64.SETLFS(1, drivenumber, 15)
void c64.OPEN()
c64.CLRCHN()
c64.CLOSE(1)
}
2021-12-03 23:07:21 +00:00
2022-08-01 20:58:03 +00:00
sub send_command(ubyte drivenumber, uword commandptr) {
; -- send a dos command to the drive
c64.SETNAM(string.length(commandptr), commandptr)
c64.SETLFS(15, drivenumber, 15)
void c64.OPEN()
c64.CLRCHN()
c64.CLOSE(15)
}
2020-10-13 23:17:18 +00:00
}