CX16: diskio.f_write() now uses fast MCIOUT block writes, including hiram bank boundary wrap-over

This commit is contained in:
Irmen de Jong 2023-11-07 23:39:39 +01:00
parent ff324955dd
commit c5a333a904
3 changed files with 53 additions and 79 deletions

View File

@ -312,13 +312,12 @@ close_end:
reset_read_channel() reset_read_channel()
list_blocks = 0 ; we reuse this variable for the total number of bytes read list_blocks = 0 ; we reuse this variable for the total number of bytes read
; commander X16 supports fast block-read via MACPTR() kernal call
uword readsize uword readsize
while num_bytes { while num_bytes {
readsize = 255 readsize = 255
if num_bytes<readsize if num_bytes<readsize
readsize = num_bytes readsize = num_bytes
readsize = cx16.MACPTR(lsb(readsize), bufferpointer, false) readsize = cx16.MACPTR(lsb(readsize), bufferpointer, false) ; fast block reads
if_cs if_cs
goto byte_read_loop ; MACPTR block read not supported, do fallback loop goto byte_read_loop ; MACPTR block read not supported, do fallback loop
list_blocks += readsize list_blocks += readsize
@ -433,6 +432,21 @@ _end rts
; -- write the given number of bytes to the currently open file ; -- write the given number of bytes to the currently open file
if num_bytes!=0 { if num_bytes!=0 {
reset_write_channel() reset_write_channel()
do {
cx16.r0 = cx16.MCIOUT(lsb(num_bytes), bufferpointer, false) ; fast block writes
if_cs
goto no_mciout
num_bytes -= cx16.r0
bufferpointer += cx16.r0
if msb(bufferpointer) == $c0
bufferpointer = mkword($a0, lsb(bufferpointer)) ; wrap over bank boundary
if cbm.READST()!=0
return false
} until num_bytes==0
return not cbm.READST()
no_mciout:
; the device doesn't support MCIOUT, use a normal per-byte write loop
repeat num_bytes { repeat num_bytes {
cbm.CHROUT(@(bufferpointer)) cbm.CHROUT(@(bufferpointer))
bufferpointer++ bufferpointer++

View File

@ -21,7 +21,7 @@ while still being low level enough to create high performance programs.
You can compile programs for various machines with this CPU: You can compile programs for various machines with this CPU:
* Commodore 64 * Commodore 64
* Commander X16 (release R42 or newer is required) * Commander X16
* Commodore 128 (limited support for now) * Commodore 128 (limited support for now)
* Atari 800 XL (limited support for now) * Atari 800 XL (limited support for now)
@ -181,7 +181,7 @@ For MacOS you can use the Homebrew system to install a recent version of OpenJDK
Finally: an **emulator** (or a real machine of course) to test and run your programs on. Finally: an **emulator** (or a real machine of course) to test and run your programs on.
In C64 mode, the compiler assumes the presence of the `VICE emulator <http://vice-emu.sourceforge.net/>`_. In C64 mode, the compiler assumes the presence of the `VICE emulator <http://vice-emu.sourceforge.net/>`_.
If you're targeting the Commander X16 instead, If you're targeting the Commander X16 instead,
download a recent emulator version (R42 or newer) for the CommanderX16, such as `x16emu <https://cx16forum.com/forum/viewforum.php?f=30>`_ download a recent emulator version for the CommanderX16, such as `x16emu <https://cx16forum.com/forum/viewforum.php?f=30>`_
(preferred, this is the official emulator. If required, source code is `here <https://github.com/X16Community/x16-emulator/>`_. (preferred, this is the official emulator. If required, source code is `here <https://github.com/X16Community/x16-emulator/>`_.
There is also `Box16 <https://github.com/indigodarkwolf/box16>`_ which has powerful debugging features. There is also `Box16 <https://github.com/indigodarkwolf/box16>`_ which has powerful debugging features.
You can select which one you want to launch using the ``-emu`` or ``-emu2`` command line options. You can select which one you want to launch using the ``-emu`` or ``-emu2`` command line options.

View File

@ -6,14 +6,13 @@
main { main {
ubyte[256] buffer = 0 to 255 ubyte[256] buffer = 0 to 255
const ubyte REPEATS = 2
sub print_speed(uword jiffies) { sub print_speed(uword jiffies) {
if jiffies==0 { if jiffies==0 {
txt.print("\n 0 jiffies measured, speed is extremely high\n") txt.print("\n 0 jiffies measured, speed is extremely high\n")
return return
} }
float speed = 65536.0 * REPEATS / (jiffies as float / 60.0) float speed = floats.floor(65536.0 / (jiffies as float / 60.0))
txt.nl() txt.nl()
txt.print_uw(jiffies) txt.print_uw(jiffies)
txt.print(" jiffies = ") txt.print(" jiffies = ")
@ -22,95 +21,56 @@ main {
} }
sub start() { sub start() {
txt.print("\n\ndisk benchmark. drive 8. repeats = ") txt.print("\n\ndisk benchmark on drive 8.\n\n")
txt.print_ub(REPEATS)
uword batchtotaltime uword batchtotaltime
txt.print("\n\nwriting 64kb using save") txt.print("writing 64kb using save()")
batchtotaltime = 0 cbm.SETTIM(0,0,0)
repeat REPEATS { ; save 2 times 32Kb to make it 64Kb total
cbm.SETTIM(0,0,0) void diskio.save("@:benchmark.dat", $100, 32768)
void diskio.save("@:benchmark.dat", $100, 32768) void diskio.save("@:benchmark.dat", $100, 32768)
void diskio.save("@:benchmark.dat", $100, 32768) print_speed(cbm.RDTIM16())
batchtotaltime += cbm.RDTIM16()
txt.chrout('.')
}
print_speed(batchtotaltime)
txt.print("\nwriting 64kb sequentially") txt.print("\nwriting 64kb sequentially")
batchtotaltime = 0 if diskio.f_open_w("@:benchmark.dat") {
repeat REPEATS { cbm.SETTIM(0,0,0)
if diskio.f_open_w("@:benchmark.dat") { repeat 65536/256 {
cbm.SETTIM(0,0,0) if not diskio.f_write(buffer, 256)
repeat 65536/256 { sys.exit(1)
if not diskio.f_write(buffer, 256)
sys.exit(1)
}
batchtotaltime += cbm.RDTIM16()
diskio.f_close_w()
} }
txt.chrout('.') diskio.f_close_w()
print_speed(cbm.RDTIM16())
} }
print_speed(batchtotaltime)
txt.print("\nreading 64kb using load into hiram") txt.print("\nreading 64kb using load() into hiram")
batchtotaltime = 0 cbm.SETTIM(0,0,0)
repeat REPEATS { cx16.rambank(4)
cbm.SETTIM(0,0,0) if not diskio.load("benchmark.dat", $a000)
cx16.rambank(4) sys.exit(1)
if not diskio.load("benchmark.dat", $a000) print_speed(cbm.RDTIM16())
sys.exit(1)
batchtotaltime += cbm.RDTIM16()
txt.chrout('.')
}
print_speed(batchtotaltime)
txt.print("\nreading 64kb using vload into videoram") txt.print("\nreading 64kb using vload() into vram")
batchtotaltime = 0 cbm.SETTIM(0,0,0)
repeat REPEATS { if not diskio.vload("benchmark.dat", 0, $0000)
cbm.SETTIM(0,0,0) sys.exit(1)
if not diskio.vload("benchmark.dat", 0, $0000) print_speed(cbm.RDTIM16())
sys.exit(1)
batchtotaltime += cbm.RDTIM16()
txt.chrout('.')
}
print_speed(batchtotaltime)
txt.print("\nreading 64kb sequentially") txt.print("\nreading 64kb sequentially")
batchtotaltime = 0 if diskio.f_open("benchmark.dat") {
repeat REPEATS { cbm.SETTIM(0,0,0)
if diskio.f_open("benchmark.dat") { repeat 65536/255 {
cbm.SETTIM(0,0,0) if not diskio.f_read(buffer, 255)
repeat 65536/255 { sys.exit(1)
if not diskio.f_read(buffer, 255)
sys.exit(1)
}
batchtotaltime += cbm.RDTIM16()
diskio.f_close()
} }
txt.chrout('.') diskio.f_close()
print_speed(cbm.RDTIM16())
} }
print_speed(batchtotaltime)
txt.print("\nreading 64kb sequentially (x16 optimized)")
batchtotaltime = 0
repeat REPEATS {
if diskio.f_open("benchmark.dat") {
cbm.SETTIM(0,0,0)
repeat 65536/255 {
if not diskio.f_read(buffer, 255)
sys.exit(1)
}
batchtotaltime += cbm.RDTIM16()
diskio.f_close()
}
txt.chrout('.')
}
print_speed(batchtotaltime)
txt.nl() txt.nl()
txt.print(diskio.status()) txt.print(diskio.status())
txt.print("\ndone.\n") txt.print("\ndone.\n")
diskio.delete("benchmark.dat")
} }
} }