ASM & Hex Adding a new type [GS]

Started by ElectroMan May 14th, 2018 4:38 AM
  • 865 views
  • 3 replies
Seen February 21st, 2019
Posted May 16th, 2018
4 posts
3.7 Years
The main question I have is how do I make a pointer to an address in another bank work?

For the past couple days I've been fiddling with an Hex Editor and checking the inner workings of Pokémon Gold. With the help of this very forum, I found the type effectiveness chart in address 0x34D01. The type chart is composed of three bytes for each type effectiveness to consider. (Those not in the list are assumed by the game to be normal effectiveness.)

Problem
In normal circumstances this list has length of 332 bytes, which includes a "Foresight demarcation" byte FE and a termination byte FF, totalling 110 type interactions. The two pointers that make use of this list, as far as I can tell, are in addresses 0x34891 and 0x34935 in the same memory bank. It's attractive to add more types into the engine, which is what I am looking into. Adding the Fairy-type, for example, would yield 12 more type interactions to consider, which would mean adding 36 new bytes to the list. This is impossible where the list stands in the memory since it's tightly surrounded on both ends by relevant engine data.

Possible solution
The bank this list is allocated in is unusually tight and not flexible at all. There is no space at the end to copy the list and expand it. The only other option is to write it in another free space in a different bank and have the pointers point to them. This is where I hit a brick wall. Doing so in, for example, the free space in the bank right after (address 0x3B6A0) means setting the pointers to A0 76, which does not work at all. Am I missing something in doing this? I'm guessing it needs another byte to specify the bank number, but this would write over bytes right after the pointers.

miksy91

Dark Energy is back in action! ;)

Male
Finland
Seen September 6th, 2019
Posted August 30th, 2019
1,485 posts
13.3 Years
You can only point to addresses within the same rom bank. For example pointer A0 76 in this case refers to address 0x376A0 (and not 0x3B6A0) because the rom bank is 0x4000 bytes long starting at 0x34000.

In order to expand the table, you could either:
1) try moving the table to another rom bank (requires at least some asm hacking),
2) try moving most of the asm routine handling the table along with the table to another rom bank,
3) try finding some other data to move to another rom bank, or
4) try moving data following the type effectiveness table at the end of the rom bank. I take it you would need to move 36 bytes of data at the minimum.

Unfortunately none of the previous options are easy to take. The fourth one might be easiest thing to do, but that wouldn't generalize for example for adding two new types.

In my own hack, I happened to re-locate all the trainer data along with around 0x200 bytes of code handling the data to another, originally empty rom bank (and thus did what I mentioned as option 2 here). It wasn't easy though and required quite a lot of debugging and "backtracking" code handling the trainer data pointer table in such way that it was possible. I basically had to understand at least somewhat properly, what the original routine was like and where it was initially accessed from and in what situations. After understanding these, it was possible to move the data by changing pointers pointing to the "start points" of the actual code handling the trainer data.

I can't unfortunately give a clear solution for you to overcome this issue. You could however think about moving to editing pokecrystal disassembly because it provides for example more flexibility in tackling issues such as you have right here. With disassembly, you could easily expand the table in place getting the 12 interactions for Fairy type. This would mean that all the following data in the same rom bank would just end up 36 bytes ahead of their original location. And thus you would only run into the same issue with there not being enough space in this rom bank if there wasn't originally 36 bytes of free space at the end of it.
Pokémon Dark Energy
Some ROM hacking related stuff
Seen February 21st, 2019
Posted May 16th, 2018
4 posts
3.7 Years
Thank you very much for the detailed reply miksy91.

The reason I wanted to do the binary hacking in the first place is because I am doing a simple randomizer, that will consist of a program that takes as input ROM data, and through lookup tables of its own, would know which bits to flip according to another lookup table. After all it's done I would like an option to update move data to newer generations and add the new type chart, including Fairy-type.

I understand the options available now, after digging into ASM documentation and such. I did get pokecrystal in my PC and tested it out for myself in a Pokémon Crystal ROM. And in fact it does add onto the list at the end and repoint all the pointers to that bank. So what I did was I only added one type interaction through pokecrystal (insert 3 bytes into the end of the list), effectively shifting everything coming afterwards in the bank, and compared with a source ROM. Apart from the bank in question (bank 13), which has differences too numerous to enumerate, here's a list of all addresses of the pointers affected (with the 3-byte shift):

Bank 1:
Spoiler:
0xE97F
0xF053
0xF4E3
0xF4EC
0xF4F2


Bank 9:
Spoiler:
0x271B3


Bank 10:
Spoiler:
0x2C501


(Bank 13)

Bank 14:
Spoiler:
0x38562
0x38D6C
0x38D72
0x393FA
0x39401
0x39407
0x3C2A3
0x3C2D4
0x3C2E4
0x3C371
0x3C378
0x3C480
0x3C907
0x3C958
0x3C9F6
0x3CA64
0x3D8F8
0x3DD30
0x3DDB0
0x3DDEA
0x3DE27
0x3DE2F
0x3DE5A
0x3DEBF
0x3DEF3
0x3DEFD
0x3DF00
0x3DF03
0x3DF06
0x3DF09
0x3DF0C
0x3DF0F
0x3E4AD
0x3E73D
0x3E886
0x3FD32
0x3FD36 to 0x3FDC1 (pointer table)
0x3FDC6 to 0x3FE6B (pointer table)
0x3FE6E to 0x3FE85 (pointer table)


Bank 62:
Spoiler:
0xFBD4E
0xFBD6C
0xFBD74


Additionally, right at the start, in bank 0, there's a 2 byte change which I don't know the significance of:

0x14E - 18 D2 -> F5 52

So my mode of attack will be to create a ROM with the interactions plugged in pokecrystal (I changed the target ROM from Gold to Crystal), and have my program look into all those addresses, repoint them all accordingly, and completely rewrite bank 13 for ease of implementation. As of right now that is the only tangible method I can think of and it shouldn't be too much of a hassle.

If it is a matter of public interest, I may post bank 13 in its entirety with the Gen VI interactions built in, then all the value of all the pointers in those addresses I listed, in case someone in the future wants to implement this method. Though doing so in the disassembler is simple enough, so maybe it's not that interesting a deal.

miksy91

Dark Energy is back in action! ;)

Male
Finland
Seen September 6th, 2019
Posted August 30th, 2019
1,485 posts
13.3 Years
And in fact it does add onto the list at the end and repoint all the pointers to that bank.
I can't tell if you just wrote this in a lazy way here, but I'm pretty sure no references / pointers to bank 13, that point to offsets in front of the type effectiveness table, are changed. Just by expanding the table, you're not really touching any of the previous data in the same rom bank.

Additionally, right at the start, in bank 0, there's a 2 byte change which I don't know the significance of:

0x14E - 18 D2 -> F5 52
Address 0x14E contains the "Global checksum" over the whole rom data. GB / GBC / GBA console might work so that it first calculates checksum over the whole rom data and compares it to the global checksum. If these two wouldn't match, it would know that the rom is corrupted and refuse to start its execution (= let the player play the game). Apparently GB doesn't verify the checksum.

More info here: http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header

Nevertheless, I would just assume that during compilation of pokecrystal, the global checksum is always calculated to be correct. Some rom editing tools I've been using for hacking Dark Energy (Silver rom hack) seem to also touch this without me knowing it which I've been quite surprised of. Haven't noticed which tool has been modifying it on the background without me ever accessing that address though.

But yeah, sounds like a reasonable way to tackle this issue :)
Best of luck! I believe you can make it!
Pokémon Dark Energy
Some ROM hacking related stuff