The Socrates Gameboy Advance Development Engine
The SGADE is a development library for the Nintendo Gameboy
Advance. It's free for all uses and is distributed without guarantees.
For more information visit
the SGADE page.
Introduction to the Documentation
The documentation for the SGADE is divided into several parts. You are now reading the largest section. It contains a complete reference to all code, and some background information on the SGADE development philosophy and codestyle. Other information can be found in the FAQ and the the tutorials. These can be found on the SGADE website.
Before you start using the SGADE I strongly suggest reading all information below. After that I would browse this reference for a bit, and then take a go through the tutorials.
Philosophy
I believe in object and component oriented programming. However, unlike some people, I also believe that one can use any coding paradigm in any language. I don't need C++ or Java to use OOP, and I could do functional programming in assembly. Some languages might be better suited for some paradigms, but some languages are also better suited for some platforms. This is the reason I chose C over C++ for Gameboy Advance development.
I can see the merits in using C++ for a GBA project, but only for advanced management systems. If, for example, I had to write a strategy game for the GBA, I would probably use C++ constructs to manage units and resources. But for Socrates, C gave me all I ever needed. Object oriented programming without the memory overhead and performance drawbacks of C++.
If anyone wants to discuss this with me, and wants to tell me C++ can be just as fast, I'd love a discussion. But not until you've read Scott Meyer's books: Effective C++ and More Effective C++.
So, I would be using C. How then is OOP reflected in my C coding? Two things are important here. This pointers and singletons.
This pointers are used whenever a function acts upon an object. In C++ all methods belonging to a class receive an implicit (hidden) this pointer. Whenever you invoke a method on a class like this:
object.Method();
What C++ actually does is this:
Method( &object );
So all we have to do to emulate an object oriented class-method-like system is provide the this pointer ourselves. What better than using a short example. Take a look at the following C++ code.
// Define the class class SoClass { // Attributes; int m_Attribute; // Methods; void Method1( void ); void Method2( int a_Argument ); int Method3( void ); } // Declare an instance; SoClass object // Use the class object.Method1(); object.Method2( 10 ); int i = object.Method3();
This would be written in C (the SGADE) as follows:
// Define the structure typedef struct { // Attributes; int attribute; } SoClass; // Define the methods; void SoClassMethod1( SoClass* a_This ); void SoClassMethod2( SoClass* a_This, int a_Argument ); int SoClassMethod3( SoClass* a_This ); // Declare an instance; SoClass object // Use the class SoClassMethod1( &object ); SoClassMethod2( &object, 10 ); int i = SoClassMethod3( &object );
Once you realize there is actually no difference between the above C++ and C code, nothing stops you from doing OOP in C. It is true that the often called 'true' OOP concepts like polymorphism and inheritance require more complicated constructs, but most of it can be solved using clever casting and function pointers.
What about singletons then? Well, targeting the Gameboy Advance, it turns out that a lot of classes are often instantiated only once. A good example is an interrupt manager or a mode 4 renderer. All methods belonging to such an object will always receive the same this pointer. This would be nonsense ofcourse, and therefore we treat these objects as singletons. In the SGADE a singleton is a group of global functions without this pointers. But we treat those as methods belonging to and acting upon a single object and not as seperate functions. Consider the following functions:
void SoMode4RendererEnable( void ); void SoMode4RendererFlip( void ); void SoMode4RendererClear( void ); ....
All of these functions act upon a global fictional object called SoMode4Renderer. There is no SoMode4Renderer type, but the object is there. You will never see it, but just remember that whenever you use a singleton.
C, as opposed to C++, has no build in information hiding facilities. Every attribute of a structure is public (for the compiler). However, you should always treat all members of every structure as private. Use the supplied methods to act upon these structures.
There is a single exception to this. The SoVector3 and SoVector2 structures (because of their simplicity) have public members. Every other structure has only private members. These are marked as 'For Internal Use Only'. Treat them that way.
Code Style
I use a fairly strict coding style. Uniform and consistent coding improves readability. I use the following rules for coding.
// A global variable. u32 g_GlobalVariable; // A static variable. static u32 s_StaticVariable; // -------------------------------------------------------------------- // // \brief A global function. // \param a_Argument1 First argument of the function // \param a_Argument2 First argument of the function // // \return The first argument added to the second argument. // // This function does blah blah blah // blah blah blah // blah blah blah // // -------------------------------------------------------------------- u32 SoGlobalFunction( u32 a_Argument1, u32 a_Argument2 ) { // A local variable. u32 localVariable; // Do the calculation localVariable = a_Argument1 + a_Argument2; // Done; return localVariable; } // -------------------------------------------------------------------- // -------------------------------------------------------------------- // // \brief This structure represents blah blah; // // This structure can be used to do blah blah blah blah... // // -------------------------------------------------------------------- typedef struct { u32 m_MemberAttribute1; // Attribute that is for blah.... u32 m_MemberAttribute2; // Attribute that is for bleh... } SoSomeStructure // -------------------------------------------------------------------- // -------------------------------------------------------------------- // // \brief Method belonging to the SoSomeStructure class // // \param a_This This pointer // // This function does blah blah blah blah... // // -------------------------------------------------------------------- void SoSomeStructureMethod( SoSomeStructure* a_This ) { // Acces the member of the given this pointer. a_This->m_MemberAttribute = 10; } // --------------------------------------------------------------------
Just look at the above example and some of the SGADE code and you'll soon see the consistency and particular coding practices I use to improve development.
On Doxygen Source Commenting
Doxygen is a tool that extracts comments from source code and creates documentation in HTML, Latex, or other formats. The very words you are reading now (if you are reading this documentation in HTML format) have been extraced by Doxygen.
More information on Doxygen can be found on its website at http://www.doxygen.org I'll give some short tips and advice that might help when you start browsing the SGADE source code.
Doxygen parses the sourcecode and uses the source surrounding comments to get information about this code. You can add certain tags to the comments to give Doxygen information about what you mean with the code following the comments.
A Doxygen compatible source comment can be given in the following ways:
Where to from here
Now that you have read something about the philosophy and coding style of the SGADE you know what to expect when using the SGADE. I suggest you start by browsing this reference, especially the modules section at the top of this page. After that, browse through some of the code and try some tutorials.