Zalo DS Blog

Tuesday, January 03, 2017

ZGB, a little engine for the Game Boy

2016 has been an interesting year for the Game Boy scene. I remember back in 2015 talking with people developing for the Game Boy saying lots of docs with important info had been lost over the years and that the scene was dying... Well, I am not sure what happened, but in this past year I've seen some really cool games like: carazu, Rocket Man, Where's my cake?Soup Raiders: Jailbreak, Biotic Limit, Snake Bird, Araku Hime: The Red Princess, Guns & Riders... it seems that the game boy scene has revived!!


Besides Pretty Princess' Castle Escape and Super Princess' 2092 Exodus I have been working on an engine that at some point I decided to name ZGB. This is the engine that both games are using. Some of its features:

- 4 directional scroll that allows maps bigger than 32x32. This is done updating the current row and column as the scroll moves.
- Sprites pool, that will help you manage everything that is moving on screen. It will also handle the creation and destruction of new sprites on screen
- Animations
- Collisions, sprite vs sprite and sprite vs background
- Automatized build support. Just 3 lines of code
- Bank management. Easy to select the bank for every file on the project and transparent bank switching in most cases
- Fonts and printing, and also some tools that will help to debug some values
- Music, using the legacy version of gbt-player
- Sound effects, using the fixed version of the sound sample that comes with the gbdk

ZGB is available on github. You can take a look at all the things you can do with it and there is a tutorial showing you how to create a game step by step. You can also download the source code from Pretty Princess' Castle Escape and Super Princess' 2092 Exodus and see how they do their stuff (or even create some rom hacks if you want :P)



There is a tutorial showing you how to code this

Just for clarification: this is not the definitive engine for the Game Boy. It is written in C using gbdk and that adds a lot of extra garbage on the code . Also there are some parts that still could be optimized a lot. But I think it is good for people who want to do something relatively fast (You know what other options you have if you really want to squeeze the machine). I think it perfectly fits on a game jam. 

There will be more game jams in 2017. I'd like to ask you to give ZGB a try. You'll make me very happy if you create something fun with it (I might even cry). I have already fulfilled one of my childhood's dreams and would like to see you doing it too: create a videogame for the Game Boy.

Happy coding!

ZGB on github

Monday, January 02, 2017

Super Princess' 2092 Exodus

Initially developed for the gbjam5 this is the second game I develop for the Game Boy and also together with sergeeo doing the art and music.

The gbjam5 ran from October 1st 2016 at 7:00 AM to October 10th 2016 at 7:00 AM. 399 games were entered, wow! Contrary to the bitbitJAM the games were not required to work on real hardware, actually the games just needed to be thematized as Game Boy games. I already had the engine I created for Pretty Princess' Castle Escape and I wanted to give it another try. Most of the time I spent on the bitbitJam was actually on the engine and not the game itself, so I knew we could do something better.


The first version of Super Princess' 2092 Exodus was developed in 48 hours. It only contained one level (7 screens) but it was more complete than Pretty Princess. I saw there was still a lot of improvements that could be done on the engine so I decided to continue working on it for a while. At the same time we also wanted to improve the game after the jam, so since them we have:

- Improved the jump (that was the main complain from people)
- Added 2 new levels, with their music, tileset and maps
- Added the screen transition similiar to the one you see in Megaman Games
- Moving Platforms
- 5 new enemies
- Better menus
- Sound effects
- An ending!

The game is not hard but it isn't easy either... in other words you won't finish it on your first try, just like videogames used to be. If you get killed, just try again



We are very happy with the result and hope you all enjoy it. You can play it here (just remember the experience is much better if you download the rom and play it on an emulator, or even better on real hardware)

Source code is also available on github

Sunday, December 04, 2016

Game Boy Development - Tips and Tricks (III)

This is the 3rd post on the series Game Boy Development - Tips and Tricks

7. SDCC Issues


No matter how you look at it, the SDCC that comes with the GBDK has some serious issues. Here I am going to talk a little bit about some of them that I have been able to isolate an reproduce 100% and the workarounds I was forced to use.

1. Minus unary operator (-) doesn't work with numbers bigger than 130

The minus operator used for negating a number either gives you a random value or crashes. You can easily test this with the next code: 

void Test0()  {
INT16 n   = 1000;
INT16 tmp = -n;
//Printing -n crashes
printf("%d neg: %d", n, tmp);
}

