Register - Login
Views: 99793797
Main - Memberlist - Active users - Calendar - Wiki - IRC Chat - Online users
Ranks - Rules/FAQ - Stats - Latest Posts - Color Chart - Smilies
05-03-22 05:06:11 AM
Jul - General Game/ROM Hacking - Help calculating pointers [GBC] New poll - New thread - New reply
Next newer thread | Next older thread
devin

Yoshi
i'm mima irl
Level: 112


Posts: 37/3519
EXP: 14931833
For next: 406372

Since: 04-29-08

Pronouns: any
From: FL

Since last post: 306 days
Last activity: 3 days

Posted on 03-24-09 05:30:57 AM (last edited by devin at 03-24-09 03:06 PM) Link | Quote
Lately I've been tooling around with GBC hacking again. Right now I'm trying to determine at what point certain graphics are loaded into VRAM, so first I realized i would need to know how to calculate pointer addresses. So I looked around and found this document by Coolboyman:
http://www.zophar.net/documents/gb/gameboy-pointer-hacking.html

At first it seemed to do a good job of explaining the process. I already know about the concept of ROM banks and little-endianness and all that so I didn't have a hard time making sense of things. But then when I tried to actually calculate and search the pointer, I wasn't successful.

In this particular case, let's say the address that I was after in the ROM file is $064000. So after following the procedure in the text file, I get a pointer value of $1B0040. Searched for it and found nothing, so I also tried just $0040 but that inevitably returned way too many matches to be useful.

So am I messing up somewhere in this process? Is there some other more accessible tutorial that I can look at?

[as an aside, i have no idea if there is such a thing as an unheadered GBC rom -- could the fact that this ROM is headered be messing me up?]

Thanks in advance, guys.

EDIT: I found this wiki article - http://www.datacrystal.org/wiki/Pointer#Game_Boy_Pointers which does a better job at figuring out the bank number but I'm still having no luck searching. Any ideas?


____________________
IIMarckus
Member
Level: 25


Posts: 10/111
EXP: 82290
For next: 7330

Since: 10-11-08


Since last post: 3.0 years
Last activity: 1.8 years

Posted on 03-24-09 04:21:59 PM Link | Quote
For one, offset 0x064000 is in bank 19, not 1B. Bank byte = offset / 0x4000

Another issue here is that the GBC doesn’t really have a native format for three‐byte pointers. Some games store the bank byte preceding the pointer, sometimes following the pointer, and sometimes it’s nowhere near the pointer (for instance, if it is inline with some ASM). The only real way to find your pointer if the first two formats don’t give results is to find all instances of $0040 and check them; a corrupter would really help with this. Also, sometimes pointers that are only two bytes long point to within the bank—thus, if there are any instances of $0040 in bank $19, it’s a good bet that one of those is correct.

Originally posted by devin
[as an aside, i have no idea if there is such a thing as an unheadered GBC rom -- could the fact that this ROM is headered be messing me up?]

All GBC ROMs have the same header format AFAIK.

____________________
devin

Yoshi
i'm mima irl
Level: 112


Posts: 38/3519
EXP: 14931833
For next: 406372

Since: 04-29-08

Pronouns: any
From: FL

Since last post: 306 days
Last activity: 3 days

Posted on 03-24-09 06:28:41 PM (last edited by devin at 03-24-09 03:30 PM) Link | Quote
Originally posted by IIMarckus
For one, offset 0x064000 is in bank 19, not 1B. Bank byte = offset / 0x4000


I figured that now after looking at the Data Crystal article. That was the address I originally found using the first article I linked which seems to be wrong or just really poorly written and misleading about ROM banks. Still no luck searching for the 'correct' pointer either, though

Originally posted by IIMarckus

Another issue here is that the GBC doesn’t really have a native format for three‐byte pointers. Some games store the bank byte preceding the pointer, sometimes following the pointer, and sometimes it’s nowhere near the pointer (for instance, if it is inline with some ASM). The only real way to find your pointer if the first two formats don’t give results is to find all instances of $0040 and check them; a corrupter would really help with this. Also, sometimes pointers that are only two bytes long point to within the bank—thus, if there are any instances of $0040 in bank $19, it’s a good bet that one of those is correct.


I thought about that, but in the end it's practically impossible for a 2-byte pointer to be used in this case because bank $19 is nothing but uncompressed graphics and no other code or data. There were quite a few matches for $0040 but that's just because there were a lot of low-detail graphics data that happened to match that value. I also tried searching $004019 instead, still no dice.

I did manage to find a pointer table for a different section of data using the address to a different known data location, which used a standard three-byte pointer, so at least I know I'm calculating it correctly. But I still have no idea about the pointer to those graphics. I guess I'll try plugging away with a corrupter later on and see what happens.

