’Cause all games were better on the GBC

You are not logged in.

#1 2013-08-27 21:57:50

Registered: 2013-02-04
Post 46/118

Setting up RGBDS (IIMarckus)

Posted by IIMarckus on Fri Jul 03, 2009

RGBDS is an assembler package for creating Game Boy ROMs. It is no doubt the most popular GB assembler nowadays, and was widely used back in the GBC’s heyday—even for official games, as it was more usable than Nintendo’s own tools!

That said, Otaku no Zoku (the last maintainer) stopped working on it back in 1999, so there are a few forks lying around the net. I know of two: Lai’s and vegard’s. Use Lai’s for now, because it allows partial inclusion of binary files—for what we’re doing, we need to embed large chunks of the original ROM into the output. I’ve talked to vegard and he says he’ll add in Lai’s modifications sometime, but it hasn’t happened yet.

UNIX install

Make sure you have GNU Make (pmake won’t work), GCC, and Bison installed on your machine. Just grab the source, extract, cd to the src/ directory, and gmake install / make install. This should put the programs somewhere in your $PATH, so everything’s ready to go.

Windows install

Windows users can grab a precompiled version—if you do this, be sure to grab the original source code (linked above), as it comes with helpful HTML documentation for the assembler.

If you have Cygwin, you can of course install GNU Make, GCC, and Bison through that and compile the source yourself. You should get the same results in the end.

Assembling a ROM

RGBDS has a nice INCBIN command, which includes a portion of a ROM file. Unfortunately you cannot include more bytes than the size of a bank—you’ll have to include the ROM in chunks of 0x4000 bytes, and create a section for each. Rather than type it all manually, I just used Perl:

printf "SECTION \"bank0\",HOME\n"
       ."INCBIN \"baserom.gbc\",0,\$4000\n\n";

    for($bank = 1; $bank <= 0x7F; $bank++)
       printf "SECTION \"bank%X\",DATA,BANK[\$%X]\n"
          ."INCBIN \"baserom.gbc\",\$%X,\$4000\n\n",$bank,$bank,$bank * 0x4000;

That resulted in this file. There’s your base ASM source. To assemble it, run rgbasm -ooutfile.o infile.asm (with your base rom named “baserom.gbc” and in the same directory). This makes an object file, which can theoretically be linked with other object files to make a ROM. In practice we only need one object file, though.

To link, we need a linkfile. This tells the linker which object files to take in, and what ROM to put out. We only need to make this once. Since we’re taking one input file and making one ROM from it, it should look like this:



Name it whatever you want, or something.

Now run xlink -z0, and you get a playable ROM file! The -z0 fills empty space in banks with 00.

The last thing is to run RGBFix, which changes the checksums in the ROM header (among other things). rgbfix -p0 -v outfile.gbc and boom, you’re done.

So what can you do with this?

Right now it compiles to an exact copy. What if we want to change things? Well, go to the bank you want to edit and change the incbin to include less than $4000 bytes, then do stuff.

Example: In Red, edit wild Pokémon by replacing bank 3 with:

INCBIN "baserom.gbc",$C000,$10DD
    NoWildMonsters: ; a word followed by a colon is a label that can be referenced elsewhere in the program
       dw 0 ; dw inserts a word, aka two bytes. you could just as easily do this with db 0,0
       db $19 ; encounter rate
       db 3,$24 ; level 3 Pidgey
       db 3,$A5 ; $ means the number is hexadecimal
       db 3,$A5 ; % means the number is binary
       db 2,$A5 ; no prefix means the number is decimal
       db 2,$24
    ;etc, don't forget to include the rest of the bank

You can write the pointer to Route1Monsters with dw Route1Monsters, and the bank number with db BANK(Route1Monsters).

You can also define names for values to make things more readable:

    PIDGEY EQU $24

       db $19 ; encounter rate
       db 3,PIDGEY
       db 3,RATTATA
       db 3,RATTATA
       db 2,RATTATA
       db 2,PIDGEY
    ; etc

Tada, instant wild Pokémon editor!

Even better, RGBDS has a nice macro system. Rather than insert text and manually calculate the bank and pointer to it, just prefix the text with a label and use this in your source:

       db $17
       dw \1
       db BANK(\1)

Then typing “TX_FAR labelname” will instantly write all the bytes for you, no calculation needed. You could even move the text elsewhere in the ROM, and it would still work fine as long as the label is in place.

No doubt most of the G/S scripting commands could be implemented this way.

Of course, since we’re including chunks of the ROM that means we have to be careful not to shift any data in those chunks to different offsets. This would be no problem if we weren’t including any data with pointers in the first place. This means that the more of the ROM that is disassembled, the easier it will be to write more ASM. That’s why I’ve been (slowly) working on what will hopefully become a complete disassembly of Pokémon Red. This is a long‐term project, and will be made public when a friend of mine sets up a version control server for it. In the meantime, try this out, and read the documentation!

Posted by IIMarckus on Fri Jul 03, 2009
Funny how I just spent 20 minutes writing an ASM tutorial that has no ASM in it.

Posted by Hat on Fri Jul 03, 2009
Excellent! This tutorial will definitely make my life easier later on (random stuff). Lots of thanks to you, IIMarckus, for posting this up.

Have fun with the Red disassembly process!

Posted by Melash on Sat Jul 04, 2009
Yeah, I agree, this is excellent. I remember you talking to me about a 'project', so this must have been it. Anyway, I really hope you finish the Red disassembly process, it should help hackers out quite a bit. I'm downloading this program right now, so I'll post later on how useful it was. Thanks for posting this!

Edits changed to … d00.tar.gz changed to … d00.tar.gz.
Links to RGBDS commands left out, no longer working.


Board footer

Powered by FluxBB