From 7b6c742178f380a20790a54314c4f6e46a44325a Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 23 Nov 2022 23:20:24 +0100 Subject: [PATCH] fixed diskio.f_read() for small read sizes --- compiler/res/prog8lib/cx16/cx16diskio.p8 | 41 ++++++++------------ compiler/res/prog8lib/diskio.p8 | 31 ++++++--------- docs/source/todo.rst | 4 +- examples/cx16/fileseek.p8 | 49 +++++++++++++++--------- 4 files changed, 61 insertions(+), 64 deletions(-) diff --git a/compiler/res/prog8lib/cx16/cx16diskio.p8 b/compiler/res/prog8lib/cx16/cx16diskio.p8 index 1cb2a35b4..a9093b05d 100644 --- a/compiler/res/prog8lib/cx16/cx16diskio.p8 +++ b/compiler/res/prog8lib/cx16/cx16diskio.p8 @@ -96,7 +96,6 @@ internal_vload: 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 @@ -126,29 +125,23 @@ byte_read_loop: ; fallback if macptr() isn't supported on the device lda bufferpointer+1 sta m_in_buffer+2 }} - repeat num_bytes { + while num_bytes { + if c64.READST() { + diskio.f_close() + if c64.READST() & $40 ; eof? + return diskio.list_blocks ; number of bytes read + return 0 ; error. + } %asm {{ jsr c64.CHRIN - sta cx16.r5L m_in_buffer sta $ffff inc m_in_buffer+1 bne + inc m_in_buffer+2 -+ inc diskio.list_blocks - bne + - inc diskio.list_blocks+1 + }} - - if cx16.r5L==$0d { ; chance on I/o error status? - cx16.r5L = c64.READST() - if cx16.r5L & $40 { - diskio.f_close() ; end of file, close it - diskio.list_blocks-- ; don't count that last CHRIN read - } - if cx16.r5L - return diskio.list_blocks ; number of bytes read - } + diskio.list_blocks++ + num_bytes-- } return diskio.list_blocks ; number of bytes read } @@ -162,9 +155,9 @@ m_in_buffer sta $ffff uword total_read = 0 while not c64.READST() { - uword size = cx16diskio.f_read(bufferpointer, 256) - total_read += size - bufferpointer += size + cx16.r0 = cx16diskio.f_read(bufferpointer, 256) + total_read += cx16.r0 + bufferpointer += cx16.r0 } return total_read } @@ -228,11 +221,11 @@ m_in_buffer sta $ffff ; 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 +; cx16diskio.f_seek.command[1] = 13 ; f_open_w uses channel 13 +; cx16diskio.f_seek.command[2] = lsb(pos_loword) +; cx16diskio.f_seek.command[3] = msb(pos_loword) +; cx16diskio.f_seek.command[4] = lsb(pos_hiword) +; cx16diskio.f_seek.command[5] = msb(pos_hiword) ; goto cx16diskio.f_seek.send_command ; } } diff --git a/compiler/res/prog8lib/diskio.p8 b/compiler/res/prog8lib/diskio.p8 index 18643790f..65a26de4b 100644 --- a/compiler/res/prog8lib/diskio.p8 +++ b/compiler/res/prog8lib/diskio.p8 @@ -287,7 +287,6 @@ close_end: return 0 list_blocks = 0 ; we reuse this variable for the total number of bytes read - void c64.CHKIN(12) ; use #12 as input channel again %asm {{ lda bufferpointer @@ -295,29 +294,23 @@ close_end: lda bufferpointer+1 sta m_in_buffer+2 }} - repeat num_bytes { + while num_bytes { + if c64.READST() { + f_close() + if c64.READST() & $40 ; eof? + return list_blocks ; number of bytes read + return 0 ; error. + } %asm {{ jsr c64.CHRIN - sta cx16.r5L m_in_buffer sta $ffff inc m_in_buffer+1 bne + inc m_in_buffer+2 -+ inc list_blocks - bne + - inc list_blocks+1 + }} - - if cx16.r5L==$0d { ; chance on I/o error status? - cx16.r5L = c64.READST() - if cx16.r5L & $40 { - f_close() ; end of file, close it - list_blocks-- ; don't count that last CHRIN read - } - if cx16.r5L - return list_blocks ; number of bytes read - } + list_blocks++ + num_bytes-- } return list_blocks ; number of bytes read } @@ -329,9 +322,9 @@ m_in_buffer sta $ffff uword total_read = 0 while not c64.READST() { - uword size = f_read(bufferpointer, 256) - total_read += size - bufferpointer += size + cx16.r0 = f_read(bufferpointer, 256) + total_read += cx16.r0 + bufferpointer += cx16.r0 } return total_read } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index e71f82df1..26fd3468e 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,10 +3,10 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- 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 +- duplicate diskio for cx16 (get rid of cx16diskio, just copy diskio and tweak everything) +- get f_seek_w working like in the BASIC program - this needs the changes to diskio.f_open to use suffixes ,p,m - 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) diff --git a/examples/cx16/fileseek.p8 b/examples/cx16/fileseek.p8 index 8f0256c36..7cd99d2fc 100644 --- a/examples/cx16/fileseek.p8 +++ b/examples/cx16/fileseek.p8 @@ -8,15 +8,15 @@ %option no_sysinit main { - str FILENAME = "seektestfile.bin" + uword megabuffer = memory("megabuffer", 20000, 256) 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." + if diskio.f_open_w(8, "@:seektestfile.bin,p,m") { + repeat 100 { + str text = "hello world.\n" void diskio.f_write(text, string.length(text)) total += string.length(text) } @@ -32,11 +32,9 @@ main { 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() +; txt.print("\nseeking to 1292 and writing a few bytes...\n") +; if diskio.f_open_w(8, "seektestfile.bin,p,m") { +; cx16diskio.f_seek_w(0, 1292) ; void diskio.f_write("123", 3) ; diskio.f_close_w() ; } else { @@ -49,31 +47,44 @@ main { } sub read_last_bytes() { - ; read the last 10 bytes of the 12000 bytes file - ubyte[256] buffer + ; read the last 10 bytes of the 1300 bytes file uword total = 0 uword size - txt.print("\nseeking to 11990 and reading...\n") - if diskio.f_open(8, FILENAME) { - cx16diskio.f_seek(0, 11990) + txt.print("\nreading...\n") + if diskio.f_open(8, "seektestfile.bin,p,r") { + size = diskio.f_read_all(megabuffer) + diskio.f_close() + txt.print("size read:") + txt.print_uw(size) + txt.nl() + } else { + txt.print("error!\n") + sys.exit(1) + } + + txt.print("\nseeking to 1290 and reading...\n") + if diskio.f_open(8, "seektestfile.bin,p,r") { + cx16diskio.f_seek(0, 1290) + uword ptr = megabuffer do { - size = diskio.f_read(buffer, sizeof(buffer)) + size = diskio.f_read(ptr, 255) total += size + ptr += size } until size==0 diskio.f_close() txt.print("size read=") txt.print_uw(total) txt.nl() - buffer[lsb(total)] = 0 + megabuffer[lsb(total)] = 0 txt.print("buffer read=") ubyte idx for idx in 0 to lsb(total-1) { - txt.print_ubhex(buffer[idx], false) + txt.print_ubhex(megabuffer[idx], false) txt.spc() } txt.spc() txt.chrout('{') - txt.print(buffer) + txt.print(megabuffer) txt.chrout('}') txt.nl() } else {