____________________
IIMarckus
Member
Level: 25


Posts: 11/111
EXP: 82290
For next: 7330

Since: 10-11-08


Since last post: 3.0 years
Last activity: 1.8 years

Posted on 03-24-09 06:31:30 PM Link | Quote
Out of curiosity, what game are you working on?
devin

Yoshi
i'm mima irl
Level: 112


Posts: 39/3519
EXP: 14931833
For next: 406372

Since: 04-29-08

Pronouns: any
From: FL

Since last post: 306 days
Last activity: 3 days

Posted on 03-24-09 06:37:49 PM Link | Quote
It's Kirby's Block Ball. I already did a tiny amount of hacking with that game a few years ago and it's a simple enough game to be a relatively easy 'first project'.

____________________
Tanks

360? Yessum.
Level: 121


Posts: 2319/4170
EXP: 19808478
For next: 248218

Since: 07-10-07

From: VA

Since last post: 9.5 years
Last activity: 9.5 years

Posted on 03-27-09 03:27:36 AM Link | Quote
You, sir, need to speak to Erika. I know it's been a while since she's touched GB, but she might be able to lend a hand.

____________________

Erika
Catgirl
미안합니다
Level: 68


Posts: 593/1088
EXP: 2637490
For next: 91310

Since: 07-19-07


Since last post: 9.5 years
Last activity: 9.3 years

Posted on 03-27-09 04:33:41 PM Link | Quote
I wouldn't know much more than what he's doing tbh...because I'd have likely gone about it the same way I really need to re-learn z80..

____________________
Tanks

360? Yessum.
Level: 121


Posts: 2322/4170
EXP: 19808478
For next: 248218

Since: 07-10-07

From: VA

Since last post: 9.5 years
Last activity: 9.5 years

Posted on 03-27-09 05:51:04 PM Link | Quote
Originally posted by Erika
I wouldn't know much more than what he's doing tbh...because I'd have likely gone about it the same way I really need to re-learn z80..


Well there goes my BRILLIANT suggestion.

____________________

devin

Yoshi
i'm mima irl
Level: 112


Posts: 44/3519
EXP: 14931833
For next: 406372

Since: 04-29-08

Pronouns: any
From: FL

Since last post: 306 days
Last activity: 3 days

Posted on 03-27-09 06:19:53 PM Link | Quote
Aww


Well there's always the 'corrupt the hell out of everything' option which I still haven't tried. I guess once I have some time this weekend I'll be doing that for a while.

____________________
Tauwasser
"dumb piece of shit needs to learn some fucking ettiquette" - Anonymous
Level: 21


Posts: 1/73
EXP: 43078
For next: 6865

Since: 04-10-09


Since last post: 11.1 years
Last activity: 10.0 years

Posted on 04-11-09 12:07:32 AM (last edited by Tauwasser at 04-10-09 09:31 PM) Link | Quote
You probably haven't had a very close look at this rom...
Actually all data in every rombank but rombank 0x00 starts at 0x4001. That is, because the rombank number is stored at 0x4000 except for rombank 0x00. This is done in very many gameboy games, as the game can then relax and not track every bank swap because it just has to read from 0x4000 to know where it currently is.

Anyway, I took a look. The data you're looking for seems to be general sprite data or something that is loaded for every level. So ok, here it goes.

There is a pointertable at 0xE9B. It contains 0x10 2byte-pointers. There are many others like at 0x1016 that have the same layout. These are always referencing the following structure:

[length (2byte, signed)][source pointer (2byte)][destination pointer(2byte)][rom bank]...

All 2byte values are LE.
Now. It has two modes for copying data. If length is negative (bit 7 SET), then it will perform decompression, else it will simply copy the bytes from (rom bank) : (source pointer) to destination in ram/vram.

This will loop until a length of 0x0000 is encountered

However, if it is told to decompress, it will actually point to a structure like this:

[decompressed length (2byte)] [compressed data]...

The decompressed length should be reasonable, of course. Also, the data should not cross rom bank boundaries obviously. Anyway, it's an lzXX-style compression routine, here goes:

[compression byte] 8 * [packet]

The compression byte is read from bit0 to bit7 (from lo to hi). A set bit (1) means that the packet is a direct copy of one byte. A reset bit (0) means that it will tack a 2-byte packet:

FEDCBA9876543210
OOOOOOOOOOLLLL

Repetition length is L + 3 bytes. Repetition offset is bits 4 to F, remember endianness! If the offset is actually in front of the buffer (meaning you would read before the data you already wrote), you cause to copy 0x00 instead of any data that there might be. If you're less bytes from the start of your data than you would copy, then you start copying from the start of the decompressed data when you copied enough 0x00 to be inside of the data boundary again.

Examples:

