How about storing a jmp address into two registers? So whenever a bank is switched, the code does e.g. JMP (0033). Unless both bytes are 0. And maybe something similar for JSR. This would make banking a bit easier too.
Unfortunately, we can only write to those registers. Once we read, the TIA will respond and drive the bus. We could still go for some DPC+ like features and introduce data / jump streams if we like, though, but I would like to keep this out of scope for now.
Don't forget about the mirrors. Legacy bank schemes avoided differentiating mirrors because of pin counts and complexity. You already have the full address bus, so why not leverage it.
Something I had proposed a while back was to use different mirrors for different page sizes. I.E. Storing $05 to $003e would activate the 5th 4KB page. Storing $05 to $013e would activate the 5th 2KB page at $f000-$f7ff. Storing $05 to $023e would activate the 5th 2KB page at $f800-$ffff.
That's pretty clever. Making use of the available mirrors, we could easily support fully configurable slots from 4k down to 256 bytes (at the price of losing one cycle for the non-zeropage access). What about the following: We divide the 4k into 16 256 byte chunks that can be switched either individually or combined as larger chunks. In order to switch banks, we use the TIA mirrors starting from $012d. For each slot size, we use a single set of TIA mirrors, i.e. $012d -- $01ef for 4k, $022d -- $023f for 2k, and so on. We use $2f to switch the individual slot modes (bit 0-3 = slot number, bit 4-6 = mode), and use the registers starting from $30 to change the banks for the individual slots. Each slot has a register for the low byte and one register for the high byte, and actual banking is triggered by writes to the low byte (not high bytes or $2f). Altogether, we'd have:
- $012f: Change 4k slot mode; bit 4-6 = mode: ROM, RAM r/w, RAM r/o, RAM w/o
- $0130 -- $0131: 4k bank lo / 4k bank hi
- $022f: Change 2k slot mode: bit 0-3 = slot 0-1, bit 4-6 = mode
- $0230 -- $0231: 2k slot 0 bank lo / hi
- $0232 -- $0233: 2k slot 1 bank lo / hi
- $032f: Change 1k slot mode: bit 0-3 = slot 0-3, bit 4-6 = mode
- $0330 -- $0337: 1k slot 0-3 bank lo / hi
- $042f: Change 512b slot mode: bit 0-3 = slot 0-7, bit 4-6 = mode
- $0430 -- $043f: 512b slot 0-7 bank lo / hi
- $052f: Change 256b slot mode: bit 0-3 = slot 0-15, bit 4-6 = mode
- $0530 -- $053f: 256b slot 0-7 bank lo / hi
- $0630 -- $063f: 256b slot 8-15 bank lo / hi
Hi bytes and slot modes are "sticky", so after the slots have been configured, switching could usually be done simply by writing the low byte for the corresponding slot. The other functionality we discussed could be placed like such:
- $012d: store banking configuration to slot (up to 256 possible slots, provided there is enough RAM)
- $012e: load banking configuration from slot
- $022d: load a chunk from the extended image using the relocation descriptor at the specified 16 byte offset in cartridge address space (0 - 4k)
The image would have a small header that declares the amount of RAM, ROM and the number of config slots that are required (so the cartridge can check whether it can support the image and partition its memory accordingly). The initial ROM image is read from the beginning of the image, and chunk loads can be used to swap other parts of the image either into RAM or ROM. Chunk loading from SD is slow and needs to be async, so the code has to be run from RIOT RAM. After writing $022d, the cartridge goes offline, and the code in RIOT RAM has to poll until the cartridge comes back online. The descriptors are simple date structures that define which block of the image should be loaded where into either RAM or ROM.
As an example, the following code would switch to a plain 4k ROM image with 128 byte SARA-style RAM at $f000:
A lot of those writes are just for illustration and could be left out if we define the initial state as 1. all hi bytes zero and 2. all slots in ROM mode. In order to switch to another 4k bank, we'd simply write to $0130 (this would override the RAM bank, however), and if we wanted to switch in the fourth 2k ROM bank at $f800, we'd use
(assuming the initial state is as described above and the configuration hasn't been changed since).
What do you think?
Edited by DirtyHairy, Tue May 29, 2018 5:53 PM.