Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)
You are not logged in.
Hi, I feel comfortable using OOP (I use it at work, C#) and I'm new using C.
That's why I'm trying to use a more OOP approximated option while programming on gbdk.
I've done a small test simulating a Human class.
I have 2 files, main and human:
human.c
#include <gb/gb.h> #include <stdio.h> #include <string.h> struct HumanStruct { char *country; }; void SetAsSpanish(struct HumanStruct *const); void SetAsEnglish(struct HumanStruct *const); void SetAsFrench(struct HumanStruct *const); void Speak(struct HumanStruct *const); void SetAsSpanish(struct HumanStruct *const human) { human->country = "spain"; } void SetAsEnglish(struct HumanStruct *const human) { human->country = "england"; } void SetAsFrench(struct HumanStruct *const human) { human->country = "france"; } void Speak(struct HumanStruct *const this) { if (strcmp(this->country, "spain") == 0) { printf("Hola"); } else if (strcmp(this->country, "england") == 0) { printf("Hello"); } else if (strcmp(this->country, "france") == 0) { printf("Bonjour"); } }
main.c
#include <gb/gb.h> #include <stdio.h> #include "human.c" void main() { struct HumanStruct Human spanish; SetAsSpanish(&spanish); struct HumanStruct Human english; SetAsEnglish(&english); struct HumanStruct Human french; SetAsFrench(&french); Speak(&spanish); delay(1000); printf("\n"); Speak(&english); delay(1000); printf("\n"); Speak(&french); }
This work as expected, but when I try to use a human.h to define the human "public interface" I can make it work
human.h
typedef struct HumanStruct Human; void SetAsSpanish(struct HumanStruct *const); void SetAsEnglish(struct HumanStruct *const); void SetAsFrench(struct HumanStruct *const); void Speak(struct HumanStruct *const);
human.c
#include <gb/gb.h> #include <stdio.h> #include <string.h> #include "human.h" struct HumanStruct { char *country; }; void SetAsSpanish(struct HumanStruct *const human) { human->country = "spain"; } void SetAsEnglish(struct HumanStruct *const human) { human->country = "england"; } void SetAsFrench(struct HumanStruct *const human) { human->country = "france"; } void Speak(struct HumanStruct *const this) { if (strcmp(this->country, "spain") == 0) { printf("Hola"); } else if (strcmp(this->country, "england") == 0) { printf("Hello"); } else if (strcmp(this->country, "france") == 0) { printf("Bonjour"); } }
main.c
#include <gb/gb.h> #include <stdio.h> #include "human.h" void main() { Human* spanish; SetAsSpanish(spanish); Human* english; SetAsEnglish(english); Human* french; SetAsFrench(french); Speak(spanish); delay(1000); printf("\n"); Speak(english); delay(1000); printf("\n"); Speak(french); }
I can't get it compiled. What I'm doing wrong?
Thank you
Offline
this is invalid: void SetAsSpanish(struct HumanStruct *const); you can't have a parameter without a name unless it is a "..."
that approach you use is not an "object oriented", it's just a simple c-style api. neither of 3 key oop features are acheived here: incapsulation, inheritance, polymorphism. try google something like "object oriented C", for example this: https://www.cs.rit.edu/~ats/books/ooc.pdf
it is interesting to use oop with GB as a project itself, but not much help when you want to make a game or something, because you get rather slow and size-greedy code, while on game boy you are lacking both: speed and space.
also be sure, that you are using gbdk-2020.
Offline
Shkire,
If your game is not likely to be resource or processor speed constrained, then writing more efficient and compact code may not be as critical- yet they are still good habits to have on the platform.
Below are some links you might want to review if you have not already. Some of the material is dated and some might not apply anymore or as directly to GBDK (z88dk specifics). But overall resources such as these can start to give you an understanding of how to approach writing software on a system with limited resources, especially if you are coming from a higher level language and do not have much experience in the area. Things that are easy to take for granted when writing software on powerful modern hardware can have big consequences on these old platforms.
http://gbdk.sourceforge.net/guidelines.html
https://github.com/z88dk/z88dk/wiki/WritingOptimalCode
Others here may have suggestions for more recent and specific coding guidelines for working with GBDK and the Game Boy.
Best of luck on your projects!
Offline
bbbbbr i won't suggest both of those links: the first one is too old and contains outdated info, the second one relates to z80 more than to gbz80. maybe someone should write a better guide that meets the recent SDCC features.
Offline
Perhaps you are tempted to write a guide?
In the absence of a better ones though, they still have useful information. Such as:
* Using global variables is generally more efficient that using local variables - (in other contexts use of global vars may be discouraged, but there are some speed and compactness benefits to using them more liberally in this environment)
* Avoid using multiplications, divisions and modulos as much as possible - (there are many small ways to minimize these- such as the item below)
* Compute things once and store the result - (look up tables/etc can improve speed and reduce code size)
* Avoid long lists of function parameters - (passing many parameters can add overhead, especially if the function is called often)
* Use types of appropriate size - (8 bit types will be more efficient and compact than 16 and 32 bit types)
Offline
by your ##:
# yes, but it's better to use static variables than global
# avoid, if divider is not a power of 2. modern sdcc uses shifts and swap instruction nicely for optimization
# yes. that's common everywhere
# yes. also use inline functions if the function is short
# yes. also types may be promoted, some special C syntax kung-fu is required
also i might add:
# use profiling, look into generated asm, write several versions of a function to choose better (faster) one.
# don't forget const for arrays and structs with constant data - that reduces size of the rom significantly.
# use --max-allocs-per-node with some big values, like 50000; --opt-code-speed barely adds anything
# use latest SDCC builds from sdcc.sourceforge.net/snap.php i use #11845 it works very well and for now has all important fixes.
...
profit
Offline
Don't do loops over arrays of structs like this:
Enemy enemy[10]; for (i = 0; i < 10; i++) { enemy[i].x = rand(); enemy[i].y = rand(); }
Do them like this:
Enemy enemy[10]; Enemy *e = &(enemy[0]); for (i = 0; i < 10; i++) { e->x = rand(); e->y = rand(); e++; }
This way it will just have to add the size of the struct rather than to multiply (current pointer = size of struct * current index).
Better yet, do this:
Enemy enemy[10]; Enemy *e = &(enemy[0]); for (i = 10 - 1; i != 0; i--) { e->x = rand(); e->y = rand(); e++; }
It's faster to check if a variable is 0 than if it is equal to some other value.
Last edited by AntonioND (2020-09-04 19:44:54)
Offline