[10][00][00][1D][00]
(length) (compression byte) (1 packet)

would produce: [00][00][00][00][00][00][00][00] [00][00][00][00][00][00][00][00] (0x10 times 0x00)

[10][00][01][01][3C][00]
(length) (compression byte) (2 packets)

would produce: [01][00][00][01][00][00][01][00] [00][01][00][00][01][00][00][01] (5 times 0x01 0x00 0x00 then one 0x01 again)

Routine for all that at approx. 00:0E6B.

____________________
cYa,

Tauwasser
devin

Yoshi
i'm mima irl
Level: 112


Posts: 87/3519
EXP: 14931833
For next: 406372

Since: 04-29-08

Pronouns: any
From: FL

Since last post: 306 days
Last activity: 3 days

Posted on 04-11-09 05:22:29 AM (last edited by devin at 04-11-09 02:23 AM) Link | Quote
Wow, thanks

I don't have my copy of the ROM handy at this very moment but I'll definitely look into that stuff ASAP. I had already noticed the byte at the beginning of every bank but I didn't really notice that they referred to the number of the bank itself.

As for the pointer tables, that's just the thing I was looking for Regarding the compression, did you happen to notice if any of the data referenced in the two tables you found actually utilized that compression scheme? Out of all the data I've found for the game so far (mostly tilemaps and sprite/tile graphics) was completely uncompressed so the possibility of having to deal with compressed data didn't cross my mind at all.

However the compression might be the reason why my attempts to find any other data about the game yielded completely unpredictable results (as I said, i don't currently have a copy of the rom available so i can't check it out myself just yet.)

Anyway, thanks a ton for the info I'll be sure to give it a look the next time that I can.

____________________
Dwedit
Member
Level: 19


Posts: 45/61
EXP: 34966
For next: 811

Since: 08-03-07


Since last post: 111 days
Last activity: 78 days

Posted on 04-11-09 07:16:33 AM Link | Quote
Originally posted by Tauwasser
the rombank number is stored at 0x4000


Interesting...
I know how Zelda did it (store the bank number at FF98 before writing the bank number to ROM), but that's another decent way to do it. Only problem is that you lose the ability to have contiguous data across pages. I'd say the Zelda method is better.

____________________
Tauwasser
"dumb piece of shit needs to learn some fucking ettiquette" - Anonymous
Level: 21


Posts: 2/73
EXP: 43078
For next: 6865

Since: 04-10-09


Since last post: 11.1 years
Last activity: 10.0 years

Posted on 04-11-09 02:25:04 PM Link | Quote
@Dwedit: Yep. Ususally older games do this only. Maybe it was stuff from the original SDK. Of course you would still have to write code that can change the rombanks if data crosses boundaries (like in Zelda iirc), however, it has some pros and cons for both methods. I know Pokémon G/S also does keep track of the rom bank (also FF98 iirc lol), however, it always has to utilize multiple registers to get a bank swap/call into another bank, so you have to write all arguments to the functions you call to stack or into other ram locations... a bit icky...
The best way I have seen to this day is utilized in shin megami tensei: devil children. They just have a rst $0 defined to take the next 3 bytes and branch to it, so you can keep all your registers' contents

@devin: Yes, some data actually uses this compression method. The decompression routine can be called seperately and a lot of data uses it as far as I can tell. For example in the intro etc. Also, you could just check the table offsets I gave you and find out for yourself

cYa,

Tauwasser

____________________
cYa,

Tauwasser
devin

Yoshi
i'm mima irl
Level: 112


Posts: 88/3519
EXP: 14931833
For next: 406372

Since: 04-29-08

Pronouns: any
From: FL

Since last post: 306 days
Last activity: 3 days

Posted on 04-11-09 08:22:32 PM (last edited by devin at 04-11-09 10:07 PM) Link | Quote
I'm looking at those two pointer tables right now, here's what i've found:

The first table (at $e9b) points to nothing but instances of that structure which all reference$10001, which is the address of Kirby sprite graphics and stuff like that There are actually more instances of the same structure located in between, which load level-specific tile graphics and enemy graphics. Apparently it keeps reading that type of structure until it reads two zero bytes. I didn't see this part written in your post before, whoops

Haven't really looked at the other table yet, I'll check it out later.

edit: the table at $1016 is cutscene graphics

____________________
Next newer thread | Next older thread
Jul - General Game/ROM Hacking - Help calculating pointers [GBC] New poll - New thread - New reply


Rusted Logic

Acmlmboard - commit 47be4dc [2021-08-23]
©2000-2022 Acmlm, Xkeeper, Kaito Sinclaire, et al.

32 database queries, 7 query cache hits.
Query execution time: 0.086024 seconds
Script execution time: 0.025605 seconds
Total render time: 0.111629 seconds