The PokéCommunity Forums  

Go Back   The PokéCommunity Forums > Fan Games > Binary ROM Hacking
Reload this Page Script How to check if a Pokémon species has already been "caught" (or "seen") in the Pokédex?

Notices
For all updates, view the main page.

Binary ROM Hacking Need a helping hand or just want to talk about binary ROM hacks? Get comments and answers to any ROM Hacking-related problems, questions or thoughts you have here.

Ad Content
Reply
 
Thread Tools
  #1   Link to this post, but load the entire thread.  
Old January 16th, 2020 (1:38 AM). Edited January 16th, 2020 by Dr. POP.
Dr. POP's Avatar
Dr. POP Dr. POP is offline
 
Join Date: Sep 2009
Location: Mt. Silver
Gender: Male
Posts: 119
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.
Spoiler:
Quote:
Originally Posted by Jambo51 View Post
(...)

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


(...)

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.)
Spoiler:
Quote:
Originally Posted by Zeturic View Post
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).

(...)

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):
Quote:
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.
[0x0300500C] + 0x0028   52bytes Flags of Pokemon caught
[0x0300500C] + 0x005c   52bytes Flags of Pokemon seen
[0x0300500C] + 0x0F20    4b    Unknown (encryption key for hidden vars)
[0x0300500C] + 0x0F24        End (byte after)
However, with the flags being a 52-byte long index/table/something, I am not sure how to read this for ca. 400+ species.

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.)
Reply With Quote
Reply

Quick Reply

Join the conversation!

Create an account to post a reply in this thread, participate in other discussions, and more!

Create a PokéCommunity Account
Ad Content

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -8. The time now is 9:15 AM.