For some reason it only fails with numbers bigger than 130, so you can safely use if with 8 bits values (because the biggest 8 bit signed is 127). You shouldn't use it with unsigned values for obvious reasons.
The workaround is simple but annoying, use the next macro that negates a two's complement number

#define NEG(A) (0xFFFF - A + 1)
void Test0()  {
INT16 n   = 1000;
INT16 tmp = -n;
//Workaround
printf("%d neg: %d\n", n, NEG(n));
}

2. Extra cast is required for adding  an 8-bit value to an unsigned 16-bit value

I have to admit I wasn't sure at first it this was a bug or not. Mixing signed and unsigned values is always complicated but when you start using unsigned values is going to happen sooner or later. I just wrote a similar code on Visual Studio using shorts and ints and it seem to be a bug according to that.

Calling the next function with v0=100 and v1=-50 outputs 306 instead of 50

void Test1(UINT16 v0, INT8 v1) {
printf("%d ", v0 + v1);
}

At least for this one there is an explanation. The compiler is converting v1  to unsigned (256 - 50 = 206) and adding that value wich gives that result.

If Instead of writing the test as a function with two parameters we declare the vars as local:

void Test1() {
UINT16 v0 = 100;
INT8 v1 = -50;
printf("%d ", v0 + v1);
}

then it outputs 50. This is probably resolved by the compiler but because of the lack of consistency there is definitely something wrong going on here 

The workaround is simple (but once again annoying), you just have to force a cast like this:

void Test1(UINT16 v0, INT8 v1) {
printf("%d", v0 + (INT16)v1);
}

3. Right Shift operator (>>) doesn't work with 16-bit values

Similar to the unary minus, the >> operator either crashes or gives you a random value. The next code crashes:

void Test2() {
UINT16 v16 = 50;
UINT16 n = 2;
printf("%d ", v16 >> n);
}

Also 50 >> n or v16 >> 2 will crash but if you write 50 >> 2 that works, I think the compiler is resolving that on compilation time. The workaroud I found here is a big surprising since it uses the operator itself. You just need to use the next function:

INT16 DespRight(INT16 a, INT8 b) {
return a >> b;
}

void Test2() {
UINT16 v16 = 50;
UINT16 n = 2;
printf("%d \n", DespRight(v16, n));
}

that seems to stop some kind of optimization that at the end is breaking up everything... strange
The Left Shift operator (<<) seems to work without problems

4. Comparing 8 bit value from struct with another 8 bit value fails


This one was causing a very odd behaviour on my engine making some sprites not properly being spawned. Calling Test3 here with a value of 5 will output 1 (TRUE)

struct StructTest {
UINT8 v8;
};

void Test3(UINT8 v8_0) {
struct StructTest test = {0};

printf("%d ", (UINT16)(test.v8 == v8_0));
}

This won't happen if you use 16-bit values instead. I found a couple of workarounds here, you can either change the order of the comparison:

void Test3_fix(UINT8 v8_0) {
struct StructTest test = {0};
printf("%d ", (UINT16)(v8_0 == test.v8));
}

or cast the values to 16-bit

void Test3_fix(UINT8 v8_0) {
struct StructTest test = {0};
printf("%d\n", ((UINT16)v8_0 == (UINT16)test.v8));
}

Something interesting is that if you write the code followed by the workarounds like this:

void Test3(UINT8 v8_0) {
struct StructTest test = {0};

printf("%d ", (UINT16)(test.v8 == v8_0));
printf("%d ", (UINT16)(v8_0 == test.v8)); 
printf("%d\n", ((UINT16)v8_0 == (UINT16)test.v8));
}

then it outputs the right value (¿?¿?) in the 3 cases

That's all for now. I have created a public repository wit the tests here, feel free to contribute and if you find any mistake on anything I said please let me know. I have tried to compile all this using gbdk-n which works with the latest version of sdcc but since it doesn't support printf I haven't been able to test it. Also gbdk-n doesn't have proper support for banks yet and that is a big problem. 


Sunday, September 11, 2016

Getting the Wii core back

One of the things that has been bothering me over the past 4 years is not being able to compile for the Wii. I had support for it a few years back, but then I introduced several improvements and never found the time to work on them for the Wii.

Recently with the 3ds port a bit more stable I decided to get it back. There are other platforms I want to support in the future but before that it is important to get all my cores up to date. Taking advantage of all the things I did for the 3ds and all the improvements that had been added to Dolphin during all these years I had finally updated it!

And of course I had compiled a version of

Rokoban





and Whack Mania




