#111896 - Diirewolf - Mon Dec 11, 2006 3:42 pm
Many people tell me that when programming for GBA, using classes is a bit too much for the GBA to handle and since i am coming from C# coding, I really cannot imagine a game without incorporating classes. For example, lets take Super Mario Advance 2, SMW. How would they have programmed such a game with no use of classes? How would they have different characters like blocks, question marks, mario etc. without classes? Please provide me with some guidance.
Thanks
#111900 - keldon - Mon Dec 11, 2006 4:13 pm
There are structs!
#111901 - sgeos - Mon Dec 11, 2006 4:30 pm
Many if not most commercial games use classes. Use whatever works.
-Brendan
#111902 - Diirewolf - Mon Dec 11, 2006 4:33 pm
structs cannot incorporate inheritance and not even methods.
by commercial games, are you reffering to GBA games as well?
#111904 - Ant6n - Mon Dec 11, 2006 4:58 pm
mmh, i wonder whether this works:
Code: |
Typedef struct{
s32 n;
} Int;
Int_Add(Int *int,s32 int);
Int_Mul(Int *int,Int *int);
typedef struct{
Int r; //real part
s32 i; //imaginary part
} GaussInt;
Gauss_Add(GaussInt *gint,s32 r,s32 i);
...
GaussInt x;
...
Int_Add(&x,5); |
I guess at the end of the day you can use classes, but write the 'inner loop' in C. and structs can surely incorporate functions, you can just define one member to be a function pointer and then use it like an object -- but then you'd start emulating oop which would defeat the purpose cuz you'd have all these useless function pointer using up space and time.
#111908 - col - Mon Dec 11, 2006 5:29 pm
Using classes on GBA is fine, just be careful how you use them.
There is a small performance hit when using dynamic binding, but nothing to be concerned about - just be aware. If you are writing code where it becomes an issue, you should probably switch to hand coded assembly.
The real issue using 'classes' with GBA and where others possibly get their 'No classes on GBA' ideas from is memory management.
In most cases you should try to avoid using dynamic allocation of class instances... if you are going to use techniques that depend on dynamic allocation, its best to design and implement your own memory management subsystems.
Fwiw, I've used C++ with polymorphic class heirarchies and dynamic allocation on GBA with no major performance issues.
You just be aware of and in control of whats going on 'under the hood'
#111910 - kusma - Mon Dec 11, 2006 5:46 pm
Use of classes in itself is completely OK on the GBA, what you need to be a bit careful about is C++-features that actually bloat code and/or data-size. This means stuff like virtual member functions, exceptions and templates (and hence STL). I'm not saying you shouldn't use any of these features, just that you need to realize the consequences.
#111912 - Edelnutte - Mon Dec 11, 2006 6:15 pm
Diirewolf wrote: |
I really cannot imagine a game without incorporating classes. For example, lets take Super Mario Advance 2, SMW. How would they have programmed such a game with no use of classes? How would they have different characters like blocks, question marks, mario etc. without classes? |
I can't imagine to actually use classes (I just learned it today in school so it might be an explanation) but I can't Imagine that avoiding classes is that difficult.
#111915 - gmiller - Mon Dec 11, 2006 6:27 pm
To emulate member functions requires a single pointer in each instance pointing to the member function table for that class. You are correct that inheritance and other things are harder to emulate in C. The original C++ compilers generated C and then compiled the code with the C compiler. The understanding of how to implement these things does make it harder to do but it can be done.
The bottom line is what you are comfortable with and what fits the memory you have available. Finely crafted assembly is usually smaller and faster than C, C is generally smaller and sometimes faster than C++. I know there will be a lot of feedback on the prior statement but this is my experience. if you really understand the way C++ works you can produce code in C++ that has a small memory footprint and runs well but it is not always that easy to do. C does not have an easy object oriented approach to solving problems and if you want it you do have to work harder to get there. Assembly is a very lean and mean approach and suffer the same issues with an object oriented implementation that C does. Both C and Assembly are function/procedural approaches to problems so they require that type of mindset.
The bottom line is that you can produce a gem with any of the languages or shit. The programmer is what makes the difference.
#111922 - sajiimori - Mon Dec 11, 2006 7:05 pm
Another point for Diirewolf: One of the key features of C++ is that you don't pay for what you don't use. The "class" and "struct" keywords are identical, except that "class" defaults to private. Declaring a data structure using the "class" keyword implies zero additional cost.
#111944 - tepples - Tue Dec 12, 2006 12:21 am
You don't pay for what you don't use, but often developers are bullied into using overly heavy stuff like iostream because it's "say-fur" than cstdio.
hello_c_style.cpp, compiled using G++ for Windows, is 5.5 KiB.
Code: |
//g++ -Wall -O -s hello_c_style.cpp -o hello.exe
#include <cstdio>
int main(void) {
fputs("Hello world\n", stdout);
return 0;
}
|
hello_c++_style.cpp, compiled using G++ for Windows, is 260 KiB.
Code: |
//g++ -Wall -O -s hello_c++_style.cpp -o hello.exe
#include <iostream>
using std::cout;
int main() {
cout << "Hello world\n";
return 0;
}
|
If the overhead of devkitPro's C++ library is anything like the overhead of MinGW's C++ library, this would leave 0 room for engine logic, game logic, or assets in your multiboot version.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#111951 - poslundc - Tue Dec 12, 2006 1:06 am
The GBA is one of the few remaining platforms where I would advise a newcomer to start with C and then work their way up to C++, once they have a better understanding of the platform, its limitations, and how the features of the language will impact with those limitations.
Diirewolf: travel back with me to a time before time, when java was naught but a drink and if you used the Internet it meant you were familiar with the phrase "no carrier".
Back in these dark times, the features which would eventually become intrinsic to object-oriented programming were simulated using a number of techniques, such as:
- Class methods: any struct that has the need for methods will typically get its own file, with functions that have a common name prefix so you can tell they are meant to operate in that domain. Then typically the first parameter to the function is the pointer to the struct you wish to operate on. So:
Code: |
Sprite *s;
s->setPosition(10, 5); |
becomes something like:
Code: |
Sprite *s;
Sprite_setPosition(s, 10, 5); |
- Polymorphism: structures would have an ID value that was usually an enumeration indicating what "kind" of descendant-object it was. This ID was then either used in a switch statement, or used to index into a table of function pointers to determine a course of action.
- Encapsulation: this was achieved (and often not) largely through effective documentation and programmer discipline.
So why even consider doing things with such backwards, ossified techniques?
Well, on a limited platform such as the GBA the cost of little things add up quickly. Many novice C++ programmers don't realize that inheritance and the OOP paradigm is not the solution to everything, and can even exacerbate problems when used recklessly. If you only ever design with those tools, chances are you may wind up designing a system that's very bloated for a platform that only has 256K of external RAM and 16MHz of horsepower.
Things like dynamic memory allocation need to be carefully controlled in such a tight environment, and polymorphism relies almost entirely on the heavy use of that mechanism. If you're new-ing everywhere instead of only where you must, you'll blow the heap in no time.
Not to mention other costly features of C++, like RTTI and multiple inheritance! Not that these things should never be used, just that you shouldn't use them without being aware of both the costs involved, and what alternatives you have.
Which is why I think C is a good starting point for the GBA if you're new to low-level programming. You're a lot closer to the language implementation, and it gives you a better feel for what's costing you what. If you were to then move onto C++ you would possess far more wisdom as to what ought to be used when.
Dan.
Last edited by poslundc on Tue Dec 12, 2006 1:07 am; edited 1 time in total
#111952 - sajiimori - Tue Dec 12, 2006 1:06 am
Quote: |
You don't pay for what you don't use, but often developers are bullied into using overly heavy stuff like iostream because it's "say-fur" than cstdio. |
It is safer.
If homebrew programmers are letting themselves get bullied, maybe they need to work on their self-esteem.
Anyway, I'd recommend checking the effects of compiling with various settings instead of speculating about them.
#111962 - gmiller - Tue Dec 12, 2006 1:57 am
C++ has some nice features like through and catch for error handling that can make a big difference in the performance on CICS machines but to little to help RISC machines like the ARM7 in the GBA.
I would have people use the features of C++ but know what they cost. Compile your code doing things by hand and doing things with the libraary and then check the map to see what effect it had on your code. Then at least you know what using the feature will cost you.
Safe is usually not fast and fast is usually not safe so decide where you want to expose yourself and then test things out. There are safe equivalents to some dangerous C functions (snprintf instead of sprintf for example) which should be used but there are cases where you might want to use the smaller faster sprintf anyway. If you are going to play with guns just know where they are pointing. ..
#111964 - sajiimori - Tue Dec 12, 2006 2:16 am
gmiller, I've never heard about any particular relationship between exception handling and the feature-richness of CPU instruction sets. Care to elaborate?
#111970 - Miked0801 - Tue Dec 12, 2006 3:15 am
Exception handling on the GBA is a bazooka used as a fly-swatter. Then again, I am heavily biased to the C/Asm side of things ;)
#112019 - gmiller - Tue Dec 12, 2006 2:48 pm
Since the CISC machines can do out of order execution. Having a set of code where errors will be "thrown" allows for simple sequential code structure that does not involve a lot of branch prediction which keeps the pipeline working efficiently. The ARM7 3 stage pipeline helps sequential instructions work better but there is no out of order capability. This means that the "throw" structure will help ARM but not as much as it will a CICS. There is also branch slot delay for some RISC machines which can be a reason to have "branch less" sections of code. Now the performance hits of these types of things might not be great but it can impact tight performance requirement code.
The current x86 family has a least a 15 stage pipeline with out of order execution as long as the dependencies are low enough to get the instruction pool working for you.
#112020 - gmiller - Tue Dec 12, 2006 2:52 pm
Miked0801 wrote: |
Exception handling on the GBA is a bazooka used as a fly-swatter. Then again, I am heavily biased to the C/Asm side of things ;) |
I use C and some ASM mostly and only resort to C++ when I can't do the work another way. I usually just wrap some C code with C++ to keep from paying the price of C++. But since I cam from pure assembly for 10 years before I did C and then did C++ I am biased as well.
But I do think you need to use what you are comfortable with to do a good job but you also need to know what the different approaches are costing you.
#112326 - sgeos - Fri Dec 15, 2006 6:51 am
Diirewolf wrote: |
structs cannot incorporate inheritance and not even methods. |
Do what you need to do, and know why you are doing it. If you are worried, figure out what the alternatives are and choose a solution based on objective criteria. When I say "objective", I'm not talking OOP, I'm talking about using neutral and meaningful metrics.
Diirewolf wrote: |
by commercial games, are you reffering to GBA games as well? |
Yes, although I doubt there will be many more commercial GBA games. Many if not most commericial GBA games use scripting systems. A scripting system is most likely going to be slower and maybe even heavier than C++. Just do what you need to do to get the job done (within reason). Remember, programmer time is just as or even more important as execution time in most cases. (In other words, the game needs to launch == the job needs to get done.)
-Brendan