View Full Version : [Tutorial] Cy-Chan's Guide to Re-Pointing for Newbies (GB/C & GBA)

January 26th, 2009, 2:41 PM
To start with, the one people are probably more interested in...

Cy-Chan's Quickie Guide to GBA Pointers!

What are pointers? Well, an equivalent in other programming languages would be a "goto", "gosub" or perhaps a "call" command. They make the code start reading from a new area.

In hex, these areas are known as addresses, of such range from $000000 to $FFFFFF (in a standard GBA rom), obviously "0" being the lowest number in the hexadecimal format, and "F" being the highest.

In the GBA games, pointers are very simple. ASM reads bytes backwards, so hex address $7A6B5C becomes 5C6B7A08.

But wait! Reversed would mean "$7A6B5C" becomes "C5B6A7"! Cy-Chan, you suck! Ahah, but that is majorly incorrect! You see, a single digit value is known as a "bit", and the hexadecimal format works with "bytes", that is, the combination of two values.

Now, what about that 08? Well, the memory bank for the GBA is made up of several sections. For example, 02 is RAM, 03 is DMA; check the memory viewer in VBA for more detail. So, when referring to ROM information (the bit we hack), the full address will start with 08. In an extended ROM, any addresses past 08FFFFFF simply loop back to 0, but use 09 as the indentifier instead.

So that's why pointing to $7A6B5C in ROM would be done with the pointer 5C6B7A08.

And now for something awesome!

Cy-Chan's Quickie Guide to GB/GBC Pointers!

Oh gosh, I couldn't resist. After recently hacking a bit of Gold for fun, I learnt about some of the architecture there too, and found that the pointer hacking guides currently out there are a bit vague.

So, to start, there's a 3-bit pointer system. Let's say we want to point to $3B1C2. The simple part; take the last two bytes and reverse them. Currently, our pointer is C2B1.

The last value in the pointer needs to then be between 40 and 7F, so, subtract or add 40 until the byte is between them. B1 - 40 = 71, so our pointer stands at C271.

Then, divide the address by 4000. This gives us 0E. This is our bank number. We place this at the beginning of the pointer (so, 0EC271). Ta-dah! 3-byte pointer.

Now, what is a bank number, you ask? Well, the GBC is much smaller than the GBA, and can only keep a certain amount of data loaded at one time (8000 bytes, to be exact). 4000 of these bytes are known as bank 0, basically the default bank that contains all the really important stuff.

The other 4000 are used for bank switching. So, if a pointer says to use bank 31 (31*4000 = C4000), then that bank is loaded, and it is pointed to.

What about the last byte in the pointer; why does this have to be between 40 and 7F? Ahah, well the switch bank is stored between $4000 and $7FFF. If we take the last two bytes of our previous example pointer (2C71), and re-reverse them (712C)... well, look at that. It sits nicely within the switch bank.

If we hadn't made that last byte fit between 40 and 7F, it would instead point to C271, a location within RAM!

That brings us to another problem though. A lot of the time, the bank number is omitted from the pointer, making a 2-byte pointer instead. This is because, if the bank is already loaded, then it doesn't need to be re-loaded, does it?

However, what if we wanted to switch bank? Sadly, this is where many people get frustrated. Changing a 2-byte pointer to a 3-byte pointer requires ASM. This is because the bank has already been loaded by an ASM command (to register A, to those who know their business), while the pointer is loaded by another command (in hex "21", usually).

Changing the bank number could potentially screw up several routines, so one needs to be careful when messing around with it.

Cy-Chan's Guide to Memory Maps

Just a quick addition here. On the GBA (and GBC) there's things known as memory maps. These are what contain all the data. Different sections are allocated to different portions of memory, so that's why $08000000 contains all the ROM (read-only memory) information, and why $02000000 contains RAM.

A full memory map can be found in the GBATek, alongside a load of other useful information, if anyone wants to Google it.