If anyone is still playing Wii homebrew games out there, please let me know your thoughts!

Sunday, July 31, 2016

Game Boy Development - Tips and Tricks (II)

5. The game loop

Most of the examples I've seen contain a main loop similar to this

void main() {
<game initializations>
while(1) {
wait_vbl_done();
...
<process input>
<your frame update>
}
}

this is a good starting point. Waiting for the vblank interruption prevents your game from running faster than it  should. If you start with this and keep coding you'll eventually notice a frame rate slowdown. A high slowdown actually, and that is because your frame update at some point takes more time than what is available between 2 vblanks, but you are still waiting an extra vblank.

1. Skipping vblank wait when we don't need it

One way to improve the previous code will be:

void vbl_update() {
vbl_count ++;
}

void main() {

//Subscribe vbl_update to vblank interruption
disable_interrupts();
add_VBL(vbl_update);
set_interrupts(VBL_IFLAG);
enable_interrupts();


while(1) {
if(vbl_count == 0)
wait_vbl_done();
vbl_count = 0;
...


}
}

in this new code we have declared an interruption that will store in a var the number of vblanks that have happened during the current frame. If there are more than one we no longer need to wait to the vblank and we can continue processing. Bear in mind this can duplicate your framerate up to x2 specially in situations where your processing takes more than one vblank just for a few instructions

2. Frame skipping

This is a good improvement, but it can be improved even more by using frame skipping. As its name says it consists of skipping the painting of some frames to save processing time and this way keeping the game logic running without suffering an slow down. So let's say your game is running at 60Hz meaning your fixed update time is 0.016 secs aprox, in normal conditions you will update your logic 0.016 secs, paint, update 0.016 secs, paint... and so on. Then at some point you realize that updating your logic takes more than 0.16 secs and in order to prevent an slow down  you start dropping frames like: update 0.016 secs, update 0.016 secs, paint, update 0.016 secs, update 0.016 secs...

In the Game Boy the painting happens automatically and it takes 0 processing time from your main loop. The only thing you need to do is prepare the OAM table and update the scroll coordinates and it will just happen. So just doing two consecutive updates during one frame iteration will not help up us at all

Once thing we can do though is processing several updates together. Instead of updating 0.016 secs and then update 0.016 secs we can do one single update of 0.032 secs which basically means multiplying all your updating calculations by 2 (which is a very simple operation as we saw), like this:

...
while(1) {
if(vbl_count == 0)
wait_vbl_done();
delta_time = vbl_count ? 1 : 0;
vbl_count = 0;
...
}
...

so now we have a var called delta_time that is 1 or 0 depending on having to do frame skipping or not. If for example in some of your updates you were doing
 sprite.x += 1;
you just need to change it to:
 sprite.x += 1 << delta_time;
x <<  0 is the same as multiplying by 1 and x << 1 is the same as multiplying by 2

On this implementation we are just skipping one frame, doing 2 will be complicated because that cannot be done with a shift operator. Skipping 3 will be posible but If you need to do that you should probably take a look at your calculations and try to optimize a little bit (I mean your update is taking 4 times what it should...)

3. Keeping the scroll movement smooth

Even though your game is not running at 60Hz you can still do your scroll being updated at 60Hz if you update  the scroll position registers during the vblank interruption. In order to do this you should store your scroll position in a variable during your update process and then refresh the scroll position registers during vblank. But instead of doing

SCX_REG = scroll_x;

update them like this:

if(old_scroll_x < scroll_x)
old_scroll_x ++;
else if(old_scroll_x > scroll_x)
old_scroll_x --;
SCX_REG = old_scroll_x;

where scroll_x is the current x position of the scroll and old_scroll_x is the position in the previous frame. If your scroll was moving faster than one pixel per frame sometimes you can improve this with an small spring interpolation

if(old_scroll_x < scroll_x)
old_scroll_x += (scroll_x - old_scroll_x + 1) >> 1;
else if(old_scroll_x > scroll_x)
old_scroll_x -= (old_scroll_x - scroll_x + 1) >> 1;
SCX_REG = old_scroll_x;

And you should do the same for the y axis. You can check the full implementation here

6. Funny things in the world of 8 bits

Here is a list of some of the things that made me waste some time because I am not very used to work with these kind of limitations

- printf implementation only works with 16bits values. Funny when this is the only method you have to get some debug info and you realize you are printing all that info incorrectly. If you want to print the values of 8bits vars ensure you do a casting:
printf("signed:%d - unsigend %u", (INT16)signed_8_x, (UINT16)unsigned_8_x)

