Main Menu
Main Page
Forums
Recent changes
Random page
Help

Databases
GlitchDex
AttackDex
ItemDex
TrainerDex
TypeDex
UnownDex
More

Major Glitches
Trainer escape glitch
Old man trick
Celebi Egg trick
Select glitches (Japan)
SRAM glitch
CoolTrainer♀ corruption
LOL glitch
Rival LOL glitch
Super Glitch
ZZAZZ glitch
Pomeg corruption glitch (Glitzer Popping)
Tweaking
Elite Four door glitch (Japan)
Pokémon merge glitch
Pokémon cloning
Time Capsule exploit
Arbitrary code execution
Coin Case glitches
More

Other Glitch Categories
Glitches by generation
Glitches between two generations
Japan-only/language specific glitches
Music glitches
Natural glitches
Non-core series glitches
Non-Pokémon glitches
Officially acknowledged glitches
Recurring glitches
Dead glitches

References
Pokémon GameShark codes
The Big HEX List
Glitch Pokémon cries
GB programming
Curiosities
Debugging features
Easter eggs
Error traps
Glitch areas
Glitch myths
Non-glitch exploits
Placeholder texts
Pokémon glitch terminology
Unused content and prerelease information

Useful Tools
8F Helper
GBz80 to Items
Old man trick name generator
PATH (Prama's Advanced Tweaking Heaven)
Save file editors
Special stat/Pokémon converter
Trainer escape Trainer Pokémon finder

Affiliates
Legendary Star Blob 2 (Hakuda)
Pokémon Speedruns wiki
PRAMA Initiative
Become an affiliate!

Technical
Site Source Code

Search Wiki

 

Search Forums

 

Author Topic: Crystal: Unused party sanitisation function  (Read 304 times)

0 Members and 1 Guest are viewing this topic.

Wack0

  • Coder, reverser, beta collector [BetaArchive staff]
  • Staff
  • *****
  • Offline Offline
  • Gender: Male
  • cBRH - Doing nothing since 2k7
    • View Profile
Crystal: Unused party sanitisation function
« on: October 03, 2017, 10:37:50 am »
I was looking in pokecrystal for something unrelated and this caught my eye.

As the filename would have you expect, it's in EN Crystal at $13A47 (4:7A47). (It's in JP Crystal at $13BB3 (4:7BB3)). That's near the end of the bank, located after some Bug-Catching Contest-related stuff, and before a function that uses a lookup table to find square roots. It appears to not be in G/S (and given that it calls a function in a bank related to mobile code, that's not unexpected).

It is completely unreferenced and unused in at least JP and EN Crystal.

Here's what it does:

  • If the number of Pokémon in the party is over 6, set it to 6
  • The party species bytes are checked. If a byte is an invalid species ($00, $FC, $FE, $FF), change that species byte and the first species byte of that Pokémon structure to Smeargle ($EB).
  • For all Pokémon in the party:
    • If the second species byte in the Pokémon structure is invalid ($FD (Egg) is also considered invalid here), change it to Smeargle.
    • If the Pokémon's level is below 2, set it to 2; if it is over 100, set it to 100. Recalculate the Pokémon's stats, no matter whether or not the level was modified.
    • If the Pokémon's nickname is unterminated after 6 bytes, terminate it by setting the 6th byte to $50; if the nickname has any invalid characters (defined here as anything that is not $00, $05 - $13, $19 - $1C, $26 - $34, $3A - $3E, $40 - $48, $60 - $FF; a function in a bank related to mobile functionality is called to do this), set it to the Pokémon species name (if the Pokémon is an Egg, then set it to "タマゴ" ("Tamago"/Egg) followed by 50 50 50 instead)
    • If the Pokémon's Original Trainer name is unterminated after 6 bytes, terminate it by setting the 6th byte to $50; if it has any invalid characters, set it to the player's name
    • If the Pokémon has an invalid move in slot 1 ($00, $FC, $FD, $FE, $FF), replace it with Pound. If there is an invalid move in slot 2, 3, or 4, delete all moves starting from that slot(!!!).

