added bonkram chunk to chunkfile example

This commit is contained in:
Irmen de Jong
2023-09-25 22:14:03 +02:00
parent 390263a34e
commit 5268b05060
5 changed files with 92 additions and 32 deletions

View File

@@ -1,6 +1,7 @@
TODO TODO
==== ====
- add a compiler switch to replace all calls to the math word mul routine on the X16 by the verafx call instead.
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 .... - [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
- [on branch: ir-less-branch-opcodes] IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction - [on branch: ir-less-branch-opcodes] IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction
- IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? etc), but only after setting the status bits is verified! - IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? etc), but only after setting the status bits is verified!

View File

@@ -3,14 +3,17 @@ from typing import Sequence
# Chunk types: # Chunk types:
# user types: 0 - 239 # user types: 0 - 239
# reserved: 240 - 249 # reserved: 240 - 248
CHUNK_DUMMY = 250 CHUNK_DUMMY = 249
CHUNK_BONKRAM = 250
CHUNK_SYSTEMRAM = 251 CHUNK_SYSTEMRAM = 251
CHUNK_VIDEORAM = 252 CHUNK_VIDEORAM = 252
CHUNK_PAUSE = 253 CHUNK_PAUSE = 253
CHUNK_EOF = 254 CHUNK_EOF = 254
CHUNK_IGNORE = 255 CHUNK_IGNORE = 255
ChunksWithData = {CHUNK_DUMMY, CHUNK_SYSTEMRAM, CHUNK_VIDEORAM, CHUNK_BONKRAM}
class LoadList: class LoadList:
def __init__(self): def __init__(self):
@@ -26,8 +29,8 @@ class LoadList:
raise ValueError("chunktype must be 0 - 255") raise ValueError("chunktype must be 0 - 255")
if size < 0 or size > 65535: if size < 0 or size > 65535:
raise ValueError(f"size must be 0 - 65535 bytes") raise ValueError(f"size must be 0 - 65535 bytes")
if bank < 0 or bank > 31: if bank < 0 or bank > 255:
raise ValueError("bank must be 0 - 31") raise ValueError("bank must be 0 - 255")
if address < 0 or address > 65535: if address < 0 or address > 65535:
raise ValueError("address must be 0 - 65535") raise ValueError("address must be 0 - 65535")
data = struct.pack("<BHBH", chunktype, size, bank, address) data = struct.pack("<BHBH", chunktype, size, bank, address)
@@ -88,7 +91,7 @@ class MultiChunkFile:
for chunk in loadlist.parse(): for chunk in loadlist.parse():
if chunk[0] == CHUNK_EOF: if chunk[0] == CHUNK_EOF:
break break
elif chunk[0] in (CHUNK_DUMMY, CHUNK_SYSTEMRAM, CHUNK_VIDEORAM) or chunk[0] < 240: elif chunk[0] in ChunksWithData or chunk[0] < 240:
data = inf.read(chunk[1]) data = inf.read(chunk[1])
self.chunks.append(data) self.chunks.append(data)
num_data += 1 num_data += 1
@@ -141,7 +144,7 @@ class MultiChunkFile:
if lc[0] == CHUNK_EOF: if lc[0] == CHUNK_EOF:
eof_found = True eof_found = True
break break
elif lc[0] in (CHUNK_DUMMY, CHUNK_SYSTEMRAM, CHUNK_VIDEORAM) or lc[0] < 240: elif lc[0] in ChunksWithData or lc[0] < 240:
size, bank, address = lc[1:] size, bank, address = lc[1:]
data = next(chunk_iter) data = next(chunk_iter)
if isinstance(data, bytes): if isinstance(data, bytes):
@@ -164,6 +167,8 @@ class MultiChunkFile:
def add_SystemRam(self, bank: int, address: int, data: bytes, chunksize: int = 0xfe00) -> None: def add_SystemRam(self, bank: int, address: int, data: bytes, chunksize: int = 0xfe00) -> None:
if address >= 0xa000 and address < 0xc000: if address >= 0xa000 and address < 0xc000:
raise ValueError("use add_BankedRam instead to load chunks into banked ram $a000-$c000") raise ValueError("use add_BankedRam instead to load chunks into banked ram $a000-$c000")
if bank < 0 or bank > 31:
raise ValueError("bank must be 0 - 31")
while data: while data:
if address >= 65536: if address >= 65536:
raise ValueError("data too large for system ram") raise ValueError("data too large for system ram")
@@ -175,10 +180,10 @@ class MultiChunkFile:
if address < 0xa000 or address >= 0xc000: if address < 0xa000 or address >= 0xc000:
raise ValueError("use add_SystemRam instead to load chunks into normal system ram") raise ValueError("use add_SystemRam instead to load chunks into normal system ram")
if chunksize > 0x2000: if chunksize > 0x2000:
raise ValueError("chunksize too large for banked ram") raise ValueError("chunksize too large for banked ram, max 8K")
while data: while data:
if address >= 0xc000: if address >= 0xc000:
address -= 0xc000 address -= 0x2000
bank += 1 bank += 1
if bank >= 32: if bank >= 32:
raise ValueError("data too large for banked ram") raise ValueError("data too large for banked ram")
@@ -186,6 +191,23 @@ class MultiChunkFile:
data = data[chunksize:] data = data[chunksize:]
address += chunksize address += chunksize
def add_BonkRam(self, bonk: int, address: int, data: bytes, chunksize: int = 0x4000) -> None:
if bonk < 32 or bonk > 255:
raise ValueError("bank for bonk ram (cartridge ram) must be 32 - 255")
if chunksize > 0x4000:
raise ValueError("chunksize too large for bonk ram (cartridge ram), max 16K")
if address < 0xc000 or address > 0xffff:
raise ValueError("use add_SystemRam instead to load chunks into normal system ram")
while data:
if address > 0xffff:
address -= 0x4000
bonk += 1
if bonk > 255:
raise ValueError("data too large for bonk ram (cartridge ram)")
self.add_chunk(CHUNK_BONKRAM, bonk, address, data[:chunksize])
data = data[chunksize:]
address += chunksize
def add_VideoRam(self, bank: int, address: int, data: bytes, chunksize: int = 0xfe00) -> None: def add_VideoRam(self, bank: int, address: int, data: bytes, chunksize: int = 0xfe00) -> None:
if bank < 0 or bank > 1: if bank < 0 or bank > 1:
raise ValueError("bank for videoram must be 0 or 1") raise ValueError("bank for videoram must be 0 or 1")
@@ -268,6 +290,7 @@ The four files are the two ME- and the two DS- TITLESCREEN.BIN and .PAL files, a
mcf.add_VideoRam(1, 0xfa00, palette2) mcf.add_VideoRam(1, 0xfa00, palette2)
mcf.add_VideoRam(0, 0, bitmap2) mcf.add_VideoRam(0, 0, bitmap2)
mcf.add_Pause(222) mcf.add_Pause(222)
mcf.add_BonkRam(32, 0xc000, bytearray(32768))
mcf.add_Pause(111) mcf.add_Pause(111)
mcf.add_EOF() mcf.add_EOF()
mcf.write("demo.mcf") mcf.write("demo.mcf")

View File

@@ -7,11 +7,14 @@ main {
sub start() { sub start() {
uword duration uword duration
ubyte[256] bonkbuffer
set_screen_mode() set_screen_mode()
cbm.SETTIM(0,0,0) cbm.SETTIM(0,0,0)
mcf.set_callbacks(mcf_get_buffer, mcf_process_chunk) ; not needed if the stream has no custom chunk types mcf.set_callbacks(mcf_get_buffer, mcf_process_chunk) ; not needed if the stream has no custom chunk types
mcf.set_bonkbuffer(bonkbuffer)
if mcf.open("demo.mcf", 8, 2) { if mcf.open("demo.mcf", 8, 2) {
repeat { repeat {
mcf.stream() mcf.stream()

View File

@@ -3,14 +3,16 @@
; Streaming routine for MCF files (multipurpose chunk format): ; Streaming routine for MCF files (multipurpose chunk format):
; 1. call open() ; 1. call open()
; 2. set callbacks if needed, set_callbacks() ; 2. set callbacks if needed; set_callbacks()
; 3. call stream() in a loop ; 3. set bonk ram (cartridge ram) load buffer, if needed; set_bonkbuffer()
; 4. call close() if you want to cleanup halfway through for some reason ; 4. call stream() in a loop
; 5. call close() if you want to cleanup halfway through for some reason
mcf { mcf {
uword loadlist_buf = memory("loadlist", 256, 0) uword loadlist_buf = memory("loadlist", 256, 0)
uword @zp loadlist_ptr uword @zp loadlist_ptr
uword bonkbuffer
bool needs_loadlist bool needs_loadlist
ubyte file_channel ubyte file_channel
@@ -49,6 +51,11 @@ mcf {
}} }}
} }
sub set_bonkbuffer(uword buffer) {
; needs to be a buffer of 256 bytes (1 page)
bonkbuffer = buffer
}
sub stream() { sub stream() {
repeat { repeat {
if needs_loadlist { if needs_loadlist {
@@ -89,6 +96,15 @@ mcf {
loadlist_ptr+=6 loadlist_ptr+=6
} }
250 -> { 250 -> {
; bonk ram (cartridge ram)
; This cannot use MACPTR (because the kernal rom isn't banked in)
; so we have to load it into a buffer and copy it manually.
; Because this will be rarely used, the buffer is not allocated here to save memory, and instead
; the user has to set it with the config routine when the program wants to use this chunk type.
blockload_bonkram(peekw(loadlist_ptr+1), peek(loadlist_ptr+3), peekw(loadlist_ptr+4))
loadlist_ptr+=6
}
249 -> {
; dummy chunk ; dummy chunk
blockload_dummy(peekw(loadlist_ptr+1)) blockload_dummy(peekw(loadlist_ptr+1))
loadlist_ptr+=6 loadlist_ptr+=6
@@ -158,6 +174,22 @@ processchunk_call jsr $ffff ; modified
cx16.rambank(orig_ram_bank) cx16.rambank(orig_ram_bank)
} }
sub blockload_bonkram(uword size, ubyte bonk, uword address) {
ubyte orig_rom_bank = cx16.getrombank()
cx16.r3 = address
while size {
ubyte readsize = 255
if size < 255
readsize = lsb(size)
cx16.r2 = cx16.macptr(readsize, bonkbuffer, false) ; can't macptr directly to bonk ram
cx16.rombank(bonk)
sys.memcopy(bonkbuffer, cx16.r3, cx16.r2) ; copy to bonk ram
cx16.rombank(orig_rom_bank)
size -= cx16.r2
cx16.r3 += cx16.r2
}
}
sub readblock(uword size, uword address, bool dontAdvance) -> uword { sub readblock(uword size, uword address, bool dontAdvance) -> uword {
if msb(size)>=2 if msb(size)>=2
return cx16.macptr(0, address, dontAdvance) ; read 512 bytes return cx16.macptr(0, address, dontAdvance) ; read 512 bytes

View File

@@ -64,10 +64,11 @@ If there are more chunks in the file than fit in a single loadlist, we simply ad
### Chunk types ### Chunk types
| chunk type | meaning | | chunk type | meaning |
|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 0 - 239 | custom chunk types. See below. | | 0 - 239 | custom chunk types. See below. |
| 240 - 249 | reserved for future system chunk types. | | 240 - 248 | reserved for future system chunk types. |
| 250 | dummy chunk: read a chunk of the specified number of bytes but don't do anything with it. Useful to realign the file I/O on disk block size. | | 249 | dummy chunk: read a chunk of the specified number of bytes but don't do anything with it. Useful to realign the file I/O on disk block size. |
| 250 | bonk ram load: use banknumber + address to set the Cartridge RAM ('bonk' RAM) bank and load address and loads the chunk there, then continue streaming. Note this is slower than other types of ram. Rquires 1 page of user chosen buffer area. |
| 251 | system ram load: use banknumber + address to set the RAM bank and load address and loads the chunk there, then continue streaming. | | 251 | system ram load: use banknumber + address to set the RAM bank and load address and loads the chunk there, then continue streaming. |
| 252 | video ram load: use banknumber + address to set the Vera VRAM bank (hi byte) and load address (mid+lo byte) and loads the chunk into video ram there, then continue streaming. | | 252 | video ram load: use banknumber + address to set the Vera VRAM bank (hi byte) and load address (mid+lo byte) and loads the chunk into video ram there, then continue streaming. |
| 253 | pause streaming. Returns from stream routine with pause status: Carry=clear. And reg.r0=size. until perhaps the program calls the stream routine again to resume. | | 253 | pause streaming. Returns from stream routine with pause status: Carry=clear. And reg.r0=size. until perhaps the program calls the stream routine again to resume. |