- lcc optimizes array indexing using ints, which in 8bits limits array access to 128 as stated in the documentation. It also says that for statically allocated arrays this doesn't apply. At some point of the implementation of the SpriteManager I started seeing some weird behaviour and it took me a while to discover that actually when accessing sprite[10] the 10 was calculated as sizeof(struct sprite) * 10 instead of sizeof(struct sprite) * (UINT16)10 giving me te wrong address of sprite 10 and causing some weird behaviour

- As seen above it is actually a very bad idea to randomly acess an element of an array of structs because it contains a multiplication. Instead it is a good idea to create an array of pointers to the elements of the array on startup and use this array instead

- I've read in lots of places that structs have a lot of problems and you shouldn't use them... as far as I have seen there are no problems using them (except for the array accessing issue which actually makes sense for optimization purposes)

- Also, I've read in lots of places that you cannot use pointers to functions. I have successfully used pointers to functions of 0 and 1 parameters. And the GDBK uses this for interruption handler!

- There are a lot of tutorials telling you how to do things... you'll be surprised to see some of them contain errors and you should use them as reference but never as the absolute truth. Once again check this post from AntonioND

- As a final conclussion... is the GBDK a mess like lots of people are saying on lots of forums and blogs? I have been using it for a month and I can tell you that is a lie. I am not gonna say working with it is easy but that's not the GBDK's fault alone. First there is the SDCC which is the compiler the GBDK is using and probably the one people should be blaming. There is a new version of the GDBK using the latest version of SDCC here, I didnt' have the time to test it. But most of the things people seem to complain about are more related to a lack of C knowledge (and again, this is not a good enviroment for learning it) and the limitations of having to work with and 8-bit machine. The creators of the GBDk are perfectly aware of this as you can see here

Thursday, July 28, 2016

Game Boy Development - Tips and Tricks (I)


As promised here is the first post with some advices based on my experience programming for the Game Boy during the Bit Bit Jam 3.

1. Choosing your SDK

The Gameboy has some different SDks you can choose to work with. The two main ones are the GBDK and the RGBDS. Choosing between any of them depends on what you want to accomplish and what skills you have. Check the next table with pros and cons of each one


GBDK RGBDS
C and asm asm (better than asm in GBDK*)
Slower if you use C Asm is always faster but requires experience
Faster to write programs in C Assembly is very low level, requires more time
Reliable for a jam If you are not an skilled programmer you might not finish your jam entry
Horrible SDK for learning C because of the 8bits limitations, no debugger.... Perfect for learning asm. You can even use a debugger with the BGB emulator 


With all these in mind, I chose GBDK because I have a lot of experience with C and C++ and I was feelling more confident to finish the game with it.

*so I've heard, because I didn't have the chance to try it

2. Getting your environment ready

I will suggest spending some time doing this, it can save you from lot of problems that will happen that last hour before sending the game. Code completion, launching the emu after compiling and the ability to add or delete files from your project easily are the things you should focus to get before starting your project.

A couple of weeks before the jam I started playing with GBDK and getting my development environment ready. Same as I did for the 3ds, Ds and the Wii I started configuring visual studio and some makefiles (see this post for more info). Most of the tutorials I followed along the internet were using some dos .bat files but I was looking for something more general. I created a makefile that:

- Compiles any source found under the folder src, so you don't have to specify the list of files to compile

- Parse the extension of the file to select the bank (anything.c will be on bank0, anything.b1.c will be on bank1, anything.b2.c on bank 2 and so on...)

- Automatically changes the unsigned char of the resources exported by GameBoy Map Builder and GameBoy Tile designed to const unsigned char

And some other features that you can check here. The important thing is having a confortable environment so you only have to worry about coding the videogame

If you are under Windows you will need a way to run makefiles. Since I have been using devkitpro for a long time I already had msys installed. One funny thing that I noticed is that the version of make that comes with devkitpro doesn't display any compilation errors so I guess the stderr is not properly configured. If you have the same problem you just need to download the last version of make for windows here

3. Banks

