; Cx16 specific disk drive I/O routines. %import diskio %import string cx16diskio { ; Use kernal LOAD routine to load the given program file in memory. ; This is similar to Basic's LOAD "filename",drive / LOAD "filename",drive,1 ; 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. ; Returns the end load address+1 if successful or 0 if a load error occurred. ; You can use the load_size() function to calcuate the size of the file that was loaded. sub load(ubyte drivenumber, uword filenameptr, ubyte bank, uword address_override) -> uword { cx16.rambank(bank) return diskio.load(drivenumber, filenameptr, address_override) } ; 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. ; The load address is mandatory. Returns the number of bytes loaded. ; If you load into regular system ram, use cx16.getrambank() for the bank argument, ; or alternatively make sure to reset the correct ram bank yourself after the load! ; Returns the end load address+1 if successful or 0 if a load error occurred. ; You can use the load_size() function to calcuate the size of the file that was loaded. sub load_raw(ubyte drivenumber, uword filenameptr, ubyte bank, uword address) -> uword { cx16.rambank(bank) return diskio.load_headerless_cx16(drivenumber, filenameptr, address, true) } ; For use directly after a load or load_raw call (don't mess with the ram bank yet): ; Calculates the number of bytes loaded (files > 64Kb ar truncated to 16 bits) sub load_size(ubyte startbank, uword startaddress, uword endaddress) -> uword { return $2000 * (cx16.getrambank() - startbank) + endaddress - startaddress } asmsub vload(str name @R0, ubyte drivenumber @Y, ubyte bank @A, uword address @R1) -> ubyte @A { ; -- like the basic command VLOAD "filename",drivenumber,bank,address ; loads a file into Vera's video memory in the given bank:address, returns success in A ; the file has to have the usual 2 byte header (which will be skipped) %asm {{ clc internal_vload: phx pha tya tax bcc + ldy #%00000010 ; headerless load mode bne ++ + ldy #0 ; normal load mode + lda #1 jsr c64.SETLFS lda cx16.r0 ldy cx16.r0+1 jsr prog8_lib.strlen tya ldx cx16.r0 ldy cx16.r0+1 jsr c64.SETNAM pla clc adc #2 ldx cx16.r1 ldy cx16.r1+1 stz P8ZP_SCRATCH_B1 jsr c64.LOAD bcs + inc P8ZP_SCRATCH_B1 + jsr c64.CLRCHN lda #1 jsr c64.CLOSE plx lda P8ZP_SCRATCH_B1 rts }} } asmsub vload_raw(str name @R0, ubyte drivenumber @Y, ubyte bank @A, uword address @R1) -> ubyte @A { ; -- like the basic command BVLOAD "filename",drivenumber,bank,address ; loads a file into Vera's video memory in the given bank:address, returns success in A ; the file is read fully including the first two bytes. %asm {{ sec jmp vload.internal_vload }} } ; replacement function that makes use of fast block read capability of the X16 ; use this in place of regular diskio.f_read() 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) if not diskio.iteration_in_progress or not num_bytes return 0 diskio.list_blocks = 0 ; we reuse this variable for the total number of bytes read void c64.CHKIN(12) ; use #12 as input channel again ; commander X16 supports fast block-read via macptr() kernal call uword size while num_bytes { size = 255 if num_bytes uword { ; -- read the full contents of the file, returns number of bytes read. if not diskio.iteration_in_progress return 0 uword total_read = 0 while not c64.READST() { uword size = cx16diskio.f_read(bufferpointer, 256) total_read += size bufferpointer += size } return total_read } sub chdir(ubyte drivenumber, str path) { ; -- change current directory. diskio.list_filename[0] = 'c' diskio.list_filename[1] = 'd' diskio.list_filename[2] = ':' void string.copy(path, &diskio.list_filename+3) diskio.send_command(drivenumber, diskio.list_filename) } sub mkdir(ubyte drivenumber, str name) { ; -- make a new subdirectory. diskio.list_filename[0] = 'm' diskio.list_filename[1] = 'd' diskio.list_filename[2] = ':' void string.copy(name, &diskio.list_filename+3) diskio.send_command(drivenumber, diskio.list_filename) } sub rmdir(ubyte drivenumber, str name) { ; -- remove a subdirectory. void string.find(name, '*') if_cs return ; refuse to act on a wildcard * diskio.list_filename[0] = 'r' diskio.list_filename[1] = 'd' diskio.list_filename[2] = ':' void string.copy(name, &diskio.list_filename+3) diskio.send_command(drivenumber, diskio.list_filename) } sub relabel(ubyte drivenumber, str name) { ; -- change the disk label. diskio.list_filename[0] = 'r' diskio.list_filename[1] = '-' diskio.list_filename[2] = 'h' diskio.list_filename[3] = ':' void string.copy(name, &diskio.list_filename+4) diskio.send_command(drivenumber, diskio.list_filename) } sub f_seek(uword pos_hiword, uword pos_loword) { ; -- seek in the reading file opened with f_open, to the given 32-bits position ubyte[6] command = ['p',0,0,0,0,0] command[1] = 12 ; f_open uses channel 12 command[2] = lsb(pos_loword) command[3] = msb(pos_loword) command[4] = lsb(pos_hiword) command[5] = msb(pos_hiword) send_command: c64.SETNAM(sizeof(command), &command) c64.SETLFS(15, diskio.last_drivenumber, 15) void c64.OPEN() c64.CLOSE(15) } ; TODO see if we can get this to work as well: ; sub f_seek_w(uword pos_hiword, uword pos_loword) { ; ; -- seek in the output file opened with f_open_w, to the given 32-bits position ; cx16diskio.f_seek.command[1] = 1 ; f_open_w uses secondary channel 1 ; cx16diskio.f_seek.command[2] = poslo ; cx16diskio.f_seek.command[3] = posmidlo ; cx16diskio.f_seek.command[4] = posmidhi ; cx16diskio.f_seek.command[5] = poshi ; goto cx16diskio.f_seek.send_command ; } }