added cx16diskio.f_seek() function to seek to a position in an opened file

f_open uses channel 12 now, f_open_w uses 13
This commit is contained in:
Irmen de Jong 2022-11-23 01:14:43 +01:00
parent 7ebcb219d6
commit f870e4965a
5 changed files with 151 additions and 32 deletions

View File

@ -35,8 +35,8 @@ cx16diskio {
return $2000 * (cx16.getrambank() - startbank) + endaddress - startaddress
}
asmsub vload(str name @R0, ubyte device @Y, ubyte bank @A, uword address @R1) -> ubyte @A {
; -- like the basic command VLOAD "filename",device,bank,address
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 {{
@ -77,8 +77,8 @@ internal_vload:
}}
}
asmsub vload_raw(str name @R0, ubyte device @Y, ubyte bank @A, uword address @R1) -> ubyte @A {
; -- like the basic command BVLOAD "filename",device,bank,address
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 {{
@ -104,7 +104,7 @@ internal_vload:
num_bytes--
}
void c64.CHKIN(11) ; use #11 as input channel again
void c64.CHKIN(12) ; use #12 as input channel again
; commander X16 supports fast block-read via macptr() kernal call
uword size
@ -191,7 +191,7 @@ m_in_buffer sta $ffff
diskio.list_filename[1] = 'd'
diskio.list_filename[2] = ':'
void string.copy(path, &diskio.list_filename+3)
void diskio.send_command(drivenumber, diskio.list_filename)
diskio.send_command(drivenumber, diskio.list_filename)
}
sub mkdir(ubyte drivenumber, str name) {
@ -200,7 +200,7 @@ m_in_buffer sta $ffff
diskio.list_filename[1] = 'd'
diskio.list_filename[2] = ':'
void string.copy(name, &diskio.list_filename+3)
void diskio.send_command(drivenumber, diskio.list_filename)
diskio.send_command(drivenumber, diskio.list_filename)
}
sub rmdir(ubyte drivenumber, str name) {
@ -212,7 +212,7 @@ m_in_buffer sta $ffff
diskio.list_filename[1] = 'd'
diskio.list_filename[2] = ':'
void string.copy(name, &diskio.list_filename+3)
void diskio.send_command(drivenumber, diskio.list_filename)
diskio.send_command(drivenumber, diskio.list_filename)
}
sub relabel(ubyte drivenumber, str name) {
@ -222,6 +222,33 @@ m_in_buffer sta $ffff
diskio.list_filename[2] = 'h'
diskio.list_filename[3] = ':'
void string.copy(name, &diskio.list_filename+4)
void diskio.send_command(drivenumber, diskio.list_filename)
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)
diskio.have_first_byte = false
}
; 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
; }
}

View File

