Jump to content

Recommended Posts

Posted (edited)

** You will need to understand Part 1 of this tutorial before you can decompress the files used in any other parts**

Trainer Offsets: colosseum trainer data.json

Shadow Pokémon Original Offsets: shadow trainer data.json

For each trainer there are 6 Pokémon entries but not all of the slots have to be used. After 6 slots of Pokémon, there is one unused entry then the first slot of the next trainer is right after that. This means that you can start at the first trainer and to get to the next trainer all you need to do is jump 7 slots. This also means that you can easily give any trainer up to 6 Pokémon without having to repoint or expand the data. (Of course the more Pokémon you add the larger the compressed file size will become).

Each Pokémon has a byte which you can set to make it a Shadow Pokémon. That byte is effectively the flag that gets set when you catch that Pokémon and just by setting the flag the game will consider it to be a Shadow Pokémon and your partner will react to it (even if she hasn't actually joined you yet). I don't actually change this because setting this flag to an unused flag just means every time you fight that trainer they will have the Shadow Pokémon no matter how many times you catch it. If you use a flag that is used by the game then you will affect the trainers who's teams rely on that flag. So if I set the flag to the same flag that Evice's Tyranitar uses, then when I reach Evice he won't use the team with Shadow Tyranitar, he'll just use the replacement one.

Also each team that has a Shadow Pokémon has an exact copy of the Shadow Pokémon. So if you want to change one of its moves you will have to change that move on every team that it appears on which can sometimes be up to 4 teams. I made a program that takes the changes to one and applies it to all of the other iterations automatically. In the source code there is a .json file containing all the default occurrences of each Shadow Pokémon.

The source code also contains a .json file with details for each trainer in the game. Since I don't know where the trainer data is saved I had to fill it in manually. I recorder the name, trainer class, in-game location and file offset for each of the trainers.

The first trainer in Colosseum (Folly at the Phenac city entrance) is in the common_rel at offset 658820 (0xA0D84). Each Pokémon is 80 (0x50) bytes long and so each team is 480 bytes long and to go from the start of one team to the start of the next team you jump 560 bytes (because there is an empty Pokémon inbetween). The actual first Pokémon entry is at offset 0x9FE28 but the first few are a bit dodgy, maybe used when they were testing the game. Folly's Pokémon start at the 0x31 (49th) Pokémon entry.

N.B. The trainers don't change their teams based on the Shadow Pokémon you've caught but based on the flag set when it was caught. So when you catch a trainer's Shadow Pokémon, the next time you fight them the game loads up a different team so you will find trainers who have two different teams, one for if you've caught their Shadow Pokémon and one for if you haven't even if the "caught" team is just the same team without the Shadow Pokémon.

When I was still trying to figure the game out, the trainers were the first thing I researched and the first thing I discovered. This meant that at the time I was documenting it and writing my programs I didn't have everything fully figured out yet. I noticed that each Pokémon has the value (0x0004) in it at a certain point and so I used this to search for Pokémon before I realized they were all next to each other and the distances between them were just unused Pokémon. All of the offsets in this section are relative to this 0x0004 value which is actually 12 bytes into the Pokémon's data. If you want you can subtract 12 bytes from each of the start offsets I use in the trainer data json files and then add 12 bytes to each of the offsets in the Pokemon.swift object from the source code (the same offsets in the table below.) I just stuck with it because it would be tedious to update all my code (I'll do it eventually).

The Pokémon's ability can be either 0 or 1, each representing one of the two abilities set in the stats for that Pokémon. You can't give it any ability. For values of other variables like genders, items and natures check out the enumerations in the source code on GitHub.

For the values of the Pokémon's ability, nature, gender, EVs and IVs you can set the value to 0xFF (255) and the game will automatically replace those values with randomly generated values. All the Shadow Pokémon had 0xFF for those values by default.

The "FF Offsets" detailed below are the bytes which are set to 0xFF for any Pokémon that isn't in use. I'm not sure if it's required by the game but my program will fill them in automatically for me when I delete a Pokémon from a trainer while setting all the other necessary values to 0. However if you do something as simple as putting an invalid species for the Pokémon like Pokémon number 0 or Pokémon number 252 (which is one of the empty slots in gen III) then the game will play as usual but the team will be loaded without that Pokémon.

However, if you set proper stats for the Pokémon in slot 252 including choosing one of the models and names already available in the game files then the Pokémon will be playable. You could use this for something like making a duplicate of a Pokémon except it has different abilities and that way you could in essence have a Pokémon with up to 4 different abilities because you could use the two species interchangeably. You could also make something like Meowstic/Gallade/Frosslass where you make a copy of a Pokémon except one of them is all male and the other is all female. You could then give them different level up moves or different evolutions depending on which one it is. In the future, if we crack the model formats we could probably use those slots to add new Pokémon without having to replace old ones.

Just to clarify, the offsets for each variable are relative to the "four offset" at 0x12 from the actual start of the Pokémon so the first variable is documented as being at an offset of -12 from the 0x0004 but is really at an offset of 0x00 from the Pokémon start. I will also add the "true offset" which is relative to the actual start of the Pokémon but if you are comparing with my source code on git hub then use the four offset.

Trainer Pokémon data table

Variable Size (bytes) Offset from 0x0004 True Offset  
Ability 1 0x0C 0x00  
Gender 1 0x0B 0x01  
Nature 1 0x0A 0x02  
Shadow ID 1 0x09 0x03  
Level 1 0x08 0x04  
Pokémon Species 2 0x02 0x0A  
"Four offset" 2 0x00 0x0C (almost always 0x0004)
Held Item 2 0x06 0x12  
HP IV 1 0x10 0x1C  
Attack IV 1 0x11 0x1D  
Defense IV 1 0x12 0x1E  
Sp. Attack IV 1 0x13 0x1F  
Sp. Defense IV 1 0x14 0x20  
Speed IV 1 0x15 0x21  
HP EV 1 0x17 0x23  
Attack EV 1 0x19 0x25  
Defense EV 1 0x1B 0x27  
Sp. Attack EV 1 0x1D 0x29  
Sp. Defense EV 1 0x1F 0x2B  
Speed EV 1 0x21 0x2D  
Move 1 2 0x2A 0x36  
Move 2 2 0x32 0x3E  
Move 3 2 0x3A 0x46  
Move 4 2 0x42 0x4E  
ID String of Name 2 0x0A 0x16 (The Pokémon's nickname will be the string this points to. This is why with the current AR codes when you change a Pokémon's species it's name doesn't change. For the most part setting this value to 1000 + the Pokémon's national dex number, i.e. Bulbasaur is 1001 (0x3E9) and Treeko is 1252 (0x4E4), gives you the right string but I think it stops following the trend somewhere half way through the gen III Pokémon. I haven't tested it but it may be possible to give a trainer's Pokémon a nickname by setting this to the id of a string you've changed.)

Typically a trainer will send their Pokémon out in the order they are specified in the data. However, sometimes, and for reasons I don't know yet, a Pokémon will be sent out in a different order to that specified. Usually they are Shadow Pokémon. Most are simply added to the team last but some are added first and still get sent out last every time. Some are added first and come out first as expected. Sometimes a trainer will randomly mix up their Pokémon order in different battles (like after a soft reset). More research is required.

Editing the trainer teams is really fun and creating lots of interesting teams will likely be the main goal in many hacks. However, the more you change, the more likely you are to be increasing the compression size as you start to make lots of unique Pokémon, while the original has a lot of repetition since it didn't feature that many, especially not from gen I. The battle mode trainers are made to be more competitive, but the story mode trainers never have any IVs or EVs on them (hence they're almost all so pathetically weak) although they sometimes have beneficial natures. They almost never have held items either. Almost no trainers have 6 Pokémon and they don't all know 4 moves. This means that the process of making the teams more fun, varied or competitive will almost definitely result in a much larger compressed file size.

By far the best way to decrease the compressed file size is to put 0x00s over all the Pokémon in battle mode if you don't mind not having it in your hack. This will give you enough space to go wild. By doing this my common_rel is 7 KB smaller than the original even though I've changed and added so many Pokémon as well as editing a lot of moves and stats. You can choose to just remove moves, items, evs and/or ivs or even 1 or 2 Pokémon from battle mode teams rather than removing all of their Pokémon completely in order to have a more competitive story for a less competitive battle mode. You can also rely on remove data from other parts of the file like the moves, stats and text since there are all of them in the same file. Finally, you could delete some Pokémon from some of the less important story mode characters. There are Zigzagoon and Hoothoot that were going to get OHKO'd anyway so might as well save the space.

I'm sure we'll soon find out how to safely increase file sizes and then we won't have to make these trade-offs but I think it's worth it for now.

While writing this documentation I have just finally found where the trainer data is stored in Colosseum! It is in the common_rel file with the first trainer being at offset 0x92F04. The order of the trainer data seems to differ from the order of the trainer teams though. Each entry is 52 (0x34) bytes long. The id of the trainer's name string refers to text in the common_rel string table. There are 3 optional string ids at the end of each trainer's data. The first being what they say before the fight (usually only used in colosseums since the you don't see those battles are initiated automatically), the second is what they say if they win (usually only for colosseums and mount battle because anywhere else you just "black out")and they third is what they say if they lose. These strings are found in the string tables in fight_common.fsys's "fight" and "tool_fight" files. Each trainer also has an index for their in-battle model and their trainer class. I will compile a list of these indexes eventually. The index of the trainer's first Pokémon also gets 2 bytes. The Pokémon at index 1 starts at offset 0x9FE28 (a value of 0x31 means the 49th Pokémon entry including the empty rows between trainer teams). Each trainer can also have up to 8 items like potions and x-attacks.

Trainer data table

Variable Size (bytes) Offsets
Index of Trainer Class Name 1 0x03
Index of Trainer's First Pokémon 2 0x04
Name String ID 2 0x0A
Index of Trainer Model 1 0x13
Item 1 2 0x14
Item 2 2 0x16
Item 3 2 0x18
Item 4 2 0x1A
Item 5 2 0x1C
Item 6 2 0x1E
Item 7 2 0x20
Item 8 2 0x22
Post Battle String ID 2 0x26
Win String ID 2 0x2A
Lose String ID 2 0x2E

va-1.jpg

Part 8:

 


View full tutorial

Edited by StarsMmd
  • 4 weeks later...
Posted

I was looking at the Colosseum Trainer Pokemon data, and I noticed a couple of things.

First, I think the EVs take 2 bytes each. For one thing, they have the space. (HP EV would start at offset 0x22, Attack EV would start at 0x24, etc...) If you think about it, 255 (0xFF) is a valid EV value. If EVs can be randomized like you say, then it would make sense that you couldn't mix that trigger (0xFF) up with a valid value; so I think their random value is actually 0xFFFF. I haven't tested it for a few reasons, perhaps mostly because I wouldn't know how to check the Pokemon's EVs to know when they've actually been randomized.

The other thing is, you missed the Pokemon's moveset. All four of the Pokemon's moves are given at offsets 0x36, 0x3E, 0x46, and 0x4E, respectively, with each taking 2 bytes.

Posted

Yeah, I noticed they were 2 bytes each but I just ignored it since the maximum value for an EV is only 1byte. 0xFFFF does make sense for randomising the value as it is used as a randomiser value for a lot of variables. I didn't consider that since the game never randomises EVs. I lost interest in colosseum when I realised I could implement the phsyical/special class split in xD so I probably won't get around to testing your theory but if/when you do I'm curious to know.

And yeah sorry, I spent about a week typing up everything I knew on notepad and then copy and pasted it onto the forums at about 5am in the morning so I probably made a few mistakes along the way. I will correct that now, thanks for pointing it out.

I should probably post my discoveries as they come rather than piling them up... I think I'll post some updates soon.

Posted (edited)

I've parsed out a few things about Trainers and their Pokemon that were missing from above. I'm just gonna repeat some of what you've already written above, just so I can make complete thoughts. It's possible some things are off, like what I've assumed to be the first and last entries of a data set. Any static values might also actually have some meaning, but they're impossible to figure out just from looking at the raw data.

One thing I realized is that, if string IDs are really 4 bytes long like you describe in your tutorial part 2, then they're probably 4 bytes in all other structures too. I was able to use the Dolphin debugger to test this, changing an NPC's string ID from 0000NNNN to 1000NNNN and when I tried to speak to them they didn't say anything (the dialogue window flashed briefly, like it wanted to print but didn't have anything to print).

You also said, StarsMmd, that every 7 entries is the team for a different Trainer, but it turns out that's not strictly true, because one of Ein's teams starts at 2814 and then Eagun's starts at 2822 (everything after that then continues the pattern of 7 entries per "team"). I kind of wonder if, when the game loads a team, if it just reads the first 6 Pokemon entries from that index, or if it reads to the first "empty" entry, or what; I wonder what would happen if you tried to put one "empty" entry right in the middle of a "team", or if you didn't put any empty entry for like 20 entries. At any rate, it's apparent that the game doesn't strictly care what index you give it to start (though it may care what comes after that).

Also, the early Trainer/Trainer Pokemon indices may get used for externally sourced data, like e-Reader card Trainers and versus battles, given the strings associated with those Trainers.

Trainer class data:

  • In: common.fsys\common_rel.fdat
  • Start: 0x90F70
  • Entry size: 0x0C (dec 12)
  • Entry count: 42

Offsets...

  • 0x00 -- 2 bytes -- Payout
  • 0x02 -- 2 bytes -- 0
  • 0x04 -- 4 bytes -- Name string (ID)
  • 0x08 -- 2 bytes -- 0
  • 0x0A -- 2 bytes -- Unknown...

The entries for this data correspond to the Trainer class indices used in the Trainer data. With the start position I've given for this, that would be a 0-based index.

I think the final prize money is Payout * 2 * Max_Pokemon_Level, but I haven't checked enough to be sure it's not actually multiplied by the level of the last Pokemon in the Trainer's team. Even though the high byte is always 0 naturally, I tried changing it in the Dolphin debugger, and it definitely affects the final prize money.

I'm also assuming the 0x0A value is two bytes, and not two different 1-byte values. Both bytes do see use. If you sort by this value, you get some interesting groupings, like two groups you could mostly call "good guys" and "bad guys": they're almost all common Trainer classes, and one of the groups is almost exclusively those classes that can own a Shadow Pokemon (Researcher and News Caster buck the trend) and the other group is exclusively classes that don't.

Trainer data:

  • In: common.fsys\common_rel.fdat
  • Start: 0x92ED0
  • Entry size: 0x34 (dec 52)
  • Entry count: 819

This data could possibly start one "entry" farther back, at a "round" 0x92ED0. All of the bytes for that entry would be 0 except for offset 0x00, which would be 2. I don't know of any way to say for sure that it can't start there... Maybe if I found whatever structure defines which Trainer/team is in a map.

Offsets...

  • 0x00 -- 1 byte -- Gender (0: male, 1: female)
  • 0x01 -- 1 byte -- 0
  • 0x03 -- 2 bytes -- Trainer class (index)
  • 0x04 -- 2 bytes -- First Pokemon (index)
  • 0x06 -- 2 bytes -- AI
  • 0x08 -- 4 bytes -- Name string (ID)
  • 0x0C -- 4 bytes -- Opening animation (index)
  • 0x10 -- 4 bytes -- Model (index)
  • 0x14 -- 2 bytes -- Item 1 (index)
  • 0x16 -- 2 bytes -- Item 2 (index)
  • 0x18 -- 2 bytes -- Item 3 (index)
  • 0x1A -- 2 bytes -- Item 4 (index)
  • 0x1C -- 2 bytes -- Item 5 (index)
  • 0x1E -- 2 bytes -- Item 6 (index)
  • 0x20 -- 2 bytes -- Item 7 (index)
  • 0x22 -- 2 bytes -- Item 8 (index)
  • 0x24 -- 4 bytes -- Pre-battle string (ID)
  • 0x28 -- 4 bytes -- Win string (ID)
  • 0x2C -- 4 bytes -- Lose string (ID)
  • 0x30 -- 4 bytes -- Alternate lose string (ID)

FYI, given what I've assumed below is the start of the Trainer Pokemon data, the First Pokemon value would be a 0-based index into that data.

For the AI, there are many possible values, the specifics of which I mostly don't know. Some AIs obey the priority bytes in the Trainer Pokemon data, while some ignore them and just send the Pokemon out in the order they're read. The Battle Mode Trainers tend to get unique values here (especially, Mt Battle Area Leaders get special values here, while the 9 Trainers before them usually get some common value, with the notable exception of Trainers 91-99), as do the "boss" characters in the Story Mode, while the run-of-the-mill Story Mode Trainers tend to be given one of several common values (it's possible their AI advances as the player gets farther into the story, but I didn't check that thoroughly).

The opening animation value basically just points to miscellaneous in-battle animations (things like ball effects, stat boosts...if you want to know everything, the best option may be to just try them all and see for yourself) and plays them, often applying them to the Trainer if possible. Most of these probably aren't actually meant to be used in this structure and are instead just available as a kind of side effect of the intended use. The game only naturally uses 0x60-0x66 for this value, on the Cipher Admins and Gonzap, Nascour, and Evice, which makes them strike a pose and makes the camera behave in a certain way. Note that the animation that results (particularly for such poses) can depend on the Trainer's model.

Maybe you got it backwards, StarsMmd, but you said above that 0x24 is a post-battle string, when in fact it

a pre-battle string instead.

The "alternate lose string" is triggered when the Trainer's Shadow Pokemon is captured. (It's only naturally used for Rogue Cail.

,
.) If the Trainer's Shadow Pokemon was caught and this value is 0, the default lose string is shown instead.

