I recently had a panic attack whereby I thought I had run out of RAM for my game. To fix the problem I needed to determine exactly how much RAM it occupies. Finding out the true size of your program isn't too easy. If you just go by the size of the MAIN file you're leaving out all the unitialized variables and arrays. Since these structures don't actually contain data at compile-time, GCC doesn't allocate space for them within MAIN. This actually is a good thing since it saves you download time; there's no need to transmit a bunch of zeroes anyway. But it makes determining your program's true size difficult.
While sulking about my realization that my game had hit a major snag, I started perusing the contents of the GCC folder. In the "bin/" area is a little utility called nm.exe. I have no idea what it stands for, but this little bugger saved me from hours of frustration.
You invoke it giving the name of your MAIN file:
D:\DSI\EV> nm main
The output is a list that gives you the starting addresses of all functions, global variables, arrays, or anything else that takes up RAM (and is static of course - it doesn't give the address for variables allocated at runtime since it obviously doesn't know them). The output looks something like this:
8002d4d8 A ApplyMatrix 8002cde0 A ApplyMatrixLV 8002d528 A ApplyMatrixSV 80063f9c A CLIP2 8003c388 A CdPlay 8003bf60 A CdRead 8003c2b4 A CdReadExec 8003c14c A CdReadFile 8003c068 A CdReadSync 8003b198 A CdSearchFile 800282e0 A ClearImage 8002c898 A CompMatrix 8002814c A DrawSync 80042f28 A EnterCriticalSection
It continues on but you get the idea. This list is in alphabetical order. That's not entirely useful for our purposes so I'd recommend putting it through "sort" first:
D:\DSI\EV> nm main | sort > nm.out
I also redirected output to a file so it's easier to read. So then you end up with a list ordered by address:
800100c8 A GetPadBuf 8001012c A TestCard 80010700 A InitHeap 80010754 A malloc 80010924 A free 8001095c A realloc 800109f0 A calloc 80010c90 A SsGetMute 80010cb4 A SsGetMVol 80010d34 A SsGetSerialAttr 80010dcc A SsGetSerialVol 80010ea0 A SsSetMute 80010ee0 A SsSetMVol 80010f30 A SsSetSerialAttr
This is somewhat interesting since it tells you the exact addresses and sizes of all the library functions. You could use this information to selectively overwrite the library routines you don't use with your own data (if you're really in dire need of space).
The more interesting part is farther down where it gets to your actual code. In my case, my code starts at 80012000:
80120000 T byte_to_hex 80120000 T eprol 80120000 T _ftext 801201a8 T print_mem_loc 801202e0 T screen_grabber 801204a8 t sg_init 801205dc t sg_pad_inc 801206f4 t sg_resize 80120920 t sg_move 80120b38 t sg_transmit 80121030 T msg_handler 80122854 T msg_init 80122a04 t msg_char_adjust
You should be able to recognize the names of your own functions.
Now back to my running-out-of-RAM problem. When I scanned down the list of addresses I saw the following:
80159c30 b menu_sprt 80159c60 B pad_state 80159ca0 B scrngrab_buffer 80160ee0 A _gp 801efca0 B menu_sprites 801f01a0 B map 801f01d0 B tv_text_border_array
Whoa! Judging by the difference between the address of scrngrab_buffer and menu_sprites, the buffer is sucking up 600k of space!
My routine to take screen shots allocates a lot of room and I had forgotten to take it out of my program. Once I killed it my RAM problem was solved!
Another thing I find useful is being able to spot structures that occupy lots of room. For instance:
801626d0 B WorldOT 80162700 B obj_array 8016bf00 B prev_pad 8016bf10 B hud_extra_outline
I have a structure named obj_array which has 512 entries. As you can see it occupies about 36k of space. If I could somehow reduce the structure so that each element takes up 8 bytes less, I could save 4k of that space (512 * 8 bytes).
Overall nm.exe is a good way of profiling your program to find out where your Yaroze memory is being used.
This web page and all other pages on this site are © 1998 Scott Cartier