@ -10,12 +10,12 @@ diskio {
; -- Prints the directory contents of disk drive 8-11 to the screen. Returns success.
c64.SETNAM(1, "$")
c64.SETLFS(13, drivenumber, 0)
c64.SETLFS(12, drivenumber, 0)
ubyte status = 1
void c64.OPEN() ; open 13,8,0,"$"
void c64.OPEN() ; open 12,8,0,"$"
if_cs
goto io_error
void c64.CHKIN(13) ; use #13 as input channel
void c64.CHKIN(12) ; use #12 as input channel
if_cs
goto io_error
@ -53,7 +53,7 @@ diskio {
io_error:
c64.CLRCHN() ; restore default i/o devices
c64.CLOSE(13)
c64.CLOSE(12)
if status and status & $40 == 0 { ; bit 6=end of file
txt.print("\ni/o error, status: ")
@ -69,12 +69,12 @@ io_error:
; -- Returns pointer to disk name string or 0 if failure.
c64.SETNAM(1, "$")
c64.SETLFS(13, drivenumber, 0)
c64.SETLFS(12, drivenumber, 0)
ubyte okay = false
void c64.OPEN() ; open 13,8,0,"$"
void c64.OPEN() ; open 12,8,0,"$"
if_cs
goto io_error
void c64.CHKIN(13) ; use #13 as input channel
void c64.CHKIN(12) ; use #12 as input channel
if_cs
goto io_error
@ -96,7 +96,7 @@ io_error:
io_error:
c64.CLRCHN() ; restore default i/o devices
c64.CLOSE(13)
c64.CLOSE(12)
if okay
return &list_filename
return 0
@ -109,6 +109,7 @@ io_error:
bool iteration_in_progress = false
ubyte @zp first_byte
bool have_first_byte
ubyte last_drivenumber = 8 ; which drive was last used for a f_open operation?
str list_filetype = "???" ; prg, seq, dir
str list_filename = "?" * 50
@ -249,7 +250,7 @@ close_end:
}
; ----- iterative file loader functions (uses io channel 11) -----
; ----- iterative file loader functions (uses io channel 12) -----
sub f_open(ubyte drivenumber, uword filenameptr) -> bool {
; -- open a file for iterative reading with f_read
@ -257,13 +258,14 @@ close_end:
f_close()
c64.SETNAM(string.length(filenameptr), filenameptr)
c64.SETLFS(11, drivenumber, 0)
void c64.OPEN() ; open 11,8,0,"filename"
c64.SETLFS(12, drivenumber, 12) ; note: has to be 12,x,12 because otherwise f_seek doesn't work
last_drivenumber = drivenumber
void c64.OPEN() ; open 12,8,12,"filename"
if_cc {
if c64.READST()==0 {
iteration_in_progress = true
have_first_byte = false
void c64.CHKIN(11) ; use #11 as input channel
void c64.CHKIN(12) ; use #12 as input channel
if_cc {
first_byte = c64.CHRIN() ; read first byte to test for file not found
if not c64.READST() {
@ -294,7 +296,7 @@ close_end:
num_bytes--
}
void c64.CHKIN(11) ; use #11 as input channel again
void c64.CHKIN(12) ; use #12 as input channel again
%asm {{
lda bufferpointer
@ -359,8 +361,8 @@ m_in_buffer sta $ffff
%asm {{
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldx #11
jsr c64.CHKIN ; use channel 11 again for input
ldx #12
jsr c64.CHKIN ; use channel 12 again for input
ldy #0
lda have_first_byte
beq _loop
@ -389,23 +391,23 @@ _end rts
; -- end an iterative file loading session (close channels).
if iteration_in_progress {
c64.CLRCHN()
c64.CLOSE(11)
c64.CLOSE(12)
iteration_in_progress = false
}
}
; ----- iterative file saver functions (uses io channel 14) -----
; ----- iterative file writing functions (uses io channel 13) -----
sub f_open_w(ubyte drivenumber, uword filenameptr) -> bool {
; -- 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"
c64.SETLFS(13, drivenumber, 1)
void c64.OPEN() ; open 13,8,1,"filename"
if_cc {
void c64.CHKOUT(14) ; use #14 as output channel
c64.CHKOUT(13) ; use #13 as output channel
return not c64.READST()
}
f_close_w()
@ -413,9 +415,9 @@ _end rts
}
sub f_write(uword bufferpointer, uword num_bytes) -> bool {
; -- write the given umber of bytes to the currently open file
; -- write the given number of bytes to the currently open file
if num_bytes!=0 {
void c64.CHKOUT(14) ; use #14 as output channel again
c64.CHKOUT(13) ; use #13 as output channel again
repeat num_bytes {
c64.CHROUT(@(bufferpointer))
bufferpointer++
@ -428,7 +430,7 @@ _end rts
sub f_close_w() {
; -- end an iterative file writing session (close channels).
c64.CLRCHN()
c64.CLOSE(14)
c64.CLOSE(13)
}

View File

@ -102,6 +102,7 @@ class TestCompilerOnExamplesCx16: FunSpec({
"cube3d",
"datetime",
"diskspeed",
"fileseek",
"highresbitmap",
"kefrenbars",
"keyboardhandler",

View File

@ -3,7 +3,11 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- get rid of diskio.have_first_byte. But detecting invalid filenames should still work.
- diskio.f_read doesn't signal end of file condition if the requested number of bytes==1 ?
- diskio.f_read doesn't work if used after seek with buffer too small?
- ir/vm: check weird asm chunks appearing in block?
- try to get the cx16 adpcm example to output audio
- attempt to fix the expression codegen bug with reused temp vars (github #89)
- AstIdentifiersChecker: can a subroutine really not have the same name as its enclosing block? 64tass problem?
- 6502 codegen: make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway)

85
examples/cx16/fileseek.p8 Normal file
View File

@ -0,0 +1,85 @@
; this program shows the use of the f_seek function to seek to a position in an opened file.
; (this only works on Commander X16 DOS. on sdcard, not on host filesystem.)
%import diskio
%import cx16diskio
%import textio
%zeropage basicsafe
%option no_sysinit
main {
str FILENAME = "seektestfile.bin"
sub start() {
txt.print("writing data file...\n")
uword total=0
diskio.delete(8, FILENAME)
if diskio.f_open_w(8, FILENAME) {
repeat 1000 {
str text = "hello world."
void diskio.f_write(text, string.length(text))
total += string.length(text)
}
diskio.f_close_w()
txt.print("written size=")
txt.print_uw(total)
txt.nl()
} else {
txt.print("error: ")
txt.print(diskio.status(8))
sys.exit(1)
}
read_last_bytes()
; txt.print("\nseeking to 11992 and writing a few bytes...\n")
; if diskio.f_open_w(8, FILENAME) {
; cx16diskio.f_seek_w(0,0,msb(11992),lsb(11992))
; txt.print(diskio.status(8))
; txt.nl()
; void diskio.f_write("123", 3)
; diskio.f_close_w()
; } else {
; txt.print("error: ")
; txt.print(diskio.status(8))
; sys.exit(1)
; }
;
; read_last_bytes()
}
sub read_last_bytes() {
; read the last 10 bytes of the 12000 bytes file
ubyte[256] buffer
uword total = 0
uword size
txt.print("\nseeking to 11990 and reading...\n")
if diskio.f_open(8, FILENAME) {
cx16diskio.f_seek(0, 11990)
do {
size = diskio.f_read(buffer, sizeof(buffer))
total += size
} until size==0
diskio.f_close()
txt.print("size read=")
txt.print_uw(total)
txt.nl()
buffer[lsb(total)] = 0
txt.print("buffer read=")
ubyte idx
for idx in 0 to lsb(total-1) {
txt.print_ubhex(buffer[idx], false)
txt.spc()
}
txt.spc()
txt.chrout('{')
txt.print(buffer)
txt.chrout('}')
txt.nl()
} else {
txt.print("error: ")
txt.print(diskio.status(8))
sys.exit(1)
}
}
}