One thing I was also on the lookout for was battle music, but I wasn't able to figure out a value in the Trainer data or Trainer class data that might control that. (The only good candidate in the Trainer data is 0x06, but Miror B. has a couple different values in a couple places but the same music. And as for Trainer classes, Miror B. is a Cipher Admin, but his music is much different than the other Admins'.) It may be that the music is actually set in whatever structure actually defines which Trainers are in a map. Or else in some other, probably very difficult to track down, way.

Trainer Pokemon data:

  • In: common.fsys\common_rel.fdat
  • Start: 0x9FE28
  • Entry size: 0x50 (dec 80)
  • Entry count: 5510

Offsets...

  • 0x00 -- 1 byte -- Ability slot (0-index)
  • 0x01 -- 1 byte -- Gender (0: male, 1: female, 2: genderless)
  • 0x02 -- 1 byte -- Nature (0-index)
  • 0x03 -- 1 byte -- Shadow ID
  • 0x04 -- 1 byte -- Level
  • 0x05 -- 1 byte -- Priority
  • 0x06 -- 1 byte -- Unknown...
  • 0x07 -- 1 byte -- 0
  • 0x08 -- 2 bytes -- Friendship
  • 0x0A -- 2 bytes -- Species (index)
  • 0x0C -- 2 bytes -- Ball caught in
  • 0x0E -- 2 bytes -- 0
  • 0x10 -- 2 bytes -- Item flag
  • 0x12 -- 2 bytes -- Held item (index)
  • 0x14 -- 4 bytes -- Name/nickname string (ID)
  • 0x18 -- 2 bytes -- 0
  • 0x1A -- 2 bytes -- Unknown...
  • 0x1C -- 1 byte -- HP IV
  • 0x1D -- 1 byte -- Attack IV
  • 0x1E -- 1 byte -- Defense IV
  • 0x1F -- 1 byte -- Sp Attack IV
  • 0x20 -- 1 byte -- Sp Defense IV
  • 0x21 -- 1 byte -- Speed IV
  • 0x22 -- 2 bytes -- HP EVs
  • 0x24 -- 2 bytes -- Attack EVs
  • 0x26 -- 2 bytes -- Defense EVs
  • 0x28 -- 2 bytes -- Sp Attack EVs
  • 0x2A -- 2 bytes -- Sp Defense EVs
  • 0x2C -- 2 bytes -- Speed EVs
  • 0x2E -- 2 bytes -- 0
  • 0x30 -- 1 byte -- Move 1 PP bonuses
  • 0x31 -- 3 bytes -- 0
  • 0x34 -- 2 bytes -- Moveset flag 1
  • 0x36 -- 2 bytes -- Move 1 (index)
  • 0x38 -- 1 byte -- Move 2 PP bonuses
  • 0x39 -- 3 bytes -- 0
  • 0x3C -- 2 bytes -- Moveset flag 2
  • 0x3E -- 2 bytes -- Move 2 (index)
  • 0x40 -- 1 byte -- Move 3 PP bonuses
  • 0x41 -- 3 bytes -- 0
  • 0x44 -- 2 bytes -- Moveset flag 3
  • 0x46 -- 2 bytes -- Move 3 (index)
  • 0x48 -- 1 byte -- Move 4 PP bonuses
  • 0x49 -- 3 bytes -- 0
  • 0x4C -- 2 bytes -- Moveset flag 4
  • 0x4E -- 2 bytes -- Move 4 (index)

