Hi, I wrote a simple program to see what addresses did each variable get.
And I got this result:
- Global variables get stored starting from address $6000. ( That should be Save RAM, and indeed, emulators save .sav files whenever you use global variables )
- Local variables get addresses $07FF and go downwards. Correct me if I'm wrong, but local environments should be stored in the stack right? alongside with parameters and return addresses. And the stack should go at $0100 - $01FF
Am I geting it wrong?
Should be safe then using addresses from $0200 right? unless, obviously, they hit the down-growing stack from $07FF
Is this ok? do you think this should be different?
There could be a distinction between the system stack and a data stack. Use a pointer somewhere inside the zero page as a stack pointer, then you get both a 256 byte stack, and a big stack.
But I figure most games just use static local variables.
I think local variables should to stored in Zero Page ($0-$FF), because they're accessed frequently, and Zero Page takes less time to deal with (3 cycles as apposed to 4). For my game, I have 32 bytes in Zero Page dedicated to local variables. I have 16 for the game loop, and another 16 for the NMI (so there are no RAM conflicts). These values I name "TempVars", because usually they hold a value temporarily such as a counter for a loop. However, if I'm doing a function within a function, I can push the values of these "TempVars" on the stack ($100-$1FF) as I go to the function within a function, then pull them out, restoring the values of the "TempVars" as I leave it. The stack can be really great for some things, but you have to be really careful when you use it and make sure you pull all values you push onto it after a JSR out so that your program doesn't crash when it runs into "RTS". Aside from those 32 variables (and some temp addresses) the rest of RAM is global.
In actuality, all RAM is global, I just put a series of temp variables in RAM that kind of act like local variables.
And it sounds like a really big waste to dedicate $0-$7FF as local variables, and $6000-$7FFF as global. Perhaps you want to you know, save game information in SRAM, and not just use it for variables. If you're just holding on to numeric values, $0-$7FF should be enough. However when you start decompressing maps and stuff, and you have big arrays of data, you might consider using SRAM in addition.
I'm pretty sure it should be possible to reassemble the CC65 NES libraries so that it uses either adress you desire.
And yes, the C argument stack ($400-$7ff if I remember) is completely separated from the hardware 6502 stack ($100-$1ff). The problem is that CC65 acess the stack in a SLOW way, by using indirect adressing [stackPtr],Y.
I wish there would be a way to redirect the stack so that it is limited to 256 bytes but uses indexed adressing, which is much faster. Also, either X or Y can be used permanently for the stack pointer, while the other index register coupled with the accumulator can hold 16-bit variables (CC65 uses XA).
Or, like Celius says, place a stack that is inside zero page and is more greatly limited (something arround 128 bytes, levaing the other half for system assembly functions). I think 128 bytes of argument stack should be enough if you also use globals. And dealing with locals may be slightly slower, but more proper and less propice to bugs due to variable conflicts (I just had too many of them).
I wish I had the skill to write a C compiler (which I really haven't), so I could come up with something better than CC65. Or should I just mail the people behind CC65 to show them my request, and see how feasible it would be ? Would they even listen me ? Or eventually I could just write programms in assembly, but using a stack like if it was in C so that I get less variable conflicts.
Bregalad wrote:
I'm pretty sure it should be possible to reassemble the CC65 NES libraries so that it uses either adress you desire.
Yeah, it should. I'll investigate.