I'm MeroMero (yes the same MeroMero from Smogon)
I finally jumped the gun and joined PokéCommunity just so I could share my findings.
Be ready though, this post is going to be quite long.
When an offset is followed by an asterisk (*) ,it means that the offset differs between different regions (and sometimes between games of the same region).
Unless specified otherwise, bytes’ endianness is usually little-endian.
EDIT: Type-chart updated
Changing the template’s color for ???-typed moves on the bottom screen to suit Fairy-type moves better.
This one is easy:
Go to offset 0×290
7A 5A 17 4E B5 45 72 3D 30 31 ED 28 CB 20 FB 66
DF 7E 3F F2 1E 6A DD 59 5B CD 17 C1 D6 B4 37 7F
The colors will fit the Fairy-type much more now.
Editing the Incenses-babies.
Go to offset 0×FF4AE*
You should see this:
68 01 FF 00 CA 00
2A 01 FE 00 B7 00
B7 01 3A 01 7A 00
B6 01 3B 01 B9 00
BE 01 3C 01 8F 00
CA 01 3D 01 E2 00
96 01 3E 01 3B 01
B8 01 3F 01 71 00
B1 01 40 01 66 01
Format is BB BB II II DD DD.
BB BB is the baby produced when at least one parent holds the corresponding item.
II II is the item that at least one parent has to hold.
DD DD is the default baby when none of the parent holds the corresponding item.
For example we’re going to dissect the 7th row, shall we?
96 01 is a Pokémon ID.
Invert the 2 bytes and you get 01 96.
Converting from base 16 to base 10 we get 406.
Oh, it’s Budew!
This is the same principle with the item ID and the default baby ID.
Item ID: 3E 01 => 01 3E => 318 => Rose Incense
Default baby ID: 3B 01 => 01 3B => 315 => Roselia
The instruction is as follows: If at least one of the Parents hold the Rose Incense, Budew will hatch from the egg, otherwise Roselia hatch from the egg.
So if you have understood, it means we basically have to replace all 9 instances of DD DD by their corresponding BB BB.
Change the previous bytes and you should obtain this:
68 01 FF 00 68 01
2A 01 FE 00 2A 01
B7 01 3A 01 B7 01
B6 01 3B 01 B6 01
BE 01 3C 01 BE 01
CA 01 3D 01 CA 01
96 01 3E 01 96 01
B8 01 3F 01 B8 01
B1 01 40 01 B1 01
Neat, now how about you go and hatch that Budew without a Rose Incense, hum?
* Regions’ differences:
Spanish HG 0×FF496
Spanish SS 0×FF49E
Korean HG 0×FFB5A
Korean SS 0×FFB52
Heal Bell ignores the Soundproof’s check and behaves exactly like Aromatherapy
Disclaimer: Read all the paragraph before attempting any manipulation.
Q: What are those? A: Those are the very moves blocked by Soundproof.
Each move is 2 bytes long, for example let’s try this one: 30 01.
Invert the 2 bytes and you get 01 30.
Now convert from hex to decimal and you get 304.
304 is the ID number for the move Hyper Voice!
Well what move are we trying to break already? Oh yes, Heal Bell.
So the move Heal Bell has been assigned the ID number 215.
Okay 215 in hexadecimal is D7, since moves are 2 bytes long instead let’s go with 00 D7.
Invert the 2 bytes and you get D7 00.
Time to go and check against the previous string…
HEY! But there’s no bytes equal to D7 00 in there!
Explanation: Actually this string lists the moves blocked by an opponent’s Soundproof! Have you ever tried to use Heal Bell against that Exploud? Believe it or not but it will work.
When it comes to the move Heal Bell, the game will instead perform a check against all of your team members’ abilities, and if a Pokémon affected by a major status condition happens to have Soundproof, it will not be healed.
Tough luck, huh? But this will come to an end with those simple-to-follow steps.
Go to offset 0×98A0* and change the value D7 into 00
Do the same at offset 0×21ADE*
Go to offset 0×98B0* and change the value 2B into FF (anything between 7C and FF included will do the trick)
Do the same at offset 0×9906* and offset 0×21AE4*
Offset 0×98A0 is the check for Heal Bell’s execution for the Pokémon on the battlefield, on the side of the Heal Bell’s user.
Offset 0×21ADE is the check for Heal Bell’s execution for the remaining team members of the Heal Bell’s user team.
Offset 0×98B0 is the check for Soundproof against the Heal Bell’s user.
Offset 0×9906 is the check for Soundproof against the teammate of the Heal Bell’s user (Double battle only).
Offset 0×21AE4 is the check for Soundproof against the remaining team members of the Heal Bell user’s team.
Basically the new instruction is: check if [Pokémon] used move with ID 0 and check for every instance of ability with ID 255.
You shouldn’t replace 2B by 00, because the ability with ID number 0 is used in-game when an ability gets cancelled (Gastro Acid comes to mind), whereas you can replace D7 by 00 since there is no legitimate way to get the move with ID number 0.
* Regions’ differences:
Language Offset 1 Offset 2 Offset 3 Offset 4 Offset 5
Japanese 0×98A8 0×98B8 0×990E 0×21AE6 0×21AEC
Korean 0×98A4 0×98B4 0×990A 0×21AE2 0×21AE8
Others 0×98A0 0×98B0 0×9906 0×21ADE 0×21AE4
Here is its format :
AA DD EE
_AA : attack type
_DD : defender type
_EE : effectiveness
those 3 bytes are repeated consecutively for basically each type, and the table will end at the first occurrence of AA DD equal to FF FF.
AA and DD can take one of the following values :
_0×00 : Normal
_0×01 : Fighting
_0×02 : Flying
_0×03 : Poison
_0×04 : Ground
_0×05 : Rock
_0×06 : Bug
_0×07 : Ghost
_0×08 : Steel
_0×09 : ???
_0×0A : Fire
_0×0B : Water
_0×0C : Grass
_0×0D : Electric
_0×0E : Psychic
_0×0F : Ice
_0×10 : Dragon
_0×11 : Dark
EE can take one of these 4 values :
_0×00 : ineffective
_0×05 : not very effective
_0×0A : normal damage
_0×14 : super effective
As you have guessed, EE is actually a multiplier, but before the effect is applied, EE is divided by 10, thus the origin of the coefficients ×0, ×0.5, ×1 and ×2 !
But there's a first problem, if you try to search for 00 05 05 00 08 05 0A 0A 05, etc. in the ROM, your hex editor of choice will return no results!
This is because the overlay that contains the table (overlay 12 here) is LZ-compressed (all overlays are compressed in HGSS anyways).
Decompress it with Crystal Tile 2 for example.
Okay now you search through the decompressed overlay 12 with your hex editor, and now you have found the string, great; but there's a second problem!
Look at the table, there's no EE bytes whose value is equal to 0×0A!
That's because 0A is the default multiplier in Gen 4 Pokémon games, which is why ???-typed moves/Pokémon deal/take neutral damage to/from everything. But unlike Gen 2 and Gen 3, thanks to the Physical-Special split, ???-typed moves are actually able to deal damage greater than 1HP (read real damage).
How is it going to affect us?
Well you're going to have a hard time if you want to port the Fairy type effectiveness in HGSS (for the sake of an example).
If you try to add (DON'T !) even only one more relationship, once you get into a fight you will break the game since the arm9 code will read wrong instructions from everything in the overlay 12 that come after the type table…
How to trick the game then?
First you have to understand how the game works:
Let's say you have 2 main states in Pokémon games, the overworld and the fights.
The game needs to load the following overlays for the overworld: 1, 2, 3 and 27 (Group 1)
And it needs to load these for the fights : 6, 7, 10, 12, and 18 (Group 2)
Actually the overlay 10 is loaded every time you get to choose your action, the overlay 7 when you have chosen said action (and initially at the beginning of the fight too).
Once you press continue on the menu screen, the game will load the group 1, and when you get in a fight, it will load the group 2, once you are finished with your fight the game will load again the group 1, etc.
You can see that with the RAM Viewer around address 0×021D0E00 for those who are curious
It's something like this:
If you parse through the RAM, you'll see that when the overlays from one group are loaded, the previous overlays who happened to be there will be overwritten.
The trick here is to find a place in the RAM that is not used during the fights and that could be used to fit in the new table.
And such an area exists!
It just so happen that overlay 18 and overlay 1 have the same offset in the RAM, but ovl_1 is much longer than ovl_18! That's exactly what we need.
What does it means? It basically means that the ovl_1 leftovers is basically free space during the fights!
Open your Pokémon HeartGold or Pokémon SoulSilver ROM in Crystal Tile 2.
Click the NDS icon (or alternatively click Ctrl+N).
Expand the window if necessary.
Right-click on overlay9_0012.bin and click Extract (not Export !), this will actually decompress the overlay.
Do the same for overlay9_0018.bin.
Open both decompressed files in a hex editor.
Add your improved type-chart at the end of overlay9_0018.bin
I advise you to make a full chart with all 324 relationships from the get-go, so that if you want to change something, you won't have to go through all the trouble again.
Or you can take mine, which is up to date with the relationships according to Gen 6 :
search for 7CCC2602* and change it for 60BE1F02* (4 occurrences)
search for 7DCC2602* and change it for 61BE1F02* (3 occurrences)
search for 7ECC2602* and change it for 62BE1F02* (3 occurrences)
Language original pointers updated pointers
Japanese 78C12602 E0B01F02
English 7CCC2602 60BE1F02
French 9CCC2602 A0BA1F02
German 5CCC2602 60BA1F02
Italian 1CCC2602 20BA1F02
Spanish HG 9CCC2602 A0BA1F02
Spanish SS BCCC2602 C0BA1F02
Korean 80D62602 A0C41F02
As you have guessed, the pointers will point to the type table, what you did here is relocating the pointers to the new and (admittedly) more complete table.
Save both files and close your hex editor.
Back to Crystal Tile, right-click on overlay_0012.bin and click Compression, this will actually import the LZ-compressed of your file back into the ROM.
Do the same for overlay_0018.bin, but be careful now the file is too large to be contained between ovl_17 and ovl_19 even when compressed ! But do not fret, Crystal Tile will take care of that for you.
Just click OK.
Close Crystal Tile 2, and now your ROM is ready.
Want to make Poison super-effective against Water ? Sure thing mate.
Want to make Ice resistant to Dragon ? Knock yourself out !
Want to add all the Fairy type relationships ? That's the reason that drove me to think outside the box and find a way to present you this.
Wow ! And I'm still not done, but others discoveries will be for another time, I think those will take enough of your time to swallow.
Other discoveries include:
Adding a functional item (why not, the Pixie Plate)
Adding an item's effect ID to the list of ×1.2 type-enhancer items
Edit the move Judgment so it takes into account the Fairy-Type, yes the case for type 9 is not taken into account in the move's code
Edit Pokémon coordinates and shadow on the battlefield (not by me)
The code for evolution methods 18, 19 and 1A was scrapped in HGSS
Explorer Kit was dummied out in HGSS, it will appear as a blank item
There's NO way to legitimately make Arceus stay in its ??? form in gen IV games without modifying the code, in the code the case for type 9 (???-type) is simply non-existant, plus even if you could get it you would have to modify the move Judgment too.