Most of these parameters have a "flag". This is how I think this structure is used overall... First, a default Pokemon is created based on the species and level specified by the entry; that is, it starts off looking like any random wild Pokemon you might encounter, with random IVs, Nature, gender, and Ability, no item or EVs, default moves, and I guess base friendship (friendship is the one thing I haven't bothered trying to look at closely). Then, the game reads the data for the current entry and adjusts each of the Pokemon's parameters to match the values in the entry; however, if the "flag" for one of those parameters is turned on, that parameter from the entry is ignored and the default value comes through instead.

The "flag" for Ability, gender, Nature, (probably friendship), and the IVs and EVs is just the highest bit of the specified bytes above. The game will set a flag by just setting the value to 0xFF or 0xFFFF, but that's technically a bit "overkill" and any value of at least 0x80 or 0x8000 will work. Any value that doesn't have the highest bit will cap out for the IVs, EVs, and probably friendship (and Abilities too it looks like, but the result is a blank Ability), but the game may not handle unexpected Natures or genders well. For the moves and the held item, though, the flag is the highest bit in a separate pair of bytes, and all bits besides the highest bit have no effect whatsoever on the move or item.

0x05 gives a priority for the Pokemon to be sent out, but it's up to the Trainer's AI to recognize and act on it, otherwise the Pokemon are just sent out in order. In short, a value of 3 means the Pokemon comes last and 2 means the Pokemon comes first (if there's only one...). For more details, see -hacking-tutorial-part-7-Editing-Trainers-(Colosseum)&p=205400&viewfull=1#post205400'>this post.

The unknown 0x06 byte I just...don't even know what to think of so far. There's plenty of values and plentiful enough combinations on a team.

"Ball caught in" is the 0x04 value you were noticing above, and corresponds to the values listed here (you'll notice 4 is a regular Poke Ball). 0 or anything above 12 won't show anything in the Poke Ball spot. I played with the other nearby values too, but they didn't seem to change anything as far as I could tell (or I didn't change them right).

0x1A is a bit weird, because a lot of the time it's just an incremental value, one greater than it was in the previous entry; but sometimes it skips a few or a lot and I just can't tell what it might be for.

The "PP bonuses" have a valid range of 0-3, basically meaning how many PP Ups have been used on the move, and higher values have the same effect as 3. Weirdly, I couldn't seem to find a way to increase the Pokemon's current PP; so if I put 1 PP bonus on Tackle, the Pokemon would always start with 35/42 PP.

And, just because the Pokemon data uses Natures and I'm not sure of a "good" place to post this...

Nature data:

  • In: common.fsys\common_rel.fdat
  • Start: 0x122E60
  • Entry size: 0x28 (dec 40)
  • Entry count: 25

Offsets...

  • 0x00 -- 1 byte -- Battle purification
  • 0x01 -- 1 byte -- Walking purification
  • 0x02 -- 1 byte -- Call purification (out of Hyper Mode/sleep)
  • 0x03 -- 1 byte -- Day Care purification
  • 0x04 -- 1 byte -- Cologne purification
  • 0x05 -- 1 byte -- Attack modification
  • 0x06 -- 1 byte -- Defense modification
  • 0x07 -- 1 byte -- Sp Attack modification
  • 0x08 -- 1 byte -- Sp Defense modification
  • 0x09 -- 1 byte -- Speed modification
  • 0x0A -- 1 byte -- 0x64
  • 0x0B -- 8*1 byte -- Unknown...
  • 0x13 -- 1 byte -- 0x00
  • 0x14 -- 4 bytes -- Nature string (ID)
  • 0x18 -- 7*1 byte -- Unknown...
  • 0x1F -- 7 bytes -- 0x64 (each/all)
  • 0x26 -- 2 bytes -- 0

These entries correspond to Nature indices (such as are used in the Trainer Pokemon data) with a 1-based index. That is, the first Nature/entry, Hardy, has index 1.

I've tentatively deciphered the first 5 bytes by taking what a FAQ claimed were the purification preferences of each Nature, and associating that with those bytes when they're sorted. I don't know exactly how the values influence purification (the short version is simply that higher numbers mean a larger effect), but I'm actually planning to spend some time on purification and try to put some hard numbers to it all, including these Nature effects.

The "modification" bytes have three possible values. 0x00 means the stat is increased, 0x01 means the stat is not affected, and 0x02 means the stat is decreased.

The 0x0B-0x12 and 0x18-0x1E bytes have a limited number of values, but I can't guess what they do. The interesting thing about both sets is that they tend to be in multiples of 5 and 10, like percents perhaps (the first 8 kind of tend low, and the latter 7 kind of tend higher). The only thing I can think up is that they could be AI parameters, sort of like the Emerald Battle Palace AI battles (though I don't actually have the first idea how the Battle Palace AIs were implemented). But Natures usually don't do much at all, so seeing all these values is kind of bewildering.

I also have no idea if any of the static bytes actually have some meaning. I can't help but harbor a bit of suspicion for the ones that are 0x64 (decimal 100) in particular, especially all the ones that come right after 0x1E.

Edited by Tiddlywinks
tested some things with Dolphin debugger
Posted

This is really interesting stuff. I didn't even think about structures like the natures and trainer classes. I think I actually stumbled across the trainer class one in xD but didn't realise it's significance. I assumed the prize money was a value stored with each individual trainer like in the gba games iirc.

You said you think the trainer data probably starts an entry earlier and I think you're probably right. From what I've been seeing recently a lot of tables start with an empty row for index 0. e.g. the move data and pokemon stats tables both start with empty rows since there is no pokemon or move 0. However the type data (and I'm assuming natures too) don't have that empty row since 0 is a valid type value for the normal type. Where you said the data may start an index later at 1, I can't remember what you're referring to since it has been a while since I looked at colo but it probably does start at 0 even though it's unused because 0 is a possible value that could be assigned for that variable.

On my very first editing attempt, I was changing the hex for some trainers manually using my hex editor and I accidentally set the value for a trainer's pokemon to a value between celebi and treeko. It took me a while to notice because rather than crashing the game or anything, the game just ignored that pokemon. As you will know, arrays in programming start at index 0 so it is a valid index and the game just ignores empty entries.

oh and in case you were wondering, the indexes between celebi and treeko will work if you fill those entries with values first.

Also, I don't know if you noticed but most trainers send their pokemon out in the same order as they are specified in the data. However, on rare occasions they will send them out in a different order. Most shadow pokemon are last in their teams but a few are first in their teams and yet they are still sent out last. Sometimes a trainer will just send their pokemon out in random order which changes each time you battle them. I was wondering if you'd seen any values that could specify this. I thought it could be the value in the pokemon list that is always between 0-3 but this had no effect on their ordering.

As for where the game specifies which trainer is in which map, the second file in the .fsys for each map is the file with all the scripts for that map. In xD this file is very easy to piece together because it contains a lot of human readable text in it. However, the equivalent file in colosseum has no such text and so I don't know what any of it means but it probably serves a similar purpose. The 3rd file in the map .fsys files is a string table of the strings that appear in that map. In xD if you search for any if the string ids contaibed in the third file, in the second file they will appear. You could try searching for the trainer IDs in this file. The ID is most likely the same as the index in the trainer data

Finally, since you're clearly really into this research I recommend taking a look at gecko and ar codes for pokemon colosseum. There is so much that was figured out years ago from looking at the ram. Usually they just figured out the really obvious data but sometimes you may find something interesting. like One code for xD came with a list of all the values for the trainer models.

Posted
Also, I don't know if you noticed but most trainers send their pokemon out in the same order as they are specified in the data. However, on rare occasions they will send them out in a different order. Most shadow pokemon are last in their teams but a few are first in their teams and yet they are still sent out last. Sometimes a trainer will just send their pokemon out in random order which changes each time you battle them. I was wondering if you'd seen any values that could specify this. I thought it could be the value in the pokemon list that is always between 0-3 but this had no effect on their ordering.

Yeah, I saw these

videos of
and was pretty much mind-boggled that he apparently sent out completely different Pokemon at the start. I was looking at those 0-3 values too, and I was half convinced they were "send out priority" levels (since Dakim's Pokemon in that battle all had 0 except for Houndoom at 3), but then I saw
where Dakim sent out Metang (value=2) and Golem (value=0) first, and he seems to do so consistently in other videos. So no, I can't tell right now (and may not figure out) what might control that stuff...
As for where the game specifies which trainer is in which map, the second file in the .fsys for each map is the file with all the scripts for that map. In xD this file is very easy to piece together because it contains a lot of human readable text in it. However, the equivalent file in colosseum has no such text and so I don't know what any of it means but it probably serves a similar purpose. The 3rd file in the map .fsys files is a string table of the strings that appear in that map. In xD if you search for any if the string ids contaibed in the third file, in the second file they will appear. You could try searching for the trainer IDs in this file. The ID is most likely the same as the index in the trainer data

I did actually look at those xD script files a bit, but beyond finding string IDs and noticing some patterns around them, I wasn't able to decipher anything. I've been able to handle assembly like the pokered disassembly before, but if the data in those files is assembly (I do at least understand that it's a different beast from pokered for Colo/XD), I'm having trouble understanding it so far.

Finally, since you're clearly really into this research I recommend taking a look at gecko and ar codes for pokemon colosseum. There is so much that was figured out years ago from looking at the ram. Usually they just figured out the really obvious data but sometimes you may find something interesting. like One code for xD came with a list of all the values for the trainer models.

I have seen some of those codes and lists. I'm even using a very nice one that lets me control the opponents to facilitate my investigation of unknown offsets via RAM manipulations with the Dolphin debugger. :biggrin: I also had a bit of fun playing around with one that let me change a connection to any location in xD for a while.

Posted (edited)

Hahaha it's pretty funny that we both had the same idea! I'm sure it'll become obvious eventually.

The scripts definitely aren't assembly if you compare them to start.dol but yeah it's hard to figure them out. You can tell what they're doing you just can't tell how right now. The easiest way to test would be change values and see the results ingame but that process would be so tedious. Maybe one day...

And yeah the code for controlling your opponent is one of my favourites. Very useful indeed.

And, just because the Pokemon data uses Natures and I'm not sure of a "good" place to post this...

Nature data:

  • In: common.fsys\common_rel.fdat
  • Start: 0x122E60
  • Entry size: 0x28 (dec 40)
  • Entry count: 25

Offsets...

  • 0x00 -- 1 byte -- Battle purification
  • 0x01 -- 1 byte -- Walking purification
  • 0x02 -- 1 byte -- Call purification (out of Hyper Mode/sleep)
  • 0x03 -- 1 byte -- Day Care purification
  • 0x04 -- 1 byte -- Cologne purification
  • 0x05 -- 1 byte -- Attack modification
  • 0x06 -- 1 byte -- Defense modification
  • 0x07 -- 1 byte -- Sp Attack modification
  • 0x08 -- 1 byte -- Sp Defense modification
  • 0x09 -- 1 byte -- Speed modification
  • 0x0A -- 1 byte -- 0x64
  • 0x0B -- 8*1 byte -- Unknown...
  • 0x13 -- 1 byte -- 0x00
  • 0x14 -- 4 bytes -- Nature string (ID)
  • 0x18 -- 7*1 byte -- Unknown...
  • 0x1F -- 7 bytes -- 0x64 (each/all)
  • 0x26 -- 2 bytes -- 0

These entries correspond to Nature indices (such as are used in the Trainer Pokemon data) with a 1-based index. That is, the first Nature/entry, Hardy, has index 1.

I've tentatively deciphered the first 5 bytes by taking what a FAQ claimed were the purification preferences of each Nature, and associating that with those bytes when they're sorted. I don't know exactly how the values influence purification (the short version is simply that higher numbers mean a larger effect), but I'm actually planning to spend some time on purification and try to put some hard numbers to it all, including these Nature effects.

The "modification" bytes have three possible values. 0x00 means the stat is increased, 0x01 means the stat is not affected, and 0x02 means the stat is decreased.

The 0x0B-0x12 and 0x18-0x1E bytes have a limited number of values, but I can't guess what they do. The interesting thing about both sets is that they tend to be in multiples of 5 and 10, like percents perhaps (the first 8 kind of tend low, and the latter 7 kind of tend higher). The only thing I can think up is that they could be AI parameters, sort of like the Emerald Battle Palace AI battles (though I don't actually have the first idea how the Battle Palace AIs were implemented). But Natures usually don't do much at all, so seeing all these values is kind of bewildering.

I also have no idea if any of the static bytes actually have some meaning. I can't help but harbor a bit of suspicion for the ones that are 0x64 (decimal 100) in particular, especially all the ones that come right after 0x1E.

Also I had a look on bulbapedia to see what else is affected by a pokemon's nature. The only other known effect is the effect on a pokemon's pokeblock flavour preferences. A lot of useless data like egg groups and egg cycles are carried over from the gba games so I wouldn't be surprised if most of the unknown values in the nature data were for the pokeblock data.

Also near the beginning of common_rel you will notice the ascii text for the names of all the sounds in the game from fanfares to background music. If you were to list these you could assume they're in the same order as the indexes used to reference them. You could figure out the index of miror b.s music from this and see if you can find it in those structures. There's no way to know that the songs are listed in order but it's quite likely.

Edited by StarsMmd
Posted
Also I had a look on bulbapedia to see what else is affected by a pokemon's nature. The only other known effect is the effect on a pokemon's pokeblock flavour preferences. A lot of useless data like egg groups and egg cycles are carried over from the gba games so I wouldn't be surprised if most of the unknown values in the naturehttp://projectpokemon.org/forums/showthread.php?46258-Stars-Pokemon-colosseum-and-xD-hacking-tutorial-part-7-Editing-Trainers-(Colosseum) data were for the pokeblock data.

Also near the beginning of common_rel you will notice the ascii text for the names of all the sounds in the game from fanfares to background music. If you were to list these you could assume they're in the same order as the indexes used to reference them. You could figure out the index of miror b.s music from this and see if you can find it in those structures. There's no way to know that the songs are listed in order but it's quite likely.

If anything, I would actually bet that stat boosts and Pokeblock flavor preferences would work from the same values, just applying it to different contexts (like either Attack or Spicy flavors). And besides, I don't think any of the other offsets had a distribution of values that could even match the Pokeblock preferences like the stat modification offsets do.

I'll have to keep those sound names in mind if I get around to looking for them. Thanks.

Posted

It turns out the send-out order can just depend on the AI. Normally, Willie will always send out his male Zigzagoon (the first one) first, then his female Zigzagoon. But when I gave him Dakim's AI, he sent them out randomly. On the other hand, if I gave him Dakim's first team (at Mt Battle; original order is Entei ("priority" 3), Metang (2), Marshtomp (0), Golem (0), and Camerupt (0)) with his default AI, Willie would send out Entei and Metang. So then I let him run for a while with Dakim's AI too, and I saw him send out Metang+Golem, Metang+Marshtomp, and Metang+Camerupt (though this last only came after like a dozen tries, so maybe there's some probability involved). Entei would always end up last in the party, too.

Playing with various teams and values for the "priority" byte, it's apparent that Pokemon with priority 3 get shoved to the end of the party. Pokemon with priority 2 "fight" it out for the first spot, by which I actually mean one of them is randomly chosen to be sent out first. Any priority 2 Pokemon that "lose" basically get relegated to priority 3. The Pokemon within priority 3 (including "losers" from priority 2) are ordered randomly. Pokemon with priority 0 basically don't move, and I can't actually tell any difference between that and priority 1. The Pokemon within priorities 0 and 1 (together) are ordered randomly. Anything above 3 also seems to be, practically speaking, equal to 3. (I actually tried parties with 0xFE and 0x03 together for a while, but in a dozen tries, all I got was 0xFE then 0x03 in the last two slots; but with 0xFF and 0x03 I did get them in either order. So either I'm just getting "bad" luck with 0xFE or everything above 3 doesn't necessarily get randomized with it.)

I can't say if this only holds for Dakimn's AI (0x56) or if any AI that reads and uses those priority bytes will use them in the same way. Maybe one of them clearly distinguishes 1 from 0 somehow (since it is used naturally sometimes; I haven't tried to check the AIs used where that happens, though). At the very least I imagine many AIs that use the priority bytes act the same.

I also still don't know what the byte after the priority byte does, in particular whether it plays any part in the order the Pokemon is sent out.

In other news, it turns out the game definitely stops reading as soon as it sees the first empty entry after the "first Pokemon" index from the Trainer data. This can result in a kind of amusing battle with no Pokemon on the opponent's side that ends as soon as you make any move (or when your turn is over, depending on which actions you take)... The game also stops reading after 6 Pokemon (or else there's just no way to access any more than 6).

And in yet other news, I also figured out that 0xFF isn't strictly necessary to randomize a Pokemon's IVs and such. Strictly speaking, I doubt it even "makes" anything random. I edited it into my big post above.

Posted
Ah so we were right about the priority, we just needed to factor in the AI as well! Do you happen to know if there are any AI values that actually switch pokemon during the battle?

No clue. I'd only know by seeing it happen (I haven't) or by reading a bunch of assembly that I don't even have the first clue where to find.

Posted
No clue. I'd only know by seeing it happen (I haven't) or by reading a bunch of assembly that I don't even have the first clue where to find.

