Wrote a quick tool, which takes an Outrun CPU 0 memory dump from the MAME debugger as input. As output it prints the jump table from that stage of the game that has been built and stored in RAM.
This is handy, because it formats the data and only shows the addresses which are currently enabled, and doesn't repeat addresses when they're called in succession. The table in RAM itself is 124 entries long, and updated at various points during runtime.
So here's the in-game output:
0. 0xB15E
1. 0x74E2
2. 0x3BEE
3. 0x4048 (16 times)
21. 0x4828 (15 times)
82. 0x4ADC
83. 0x5248 (5 times)
91. 0x9862
92. 0x9C84
93. 0xA568 (2 times)
95. 0x5EA8
103. 0xA816
104. 0xA7D2
105. 0xA816
106. 0xC5A4
123. 0x78B0
124. 0xE644This has made it easier to figure out exactly where in code the program is updating this table.
What else? I've been looking into the tile handling code. Tilemaps are used in OutRun for the horizon graphics (two layers) , the text layer is a tilemap and obvious things like the music selection screen are a tilemap. Each tile entry in the map is a word. The compression format for the first tilemap I've analysed in ROM is as follows:
1/ If a word
is not '0x0000', copy immediate word directly to tileram
2/ If a word
is '0x0000' a long follows which details the compression.
The upper word of the long is the tilemap value to copy.
The lower word of the long is the number of times to copy that value.
And here's how OutRun manages to store your exact route history through the levels in just a byte.
1/ There are 5 stages, and a memory location increases by 0x10 for each stage you progress.
2/ Each stage forks twice, giving 15 stages in total. At each stage, this same memory location increments as follows when the
left hand route is selected:
Stage 1 = +8 (1 << 3 - 0)
Stage 2 = +4 (1 << 3 - 1)
Stage 3 = +2 (1 << 3 - 2)
Stage 4 = +1 (1 << 3 - 3)
Stage 5 = Road doesn't split on this stage
3/ Later this indexes into a lookup table, which then makes it easy to update things like the stage map at the bottom right hand corner of the screen during gameplay.
Other than that, I'm thinking about how to represent the graphics once I convert the engine to C. Do I keep them in a similar format, and just render a final array of pixel data (similar to how an emulator would render it's display), or do I convert them to a native PNG or similar? This would make it easier for someone to replace them and change the game, but could run into problems with palette changes and so forth. Thoughts...
Anyway, this post might give you some idea of some of the things I'm doing at the moment. There's still a long way to go.