the returnvalue of the diskio.load() function family now is just the last load address+1 (like kernal's LOAD routine).

This fixes the inconsistent attempt to calculate a size, just let the caller do this if required.
Added a small helper function in cx16diskio to do this for loads that span multiple banks.
This commit is contained in:
Irmen de Jong 2021-12-14 23:54:42 +01:00
parent b21f7411dd
commit 890327b381
4 changed files with 79 additions and 37 deletions

View File

@ -11,28 +11,27 @@ cx16diskio {
; 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 number of bytes loaded (truncated to 16 bits, if the file is larger than 64 Kb,
; you'll have to compensate yourself by checking the ram banks).
; 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)
uword size = diskio.load(drivenumber, filenameptr, address_override)
if size
return size + $2000 * (cx16.getrambank() - bank)
return 0
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.
; This is different from Basic's LOAD instruction which always skips the first two bytes.
; The load address is mandatory. Returns the number of bytes loaded.
; Returns the number of bytes loaded (truncated to 16 bits, if the file is larger than 64 Kb,
; you'll have to compensate yourself by checking the ram banks).
; 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)
uword size = diskio.load_raw(drivenumber, filenameptr, address)
if size
return size + $2000 * (cx16.getrambank() - bank)
return 0
return diskio.load_raw(drivenumber, filenameptr, address)
}
; 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
}
}

View File

@ -438,9 +438,7 @@ io_error:
; 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 number of bytes loaded if address_override was given, otherwise the end address.
; TODO this is stupid - why not always return the number of bytes loaded and let the caller figure out the rest
;
; 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.
@ -448,7 +446,7 @@ io_error:
sub load(ubyte drivenumber, uword filenameptr, uword address_override) -> uword {
c64.SETNAM(string.length(filenameptr), filenameptr)
ubyte secondary = 1
uword end_of_load = 0
cx16.r1 = 0
if address_override
secondary = 0
c64.SETLFS(1, drivenumber, secondary)
@ -459,24 +457,21 @@ io_error:
ldy address_override+1
jsr c64.LOAD
bcs +
stx end_of_load
sty end_of_load+1
stx cx16.r1
sty cx16.r1+1
+ ldx P8ZP_SCRATCH_REG
}}
c64.CLRCHN()
c64.CLOSE(1)
if end_of_load
return end_of_load - address_override ; not correct when the file spans multiple RAM banks
return 0
return cx16.r1
}
; 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 number of bytes loaded.
; 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.
@ -484,15 +479,12 @@ io_error:
sub load_raw(ubyte drivenumber, uword filenameptr, uword address) -> uword {
if not f_open(drivenumber, filenameptr)
return 0
uword size = f_read(address, 2)
cx16.r1 = f_read(address, 2)
f_close()
if size!=2
if cx16.r1!=2
return 0
address += 2
size = load(drivenumber, filenameptr, address)
if size
return size+2
return 0
return load(drivenumber, filenameptr, address)
}
sub delete(ubyte drivenumber, uword filenameptr) {

View File

@ -3,8 +3,6 @@ TODO
For next compiler release (7.6)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fix return value of diskio.load() (see commment) and possibly other routines?
optimization in call convention:
non-asm subroutines with just a single byte or word parameter:
pass the parameter via A or A/Y registers.

View File

@ -1,12 +1,65 @@
%import diskio
%import cx16diskio
%import textio
%zeropage basicsafe
main {
sub start() {
str derp = "derp" * 4
derp = derp / "zzz"
derp = derp - "zzz"
derp = derp + "zzz"
txt.print(&derp+2)
uword xx
uword yy
c64.SETMSG(%10000000)
xx = diskio.load(8, "hello", 0)
txt.nl()
yy = diskio.load(8, "hello", $8800)
txt.nl()
c64.SETMSG(0)
txt.print_uwhex(xx, true)
txt.nl()
txt.print_uwhex(yy, true)
txt.nl()
c64.SETMSG(%10000000)
xx = diskio.load_raw(8, "hello", $8700)
txt.nl()
c64.SETMSG(0)
txt.print_uwhex(xx, true)
txt.nl()
txt.print("\ncx16:\n")
c64.SETMSG(%10000000)
yy = cx16diskio.load(8, "x16edit", 1, $3000)
txt.nl()
c64.SETMSG(0)
txt.print_uwhex(yy, true)
txt.nl()
c64.SETMSG(%10000000)
xx = cx16diskio.load_raw(8, "x16edit", 1, $3000)
txt.nl()
c64.SETMSG(0)
txt.print_uwhex(xx, true)
txt.nl()
txt.print_uw(cx16diskio.load_size(1, $3000, xx))
txt.nl()
c64.SETMSG(%10000000)
xx = cx16diskio.load(8, "x16edit", 4, $a100)
txt.nl()
c64.SETMSG(0)
txt.print_uwhex(xx, true)
txt.nl()
txt.print_uw(cx16diskio.load_size(4, $a100, xx))
txt.nl()
c64.SETMSG(%10000000)
xx = cx16diskio.load_raw(8, "x16edit", 4, $a100)
txt.nl()
c64.SETMSG(0)
txt.print_uwhex(xx, true)
txt.nl()
txt.print_uw(cx16diskio.load_size(4, $a100, xx))
txt.nl()
}
}