The folks over at AtariAge are going wild over 32kb cartridges, thanks to the "FlashROM99", which is a RAM-based cartridge that loads ROMs up to 32kb from SD card. One of the members attempted to convert my old Super Space Acer game (http://harmlesslion.com/sofware/space), but failed as the utility they used wasn't able to deal with numerous requirements of the program, like a loader that it required, or data files it used.
I decided to go ahead and take a stab at it myself... I found that there was a lot involved:
-The main program was 22.4k
-The sprite data was 3.75k
-The end program was 5k
-The title picture was 12k
-And the runtime library was 1.75kb
This was not going to fit in 32k, obviously, so the first task was compression. Some time ago I extracted the compression code from my VGM compressor (http://harmlesslion.com/software/vgm) in order to see if it worked standalone (and it did, though nowhere near as well as zip. However, it's much faster). I did a quick test, and found it could compress everything down from 45k to 27k. That seemed good enough.
After packing the files, I laid out my intention for the cartridge:
Every bank has a header through to >6040
Bank0 - >6000
0040 boot, unpacker (1k)
0440 SSE.pack to >A000, >13FA bytes
14C0 SSD.pack to VDP >0800, >0F00 bytes
Bank1 - >6002
0040 ssa.pack to >A000, >1FFA bytes
14C0 acer_c.pack to VDP >2000, >1800 bytes
1840 demq.pack to >2000, >066C bytes
Bank2 - >6004
0040 ssb.pack to >BFFA, >1FFA bytes
Bank3 - >6006
0040 ssc.pack to >DFF4, >1BFA bytes
1330 acer_p.pack to VDP >0000, >1800 bytes
With the layout in place, I was able to create a quick script that would copy the files and pad as appropriate for the above structure. Then I wrote a quick set of functions to unpack each file into the correct place that it went.
The main catch, however, was dealing with the dynamically loaded files. I realized that all the loads ran through the runtime, a function called DSRLNK. I wrote a little replacement function that checked the calling address and then simply unpacked the appropriate data directly into memory, then returned. Since all but one of the files load at startup, it was pretty easy.
Getting the end loader was slightly trickier, but I just had to enable cheats, then enable overdrive on the emulator, and then get to the end of the game. ;)
* on entry, WP is >209A
* copy return address to our workspace
* now figure out who to call - there are 4 options
* R14 File Vector
* A830 - SSD 2702
* DA0E - SSE 2704
* A656 - ACER_C 2706
* A638 - ACER_P 2708
* back to caller, remember to increment R14
In order for the unpacker to be able to run while switching banks on the cartridge, it needs to load to RAM. So the cartridge header (which is on all banks to ensure any startup state is okay) starts by copying the unpacker to RAM, then branching to it. The unpacker then unpacks the main program and the runtime, and jumps to THAT. The main program then requests the title screen and the sprites, and these requests are redirected to the appropriate routines in the unpack code.
Works pretty well, overall! and now it's time for bed. ;)