The C RAM Review
Coming right at you
While it's far from finished, my work on Stella has progressed to the point where I can now view the state of DPC+'s 5K of internal RAM. The 5K is comprised of 4K Display Data and 1K Frequency Data. When custom C code is used the 1K Frequency Data is by default split in half so that 512 bytes are used for Frequency while the other 512 are used for the C variable storage pool and stack. This division of RAM can be changed - Stay Frosty 2 only used 24 bytes for Frequency Data, leaving 1000 bytes for C usage.
In this screenshot you can see the contents of Display Data (the grid in the lower-right), the first two rows of hex values are the graphics for the score digits 0-3.
These two show the state of the C variable storage pool and stack when the game has initially been loaded, but never played:
Initial State of C RAM
By looking at custom2.map, one of the files generated when compiling the C code, I can find were in RAM the global C variables have been assigned:
0x40001e00 0x74 main.o0x40001e00 gMenuOptionsDatastream0x40001e0c gRoomLayout0x40001e10 gRoomLayoutAlt0x40001e14 gAccentColors0x40001e18 gMainColors0x40001e1c gEyeColors0x40001e20 gSpriteImageID0x40001e24 gSpriteY0x40001e28 gImageHeight0x40001e2c gEventDataStream0x40001e30 gImageGraphics0x40001e34 gImageColor0x40001e38 gSpriteStealth0x40001e3c gSpriteX0x40001e40 gSpriteState0x40001e44 gFlickerList10x40001e48 gFlickerList20x40001e4c gMissileControl0x40001e50 gMissileX0x40001e54 gMissileY0x40001e58 gSpriteAnimFrame0x40001e5c gAnimFrameCount0x40001e60 gSpriteAnimSeqID0x40001e64 gAnimSeq0x40001e68 gAnimSeqOffset0x40001e6c special_object0x40001e70 gMenuOptionsDatastreamByte*(.data.*)0x40001e74 . = ALIGN (0x4)0x40001e74 _edata = ..bss 0x40001e74 0x34 load address 0x00003e300x40001e74 . = ALIGN (0x4)0x40001e74 _sbss = .*(.bss).bss 0x40001e74 0x18 main.o*(COMMON)COMMON 0x40001e8c 0x1c main.o0x40001e8c gSPECIAL_ROOM_TEST0x40001e90 gRoomY0x40001e94 gScore0x40001e98 gPotentialBonus0x40001e9c gRoomX0x40001ea0 gMAX_ROBOT_TEST0x40001ea4 gAwardedBonus
To get the address as shown in Stella, ignore the leading 0x4000 then subtract 0xC00 to compensate for the 3K of RAM that's used to hold the DPC+ driver. Easy way to do that is treat anything that's 1exx as 12xx and 1fxx as 13xx. For instance, gScore holds the player's score. It's been assigned memory location 0x40001e94, so after dropping off the leading 0x4000 and changing 1e to 12 we get 1294 for the RAM location. That can be confirmed by playing a few rounds then looking at the score and RAM:
The select square (green) in the RAM grid is address 1294. gScore is an int, which uses 4 bytes of storage so the score is comprised of the bytes at 1294-1297, which is the green square and the 3 that follow it. The bytes that comprise the int are stored in the reverse order, so swap their order for the human readable value of 00001710, which matches the score shown at the bottom of the TIA Display (top-left of screenshot).
If I understand how the stack works, it builds from the end of RAM towards the C variable pool, so looking back at the Initial State of C RAM the lower section of the 13xx screenshot shows values that had been put onto the stack. All the 0s at the bottom of the 12xx screenshot and the top of the 13xx screenshot are unused RAM. After playing for a while, the State of C RAM looks like this:
Since we can't (yet) step thru the ARM code while it's running, all we can do is look at the state of RAM after the ARM code has finished executing. It looks like the RAMs pretty well used, so it's entirely possible that the resizing glitches we've been seeing are caused by the C Variables and C Stack colliding.
One of the things I learned while working on Stay Frosty 2 was the RAM that's allocated for C usage can be changed by editing the file custom/src/custom.boot.lds. The default memory allocation looks like this:
/* LPC2103 memory areas */MEMORY{boot (RX) : ORIGIN = 0xc00 , LENGTH = 128 /* C-runtime booter */C_code (RX) : ORIGIN = 0xc80 , LENGTH = 21k /* space for C code */ram : ORIGIN = 0x40001e00, LENGTH = 512 /* free RAM (less stack space) */}
In Stay Frosty 2 it looks like this:
/* LPC2103 memory areas */MEMORY{boot (RX) : ORIGIN = 0xc00 , LENGTH = 128 /* C-runtime booter */C_code (RX) : ORIGIN = 0xc80 , LENGTH = 21k /* space for C code */ram : ORIGIN = 0x40001c18, LENGTH = 1000 /* free RAM (less stack space) */}
If I page back in DPC+'s RAM display, it looks like I can change the starting point from 1200 to 1118 (due to alignment, the location needs to be a multiple of 4, so the value must end with the digit 0, 4, 8 or C), or 0x40001d18.
to be safe I checked DASM's output and see that the last thing allocated in RAM is FlickerList2, which starts at 110a and is 24 bytes long so the C storage can start at 1124, or 0x40001d24. After making that change:
/* LPC2103 memory areas */MEMORY{boot (RX) : ORIGIN = 0xc00 , LENGTH = 128 /* C-runtime booter */C_code (RX) : ORIGIN = 0xc80 , LENGTH = 21k /* space for C code */ram : ORIGIN = 0x40001d24, LENGTH = 732 /* free RAM (less stack space) *//* ram : ORIGIN = 0x40001e00, LENGTH = 512 */ /* free RAM (less stack space) */}
the new initial state of C RAM state looks like this:
And after playing the game for a while it looks like this:
The sections outlined in purple have not been used, so we shouldn't bee seeing any RAM usage collisions.
What this means is if RAM collisions were the source of the sprite resizing glitches then we shouldn't see them occur anymore. If the source of the glitch was something else, we'll still see them. As such, please play the attached ROM and let me know if you see any sprites get erroneously resized.
ROM
Source
- 3
5 Comments
Recommended Comments