From looking at the values for the AI of the trainer I'm assuming that a higher value doesn't necessarily correspond to a more intelligent AI. It would make sense for the Mt.Battle masters on battle mode to have the highest AI value in the game but this is not the case. My best guess is that the game was programmed with predefined strategies. Like you said some of the more important characters would get unique values which are tailored to their team while the generic characters are just assigned the default strategies. For example, I believe that Justy's pokemon are all very likely to use double team and Evice's Slowking will use skill swap on his Slaking. I've found that sometimes, I'll give a trainer some really creative sets like baton pass sets but they just end up spamming their attacking move.

Posted (edited)

I tried to do some digging into the heart gauge and ended up exploring the whole PKM structure. I guess this isn't exactly ROM research, but I think it's better to keep things mostly in one place, and this thread is kind of about Colosseum Pokemon already. I started this with some hints from psycommando's xD memory notes and finished it off with the help of this thread (especially some of the origin stuff and the Contest stats).

At different times, there may be a few different copies of a Pokemon's PKM floating around in RAM, but I haven't really bothered trying to differentiate them. I've also seen them in different places for different loads or saves or whatever. In one case (for in-battle I think), the PKM is also a bit longer but, again, I haven't really looked closely at it at all. The PKMs should also appear in the save file, but, one way or another, I don't think they're in a conveniently readable format, so I haven't found them in there.

I think I've also figured out how to know exactly where the PKMs are during runtime (the main ones at least; I really don't have the first idea right now how any of the copies might be related to the main ones). In short, in the US Colosseum, the pointer to the start of player data (or I think that's what it is) is stored at 0x8047ADB8 in RAM (in EU Colosseum, the pointer is at 0x804C8268; I haven't looked at JP). The PKM for the player's first party Pokemon starts at +0xA0 from the start of the player data. (In between that and the start comes other stuff like the player name and full Trainer ID.)

The above is really all you need to know to find party PKMs, but if anyone wants to figure it out from scratch (like for the JP Colosseum maybe), here's what you'd need to do... First, you have to know what r13 is set to. This holds a special address that defines where a bunch of other pointers are, and it's set when the game loads and is never altered. You can find that address by combining the bytes at offsets 0x336, 0x337, 0x33A, and 0x33B in Start.dol, or at those offsets plus 0x3000 in RAM. Then you need to search for the 16-byte sequence "38630070 4E800020 28030000 4C820020" (in RAM or in Start.dol), which should only have one match. Combine the bytes at +0x22 and +0x23 bytes from the start of that match, then add that to the r13 address and subtract 0x10000 (the 0x22/23 bytes are actually a negative/signed value, but this works a bit more directly and just as accurately). The result of that calculation should be the location of the pointer to the start of the player data.

PKM structure

  • In: RAM, or presumably save files
  • Start: Varies...
  • Size: 0x138 (dec 312)