Note that this code is only half localised in non-JP - it assumes nicknames and OT names are 6 bytes long, the list of characters considered valid assumes a Japanese game, and if an Egg's nickname contains invalid characters, it gets set to "タマゴ"; however, when removing a Pokémon's nickname, or changing its OT name, it copies the correct number of bytes for the localisation.

Given that this calls a function in a mobile-related bank, this function may have been intended to have been used to force the legitimacy of party Pokémon when using mobile-related features. Of course, it may have just been debug code.
C H E C K E D . B U I L D S . A R E . A W E S O M E N E S S

BetaArchiveSoftHistory Forumsirc.rol.im #galaxy,#softhistory

Also known as The Distractor.

Shane, please stop telling children that there's a Mew outside under the delivery trucks. - Management

Pokémon: arbitrary code execution 1996-2016

SatoMew

  • Member+
  • *
  • Offline Offline
  • Gender: Female
    • View Profile
Re: Crystal: Unused party sanitisation function
« Reply #1 on: October 03, 2017, 06:52:03 pm »
Interesting find. Mayhaps it was debug code for the PCC's Trade Corner since the attendant does inform the player that either they only have 1 Pokémon in the party or that they are trying to send an Egg or abnormal Pokémon.

Wack0

  • Coder, reverser, beta collector [BetaArchive staff]
  • Staff
  • *****
  • Offline Offline
  • Gender: Male
  • cBRH - Doing nothing since 2k7
    • View Profile
Re: Crystal: Unused party sanitisation function
« Reply #2 on: October 03, 2017, 08:32:55 pm »
Pretty sure it is debug code now.

I searched for other places where the string validity check function is called.

It's called in three places. One of those seems to be unused, and all incorporate parts of the checks detailed in the OP.

The unused occurrence and first used occurrence are in Battle Tower code, sanitising Battle Tower Pokémon after they are read. (The unused occurrence seems to have just been dummied out, as it is directly after the used code ends.)

This code sanitises Pokémon nicknames, replaces any OT name with bad characters with "CHRIS" (only one terminator this time), makes sure all nicknames and the OT name are terminated, and sanitises invalid moves in the same way as detailed in the OP (except here, move $00 is never considered invalid).

The unused half of this function replaces invalid Pokémon species ($FD being considered invalid) with Smeargle ($EB). Instead of a simple greater-than-or-equal check, it checks for equality against each invalid species value in turn. Pokémon levels are also checked, but the maximum level instead of being hardcoded is taken from SRAM at 5:B2FB.

The last occurrence is inside mobile-related code. Every single string (nickname, OT, mail, mail author) is checked for invalid bytes and termination (where the terminator is $4E for some reason) within the correct length, by bankswitched calls. If one of these checks fails, the offending string is replaced with a default string by a bankswitched call.

Here's a list of default strings used:
OT name, mail author: "クりス" Chris followed by two terminators
Pokémon nickname: "?????" unterminated(!!!)
Mail text: "こんにちは" "Konnichiwa" Hello followed by one terminator

The default strings are terminated by $50 as usual.

After checking the strings, an "item" at $C60E is checked, if it's $FF it gets replaced by $00. Finally, the exact same level checks as in the OP are performed.
C H E C K E D . B U I L D S . A R E . A W E S O M E N E S S

BetaArchiveSoftHistory Forumsirc.rol.im #galaxy,#softhistory

Also known as The Distractor.

Shane, please stop telling children that there's a Mew outside under the delivery trucks. - Management

Pokémon: arbitrary code execution 1996-2016

Háčky

  • Distinguished Member
  • *
  • Offline Offline
  • Pick which packet as an error?
    • View Profile
Re: Crystal: Unused party sanitisation function
« Reply #3 on: October 03, 2017, 11:52:59 pm »
The unused occurrence and first used occurrence are in Battle Tower code, sanitising Battle Tower Pokémon after they are read. (The unused occurrence seems to have just been dummied out, as it is directly after the used code ends.)

