There are a few useful hints on this site, especially the point "Optimization":
https://shiru.untergrund.net/articles/p ... s_in_c.htm
dougeff wrote:Passing arguments to functions is incredibly slow for the 6502. Pass 1 argument at max, it can use the a and x registers for the first argument.
If the function is implemented in C, has one parameter and is declared __fastcall__, the compiler will still put the variable into the software stack first. So, functions written in C should not use parameters at all.
If the function is implemented in Assembly, then one parameter is alright. If you declare the function as __fastcall__ (which you should do with any function anyway since there's no disadvantage in doing so), it will be put into A (or, if it's two bytes wide, into A and X) and your Assembly function can decide for itself what it wants to do with it.
Besides, even with global variables, you can still simulate normal function calls with the help of macros:
Code: Select all
extern unsigned char DoSomething_Parameter1_;
extern unsigned char DoSomething_Parameter2_;
extern unsigned char DoSomething_Parameter3_;
void __fastcall__ DoSomething_(void);
#define DoSomething(parameter1, parameter2, parameter3)\
{\
DoSomething_Parameter1_ = parameter1;\
DoSomething_Parameter2_ = parameter2;\
DoSomething_Parameter3_ = parameter3;\
DoSomething_();\
}
If you program efficiently, then C should not prevent you from writing real games.
I wrote a jump'n'run in C:
http://www.youtube.com/watch?v=Eee0yurkIW4
This game has platforms, jump physics etc., so the movement functions are a bit more complex than a simple "if button up, then check for wall at position (X, Y - 1)". And still, it works completely without lags.
Some stuff should still be written in Assembly, like general functions (CopyArray*, randomizer etc.), the stuff that happens in NMI or the sprite rendering function (the one that turns the meta sprites into hardware sprites).
But apart from that, I managed to program the whole game logic in standard C and there was never a situation where I had to optimize a random part of the game to be written in Assembly.
* CopyArray, FillArray etc. should be reimplemented because the official C functions memcpy and memset use a size parameter of two bytes (type size_t). This makes those functions bigger and more complex than if you simply use a byte value as the size parameter.
After all, when do you ever need to copy or fill more than 255 bytes to an array at once?
Also, they use local parameters.
Instead, your own CopyArray could look like this:
Code: Select all
In C:
void __fastcall__ CopyArray_(unsigned char size);
#define CopyArray(destinationArray, sourceArray, size)\
{\
CommonPointer1 = destinationArray;\
CommonPointer2 = sourceArray;\
CopyArray_(size);\
}
In Assembly:
_CopyArray_:
TAY
@loop:
CPY #0
BEQ @end
DEY
LDA (CommonPointer2), Y
STA (CommonPointer1), Y
JMP @loop
@end:
RTS
Do you already know what kind of game you want to program?
dougeff wrote:I even find debugging easier in C.
How do you debug the C code of an NES game?