Offsets...

  • 0x00 - 2 bytes - Species (index)
  • 0x02 - 2 bytes - Unknown...
  • 0x04 - 4 bytes - PID
  • 0x08 - 1 byte - Game of origin
  • 0x09 - 1 byte - "Actual region"?
  • 0x0A - 1 byte - Game region
  • 0x0B - 1 byte - Game language
  • 0x0C - 2 bytes - Met location (index)
  • 0x0E - 1 byte - Met level
  • 0x0F - 1 byte - Met ball/ball caught in (item index)
  • 0x10 - 1 byte - OT gender (0: male, 1: female)
  • 0x11 - 3 bytes - Unknown... (includes 0x02 bytes)
  • 0x14 - 4 bytes - Full OT ID (Secret ID then Trainer ID)
  • 0x18 - 22 bytes - OT name
  • 0x2E - 22 bytes - Pokemon name (nickname)
  • 0x44 - 22 bytes - Pokemon name (nickname, copy)
  • 0x5A - 2 bytes - Unknown...
  • 0x5C - 4 bytes - Current experience
  • 0x60 - 1 byte - Current level
  • 0x61 - 3 bytes - Unknown... (matches 0x11 bytes/includes 0x02 bytes)
  • 0x64 - 2 bytes - Status condition status ID
  • 0x66 - 2 bytes - Something status...
  • 0x68 - 1 byte - Status duration?
  • 0x69 - 1 byte - Something status...
  • 0x6A - 1 byte - Status iteration?
  • 0x6B - 1 bytes -Unknown... (includes 0x03 byte)
  • 0x6C - 4 bytes - Something status...
  • 0x70 - 2 bytes - Something status...
  • 0x72 - 2 bytes - Unknown... (matches 0x02 bytes)
  • 0x74 - 4 bytes - 0?
  • 0x78 - 2 bytes - Move 1 (index)
  • 0x7A - 1 byte - Move 1 current PP
  • 0x7B - 1 byte - Move 1 PP bonuses
  • 0x7C - 2 bytes - Move 2 (index)
  • 0x7E - 1 byte - Move 2 current PP
  • 0x7F - 1 byte - Move 2 PP bonuses
  • 0x80 - 2 bytes - Move 3 (index)
  • 0x82 - 1 byte - Move 3 current PP
  • 0x83 - 1 byte - Move 3 PP bonuses
  • 0x84 - 2 bytes - Move 4 (index)
  • 0x86 - 1 byte - Move 4 current PP
  • 0x87 - 1 byte - Move 4 PP bonuses
  • 0x88 - 2 bytes - Held item (index)
  • 0x8A - 2 bytes - Current HP
  • 0x8C - 2 bytes - HP stat (max)
  • 0x8E - 2 bytes - Attack stat
  • 0x90 - 2 bytes - Defense stat
  • 0x92 - 2 bytes - Sp Attack stat
  • 0x94 - 2 bytes - Sp Defense stat
  • 0x96 - 2 bytes - Speed stat
  • 0x98 - 2 bytes - HP EVs
  • 0x9A - 2 bytes - Attack EVs
  • 0x9C - 2 bytes - Defense EVs
  • 0x9E - 2 bytes - Sp Attack EVs
  • 0xA0 - 2 bytes - Sp Defense EVs
  • 0xA2 - 2 bytes - Speed EVs
  • 0xA4 - 2 bytes - HP IV
  • 0xA6 - 2 bytes - Attack IV
  • 0xA8 - 2 bytes - Defense IV
  • 0xAA - 2 bytes - Sp Attack IV
  • 0xAC - 2 bytes - Sp Defense IV
  • 0xAE - 2 bytes - Speed IV
  • 0xB0 - 2 bytes? - Friendship
  • 0xB2 - 1 byte - Cool condition
  • 0xB3 - 1 byte - Beauty condition
  • 0xB4 - 1 byte - Cute condition
  • 0xB5 - 1 byte - Smart condition
  • 0xB6 - 1 byte - Tough condition
  • 0xB7 - 1 byte - Cool Contest Ribbons
  • 0xB8 - 1 byte - Beauty Contest Ribbons
  • 0xB9 - 1 byte - Cute Contest Ribbons
  • 0xBA - 1 byte - Smart Contest Ribbons
  • 0xBB - 1 byte - Tough Contest Ribbons
  • 0xBC - 1 byte - Luster/Feel/Sheen (the limiter for the number of consumable Pokeblocks/Poffins)
  • 0xBD - 1 byte - Champion Ribbon (Hoenn Hall of Fame)
  • 0xBE - 1 byte - Winning Ribbon (Battle Tower lv50)
  • 0xBF - 1 byte - Victory Ribbon (Battle Tower lv100)
  • 0xC0 - 1 byte - Artist Ribbon
  • 0xC1 - 1 byte - Effort Ribbon
  • 0xC2 - 1 byte - Special Ribbon 1 (Marine Ribbon)
  • 0xC3 - 1 byte - Special Ribbon 2 (Land Ribbon)
  • 0xC4 - 1 byte - Special Ribbon 3 (Sky Ribbonv
  • 0xC5 - 1 byte - Special Ribbon 4 (Country Ribbon)
  • 0xC6 - 1 byte - Special Ribbon 5 (National Ribbon; given to purified Pokemon)
  • 0xC7 - 1 byte - Special Ribbon 6 (Earth Ribbon; cleared Mt. Battle)
  • 0xC8 - 1 byte - Special Ribbon 7 (World Ribbon)
  • 0xC9 - 1 byte - 0?
  • 0xCA - 1 byte - Pokerus
  • 0xCB - 1 byte - Egg (0: not, nonzero: Egg; only seems to affect Pokemon's mini/head sprite)
  • 0xCC - 1 byte - Ability slot
  • 0xCD - 1 byte - Gender something?
  • 0xCE - 1 byte - 0?
  • 0xCF - 1 byte - Markings (bit 0 (least significant): circle, bit 1: square, bit 2: triangle, bit 3: heart)
  • 0xD0 - 4 bytes - Unknown...
  • 0xD4 - 4 bytes - Unknown...
  • 0xD8 - 2 bytes - Shadow ID
  • 0xDA - 2 bytes? - Unknown...
  • 0xDC - 4 bytes - Heart gauge (fill/progress)
  • 0xE0 - 4 bytes - Experience gained as a Shadow Pokemon (applied when purified)
  • 0xE4 - 2 bytes - Friendship gained as a Shadow Pokemon (applied when purified)
  • 0xE6 - 2 bytes - Unknown...
  • 0xE8 - 2 bytes - Hyper Mode status ID (0x003E: in Hyper Mode, else: not; only applies to Shadow Pokemon)
  • 0xEA - 2 bytes - Something status...
  • 0xEC - 1 byte - Status duration?
  • 0xED - 1 byte - Something status...
  • 0xEE - 1 byte - Status iteration?
  • 0xEF - 1 bytes -Unknown...
  • 0xF0 - 4 bytes - Something status...
  • 0xF4 - 2 bytes - Something status...
  • 0xF6 - 2 bytes - Unknown...
  • 0xF8 - 3 bytes? - 0?
  • 0xFB - 1 byte - Obedience (appears to have no effect in this game)
  • 0xFC-0x134 (60 bytes) - Unknown...

The 0x02 unknown bytes (let's call them "MM NN" for simplicity) seem to be repeated in some of the other offsets marked unknown. MM NN is random for each Pokemon. The 0x11 and 0x61 unknown bytes are both the same and include MM NN, preceded by another byte which seems to differ by the language of the game the structure was created in, 0x3F for Japanese and 0x45 otherwise. The 0x6B unknown byte also contains NN and the 0x72 unknown bytes contain MM NN.

If you want to know everthing the PID/personality value controls, maybe check out Bulbapedia's article. It should be noted, though, that the Ability the Pokemon has is not directly controlled by the PID but instead by the value (byte) at offset 0xCC.

All of the origin bytes (0x08-0x0B) for some reason make the Pokemon's gender symbol become hidden if any of them is set to 0x00. Game of origin is 0x01 for FireRed, 0x02 for LeafGreen, 0x08 for Sapphire, 0x09 for Ruby, 0x0A for Emerald, or 0x0B for Colosseum. I have no idea what the "actual region" might be intended for, but I've only seen it set as 0x03 when the structure is created by Colosseum. The game region refers to the physical game's format: 0x01 means NTSC-J (Japanese), 0x02 means NTSC (US), and 0x03 means PAL (Europe). The game language (or "font" perhaps) value is 0x01 for Japanese, 0x02 for English, 0x03 for German, 0x04 for French, 0x05 for Italian, or 0x06 for Spanish.

Only the lower byte of the met location is naturally used, but changing the high byte does affect the met string. Met location strings are associated with the (met) location index in the "map/met data" table described -hacking-tutorial-part-7-Editing-Trainers-(Colosseum)&p=205678&viewfull=1#post205678'>below. If the Pokemon in question is Umbreon or Espeon, though, and if their OT info (not including gender) matches the player info (and if all the origin info also agrees that they're "native" to the game), then the met string on their summary screen will be "[Player]'s old friend". The game naturally sets the starter Umbreon and Espeon's met locations to 0x00FE, though.

Only the first copy of the Pokemon's nickname appears to be used. The second copy has no effect on anything as near as I can tell, but if the Pokemon's nickname is changed, both strings are changed to the new nickname.

Valid values for the Pokemon's status ID are 0x03 (poisoned), 0x04 (badly poisoned), 0x05 (paralyzed), 0x06 (burned), 0x07 (frozen), and 0x08 (asleep). Other values result in no status. The fainted "status" only results if the Pokemon has 0 HP.

Starting with that status ID at 0x64 and continuing through 0x73, those whole 16 bytes are actually a generic status structure that's used for all types of statuses, not just PKM status conditions. (The great majority of statuses only ever exist in transient battle data, like Light Screen.) Likewise, the Hyper Mode status bytes are really another generic status structure. The only thing that makes them special is the game's code that only recognizes certain status ID values as valid at 0x64 (in short, "status conditions", which have the values stated just above) or at 0xE8 (Hyper Mode, which has the status ID 0x3E). And outside of battle, the status ID is really the only useful field; the others are mostly only useful in battle and (especially) for battle-specific statuses. (To be honest, though, I'm not sure what, if any, effect setting some of those other fields might have when you enter battle. Sleep (duration) and toxic (iteration) are the ones that could be interesting, but I don't know.) FWIW, I'm also starting to think some of the unknown bytes might just be uninitialized data, because the "unknown" bytes in the middle of the status condition status structure are actually offsets in the structure that don't have explicit getters/setters.

For the Contest Ribbons, the values 0-4 indicate the highest Rank Contest (none/Normal/Super/Hyper/Master) the Pokemon has won a Ribbon for (meaning they also have the lower Rank Ribbons). Values higher than 4 act the same as 4.

The 0xCD byte for some reason hides the Pokemon's gender symbol (if they have one) if it is set to 0x01, but for all other values seems to have no effect. In natural use, this value always seems to be 0 (even on genderless Pokemon, which was my first guess), so I don't know what's up with this.

I can't tell what the unknown 0xD0 bytes might affect. From what I've seen, they always start with 0xFF (in the highest byte), the lowest two bytes are always 0x00, and the second-highest byte can vary (I've seen 0x00 and 0x58).

The 0xD4 bytes most of the time seem to be 0s, but it's possible for the lowest byte to be non-zero. No idea what it might affect...

The Shadow ID is naturally set by the game when an opponent's Pokemon is created from the Trainer Pokemon data structure described earlier in this thread, and equals the Shadow ID there. A Pokemon is only a Shadow Pokemon if this ID is nonzero and if the heart gauge value does not have the highest bit set. (If a Pokemon gets purified, this value is not affected, only the heart gauge value is. Pokemon that were never Shadow Pokemon naturally have 0x0000 for this value.) If the Pokemon is a Shadow Pokemon, this value controls the size of a bar of their heart gauge. The size differs depending on the ID, as defined in a Shadow IDs structure (see below). If this value is not a defined ID (0x0061 or greater), the bar size will default to 20, but the heart gauge will always appear full, even though the purification message will still change at the appropriate intervals.

The unknown 0xDA bytes appear somewhat random. I've only seen 0xC59C for Pokemon created for opponents (though I haven't looked a lot), but it can definitely be random for the player's starters (in different saves; it seems it may be the same for both starters).

The heart gauge value is how far a Pokemon is from being purified. It starts off set to a "full" gauge, which is 5 times the size of a bar (as determined by the Shadow ID). (This means that the same value here can result in different fullnesses of the heart gauge depending on the Shadow ID.) A Pokemon is only a Shadow Pokemon if this value does not have its highest bit set and if the Shadow ID is nonzero. For some reason, the game's default value here for a non-Shadow Pokemon (whether purified or never-Shadow) is 0xFFFFFF9C. The purification message changes every time the heart gauge drops below a full X bars, and also when it hits exactly 0. The purification values in the Nature table I found above are more like purification "levels", and the amount subtracted from the heart gauge for an event depends on the level. Once I check/figure out xD's heart gauge too, I'll be editing the exact details into Bulbapedia's Heart Gauge page.

The unknown 0xEC bytes might be related to Hyper Mode, since when a Pokemon enters Hyper Mode in battle, the first byte of 0xEC gets set to 0xFF. I'm not sure what effect it might have, though. (Nothing blatantly obvious, at least.) Otherwise, like 0xE4 and 0xF4, it has relatively small values (the first 2 or 3 bytes may be 0x00) and may be some degree of random...

All of the bytes from 0xFC and on are unknown. It's not really worth trying to be terribly specific here. Many can look like pointers (starting with the byte 0x80; this seems especially true of the starters), but sometimes those same bytes can be zero or can have small nonzero values instead. It also seems like there might be three groups of three (4-byte) "pointers" (except, again, they don't always look like "pointers") separated by 4 bytes of either 0s or small values. Sometimes those "pointers" seem vaguely interrelated... The lower 2 bytes at 0x124 also look like the player's TID for the starters (the lower 2 bytes of the full ID), though not for Pokemon originally created for opponents. At any rate, if these will be deciphered, someone will probably need to do a lot of work.

Like I said, I was looking for heart gauge/purification stuff, and in the PKM description above, I said that the size of a bar of the heart gauge depends on the Pokemon's Shadow ID. I also found the table that controls that in RAM.

Shadow IDs structure

  • In: RAM
  • Start: Varies...
  • Fingerprint (2nd entry): 00 00 01 00 01 4F 00 00 FF FF 00 1E 00 00 00 00 00 00 00 00 00 00 00 00
  • Entry size: 0x18 (dec 24)
  • Entry count: 97 (or 65,536?)

I also tried looking as well as I knew how through ROM files, but for the life of me I can't seem to find the exact same table. And if it's built from something else I have no idea/can't tell where that data might be located.

There may not also be a strict end to this table except the maximum Shadow ID. It seems like the Shadow ID in the PKM may just be an index (0-based) into this table, and so long as the game can read a nonzero "bar factor" at a given index, the heart gauge will work fine. I think all the "entries" beyond the initial explicitly defined 97 just have 0s in them, but all you have to do is enter a nonzero "bar factor" for a given entry (even, say, the very last one) and if you give a Pokemon that Shadow ID its heart gauge will display just fine.

Offsets...

  • 0x00 - 3 bytes? - Shadow ID
  • 0x03 - 1 byte - 0
  • 0x04 - 2 bytes - Species
  • 0x06 - 2 bytes - 0
  • 0x08 - 2 bytes - 0xFFFF
  • 0x0A - 2 bytes - Bar factor
  • 0x0C - 12 bytes - 0

For the Shadow ID, I'm just sort of assuming the field is 3 bytes, but the first byte or two may well just always be 0s. At any rate, I don't know if this actually does anything, because I tried changing the value, and it didn't seem to have any effect.

The species matches the species of Pokemon that naturally has that Shadow ID (for example, 0x014F for ID 1, Trudly's Makuhita), but I don't know that it affects anything. The game doesn't seem to care which Pokemon you give an ID to.

Also, while 0x08 is naturally 0xFFFF, it doesn't seem to matter if an entry actually has 0x0000 (or whatever, I suppose).

The "bar factor" is multiplied by 20 to get the size of a bar of the heart gauge. (This explains why the default bar size for an "undefined" ID is 20. Though technically, "undefined" just means the game read 0 for a bar factor.)

I also tried looking for a way that met location indices were associated with their strings (edit: it's actually in the "map/met" table below), as well as how/where the National Ribbon got assigned its string, but I wasn't able to find either of those things...

Edited by Tiddlywinks
PKM addresses!
Posted

Usually these kinds of tables are in common_rel or, less often, in start.dol. However, we know that common_rel is loaded into ram in its entirety and I think almost all of start.dol is as well. You can figure out where these files start and end in ram and if any data in ram is between one of the two offsets you know it is in that file. However, these files are always at the same offset in ram and you say the start of the purification table varies in ram. This potentially means it's created at runtime.

I've had a little look myself and can't track it down so my best guess is that it is created by some ASM in start.dol.

Posted (edited)

I found a list of pointers to tables in common_rel that includes all four of the ROM tables I described above. It starts at 0x478E58 in common_rel, and the addresses are all offset by 0x807628A0 (for the US ROM). There are some "empty" pointers, though, and I don't know if it might actually be multiple lists.

Going by those pointers, the Trainer data does start one entry earlier, at 0x92ED0 in common_rel instead of at 0x92F04. It also suggests that the address you gave for the "start" of the stats table in -hacking-tutorial-part-5-Editing-Pokemon-stats'>part 5 is one entry late, and they really start at 0x123250.

A bunch of the "tables" are pretty indecipherable beyond maybe telling how big the entries are. I was able to identify string IDs in some of them, though. Some of those were still hard to figure, though... But I did manage to figure out a few new tables pretty well, too.

First, let me just identify the ones that had string IDs but that were difficult to figure out otherwise, in case somebody might feel like taking a look at them...

Start: 0xB9C, entry size: 0x18 (dec 24), entry count: 54. String ID (4 bytes) at offset 0x14 of an entry. (Example string IDs: EB74-78.) Part of me wants to say this has to do with music, but it could some other sort of event.

Start: 0x3280, entry size: 0x08 (dec 8), entry count: 604. String ID at offset 0x04. The strings are all Trainer names, and the rest of the entry only uses the first two bytes, which is pretty spare data, and I can't tell what it's for (I haven't tried messing with this during runtime yet).

Start: 0x92798, entry size: 0x20 (32), entry count: 19. String ID at offset 0x1C. (String IDs (all Japanese): ECED and ED19-28.) Offsets 0x00 through 0x18 look like flags. My first thought is that this might be a debug menu or something, but I don't have the first idea how.

Start: 0x11A698, entry size: 0x14 (dec 20), entry count: 553. String IDs at offsets 0x04, 0x08, and 0x0C. All of theses strings are in Japanese. (An example of the first is EC2C; of the second is F139; and of the last is EC0C-1C.) It kind of looks like it might be debug messages for the AI routines. Those string IDs don't leave an abundance of room otherwise in an entry, though, so I'm not sure what the structure might be for.

Start: 0x11D1CC, entry size: 0x14 (dec 20), entry count: 80. String ID at offset 0x00. These strings are all in Japanese too, and it's kind of interesting because some of them say things like "Attacker", "Supporter", "Baton", and "Seal" (for example, EBFE-EC01 and F27C-81), so it kind of makes me think this might be related to AIs.

Start: 0x145224, entry size: 0x38 (dec 56), entry count: 97. String IDs at offsets 0x18 (a move name), 0x20 (in Japanese; probably everything from EC76-ECD5), 0x30 (Trainer name), and 0x34 (Trainer name). Sometimes both Trainer names are the same, sometimes not (and then they seem to stagger, so the 2nd name in one entry is the 1st name in the next entry), and I just can't imagine what it could possibly be.

With that out of the way, on to the good stuff...

Snag List messages:

  • In: common.fsys\common_rel.fdat
  • Start: 0x14675C
  • Entry size: 0x08 (dec 8)
  • Entry count: 505

The format of this is a bit like the Trainer Pokemon data. All of the entries are grouped into "sets" that are terminated by an empty entry (with all bytes 0, that is). This means the sets can (and do) have variable length. There are 97 such sets, one apparently for each defined Shadow ID (like in the Shadow IDs structure in RAM I described above).

Each entry seems to describe the message that is shown at a certain point in time in the Snag List. For most Pokemon, their "set" just has four entries that have the strings "No information", "No information", "Encountered in\n[location]! But SNAG failed!", and "SNAG succeeded in\n[location]!" (respectively), but a few sets have some extra entries/messages between those first and last two.

Offsets...

  • 0x00 -- 1 byte -- Extra message identifier?
  • 0x01 -- 1 byte -- Unknown...
  • 0x02 -- 1 byte -- Snag status
  • 0x03 -- 1 byte -- Unknown...
  • 0x04 -- 4 bytes -- Message string (ID)

If there are extra, non-default messages in a set (between the default first and last two), 0x00 will increment across those extra entries. I might wager that that's pretty much all there is to it, but I'm just not sure if it has any actual significance in any of the other (default) entries.

0x01 I'm not sure what to make of. It's got a small range, and usually equivalent entries (those with the same message, more or less) all have the same value, but I just can't figure what it's for.

0x02 is basically the Snag status of the Pokemon for that message. 0 I think means it hasn't even been seen/revealed. 9 means it's not captured and not in its last location yet. 5 means it's in its last location but not captured. And 8 means it's been captured. I assume that, if this value is 9, the game will then try to match to the 0x00 value too to determine which entry it should be using currently.

0x03 is fairly weird, and a bit hard to describe. In the first entry of a set, for some reason it's always 0. In any other entries before the last two, it has a value that is the same within that part of the set and increments across all of the sets (running from 0x34-93, not counting the first/invalid set). But in the last two entries of a set, for some reason 26 (0x1A) is added to the value. I just don't have the first clue why this is like it is...

Battle data:

  • In: common.fsys\common_rel.fdat
  • Start: 0x10B808
  • Entry size: 0x38 (dec 56)
  • Entry count: 566

This actually defines some of the things I was hoping to find before in the Trainer data, like the music and battle stage. This data is kind of an intermediary step between the Trainer data and (I presume) whatever structure defines what battles are in a map.

Offsets...

  • 0x00 -- 1 byte -- Battle type
  • 0x01 -- 1 byte -- Versus type
  • 0x02 -- 1 byte -- Unknown flag...
  • 0x03 -- 1 byte -- 0
  • 0x04 -- 2 bytes -- Stage
  • 0x06 -- 2 bytes -- 0
  • 0x08 -- 4 bytes -- Identifier string (ID)
  • 0x0C -- 4 bytes -- Music/SFX
  • 0x10 -- 4 bytes -- Transition
  • 0x14 -- 2 bytes -- 0
  • 0x16 -- 2 bytes -- Subtitle
  • 0x18 -- 2 bytes -- Participant 1
  • 0x1A -- 5 bytes -- 0
  • 0x1F -- 1 byte -- Unknown...
  • 0x20 -- 2 bytes -- Participant 2
  • 0x22 -- 5 bytes -- 0
  • 0x27 -- 1 byte -- Unknown...
  • 0x28 -- 2 bytes -- Participant 3
  • 0x2A -- 5 bytes -- 0
  • 0x2F -- 1 byte -- Unknown...
  • 0x30 -- 2 bytes -- Participant 4
  • 0x32 -- 5 bytes -- 0
  • 0x37 -- 1 byte -- Unknown...

I haven't tried to examine the battle types in depth yet, but basically they'll define things like if prize money is awarded or not (value 0x03: no prize money) or whether any win/lose/etc strings are printed. The values 0x0A, 0x0B, and 0x11 are noteworthy because they're VR battles, which basically just seems to affect the entrance (and they're the only types that do anything obvious like that). The value 0x02 seems to be for “regular” battles (most battles in Story Mode).

The versus type acts as a field into the versus types table described below. For 0x02 and 0x06 (the 4-participant types), each participant controls one Pokemon on their side, and Participants 1 and 2 are on the player/Player 1's team while Participants 3 and 4 are on the opposing team.

The "unknown flag" can have the values 0 or 1, and basically seems to be split between Colosseum/Stadium/Mt. Battle Trainers and regular (Story Mode) Trainers, but I don't know what exactly it does.

The stage defines the map that is loaded for the battle's setting. If an undefined stage is set, the game will not be able to continue beyond the fade-into-battle transition. Since I don't know where the indices and/or parameters for these stages are defined, I've listed all the possible values in the spoiler below...

  • 0x00 -- Invalid/Pyrite Colosseum (0 participants allowed, battle ends immediately)
  • 0x01 -- Pyrite Colosseum (long intro, title: Orre Colosseum)
  • 0x02 -- Pyrite Colosseum (long intro, title: Tower Colosseum)
  • 0x03 -- Pyrite Colosseum (long intro, title: Mt.Battle Colosseum)
  • 0x04 -- Pyrite Colosseum
  • 0x05 -- Outskirt Stand
  • 0x06 -- Pyrite Colosseum (long intro, title: Pyrite Colosseum)
  • 0x07 -- Phenac City outside
  • 0x08 -- Mayor's house
  • 0x09 -- Pre Gym
  • 0x0A -- Pyrite Town outside
  • 0x0B -- Pyrite Bldg (Miror B.'s hideout)
  • 0x0C -- Pyrite Cave
  • 0x0D -- Pyrite Cave
  • 0x0E -- Agate Village outside
  • 0x0F -- Relic Cave
  • 0x10 -- Relic Forest/Stone
  • 0x11 -- The Under
  • 0x12 -- The Under – TV Studio
  • 0x13 -- The Under Subway
  • 0x14 -- Shadow PKMN Lab outside
  • 0x15 -- Shadow PKMN Lab inside
  • 0x16 -- Mt. Battle outside
  • 0x17 -- Mt. Battle lobby
  • 0x18 -- Mt. Battle 1-30
  • 0x19 -- Mt. Battle 31-60
  • 0x1A -- Mt. Battle 61-99
  • 0x1B -- Realgam Tower – entrance domes
  • 0x1C -- Realgam Tower – lobby
  • 0x1D -- Realgam Tower – game room
  • 0x1E -- Realgam Tower – dining room
  • 0x1F -- Realgam Tower – 2nd floor (glitchy)
  • 0x20 -- Realgam Tower - 2nd floor side room
  • 0x21 -- Phenac Stadium (long intro, title: Phenac Stadium)
  • 0x22 -- Pyrite Colosseum (long intro, title: Pyrite Colosseum)
  • 0x23 -- Under Colosseum (long intro, title: Under Colosseum)
  • 0x24 -- Deep Colosseum (long intro, title: Deep Colosseum)
  • 0x25 -- Mt.Battle Colosseum (long intro, title: Mt.Battle Colosseum)
  • 0x26 --Tower Colosseum
  • 0x27 -- Snagem Hideout
  • 0x28 -- Mt. Battle 1-30
  • 0x29 -- Mt. Battle 31-60
  • 0x2A -- Mt. Battle 61-99
  • 0x2B -- Phenac Stadium (long intro, title: Phenac Stadium)
  • 0x2C -- Pyrite Colosseum (long intro, title: Pyrite Colosseum)
  • 0x2D -- Under Colosseum (long intro, title: Under Colosseum)
  • 0x2E -- Mt.Battle Colosseum
  • 0x2F -- Tower Colosseum (long intro, title: Tower Colosseum)
  • 0x30 -- Orre Colosseum (long intro, title: Orre Colosseum)
  • 0x31 -- Shadow PKMN Lab inside
  • >0x31 -- Undefined

The "identifier string" is just a Japanese string that describes the battle, like "Miror B. 1", "Miror B. 2", and "[Colosseum] Set 1 Person 2". It's definitely not meant to be used in-game (except perhaps in some kind of debug function).

The music/SFX defines what begins playing when the battle starts. Some values will be sounds that loop ("music", like 0x044C, a boss theme), some won't (like 0x034C, a Pokemon cry). Some values also seem to be the same, like 0x03F8 and 0x044C. 0 is a default theme that differs depending on the stage.

The transition is the transition that occurs from the overworld to in-battle. (This seems to include the very first shot of the battle. Invalid values will initially show a neutral view of the arena instead of some sort of smooth "camera" move or perspective on a participant.) The possible values are described in the spoiler below...

  • 0x00: Fade to black, no sound
  • 0x01: Spin/blur up+right, basic battle transition sfx
  • 0x02: Spin/blur down+left, basic battle transition sfx
  • 0x03: Poke Balls wipe, alternate battle transition sfx
  • 0x04: Ripple, basic battle transition sfx
  • 0x05: Same as 0x01?
  • 0x06: Same as 0x02?
  • 0x07: Same as 0x01?
  • 0x08: Fade to black, no sound
  • 0x09: Blur into a super-imposed Poke Ball symbol, basic battle transition sfx
  • 0x0A: Cut abruptly to black, no sound

The subtitle values come into play if the stage has a long intro; if it does not, this value is ignored. Appropriate values will add a subtitle under the location name and a short piece of music during the extended intro. Values can be 0x00: nothing, 0x95: "Battle 1", 0x96: "Battle 2", 0x97: "Battle 3", 0x98: "Battle 4", 0x99: "Battle 5", 0x9A: "Battle 6", 0x9B: "Final", 0x9C: "Semifinal", 0xD4: "Battle 1", 0xD5: "Battle 2", 0xD6: "Final", or 0xD7: "Semifinal". Some other values may also play a sound.

The participant fields are an index into the Trainer table described above. 0x0001 is the player/player-controlled, and is only valid for Participant 1 and only if the entry's byte 0x1F is also nonzero. (Some of the other early indices are also invalid--meaning that it results in no participant being loaded--for any participant field as well, and I'm not sure why this is.) Any non-player participant acts on their own, meaning you can set up automatic battles (which is exactly what Eagun's battle in the Relic Forest is).

The last four unknowns at 0x1F, 0x27, 0x2F, and 0x37 seem to be related to the participant fields. At the very least, if Participant 1 is 0x0001, 0x1F cannot be 0 or Participant 1 will be invalid. I would hazard they're something like flags for controlled participants (controlled from the controller ports), but if so, I haven't figured out exactly what's necessary to make them work. (It may well be that the game needs to set some other things up right (like when it loads an explicit versus mode) before those flags will work like I think they're intended.) But for the most part, I haven't noticed any effect from trying to play around with them.

Versus types:

  • In: common.fsys\common_rel.fdat
  • Start: 0x92E98
  • Entry size: 0x08 (dec 8)
  • Entry count: 7

This is used in the battle data above. It probably sees some sort of use elsewhere too, but I don't know where/how exactly right now.

Offsets...

  • 0x00 -- 1 byte -- Participants per side (so double this equals total participants)
  • 0x01 -- 1 byte -- Maximum number of Pokemon per participant
  • 0x02 -- 1 byte -- Number of Pokemon controlled by each participant
  • 0x03 -- 1 byte -- 0?
  • 0x04 -- 4 bytes -- Description string (ID)

The "maximum number of Pokemon per participant" means the Pokemon in their "party", and each participant's party is separate from anyone else's; that is, if there are four participants, the participants who are on the same team cannot in any way access their partner's Pokemon. And yes, this means that if you have a 4-person battle, you can use up to 24 total Pokemon in the battle between all the participants.

I don't exactly know what happens if you try to make the number of Pokemon controlled by each participant be 0 or greater than 2, but for now I'd wager it wouldn't be anything really interesting.

The description strings are all in Japanese and aren't really anything meant to be seen in-game, unless in a debug mode or something.

And the last thing I found is a limited maps description.

Map/met data:

  • In: common.fsys\common_rel.fdat
  • Start: 0x8D540
  • Entry size: 0x04C (dec 76)
  • Entry count: 196

Offsets...

  • 0x00 -- 1 byte -- Map type?
  • 0x01 -- 1 byte -- Data location
  • 0x02 -- 2 bytes -- 0
  • 0x04 -- 4 bytes -- Map
  • 0x08 -- 4 bytes -- 0
  • 0x0C -- 4 bytes -- Location index
  • 0x10 -- 4 bytes -- 0?
  • 0x14 -- 4 bytes -- 0?
  • 0x18 -- 4 bytes -- 0?
  • 0x1C -- 4 bytes -- 0?
  • 0x20 -- 4 bytes -- 0
  • 0x24 -- 4 bytes -- Name/met string (ID)
  • 0x28 -- 1 byte -- Unknown...
  • 0x29 -- 2 bytes -- 0
  • 0x2B -- 1 byte -- Unknown...
  • 0x2C -- 1 byte -- Unknown...
  • 0x2D -- 2 bytes -- 0
  • 0x2F -- 1 byte -- Unknown...
  • 0x30 -- 1 byte -- Unknown...
  • 0x31 -- 2 bytes -- 0
  • 0x33 -- 1 byte -- Unknown...
  • 0x34 -- 1 byte -- Unknown...
  • 0x35 -- 1 byte -- Unknown...
  • 0x36 -- 1 byte -- 0
  • 0x37 -- 1 byte -- Unknown...
  • 0x38 -- 1 byte -- Unknown...
  • 0x39 -- 2 bytes -- 0
  • 0x3B -- 1 byte -- Unknown...
  • 0x3C -- 12 bytes -- 0
  • 0x48 -- 4 bytes -- 0?

I'm not sure if the "map type" really does anything concrete or if the divisions are more or less just aesthetic/helpful. The possible values appear to be 0x20 for "normal" maps (basically all the obvious locations in Story Mode), 0x40 for a battle stage, 0x80 seems to be used for something called the "move viewer" (filename: waza_viewer), 0xA0 for fullscreen interfaces or cutscenes, and 0xC0 might be for some title stuff.

The "data location" somehow corresponds to where the game can find the map. I'm not actuallly sure what this might accomplish or be required for, because I've changed this value (at runtime) and nothing seems to happen, but the correlation is obvious. In short, 0x01 corresponds to an "S1" prefix on the map's filename, 0x00 corresponds to battle stages (this includes waza_viewer; but I actually have no idea what file(s) contain any of these), 0x02 corresponds to "M1", 0x03 to "M2", 0x04 to "M3", 0x05 to "M4", 0x06 to "D1", 0x07 to "D2", 0x08 to "D4", 0x09 is the interface and other miscellaneous stuff (most of these seem to be in their own unique files, like "evolution" or "ex_shrine"), and 0x0A corresponds to an "S2" prefix.

The "map" value at 0x07 is which map to load. This does not load a "perfect" map all by itself, but it's also not just the model. I think it may not be possible to load a perfect map just by playing with an entry here, and I don't know what all you would need to change in order to get a perfectly loaded map. In my tests changing this value, I would often end up in the middle of the map (depending on the place I tried to enter from, the game might also produce a "fatal" error), most character and item models wouldn't load, and exits didn't work unless you could just walk "off" the bounds of the map, but some scripted events would load (like a battle that was supposed to occur when I crossed I certain point, or cutscene sequences).

I think the game matches the "location index" of an entry to know which entry it should read, either for the map itself or for the met string. Oddly, although the location index here seems to be 4 bytes (change the highest and the met string won't match and the map won't load), in the PKM, the met location index only has 2 bytes.

All of the values at the "unknown" offsets seem to overlap to some degree with the divisions of the "map type", so I'm a little uncertain of that, actually. I haven't been able to figure out any of these unknown offsets just by looking at them, which is all I've done with them so far.

Also, during runtime, some of the apparently unused offsets (with 4 bytes of space; in particular, those I labeled "0?" above) get values that look like pointers written to them. I tried playing with those offsets a bit, but I couldn't tell what, if anything, the values accomplished.

I also found a table of -hacking-tutorial-part-6-Editing-Move-data&p=205679&viewfull=1#post205679'>contest stats.

Edited by Tiddlywinks
Posted

I tried looking for pointers before, but like you said my start offsets were a bit off. I concluded that the pointers must have been somewhere else and never thought to look for them again. Very useful indeed. I usually just scroll through the file and adjust the bytes per row until the bytes all align and see if I can spot anything. The really great thing about the pointers though, is that this means we can potentially increase the size of tables. I'm really glad you spotted that!

I'm in the process of documenting some of my recent findings in xD. Maybe Some of it will be of use to you. May have figured out some of the tables you haven't.

Also you found some really interesting tables. Clears up a lot of things I'd been looking for.

Posted
I found a list of pointers to tables in common_rel that includes all four of the ROM tables I described above. It starts at 0x478E58 in common_rel, and the addresses are all offset by 0x807628A0 (for the US ROM). There are some "empty" pointers, though, and I don't know if it might actually be multiple lists.

It wasn't very clear that you found the pointers in the RAM just spent a good few minutes searching common_rel itself. Also don't the pointers start at 0x478DF8 in RAM?

Also I've been wondering how the game decides if the opponents pokemon's HP is visible. It's definitely visible on mt.battle on battle mode but not in story mode. It's probably one of the unknown bytes somewhere in the tables you found. Or maybe it's just incorporated in the battle type values or something. Did you notice this?

Posted
It wasn't very clear that you found the pointers in the RAM just spent a good few minutes searching common_rel itself. Also don't the pointers start at 0x478DF8 in RAM?

Oh, sorry. The list itself kind of completely slipped my mind. When I saw this response, in fact, I even thought, "Of course it's in common_rel", but nope! :tongue:

You're right, it does seem to start at 0x478DF8. I don't know how I made that mistake... I had the right start for the EU version (which was actually my default resort for a while, because the standard Dolphin version would always freeze when trying to load the US version), but when I went to the US version, somehow I didn't reach far enough back. I didn't even realize the mistake I had made when I noticed that my lists for each version had different sizes. :frown: I actually tried to go through everything in common_rel anyway (like I said, I was mostly able to see the patterns of each table anyway, and therefore where they ended), but I should probably try to double-check that part I missed sometime.

Also I've been wondering how the game decides if the opponents pokemon's HP is visible. It's definitely visible on mt.battle on battle mode but not in story mode. It's probably one of the unknown bytes somewhere in the tables you found. Or maybe it's just incorporated in the battle type values or something. Did you notice this?

I'd cast my first bet on the battle type, but I really don't know. I had actually never noticed the opponent's HP being visible anywhere, so it never crossed my mind to look for it.

Posted

[quote name=Tiddlywinks;205678

A bunch of the "tables" are pretty indecipherable beyond maybe telling how big the entries are. I was able to identify string IDs in some of them' date=' though. Some of those were still hard to figure, though... But I did manage to figure out a few new tables pretty well, too.

First, let me just identify the ones that had string IDs but that were difficult to figure out otherwise, in case somebody might feel like taking a look at them...

Start: 0xB9C, entry size: 0x18 (dec 24), entry count: 54. String ID (4 bytes) at offset 0x14 of an entry. (Example string IDs: EB74-78.) Part of me wants to say this has to do with music, but it could some other sort of event.

Start: 0x3280, entry size: 0x08 (dec 8), entry count: 604. String ID at offset 0x04. The strings are all Trainer names, and the rest of the entry only uses the first two bytes, which is pretty spare data, and I can't tell what it's for (I haven't tried messing with this during runtime yet).

Start: 0x92798, entry size: 0x20 (32), entry count: 19. String ID at offset 0x1C. (String IDs (all Japanese): ECED and ED19-28.) Offsets 0x00 through 0x18 look like flags. My first thought is that this might be a debug menu or something, but I don't have the first idea how.

Start: 0x11A698, entry size: 0x14 (dec 20), entry count: 553. String IDs at offsets 0x04, 0x08, and 0x0C. All of theses strings are in Japanese. (An example of the first is EC2C; of the second is F139; and of the last is EC0C-1C.) It kind of looks like it might be debug messages for the AI routines. Those string IDs don't leave an abundance of room otherwise in an entry, though, so I'm not sure what the structure might be for.

Start: 0x11D1CC, entry size: 0x14 (dec 20), entry count: 80. String ID at offset 0x00. These strings are all in Japanese too, and it's kind of interesting because some of them say things like "Attacker", "Supporter", "Baton", and "Seal" (for example, EBFE-EC01 and F27C-81), so it kind of makes me think this might be related to AIs.

Start: 0x145224, entry size: 0x38 (dec 56), entry count: 97. String IDs at offsets 0x18 (a move name), 0x20 (in Japanese; probably everything from EC76-ECD5), 0x30 (Trainer name), and 0x34 (Trainer name). Sometimes both Trainer names are the same, sometimes not (and then they seem to stagger, so the 2nd name in one entry is the 1st name in the next entry), and I just can't imagine what it could possibly be.

[/quote]

My japanese is pretty good and as far as I can tell it's mostly debug text. Stuff from the debug menu and maybe some output logs. You also identified the strings that are very clearly related to the AI. They remain enigmas though. I can say that the table at 0xB9C is almost definitely not to do with music. It seems more like a list of milestones and events from the game. They probably come from a debug menu that the programmers could use to skip to certain parts of the game for testing.

[EDIT:] I don't know actually, maybe I'm wrong about it not having anything to do with music. It's pretty hard to ignore the fact that the names of all the sfx and music are listed right after it. Furthermore, I just counted the number of song names and I think it's the same as the number of entries in this table.

  • 4 weeks later...
Posted
I found a list of pointers to tables in common_rel that includes all four of the ROM tables I described above. It starts at 0x478E58 in common_rel, and the addresses are all offset by 0x807628A0 (for the US ROM). There are some "empty" pointers, though, and I don't know if it might actually be multiple lists.

Since it looks like you're taking a look at xD now You might like the list of pointers into common_rel from my ram dump of xD. It starts at 0x4E87C8 I believe.

Posted
Since it looks like you're taking a look at xD now You might like the list of pointers into common_rel from my ram dump of xD. It starts at 0x4E87C8 I believe.

Yup, I've already used that data to split up most of common_rel. =P (There's mostly just a chunk at the end that I've kind of ignored.) I may not know what everything does, but I think I know where it all starts and ends and how they're basically structured. I even discovered EU and JP string tables I sort of missed when I previously gathered up all the string tables.

FWIW, since learning about the symbol map and grasping assembly reads/stores, I've just been jumping around in Colo and trying to identify functions and structures/fields. I've been updating previous posts where relevant. One of the biggest things I found may be how to know exactly where the main party PKMs are in RAM (inserted above); that could be useful for some previous applications.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...