This code sanitises Pokémon nicknames, replaces any OT name with bad characters with "CHRIS" (only one terminator this time), makes sure all nicknames and the OT name are terminated, and sanitises invalid moves in the same way as detailed in the OP (except here, move $00 is never considered invalid).

The unused half of this function replaces invalid Pokémon species ($FD being considered invalid) with Smeargle ($EB). Instead of a simple greater-than-or-equal check, it checks for equality against each invalid species value in turn. Pokémon levels are also checked, but the maximum level instead of being hardcoded is taken from SRAM at 5:B2FB.

Both of these checks are applied to Battle Tower opponents in the Japanese version. 5:B2FB is the chosen level of the Battle Tower challenge. Oddly, move sets are sanitized twice using slightly different criteria, the difference being that ValidateBTParty checks if the first move slot is empty and fills it with Pound if it is, while CheckBTMonMovesForErrors, called from ReadBTTrainerParty, erases any moves following an invalid or empty second or third slot. The cumulative effect seems to be identical to the unused move check in bank 4.

It seems Game Freak relied solely on this client-side validation at first; the Pokémon Battle Historia reports that Pokémon with illegal move sets were found in level 100 Battle Rooms in February 2001, until some server-side checks were introduced in early March. But even in late 2002, Kakeru complained of encountering Blastoise which knew both Counter and Mirror Coat (it can learn Mirror Coat as an Egg move, and Counter using the Generation I TM, but a Pokémon with Mirror Coat can’t be traded through the Time Capsule).

The last occurrence is inside mobile-related code. Every single string (nickname, OT, mail, mail author) is checked for invalid bytes and termination (where the terminator is $4E for some reason) within the correct length, by bankswitched calls. If one of these checks fails, the offending string is replaced with a default string by a bankswitched call.

I think this one is for Pokémon received from the Trade Corner.

SatoMew

  • Member+
  • *
  • Offline Offline
  • Gender: Female
    • View Profile
Re: Crystal: Unused party sanitisation function
« Reply #4 on: October 04, 2017, 08:50:15 am »
This code sanitises Pokémon nicknames, replaces any OT name with bad characters with "CHRIS" (only one terminator this time), makes sure all nicknames and the OT name are terminated, and sanitises invalid moves in the same way as detailed in the OP (except here, move $00 is never considered invalid).

If it corresponds to "CHRIS" in English Crystal, then the localizers assumed the OT was male as the default name for both male and female players in Japanese Crystal is 「クリス」, which in English Crystal is rendered as "CHRIS" for boys and "KRIS" for girls. The game assigns these to the player when they provide a blank string on the name input screen of the new game tutorial.

Here's a list of default strings used:
OT name, mail author: "クりス" Chris followed by two terminators
Pokémon nickname: "?????" unterminated(!!!)
Mail text: "こんにちは" "Konnichiwa" Hello followed by one terminator

Wait, does the game really spell out 「クりス」? That's an awkward combination of hiragana and katakana. And oops for not terminating that 「?????」 :P

Háčky

  • Distinguished Member
  • *
  • Offline Offline
  • Pick which packet as an error?
    • View Profile
Re: Crystal: Unused party sanitisation function
« Reply #5 on: October 04, 2017, 04:04:15 pm »
Wait, does the game really spell out 「クりス」? That's an awkward combination of hiragana and katakana. And oops for not terminating that 「?????」 :P

The Generation I and II games use the same character ($D8) for リ and り (likewise with $CD for ヘ and へ); the disassemblies treat it as the hiragana by default.

SatoMew

  • Member+
  • *
  • Offline Offline
  • Gender: Female
    • View Profile
Re: Crystal: Unused party sanitisation function
« Reply #6 on: October 04, 2017, 04:24:45 pm »
The Generation I and II games use the same character ($D8) for リ and り (likewise with $CD for ヘ and へ); the disassemblies treat it as the hiragana by default.

Oh, right. Thanks, Háčky! ^^