I would recommend reading the full documentation of the GBDK prior to any development. And specially trying to understand banks, what they are and how they work. AntonioND explains it pretty well on this post. The idea is very simple. If you take a look at the size of variables of the GBDK you'll see that the size of a pointer is 2 bytes. The maximum address you can point to with 2 bytes is 65535 (2^16). In these addresses the gameboy needs to get access to everything, not only the rom. Basically it needs 32kb for internal registers: sound, video, power, etc (you can find the complete list here if you are curious) and then there are other 32 kb for rom access(the cartdridge data). These 32kb are splitted into two: a fixed part that is always accesible (called bank0) and a swapable part (by default set to bank1). You can change the starting address of bank1 and make it point to addresses beyond 65535. Each group of 16386 (16kb) is known as a bank

So the idea is splitting your code along any of these banks and before excuting any part of it swapping the start address so the code can be reached. Take some time to understand this because it is extremely important. And also pay attention to the next things:

- You can only swap banks from code that is stored in bank0. Actually you can swap banks from any bank if you dare but your program will crash and it has an easy explanation. In any computer no matter how big or small it is there is a register (usually known as EIP) that contains the address of the next instruction to be executed. If no jump occurs then this register will automatically advance to the next register and execute the next instruction and basically that's how programs run. So, what will happen if you are in bank2 for example and swap to banks3? The EIP will execute the command to change the bank (in bank2) then it will advance to the next register and will try to execute the next command. The problem is that this comand that was supposed to belong to bank2 now belongs to bank3 and it can be literally anything. An easy solution to this is calling a function on bank0 (always accesible) that swaps banks, do the job on that new bank and then before returning swap banks back to bank2

- Lcc errors. You will eventually find a message like this from the compiler "warning : possibly wrote twice at addr 407a (21>21)". This will happen everytime you write code larger than 16kb and part of it ends in addresses that belong to the next bank. When this happens you should start moving your code to another bank

- Try to fill all banks with some info. If you have decided your game is gonna take 4 banks then the size of the game will be 64kb (16kb per bank) event if you don't fill them. Because of this it is a good idea to put some info in each bank from the beginning, otherwise you won't see the message I was telling you before when a bank gets full and your program will randomly crash at some point

- A stack can be very helpful to deal with bank swapping. Implementing a stack is very simple, you can check my implementation here. Once you have a stack implemented you can use it to move between banks like I do here. Everytime I want to change to a new bank I call PUSH_BANK and when I finish I just call POP_BANK so it automatically leaves me on the previous bank. Using this technique I was able to call gbt_update that automatically changes the bank to bank1 on my vblank interruption and then return to the bank I was previously working on calling REFRESH_BANK, fixing the issue AntonioND is stating on this post

4. Basic Maths

The Gameboy isn't very powerful and it can't even deal with multiplications or divisions, so you should avoid them at all cost (you can use them, but the performance will suffer). Most of these multiplications and divisions can be replaced by simpler operations, like:

- instead of multiplying by any power of 2 use the shift left operator (<<). Specially for multiplying by 2 use x << 1

- instead of dividing by any power of 2 use the shirft right operator (>>). Specially for dividing by 2 use x >> 1

- instead of the module operator (%) with any power of 2 you can do a mask. For example for getting the module 8 of a number do x & 0x7 (7 is 111 in binary so using & here turns everything except the last 3 digits into 0 which is what we want)

- the gbdk manual encourages you to use unsigned values. Take into account that these values are always bigger than 0. So doing something like 3 - 4 will result in an overflow giving you 255 (or 65535 if you are using 16bits) and checking if this is < 0 will unexpectecly return false. The best way I found to deal with this is masking against 0x8000 (1000 0000 0000 0000 in binary) and checking that the result is 0 (that 1 in the highest bit will only happen after an overflow)

Tuesday, July 26, 2016

BitBitJam 3 - Pretty Princess' Castle Escape

The bit bit jam is a retro jam based on old systems up to 16 bits. The jam lasts one week and you can use any technology you have developed before that week. The game must work in real hardware.

Before the jam starts a theme is randomly selected and this year it was "Red Hot Princess Carnage". A total of 20 games were presented. You can take a look at all of them here, and also you can check the winners on each different category: best theme, best platform usage and funniest game

This year I ended up joininig forces with sergeeo. He was in charge of the music and graphics and I was working on all the coding stuff. Together we created Pretty Princess' Castle Escape for the old nintendo Game Boy. Althought we finished the game on time we continued working on it after the jam and finally we have released a new version we consider final. Check it out here!




We'd like to thank all  the guys playing it and specially the ones who have uploaded some videos:



Also special thanks to David Colmenero for organizing the jam and for convince me to participate

During this week I'll be posting a few entries with my experience developing using the GBDK providing some info that I hope will be usefull for someone. Stay tuned!