- 119
- Posts
- 15
- Years
- Mt. Silver
- Seen Aug 4, 2024
I'm trying to write a script in which the player receives a Pokémon if it has not been caught before. I.e. the event semi-randomly chooses a Pokémon species, checks if it's already "caught" in the Pokédex, and if it's not, gives that Pokémon to the player (if yes, repeats the script). For this, I need to check the caught/seen status of specific species in the Pokédex.
Could anyone help me how to best check for this? I would guess there are flags that can be read. This old post (also pasted below) however indicates it's more complicated. I cannot imagine I am the first one trying to do this, so perhaps there is a relatively simple way? Extensive scouring of the interwebs has not really resulted in anything so far, sadly. Thanks in advance for any help!
So far, I've gotten this far:
Jambo51 identifies a routine that does seen/caught checks. Plus some registries. But as I'm not well versed in ASM, I am not sure how to translate this to a workable (preferably XSE) script, if at all possible.
As for the Seen/Caught flags being DMA encrypted, the following DMA negation modification allows for static addresses of the Seen/Caught flags. (I have not tested it myself.)
Once DMA encryption is negated, with help from the CrystalWiki's RAM map, it theoretically allows us to find the now-static addresses of the Seen/Caught flags (I haven't calculated it yet but it should be simple):
Then there is the added difficulty that the ROM base I am using (Leon & UltimaSoul's) has the JPAN Save Block expansion installed and an expanded Pokédex, so all of the above information is probably already useless.
(I guess this is why people move to Decomp.)
Could anyone help me how to best check for this? I would guess there are flags that can be read. This old post (also pasted below) however indicates it's more complicated. I cannot imagine I am the first one trying to do this, so perhaps there is a relatively simple way? Extensive scouring of the interwebs has not really resulted in anything so far, sadly. Thanks in advance for any help!
So far, I've gotten this far:
Jambo51 identifies a routine that does seen/caught checks. Plus some registries. But as I'm not well versed in ASM, I am not sure how to translate this to a workable (preferably XSE) script, if at all possible.
Spoiler:
(...)
Seen/Caught Flags:Spoiler:There are 3 (yes, 3) sets of seen flags. I don't know why this is, but this would surely be a problem for any extension hack, as these would all need repointed to support more pokémon. These are all DMA protected, so it's impossible to give exact locations, but I do know how the game gets them, so i'll post that.
In all 3 cases, the game reads the ram location 0x0300500C for a base location, adds a specific amount to that base location, then adds the appropriate number of bytes to that to find the actual flag, the finally runs a flag decryption, but does not use the known flag decrypter at 0x6E6D0.
For the caught checks, the game runs the same routine, but passes it a different index. This makes the game check the caught flag instead of the seen flag. There are only 1 set of caught flags that i'm aware of. Again, they're DMA protected.
In any case, the routine which handles this, as well as the actual caught check, is at 0x104AB0.
These are the ones i've figured out so far:
R0 = Pokémon Species in in game index numbering.
R1 = Check Seen = 0, Check Caught = 1, Set Seen = 2, Set Caught = 3
(...)
Spoiler:
Decryption [FR]
(...)
DMA Negation [FR]
I'm calling this "negation", rather than "disabling" because the game still continues to load and store the DMA-protected data, it's just that the next pointer will always be the same, so it stays in the same place.
Existing routines will continue to work, as the pointers to the DMA-protected data are still being written correctly, it's just that, since nothing moves, following them is unnecessary - you can just read from the DMA-protected data's new static locations.
The following table of offsets is copied from DavidJCobb's Fire Red RAM Map, only with their new static locations:
Spoiler:
Code:[0x0202552C] 2b Camera X-position [0x0202552E] 2b Camera Y-position [0x02025530] 1b Current map. [0x02025531] 1b Current map bank. ------------------------------------------------------------------------- [0x02029314] Box data ------------------------------------------------------------------------- [0x02024588] 8b Character name including terminator, padded to end with 0xFFs [0x02024590] 1b Gender (00/01 m/f) [0x02024591] 1b Unknown [0x02024592] 2b Trainer ID [0x02024594] 2b Secret ID (halfword) [0x02024596] 2b Playtime (hours) [0x02024598] 1b Playtime (minutes) [0x02024599] 1b Playtime (seconds) [0x0202459A] 1b Playtime (frames) [0x0202459B] 1b Unknown [0x0202459C] 2b Options // this and above thanks to hackmew's asm tut pt. 1 ... [0x020245A2] 1b If 0xDA, then National Dex is enabled. ... [0x020254A8] 4b Security Key [0x020254AC] End (byte after) ------------------------------------------------------------------------- [0x020257BC] 4b Player's current money. [0x02000490] 4b Copy of player's current money. Doesn't seem to do anything if changed.
To use this, all you need to do is:
Code:0x0804C064: 00 21
Any old saves will have their data moved to its new static location as soon as the DMA routine is loaded, which happens quite often - at least each time a map loads. Any new saves will default to these locations and never deviate. After verifying that the given static locations are possible on a clean ROM, this essentially guarantees that disabling the DMA in this way will not cause problems.
Again, this is for Fire Red (U).
(...)
However, with the flags being a 52-byte long index/table/something, I am not sure how to read this for ca. 400+ species.Spoiler:DMA (Dynamic, exact address constantly changes)
Code:[0x03005008] + 0x0000 2b Camera X-position [0x03005008] + 0x0002 2b Camera Y-position [0x03005008] + 0x0004 1b Current map. [0x03005008] + 0x0005 1b Current map bank. [0x0300500C] + 0x0000 8b Character name including terminator, padded to end with 0xFFs [0x0300500C] + 0x0008 1b Gender (00/01 m/f) [0x0300500C] + 0x0009 1b Unknown [0x0300500C] + 0x000A 2b Trainer ID [0x0300500C] + 0x000C 2b Secret ID (halfword) [0x0300500C] + 0x000E 2b Playtime (hours) [0x0300500C] + 0x0010 1b Playtime (minutes) [0x0300500C] + 0x0011 1b Playtime (seconds) [0x0300500C] + 0x0012 1b Playtime (frames) [0x0300500C] + 0x0014 2b Options // this and above thanks to hackmew's asm tut pt. 1 [0x0300500C] + 0x001A 1b If 0xDA, then National Dex is enabled. [b][0x0300500C] + 0x0028 52bytes Flags of Pokemon caught [0x0300500C] + 0x005c 52bytes Flags of Pokemon seen[/b] [0x0300500C] + 0x0F20 4b Unknown (encryption key for hidden vars) [0x0300500C] + 0x0F24 End (byte after)
Then there is the added difficulty that the ROM base I am using (Leon & UltimaSoul's) has the JPAN Save Block expansion installed and an expanded Pokédex, so all of the above information is probably already useless.
(I guess this is why people move to Decomp.)
Last edited: