Jump to content
  • entries
    652
  • comments
    2,629
  • views
    874,032

The C RAM Review

SpiceWare

3,007 views

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.

blogentry-3056-0-43076600-1394061828_thumb.png

 

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

blogentry-3056-0-83430200-1394062128.png blogentry-3056-0-61296400-1394062137.png

 

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:

blogentry-3056-0-34745400-1394062682_thumb.png

 

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:

blogentry-3056-0-52871100-1394063913.png blogentry-3056-0-46232300-1394063921.png

 

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.

blogentry-3056-0-84254100-1394064310.png

 

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:

blogentry-3056-0-35966500-1394065237.png blogentry-3056-0-84789700-1394065242.png blogentry-3056-0-13506800-1394065248.png

 

And after playing the game for a while it looks like this:

blogentry-3056-0-02165200-1394065548.png blogentry-3056-0-79370500-1394065554.png blogentry-3056-0-35478700-1394065561.png

 

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

frantic20140305.bin

 

Source

Frantic20140305.zip

  • Like 3


5 Comments


Recommended Comments

I've played a few rounds each night with the new Frantic build1 and haven't see the 2x sprite glitch yet so at this point it seems very likely that the glitch was caused by C variables & stack colliding. Please continue testing the build though as I'm now going to concentrate on finishing my changes to Stella so I can send them in to stephena. After that I'll resume work on Frantic.

1 if you didn't make it through that super long, and possibly super boring (especially to the non-programmer), blog entry before you can find the new build by scrolling back a bit to just above this comment :)

Share this comment


Link to comment

When you say C.. is that C as in printf C?

 

That'd be interesting if you could code an Atari 2600 game in ARM C and just use a DPC+ cart for the finished game.

Share this comment


Link to comment

Yep that C - though printf is part of the stdio library (#include <stdio.h>) which doesn't make sense in the context of the 2600.

 

Some standard C libraries can be used with Atari projects, like the functions memcpy and memset that are found in the string library (#include <string.h>). However they're quite large in size, so it's best to roll your own. I was originally using the string library for those functions when working on Stay Frosty 2 back in 2010 when cd-w suggested replacing them with my own routines. I whipped up these:

 

void my_memset(unsigned char* destination, int fill_value, int count)
{
	int i;
	for (i=0;i<count;i++)
		destination[i]=fill_value;
}

void my_memcpy(unsigned char* destination, unsigned char* source, int count)
{
	int i;
	for(i=0;i<count;i++)
		destination[i] = source[i];
}
and saved 352 bytes, enough space to hold over a third of the platform/ice layout data.
  • Like 1

Share this comment


Link to comment

Some part of my brain managed to hang onto the New Zoo Revue theme song for all of these years.

 

I'd like to think that was somehow a good thing, but strongly suspect that part of my brain could have been better utilized by remembering things like math and peoples' birthdays.

Share this comment


Link to comment

I'd forgotten about it until I did up a card for a coworker a few years ago based on this:

P1020771.jpg

 

and thought "hey, the hippo from that kids show would work well" and it all came crashing back in :)

Share this comment


Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...