Code runs sequentially. This is, it goes from start to end (at least, in does at assembly level). Pointers are used in what's known as a JMP command, or a "jump" (or a "branch"; an if statement). This is where a different part of code is loaded, from a different area.

So, when we tell a pointer to go to $A01010 (1010A008), we're telling it to read information, or continue running the code in that area.

Cy-Chan's Guide to Repointing

I've mentioned pointers, and how to repoint, but there's no clear definition on what we're actually doing here, is there?

Well, sure, the rom is made up of assembly-level code. However, we're not changing that; we're just changing what it does with the code. For example, Fire Red's type weakness/resistance table is located at $24F050. We'll reverse that to make 50F02408.

Search the rom using your favorite hex editor (I personally suggest 010 Editor) for our pointer, and gosh, what do you know? Several results appear. These are all pointers to the type chart.

We know that there should be some free space around $720000, so we'll make our pointer go there. Replace all of the 50F02408 results with 00007208 (replace all is a useful function...)

Then, go to $24F050. Here is our type chart. Copy all of the information from $24F050 to $24F19E, and paste it into the blank area at $720000.

And we're done. To conserve space, you can go back and remove the data at $24F050 to $24F19E (perhaps for future use), but as far as we're concerned, the information has been transferred. Try it out; do all the types still work correctly? And now we have a ton of space to work with, so adding new weaknesses and resistances is no problem!

I personally like the idea of Water being weak to Poison, but that's just the tip of the iceberg. Adding new (special) types is quite easy to do...


Hope you enjoyed this tutorial, y'all! If you did, don't just let it die; leave comments. Feedback or whatever.

January 26th, 2009, 4:24 PM
Thanks for helping me understand pointers better : D Trying very hard no to be ignorant right now but I can't help but ask: is it possible to include a bit about finding a script offset from a GBA pointer? I still have zero understanding about that part.

January 26th, 2009, 5:04 PM
Generally to know the pointer, you'll need to know the offset it points to. If you have text in your script, you can locate it by searching for the text (in something like Translhextion), and then searching for the pointer of that text. The pointer will be located wherever you placed the text in your script (so, Message @hello; that @hello is the pointer).

February 9th, 2009, 11:58 AM
A-ha. -claps- I think I'm getting it now. Correct me if I'm wrong...

So in order to repoint data in the ROM - say, from the old type weakness/resistance table to a new and expanded one - one must change the pointer in the ASM code?

-goes to learn more about ASM- This is becoming more interesting by the minute. Hacking is quite the underappreciated art, it seems.

February 9th, 2009, 1:37 PM
Hm, not quite. ASM isn't really required knowledge, unless you're getting into really tricky stuff (such as adding animations). If you can make do without it, do so.

Anyways, peeps! I've updated the tutorial with two new sections; a quick view over memory maps, and a proper guide to repointing (rather than just explaining pointers). Both are intended for the GBA though, my apologies to you awesome GBC hackers!

February 10th, 2009, 1:49 PM


Hah, finally I know how to add that Light-type!! -hacks like crazy-


Cy-chan, you are this project's savior!

February 10th, 2009, 9:29 PM
THANK YOU SO MUCH FOR THIS! I've been wondering about how to do this for ages!
I just have one question. If you make a new type via repointing, how would you add a picture for that type, like the one that shows up on the Pokemon summary screen?

February 10th, 2009, 11:56 PM
By tinkering. The pointer to the type pictures points to some Pokéball image just before them. Then I believe there's some values after the pointer that show which image to load. You'll need to repoint it, and then mess until it works.

My Sound patch (signature) may give more information.

Kaylee Krysteenah Fynch
February 16th, 2009, 2:22 AM
I always thought there should be a light type too... I'll keep this in mind. Thanks.

February 16th, 2009, 7:48 AM
Thanks, I have never really understood Hex but this has helped a bit, now i just need to learn hex so i can apply it to the games o-o;