Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - Háčky

Pages: [1]
Emulation & ROM Hacking / Emulating the Mobile Adapter GB
« on: June 13, 2016, 11:46:06 pm »
It’s been over fifteen years and no one has done this yet?

(This post is necessarily going to be filled with technical minutiae, so if that’s not your thing, you may want to skip the entire first half of it and skim through the rest. If that is your thing, then you don’t need me to tell you what to do.)

I’ve documented most of the protocol that Game Boy Color games use to communicate with the Mobile Adapter GB, and written a proof-of-concept implementation that links with BGB and enables Mobile Trainer’s initial setup and Pokémon Crystal’s Trade Corner to work. Because I’ve been working with BGB, I’ve not yet tested anything with Game Boy Advance games, but I would expect that the protocol is the same and it should be possible to create an implementation compatible with VBA-M in the future.

As all of this information has been determined solely from analysis of Mobile Trainer and Pokémon Crystal, I can’t say whether this documentation represents how the Mobile Adapter GB hardware actually behaves, but it at least represents how these games seem to expect it to behave.

Protocol description
The Game Boy Color communicates with the Mobile Adapter GB at a clock speed of 512 KiHz (bits 0 and 1 of the SC register are set and the GBC is in double-speed mode). The protocol closely resembles the one used by the Game Boy Printer, but it has been modified for two-way communication.

A communication session consists of a series of commands sent by the Game Boy Color, each followed by a response from the Mobile Adapter GB, generally using the same command ID as the command it is responding to. A session begins with the Game Boy Color sending command $10 with the body "NINTENDO", and the Mobile Adapter GB replying with the same. The session ends when the Game Boy Color sends command $11, and the Mobile Adapter GB responds in kind.

When either device sends a packet, it begins by sending the preamble bytes $99 $66, followed by the packet data. After the packet is finished, both the sender and receiver transmit a byte containing their device ID xor $80. (The Game Boy Color’s device ID is $00. Any device ID from $08 to $0F is recognized as a Mobile Adapter GB: $08 is the PDC model, $09 is the CDMA model, $0A is the unreleased DoCoMo PHS model, and $0B is the DDI PHS model. $0C–0F were presumably reserved for future use.)

After the device ID, the sender sends $00 while the receiver confirms successful receipt of the packet by sending the packet’s command ID xor $80. If the packet checksum fails, the recipient sends $F1 instead, which instructs the other device to resend the packet. ($EE, $F0, and $F2 also appear to be error codes, but I don’t know how they’re used.)

The packet itself consists of a four-byte header, followed by the body, followed by a two-byte big-endian checksum, which is the sum of each preceding byte (not including the $99 $66 preamble). The first byte of the header is the command ID, and the fourth is the length of the packet body. The second and third bytes are unused, as far as I know, and are set to $00. While a packet is being received, the recipient continuously transmits the byte $4B.

Command listing
This list covers all of the commands supported by the standard library found in Pokémon Crystal. There is also at least one command, $1A (write configuration data), that is exclusively used by Mobile Trainer. It’s possible that some of the missing numbers are commands that exist in the hardware but were never used by any software; for instance, I would expect that there are commands for opening and closing UDP connections.

The command numbers appear to be organized such that commands numbered $1x relate to the basic operation of the Mobile Adapter GB and its attached telephone, while commands numbered $2x are network operations.

$10: Begin session
Sent to the adapter at the start of a session. The packet body is the ASCII string "NINTENDO". The adapter replies with an identical packet.

$11: End session
Sent to the adapter at the end of a session. The packet body is empty. The adapter replies with an identical empty packet.

$12: Dial telephone
Instructs the adapter to dial a telephone number. The packet body contains one byte of unknown significance, followed by the telephone number written in ASCII. The adapter’s response has an empty body.

$13: Hang up telephone
Instructs the adapter to hang up a telephone connection. The packet body is empty. The adapter replies with an identical empty packet.

$14: Wait for telephone call
Instructs the adapter to wait for a telephone call to be received. The packet body is empty. The adapter replies with an identical empty packet (only when the call is received?).

$15: Transfer data
This command is used either to send data over a TCP connection opened with command $23, or directly to another Mobile Adapter GB. While a connection is open, the Game Boy sends this packet containing one byte of unknown significance followed by zero or more bytes of data to be transmitted. The adapter replies with one byte of unknown significance followed by zero or more bytes that it has received from the other end. This is repeated until the connection is closed. The adapter sets bit 7 of the command ID while it is connected to a server, so the reply’s command ID appears as $95. When the remote server has closed the connection (e.g., at the end of an HTTP response), the reply sets the command ID byte to $9F instead.

$17: Telephone status
Sent to the adapter before attempting to dial. The packet body is empty. The adapter’s reply has one byte: $00 means that the telephone is ready to make a call, $04 or $05 means that the line is busy (I’m not sure what the difference between these values is?), and any other value seems to be an error. Some features of Mobile Trainer actually check this after dialing to make sure the line is active, but Pokémon Crystal doesn’t bother.

$19: Read configuration data
Requests a portion of the adapter’s 192-byte configuration memory. The packet body consists of two bytes; the first is an offset and the second is the number of bytes to be read. The adapter replies with a body containing one byte of unknown significance (possibly the offset, although that would be redundant?) followed by the requested data. In practice, the configuration data is read in two chunks of 96 bytes; it should be technically possible to read the full 192 bytes at once, but reading in smaller chunks is probably more reliable.

$1A: Write configuration data
Writes to a portion of the adapter’s 192-byte configuration memory. The packet body consists of one byte, which is an offset, followed by the bytes to be written. The adapter’s reply has an empty body (or, at least, Mobile Trainer doesn’t seem to care what the response is). As with the read command, Mobile Trainer chooses to write the data in two separate chunks (of 128 and 64 bytes).

$21: ISP login
Logs in to the DION service (which will then be used to connect to an Internet server). The packet body begins with the login ID and password, each prefixed by a byte denoting its length. The last eight bytes are the IPv4 addresses of two DNS servers. The adapter’s reply has a four-byte body, which might be an IPv4 address assigned to the adapter, although that doesn’t seem to be needed for anything in-game.

$22: ISP logout
Logs out of the DION service. The packet body is empty. The adapter replies with an identical packet.

$23: Open TCP connection
Opens a TCP connection to an Internet server. The packet body consists of an IPv4 address (four bytes) and a port number (two bytes, big-endian). The adapter replies with one byte of unknown significance. The adapter sets bit 7 of the command ID while it is connected to a server, so the reply’s command ID appears as $A3.

$24: Close TCP connection
Closes a TCP connection to an Internet server. The packet body contains one byte of unknown significance. The adapter replies with one byte of unknown significance.

$28: DNS query
Looks up the IP address for a domain name, presumably using the DNS server addresses sent in command $21. The packet body is the domain name. The adapter’s reply has a four-byte body containing the corresponding IPv4 address.

Configuration memory
The Mobile Adapter GB has 192 bytes of memory in which to store configuration data. This memory can be read with command $19 and written with command $1A. It is structured as follows:

Code: [Select]
$00  "MA"
$02  Set to $01 during Mobile Trainer registration
     Set to $81 when registration is successfully completed
$04  Primary DNS server (
$08  Secondary DNS server (
$0C  Login ID ("g_________")
$2C  E-mail address ("")
$4A  SMTP server ("")
$5E  POP server ("")
$76  Configuration slot 1
$8E  Configuration slot 2
$A6  Configuration slot 3
$BE  Checksum (big-endian)

Strings are null-terminated if shorter than the fields which contain them.

Each configuration slot may contain a telephone number to be used to connect to the ISP (eight bytes) and an identifying string (sixteen bytes). The telephone number is stored in a variant of binary-coded decimal, where $A represents the # key, $B represents the * key, and $F marks the end of the telephone number.

If the device ID is $08 (PDC) or $09 (CDMA), Mobile Trainer will configure it to use the telephone number #9677 and identifying string "DION PDC/CDMAONE". If the device ID is $0A (DoCoMo PHS) or $0B (DDI PHS), it will be configured with the telephone number 0077487751 and identifying string "DION DDI-POCKET".

These are always written to the first configuration slot; the other two slots are always empty (filled with $FF and $00), and it’s unclear how they would have been used. (I’m guessing they’re there in case Nintendo wanted to support an ISP other than DION in the future?) Pokémon Crystal has an option within the Mobile menu, titled 「モバイルセンターを えらぶ」 Choose a Mobile Center, for selecting which of these three configuration slots it will use.

If the device ID is one of the unused values $0C–0F, Mobile Trainer will fill the entire configuration memory with garbage data, because bounds checking is for sissies.

The checksum, like the packet checksum, is simply the sum of the preceding 190 bytes.

Mobile Trainer
Initial setup
When the Mobile Trainer cartridge is first loaded with the Mobile Adapter GB connected, a setup wizard prompts the user to enter their DION login ID, e-mail address, and password. (According to instructions published by the Nintendo Online Magazine, these credentials were provided on the 「DIONモバイルGBコース登録書」 DION Mobile GB Plan Registration Form included in the Mobile Adapter GB box. The account would expire after 15 days unless the Registration Form was filled out and mailed to KDDI.)

(Straying further from the topic, this site has some photographs of the printed matter supplied with the Mobile Adapter GB, which bizarrely includes a promotion offering baseballs signed by Kazuhiro Sasaki, then a pitcher for the Nintendo of America–owned Seattle Mariners.)

The login ID and e-mail address are stored in the adapter’s configuration memory, and the user is asked to choose whether or not the password will be saved on the Mobile Trainer cartridge. After that, Mobile Trainer attempts to log in to the DION POP e-mail server (, where the subdomain is filled in from the entered e-mail address). If the login is successful, then a welcome message is displayed, followed by the Mobile Trainer title screen.

After setup has been completed, Mobile Trainer will boot to the title screen even when the Mobile Adapter GB is not connected. (If an adapter is connected, Mobile Trainer will still check whether it has been configured, and launch the setup wizard if needed.)


Other features
I haven’t put much effort into getting any other features of Mobile Trainer working, but they all appear to be fairly straightforward: the e-mail uses DION’s POP and SMTP servers, the account management options use a simple HTTP interface, and Nintendo’s mobile homepage would have used some subset of HTML (though there probably aren’t any complete surviving copies of the pages, there are a few screenshots in this Nintendo Online Magazine article).

However, there may be significant unused content in the Mobile Trainer ROM. The most obvious instance is some text for a debug menu that’s helpfully titled 「== DEBUG MODE ==」. I also found this peculiar run of text:



GAMER's Life



To my knowledge, Bowser didn’t play baseball until 2005 on the GameCube, and I still haven’t heard any news about this Pocket Monsters Moss

One more thing I noticed is that after completing the initial setup, there are four options in the 「モバイルせってい」 Mobile Settings menu, but when Torchickens used a GameShark code to skip the initial setup, a fifth option, 「電話番号の変更」 Change telephone number, appeared. By erasing my Mobile Trainer save file and using that GameShark code, I was able to replicate this and attempted to use this option. It read the configuration data from the adapter, then started executing from WRAM and choked on opcode $FD. I’m guessing that’s not the intended behavior.

Pokémon Crystal
Initial connection
On startup, before the copyright screen, Pokémon Crystal tries to connect to the Mobile Adapter GB and check the telephone status with command $17. If this connection is successful (which does not require that the adapter even be configured), all of the game’s mobile features are unlocked except for Mobile Stadium.

(The telephone status check has no purpose: the game will recognize the adapter as connected regardless of what value it sends in response to command $17. It appears that the result of this check is used to set or clear the “unlimited battle mobile adapter” flag, but the flag is always cleared regardless of what value is sent by the adapter. I’m guessing the debug build behaved differently.)

After the successful connection, the 「モバイル プロフィール」 “Mobile Profile” screen will be presented the first time Continue is selected from the main menu, or whenever a new game is started.

Egg Ticket
When the Egg Ticket is redeemed at the PokéCom Center Trade Corner, the game makes an HTTP GET request for ("CGB-BXTJ" is the product code for the Japanese version of Pokémon Crystal; "01" denotes the game’s publisher, Nintendo.) This text file should have two lines, with CRLF line endings.

The first line is the HTTP URI that will be used to download the Odd Egg data. This URI contains a sequence of up to four capital "X"s, which the game will replace with a hexadecimal value.

(If the filename—i.e., the part of the URI after the last "/", even if it’s part of the query string—starts with a decimal digit, the game reads up to three digits from the start of the filename, interprets this as the service fee [in yen] charged for downloading this file, and prompts the user to confirm before downloading it. Since it is known that there was no service fee for the Egg Ticket event, the filename should not start with a digit, or an "X" that will be replaced by a digit.)

The second line is a series of 16-bit values written in hexadecimal (with lowercase "a""f"). These represent the cumulative probabilities of each Odd Egg being obtained. The game generates a random 16-bit number, compares it to each of these values, and downloads the Odd Egg corresponding to the first value that is greater than or equal to the random number, by filling in the "X"s in the URI with "0000" for the first Odd Egg, "0001" for the second, and so on in hexadecimal. Leading digits will be omitted if there are fewer than four "X"s to replace.

If the second line of the file is blank, the Trade Corner attendant will say 「もうしわけ ございません! ただいま タマゴけんの サービスは ちゅうし しています」 “I’m awfully sorry. The EGG TICKET exchange service isn’t running now.” Reportedly the Egg Ticket exchange service ran for the entire time that the Mobile System GB was in operation, so this text would never have been used. If the Egg Ticket service was shut down, it would have made it impossible for someone who had the Egg Ticket in their Bag to use the Trade Corner until they deposited it in their PC, which could have been confusing.

The downloaded Odd Egg file is 54 bytes, containing the 48-byte Pokémon data structure followed by the nickname, which should be 「タマゴ」 “EGG”. The OT name 「なぞ」 “ODD” is added by the game, though it goes unseen since an Egg’s OT is always shown as “?????” until it hatches.

For my implementation, I’ve copied the Odd Egg data from the English version. But according to legend, the Odd Egg received from the mobile event had a 50% chance to be Shiny, higher than the 14% chance for the in-game event in the Western versions. Does anyone know where this information came from? The only way to verify it would have been to download index.txt and read the probability values, and I’ve seen no evidence that anyone would have known how to do that at the time.


PokéCom Center Trade Corner
When a Pokémon is deposited at the Trade Corner, the game sends an HTTP GET request for The first line of this file is a URI that will be used to log in before uploading the Pokémon data. Since the service fee for the Trade Corner was ¥10, the filename in that URI should start with "10".

As far as I can tell, the server is supposed to send an HTTP 401 Unauthorized response with a WWW-Authenticate header, to which the game will respond by retrying with an Authorization header. Then the server will respond with a Gb-Auth-ID header. I can’t seem to get this process to work, so instead I’ve bypassed it by having the server send the Gb-Auth-ID on the first try.

The game POSTs a 143-byte file with the following contents:

Code: [Select]
$00  DION e-mail address (null-terminated ASCII)
$1E  Trainer ID
$20  Secret ID
$22  Offered Pokémon’s gender
$23  Offered Pokémon’s species
$24  Requested Pokémon’s gender
$25  Requested Pokémon’s species
$26  Trainer name
$2B  Offered Pokémon’s 48-byte data structure
$5B  Offered Pokémon’s OT name
$60  Offered Pokémon’s nickname
$65  Mail data (filled with 00 if not holding Mail):
$65    Message
$86    Sender’s name
$8B    Sender’s Trainer ID
$8D    Pokémon species
$8E    Item index

The genders of the offered and requested Pokémon are encoded as: $00 = gender unknown, $01 = male, $02 = female, and (for the requested Pokémon) $03 = either male or female.

After a Pokémon is deposited in the Trade Corner, the game enforces a two-hour waiting period before the status of the trade may be checked. To check if a trade has been made, the game logs in to the DION POP e-mail server and searches for an e-mail with the header X-Game-code: CGB-BXTJ-00. If it finds one, it will read the X-Game-result header, which is in the format 1 ttttssss oooo rrrr x, where tttt and ssss are the Trainer ID and Secret ID, oooo is the gender and species of the offered Pokémon, and rrrr is the gender and species of the requested Pokémon, all written in lowercase hexadecimal. The last character x is either "1" or "2", with "1" indicating that a trade partner has been found and "2" indicating that the server has given up on finding one. If a trade partner has been found, the body of the e-mail will contain the last 105 bytes of the above data structure (starting from the Trainer name) for the received Pokémon, encoded in Base64.

If no e-mail with a matching X-Game-code and X-Game-result is found, the Trade Corner attendant will give you the option to retrieve your Pokémon. If you choose to retrieve it, the game reads a URI from the second line of exchange/index.txt and POSTs a 38-byte file to it, which contains the first 38 bytes of the above data structure (up to the requested Pokémon’s species). This cancels the trade.


Cable Trade Center
I wasn’t planning to work on the multiplayer features at this point; I just wanted to see what commands they use so I could add them to the command listing.

I wrote my program so that when it received a command it didn’t recognize, it would echo that command verbatim in response. This turned out to be entirely sufficient to make the Mobile Trade screen open and let me trade with myself!


One notable feature of the mobile trade animations is that the Mobile Adapter GB is depicted using a palette chosen according to the device ID—the PDC adapter is shown as blue, the CDMA adapter is shown as yellow, the unreleased DoCoMo PHS adapter is shown as green, and the DDI PHS adapter is shown as red. There are also assigned palettes for the unused device IDs $0C–0F: purple for $0C, black for $0D, pink for $0E, and gray/violet for $0F.

Cable Club Colosseum
I was also able to get into a battle with myself in the Colosseum, though it inevitably unraveled when the opposing Pokémon fainted and it tried to send out the fainted Pokémon as a replacement for itself (since it wasn’t “my” Pokémon that fainted, I hadn’t made a selection).

I did, however, find out what an “unlimited battle mobile adapter” does: it removes the 10 minute per day limit on Colosseum battles. When entering the Colosseum without the “unlimited battle” flag, the attendant will ask: 「きょうの のこり じかんは あと 10 ふんです[。] たいせん しますか?」 “Today’s remaining time is 10 min. Would you like to battle?” (or one of a few other messages if less time is left). With the “unlimited battle” flag, she asks instead: 「モバイル たいせん では ポケモンを 3たい えらんで たいせん します[。] よろしいですか?」 “To enter a mobile battle, you must pick a team of three POKéMON. Is that OK?”


I pilfered the BGB linking code from TheZZAZZGlitch’s implementation of the Game Boy Printer protocol and wrote a script that does just enough to make these features work. Rather than connecting to a proper server, it fabricates the responses that the server should give for a limited set of commands. It completely ignores the DION login ID and password, so you can enter whatever you want in Mobile Trainer’s setup. The e-mail server is hard-coded to contain an e-mail matching the Pidgey-for-Pidgey trade that I made in the video; if you want to use the Trade Corner, you’ll have to edit that e-mail to match your Trainer ID, Secret ID, and the trade you’ve made.

I think the next step will be to set up a server that can run a fully functioning Trade Corner, and write a client that can connect to that server or make direct “calls” to other clients. There’s still the matter of getting Pokémon Crystal’s Pokémon News, Battle Tower, and Mobile Stadium features running, and after that, it might be interesting to get a couple of the other Mobile Adapter GB compatible games working. Eventually, it would be fun to build a ROM hack of the English version of Pokémon Crystal that restores all of its mobile functionality.
Pokémon Discussion / Debug menus in Japanese Crystal
« on: January 05, 2016, 09:01:23 am »
I came across what appears to be text for a few debug menus, which are only present in the Japanese version of Pokémon Crystal (not in the English version, and not in Gold and Silver). I haven’t started to work out how to load the menus—someone else might like to try!—but it does look like there’s some surviving code. They’re in bank $12, which is the same bank as the main menu.

デバックモード オン
デバックモード オフ
“Palette Change” may refer to this well-known feature. “Reset”, “Debug Mode On”, and “Debug Mode Off” are vague, but tempting. (“A secret switch! Press it? Who wouldn’t?”)

This appears to be a list of the trainers (plus アオイ/Buena) who can be registered on the Pokégear’s phone.

“Radio Tower”, “Pokémon League”, “Railway”, “Team Rocket”, “All Off”. Would probably set/clear flags of the major story events.

“X” and “Y”. Probably not a reference to the sixth-generation games :P

“Phone”, “Phone Flag”, “Radio Occupation”, “Buena Points”, “GS Ball” (!), and “Counter” (of what?).


“All”, “Raikou”, “Entei”, “Suicune”.
Interesting. English Ruby v1.1 also fixed the typo in the Pokédex entry of Mawile (they had misspelled it as MAWHILE) but since there's an English Sapphire v1.1, I don't know what else was changed.
Neither do I.

I went and found at least some of the changes that were made. I can’t be sure if this is a complete list, because I don’t have a reliable way to sift out the actual changes amidst the tens of thousands of altered pointers. All offsets are for Ruby. Offsets for version 1.1 also apply to 1.2; the only change made in 1.2 was that the Berry glitch was fixed.

Pokémon name change on evolution ($803FB68 in v1.0 and v1.1)
This function is called when a Pokémon evolves. It checks if the Pokémon’s name is the same as the species it is evolving from, and if so, changes it to the name of the species it is evolving into.

In version 1.1, this function has an additional check: if the Pokémon originates from a non-English game, the name will not be changed on evolution. So, for example, if a Bulbasaur from an Italian or Spanish game (where all Pokémon have the same names as in English) is traded to English Ruby/Sapphire v1.0, its name will be changed to “IVYSAUR” when it evolves, but in v1.1, its name will remain “BULBASAUR”, as if that was a nickname.

Today’s Smart Shopper ($81AB381 in v1.0, $81AB3A1 in v1.1)
INTERVIEWER: How are you, viewers?
Today we’re visiting the POKéMON MART
in \v3.
Let’s check on what the hot sellers
have been recently.
In version 1.1, the phrase “the POKéMON MART” was replaced with “a shop”. I don’t know that I’ve ever seen this TV program in the game (does it only appear after mixing records?), but I would guess that it can mention purchases made at the Lilycove Department Store or other shops that aren’t Poké Marts. This error was introduced in translation; the original Japanese text uses みせ shop, not フレンドリィショップ Friendly Shop.

Paras Pokédex entry ($83A268A in v1.0, $83A26A2 in v1.1)
PARAS has parasitic mushrooms growing
on its back called tochukaso. They grow
large by drawing nutrients from the BUG
POKéMON host. They are highly valued as
a medicine for extending life.
In version 1.1, the phrase “the BUG POKéMON host” was changed to “this BUG/GRASS POKéMON host”. Did someone suddenly decide that Pokédex entries have to be technically accurate? Why did they stop there? :P

Mawile Ruby Pokédex entry ($83ADDC3 in v1.0, $83ADDE2 in v1.1)
As is already well-known, Mawile’s Pokédex entry uses the spelling “MAWHILE” in Ruby v1.0, which was corrected in v1.1.

Something can’t be used on that Pokémon ($840EFA1 in v1.0, $840EFBD in v1.1)
This item can’t be used on
that POKéMON.
In version 1.1, the word “item” was deleted, so the message reads “This can’t be used on that POKéMON.” I guess this message appears in some context that doesn’t involve an item?

Font adjustments ($8EA2C44 in v1.0 and v1.1)
Version 1.1 includes some of the font changes made for the European localizations: a more legible superscript “er”, and the additions of the semicolon, French guillemets ‹›, and superscript “e” and “re”. However, the height of capital letters and the shape of the ligature œ remain as they were in the original English release.
Bulbapedia currently describes the Berry glitch like this:
The Berry glitch is a glitch only found in Pokémon Ruby and Sapphire which stops the game's internal clock…The glitch typically occurs after about a year of owning the game, or to games that have been played for over 100 hours…
Nintendo described it like this:
In Pokémon Ruby and Pokémon Sapphire, certain berry trees will stop producing berries after you've played your game for one year.

One of these turns out to be fairly accurate.

The real-time clock (RTC) in the cartridges of Pokémon Ruby, Sapphire, and Emerald reports the time as a series of binary-coded decimal bytes for the year (0–99, which represent the years 2000–2099), month (1–12), day (1–31), hour (0–23), minute (0–59), and second (0–59). (It also gives the day of the week, but the game doesn’t use it.) Because the game doesn’t care about the calendar, and maybe because Game Freak can’t do BCD math properly, the RTC value is converted to a standard integer format for the timestamp stored in the save file: a 16-bit day number followed by 8-bit hours, minutes, and seconds. In version 1.0 of Ruby and Sapphire, and English version 1.1, the conversion from the RTC’s year-month-day to the save file’s day number looks something like this:

Code: [Select]
uint16_t rtcDateToDayNumber(uint8_t * rtcDate)
{ // JP Ruby/Sapphire v1.0: $8006818
        return ymdToDayNumber(bcdToInt(*rtcDate),
                              bcdToInt(*(rtcDate + 1)),
                              bcdToInt(*(rtcDate + 2));

uint16_t ymdToDayNumber(uint8_t year, uint8_t month, uint8_t day)
{ // JP Ruby/Sapphire v1.0: $800678C
        uint16_t dayNumber;

        // add 365 or 366 days for each elapsed year
        for(int i = year - 1; i > 0; --i)
                dayNumber += 365;
                        dayNumber += 1;

        // add days for each elapsed month this year
        for(int i = month - 1; i > 0; --i)
                dayNumber += daysInMonth[i]; // array of {31, 28, 31, 30, …}
        if(month > 2 && isLeapYear(year))
                dayNumber += 1;

        // add the elapsed days
        dayNumber += day;

        return dayNumber;

When you start a new game, and the RTC is set to 2000-01-01, this function will happily start counting the days in 2000 from 1 to 366. But when the RTC ticks over to the year 2001, suddenly the day number is back to 1, because the condition on the year loop is wrong—since the RTC’s years start from 0, the loop ought to run while i >= 0.

If the save file says your planted Berries are going to grow on day 367, and the RTC says it’s currently day 1, you’re going to be waiting a while. But if you have the patience to wait 366 days until the RTC reached 2002-01-02, you could finally pick your Berries then, and the system would work correctly from that point on.

Basically, all that needs to be done to fix the Berry glitch is to add a year to the RTC to make up for the year that is lost when the date rolls over from 2000-12-31 to 2001-01-01. Less basically,
  • If the date is between 2000-01-01 and 2000-02-29, add one year, so that the day number remains the same and the glitch will not be triggered at the end of the year. (2000-02-29 is changed to 2001-03-01.)
  • If the date is between 2000-03-01 and 2000-12-31, add one year and one day, so that the day number remains the same (taking into account that 2001 is not a leap year) and the glitch will not be triggered at the end of the year.
  • If the date is in the year 2001, and the save file timestamp is greater than the current RTC value, then change the date to 2002-01-02, so that time can resume from that point.
  • If the date is in 2002 or later, there’s nothing to be done.
In later versions of Ruby and Sapphire, the ymdToDayNumber function was corrected so that the loop accounts for the days elapsed in the year 2000 (you can find it at $8009180 in English Ruby v1.2). The Berry Program Update checks the version number of the ROM and says that “There is no need to update your Berry Program” if it is a fixed version.

The Berry Program Update does nothing to help with cartridges in which the battery has been replaced. These games exhibit the same symptoms as the Berry glitch, but it is caused by the RTC being reset rather than the date conversion bug. If the save file timestamp is greater than the RTC value and the date is not in 2001, then the Berry Program Update will be “Unable to update the Berry Program.” If the RTC date is in 2001 (the battery was replaced between 1 and 2 years ago), the update will only change the date to 2002-01-02, which will still not fix the issue. For time-based events to resume after the cartridge battery is replaced, another method is needed to adjust the RTC, such as the tool on Furlock’s Forest. The in-game clock adjustment function which can be activated through Mystery Events might also be able to help, but I haven’t investigated that possibility.
While poking around in Emerald’s ROM, I noticed that at $9AA144, there’s a multiboot payload—a program designed to be transferred over the Link Cable to a connected GBA—with a header using the game ID “TEST”. (This ID is “BPEE” for Emerald, “AXVE” for Ruby… The string “TEST” is at offset $AC of the header, or $9AA1F0.)

The actual program is compressed using the LZ77 method built into the GBA BIOS, so for anyone who wants to look at it, I’ve put the decompressed file in the attachment to this post (frlge-TEST.bin). Looking at it in a sprite viewer, the file includes a complete copy of Ruby and Sapphire’s fonts, including the unused Unown font. It also contains a bunch of text in the Generation III games’ character encoding, starting at $1FDA8 of the decompressed file. Some of the latter messages hint at the origin of this program:

The save filehas been deleted...
The save file is corrupted.
There is no save file.
Please select \v0 POKéMON.
Please select a POKéMON.
Do what with \v4?
No. \v0
Select additional POKéMON!
What will
\v4 do?
Will you give in?
\v4 can’t be
switched out!
FOE \v0’s SHADOW TAG stops
\v4 from switching out!
FOE \v0’s ARENA TRAP stops
\v4 from switching out!
FOE \v0’s MAGNET PULL stops
\v4 from switching out!
\v4’s \v0 is disabled!
\v4 can’t use the same
move in a row due to the TORMENT!
\v4 can’t use
\v0 after the TAUNT!
\v4 can’t use the
sealed \v0!
CHOICE BAND allows the
use of only \v0!
There’s no PP left for
this move!
\v4 has no energy
left to battle!
\v4 is already
in battle!
\v4 has already been
You can’t switch \v4’s
POKéMON with one of yours!
\v4 has no
moves left!
Link standby...
Please don’t turn off the power.
Save failed.
The link was interrupted.
This Game Pak cannot be linked to
This Game Pak cannot trade with
Receiving move data...
Sending POKéMON data...
Receiving battle POKéMON data...
Receiving battle data...
Start POKéMON trade.
End POKéMON trade.
Sending POKé COUPONS...
Receiving POKé COUPONS...
Your Berry Program was updated.
Unable to update Berry Program.

The word “filehas” on the first line is their typo, not mine, and I’m not sure what’s so special about Charmander, Kangaskhan, and Typhlosion. (Maybe they were used to test message lengths.)

There are a few other pieces of text in the file. Bizarrely, the strings “MALICIOSO” and “GIRO FUEGO” appear at $1FBFC; those are the Spanish names of the moves Leer and Fire Spin. Also, the ASCII strings “pokemon ruby version” and “pokemon sapphire version” each appear twice near the end of the file. (Amusingly, TCRF notes the fragments of this text, as they appear within the compressed block, and calls them an “Obvious leftover from when Pokemon Ruby and Sapphire were being developed.” Not so obvious now, is it? :D)

This program was definitely based on, but is not identical to, the program that Pokémon Colosseum runs on connected GBAs for multiplayer battles and trades. Colosseum’s multiboot program also uses the game ID “TEST”—despite being used in the final version! I extracted this program from both the NTSC and PAL versions of Colosseum, and will include those decompressed files in the attachment as well for anyone who wants to try to see what the differences actually are.

(The PAL version of Colosseum actually contains six copies of the “TEST” program. One is identical to the NTSC version, and the other five are in the PAL version’s five supported languages, including a second, different English copy. That’s the one I’ve named “colo-TEST-pal-en.bin”.)

The English FireRed and LeafGreen contain exactly the same program as Emerald, and identical copies—still with English text—are in the European localizations of FireRed, LeafGreen, and Emerald. As far as I can tell, there is no equivalent to this program in the Japanese versions: the only GBA header in those ROMs, other than the cartridge header itself, is the one for the Ruby/Sapphire Berry glitch fix (which uses game ID “AGBJ”, which was probably some sort of default but also actually represents the game GetBackers Dakkanya: Jigoku no Scaramouche).

Since it’s missing from the Japanese versions and untranslated in others, it seems fairly clear that this program isn’t used in the final game, but I can’t understand what it could possibly have been used for. When a GBA is linked with Pokémon Colosseum, Colosseum itself sends the required program to the GBA. What exactly would be accomplished by sending Colosseum’s link-battle program from a GBA running FireRed/LeafGreen to another GBA? The best theory I can think of is that Nintendo of America was experimenting with adding a single-cartridge multiplayer feature to FireRed and LeafGreen, based on the code from Colosseum. But that seems unlikely; is there an obvious explanation I’m missing?
Emulation & ROM Hacking / Anatomy of an e-Reader Mystery Event
« on: November 21, 2014, 05:24:47 am »
For a long time, I didn’t know anything about the e-Reader other than that it was a short-lived gimmick on Pokémon trading cards. Once I realized that it was basically a Nintendo-approved flash cart that can install patches in games, I’ve really wanted to find out how it works and how to make my own cards for it.

I’ve made a disassembly of most of the English e-Reader cards released for Pokémon Ruby and Sapphire (excluding some promotional cards, but including the Eon Ticket). These programs are Z80 machine code which the e-Reader emulates on the GBA. The program communicates with the linked GBA running Ruby/Sapphire and sends Mystery Events data.

The first packet of data sent by a Mystery Events card is 60 bytes. It seems to be exactly the same for every card, except for two useless fields and a region code.

Code: [Select]
Offset Len  Description
$00    14   “GameFreak inc.” [sic] in ASCII
$0E    6    Unknown (00 00 00 00 00 00)
$14    4    Arbitrary number
$18    8    Arbitrary identifier in R/S charset
$24    10   Unknown (00 00 00 00 01 55 00 00 00 00)
$2A    1    01: Japanese; 02: English
$2B    1    Unknown (00)
$2C    14   “GameFreak inc.” [sic] in ASCII
$3A    2    Probably padding (00 00)

Apparently Generation III was a period in which Game Freak didn’t know what their company’s name was; it’s also spelled as one word on the title screens of the Japanese Generation III games, but as two words on the cartridge labels and most everywhere else.

On Battle e cards, the arbitrary number is $12345678 and the arbitrary identifier is “カ。ドE” (an apparent typo for カードe Card e). On the Gentleman Nils and Lady Astrid cards included in the American releases of Ruby and Sapphire, the arbitrary number is 0 and the arbitrary identifiers are “NILS” and “ASTRID”. On the Eon Ticket, the arbitrary number is 0 and the arbitrary identifier is “e reader” with no $FF terminator.

If the region code at offset $2A is wrong, the game will terminate the link with the message “Loading error. Ending session.”, which is the same message used for checksum failures.

The second packet, which contains the actual card data, is either 3072 or 6144 bytes long, starting with a 24- or 32-byte header and ending by lazily copying about 2000–5000 bytes after the end of the data, including the card’s entire Z80 program. It’s almost a quine!

Code: [Select]
Offset Len  Description
$00   1     Unknown (01)
$01   4     Base address ($02000000)
            This is where the data gets loaded in RAM, and all subsequent
            pointers are based on this location.
$05   1     01: Japanese; 02: English
$06   1     Unknown (00)
$07   1     01: Japanese; 02: English
$08   9     Unknown (00 00 00 04 00 80 01 00 00)
$11   1     Data type
              2: Variable-length data (must be used inside type 16)
              5: Custom script, runs immediately (must be used inside type 16)
              6: Custom script, runs in-game (must be used inside type 16)
              7: Enigma Berry
              11: Mixing records gift item
              13: Battle Trainer
              16: Contains multiple types

God knows why they needed two more copies of the region code, but if either is incorrect, the message “This data cannot be used in this version.” will appear. The region code in the prologue must be correct to even reach this point, so this message is never seen when scanning a real card.

For simple cards such as the Enigma Berries or Battle Trainers, which consist of a single fixed-length chunk of data, the header finishes with six more bytes:

Code: [Select]
Offset Len  Description
$12    4    Pointer to data start (always $02000018)
$16    2    Unknown (02 00)

For cards with multiple data chunks (type 16), such as the Eon Ticket, the header instead finishes with twelve more bytes:

Code: [Select]
Offset Len  Description
$12    2    Data checksum
$14    2    Padding (00 00)
$16    4    Pointer to data start (always $0200001E)
$1A    4    Pointer to data end

Unlike Pokémon data, save data, other kinds of e-Reader cards, or anything else in these games, for which a trivial bytewise or wordwise sum is sufficient to preserve integrity, this particular card structure is SERIOUS GODDAMNED BUSINESS which demands the use of a grown-up CRC function found at $08041174 in the original English Ruby. Here’s a C translation:

Code: [Select]
uint16_t compound_card_crc(const char * data, uint16_t len)
uint16_t x = 0x1121;
for(uint16_t i = 0; i < len; ++i)
x ^= data[i];
for(uint16_t j = 0; j < 8; ++j)
if(x & 1)
x = (x >> 1) ^ 0x8408;
x >>= 1;
return ~x;

This relatively impressive level of verification is used only at the time the data is transferred. Once loaded into the game, the separate chunks are protected only by a bytewise checksum preceding each one. Why did they even bother?

After the header, each chunk is declared with a type byte, followed by its data, the length of which is inferred from the type. If variable-length data (type 2) is included, it must come after all fixed-length chunks.

Variable-length data (type 2)
This chunk is used to contain the actual script code for a chunk of type 5 or 6. It has no particular structure; those other chunks include pointers to the specific addresses of the data they need.

Custom script, runs immediately (type 5)
This chunk is 4 bytes long; it’s just a pointer to a script stored in the type 2 chunk. The script is executed right away while still on the Mystery Events screen. The result of the script is given using the setbyte command ($0E):

  • setbyte 0 is a success state which displays the message “The event was safely loaded.”
  • setbyte 1 is a failure state which displays the message “Loading error. Ending session.”
  • setbyte 2 is a success state which displays the message at the address loaded with the virtualloadpointer command ($BE).
  • setbyte 3 is a failure state which displays the message at the address loaded with the virtualloadpointer command.
Both the Eon Ticket and the Japanese “Decoration Present” card (which gives the Regirock, Regice, and Registeel Dolls) use setbyte 2 or setbyte 3 to display custom messages, so “The event was safely loaded.” is never seen. The Eon Ticket’s script fails if the player already has the Eon Ticket item, if flag $00CE is set, or if the Key Items pocket is full. If the type 5 script fails, other chunks (i.e., the Norman event and the mixing records gift) will not be loaded into the save file.

Custom script, runs in-game (type 6)
This 11-byte chunk gives pointers to the start and end of a script stored in the type 2 chunk, and the “person event” in the game to which this script should be attached. The script is copied into the save file and run whenever the player interacts with that person.

Code: [Select]
Offset Len  Description
$00    1    Map bank
$01    1    Map number
$02    1    Person event number
$03    4    Pointer to script start
$07    4    Pointer to script end

The Eon Ticket gives its script to Norman (map 8.1, person event 1), but it can just as easily be assigned to anyone in Hoenn:

The killscript command ($0D) deletes the script from the save file.

Enigma Berry (type 7)
These cards define the properties of a berry which replaces the Enigma Berry as No. 43, triggering an in-game event where Norman gives you the berry at Petalburg Gym (unlike the Eon Ticket, this is hard-coded). The chunk is 1328 bytes long, most of which is just a pretty picture:

Code: [Select]
Offset Len  Description
$000   7    Berry name
$007   1    Firmness (from 1 “very soft” to 5 “super hard”)
$008   2    Size (in millimeters)
$00A   1    Maximum yield
$00B   1    Minimum yield
$00C   8    Always 00
$014   1    Hours per growth stage
$015   5    Flavor (Spicy, Dry, Sweet, Bitter, Sour)
$01A   1    Smoothness
$01B   1    Always 00
$01C   1152 Sprite (48×48 px)
$49C   32   Palette (16 colors in 15-bit BGR format)
$4BC   45   Tag description line 1
$4E9   45   Tag description line 2
$516   10   Usage by trainer
$520   8    Unknown (always 00)
$528   1    Usage as held item
$529   3    Unknown (always 00)
$52C   4    Bytewise checksum

JPAN on PokéCommunity documented this item-usage-by-trainer data structure. It consists of a six-byte bitfield followed by parameters. Parameters are included only if required.

There could well an equally-sophisticated structure for defining held item usage, but I couldn’t find information on that. The known values for offset $528 are:

Code: [Select]
$00: No effect
$04: Cures poison            (Drash Berry)
$05: Cures burn              (Japanese Yago Berry)
$06: Cures freeze            (Pumkin Berry)
$08: Cures confusion         (Japanese Touga Berry)
$17: Restores a lowered stat (Japanese Ginema Berry)
$1C: Cures infatuation       (Eggant Berry)

Incidentally, Bulbapedia claims the Kuo Berry cures a burn, but it’s actually the Yago Berry that does. Too bad it’s been closed to editing because of some new game that isn’t half as exciting as this stuff. :P

Mixing records gift item (type 11)
This chunk is written to the save file and causes an item to be received in other games when they mix records with this one. It is four bytes long:

Code: [Select]
Offset Len  Description
$00    1    Unknown (01)
$01    1    Distribution limit
$02    2    Item

For the Eon Ticket, the distribution limit is 30. This number is reduced by 1 each time the game mixes records, even if the item is not actually distributed (when mixing records with the same game again, or when the recipient does not have space for the item). Receiving the Eon Ticket in this manner automatically activates the Southern Island event.

This only seems to work with key items. Pokémon Emerald will accept key items offered in this manner from Ruby/Sapphire even if the item did not exist in the earlier games (index > $015C). However, receiving the MysticTicket, AuroraTicket, or Old Sea Map in this manner does not activate the corresponding event.

Battle Trainer (type 13)
This 188-byte chunk is written to the save file and causes a trainer to appear at a house in Mossdeep City. It may also allow this trainer to appear in the Battle Tower. Furlock’s Forest previously documented this data structure, but I’ve learned a couple of new things about it.

Code: [Select]
Offset Len  Description
$00    1    Battle Tower appearance
              0: does not appear at Battle Tower, only in Mossdeep house
              50: appears in Battle Tower Lv50 challenge
              100: appears in Battle Tower Lv100 challenge
$01    1    Trainer class
$02    1    Battle Tower floor (0: does not appear at Battle Tower)
$03    1    Unknown (always 00)
$04    8    Trainer name
$0C    2    Trainer ID (always 00000)
$0E    2    Trainer SID (always 00000)
$10    12   Pre-battle text (six easy chat halfwords)
$1C    12   Victory text (six easy chat halfwords)
$28    12   Defeat text (six easy chat halfwords)
$34    44   Pokémon 1
$60    44   Pokémon 2
$8C    44   Pokémon 3
$B8    4    Wordwise checksum

The indices for trainer classes are different than those used for the in-game trainer data. I don’t know if this list is used for anything other than e-Reader cards.

Code: [Select]
$01: *TEAM AQUA    (♂)
$02: *TEAM AQUA    (♀)
$06:  TUBER        (♀)
$07:  TUBER        (♂)
$0B:  LADY
$13:  CAMPER
$15:  PSYCHIC      (♂)
$16:  PSYCHIC      (♀)
$18: *ELITE FOUR   (Sidney)
$19: *ELITE FOUR   (Phoebe)
$1A: *LEADER       (Roxanne)
$1B: *LEADER       (Brawly)
$1C: *LEADER       (Tate&Liza)
$1D:  SCHOOL KID   (♂)
$1E:  SCHOOL KID   (♀)
$1F: *SR. AND JR.
$20:  POKéFAN      (♂)
$21:  POKéFAN      (♀)
$22:  EXPERT       (♂)
$23:  EXPERT       (♀)
$27:  TRIATHLETE   (♂ cycling)
$28:  TRIATHLETE   (♀ cycling)
$29:  TRIATHLETE   (♂ running)
$2A:  TRIATHLETE   (♀ running)
$2B:  TRIATHLETE   (♂ swimming)
$2C:  TRIATHLETE   (♀ swimming)
$32:  SWIMMER♀
$34: *TWINS
$35:  SAILOR
$36: *BOARDER      (Youngster)
$37: *BOARDER      (Youngster)
$39: *PKMN TRAINER (Wally)
$3A: *PKMN TRAINER (Brendan)
$3B: *PKMN TRAINER (Brendan)
$3C: *PKMN TRAINER (Brendan)
$40:  PKMN BREEDER (♂)
$41:  PKMN BREEDER (♀)
$42:  PKMN RANGER  (♂)
$43:  PKMN RANGER  (♀)
$45: *TEAM MAGMA   (♂)
$46: *TEAM MAGMA   (♀)
$47:  LASS
$49:  HIKER

The classes AQUA ADMIN, MAGMA ADMIN, and WINSTRATE are apparently unavailable, as are the other five Leaders and two Elite Four members. Indices greater than $4C result in mismatches between the trainer class and sprite:

This value also determines the overworld sprite shown in the Mossdeep house. Any class marked with an asterisk, and any value greater than $4C, will be shown in the overworld as a generic male NPC.

There are two identical entries for the unused BOARDER class in this list, implying that male and female versions were planned, and three identical entries each for Brendan and May, which might indicate that they were intended to have multiple sprites like the rivals in prior games.

The 44-byte substructure for Pokémon data is:

Code: [Select]
Offset Len  Description
$00    2    Species
$02    2    Held item
$04    8    Moves
$0C    1    Level
$0D    1    It’s not very effective…
$0E    6    Effort values
$14    2    OT ID (always 00000)
$16    2    OT SID (always 00000)
$18    4    Individual values (five bits each); bit 31: Ability
$1C    4    Personality value
$20    11   Nickname
$2B    1    Friendship (always 255, unless it knows Frustration)

Offset $0D represents the number of PP Ups applied, with two bits for each move. This byte is ultimately copied to offset $3B of the battle data structure, which is used to determine the moves’ maximum PP, but it is not taken into account when initializing the moves’ remaining PP at the start of the battle. For example, Collector Stuart’s Wailord has 3 PP Ups applied to Hydro Pump and Blizzard, but these moves have only 5 out of 8 PP available in the battle. If this Pokémon were holding a Leppa Berry (which it isn’t), it would be able to restore one of these moves to 8 PP after expending the original 5 PP, but otherwise PP Ups have no effect. PKMN Ranger Irazu is the other card affected by this glitch; his Pokémon each have three PP Ups for Return.

IVs and EVs seem to have been assigned a bit haphazardly in the Battle e series. Most Pokémon have two perfect IVs and four 15s except for level 100 Pokémon, which have 20s instead of 15s. A few have their IVs adjusted for the sake of Hidden Power, but there are several exceptions that appear to be by mistake, including some Pokémon with one 0 IV. EVs are generally assigned as either 252+252+6 or 255+255, but again there are a few exceptions, including one Pokémon (Psychic Natasha’s Starmie) that has an illegal EV spread of 6/0/6/252/252/0. Perfect IVs and EVs are sometimes given in the same two stats, but often not.

Open questions
  • Based on the numbering, there would appear to be around 7–10 other types of Mystery Event chunks which aren’t used in any e-Reader cards. (Notes: the berry glitch patch doesn’t use Mystery Events, the Japanese “Decoration Present” card uses type 5 scripts to award the Regi dolls, and Altering Cave wasn’t in Ruby and Sapphire.) Surely one of them was used for event Pokémon distributions, but I’m very interested in finding out what the others are.
  • The leaked German Ruby debug version contains some Mystery Event data, including a test Pokémon distribution. I did some searching through the ROM, and found the Eon Ticket script at $45DAE1. First impressions: the event’s text is translated into German, addresses are based on the ROM location rather than $02000000 (implying this can only work if transferred to another debug cartridge?), the header uses region code 4, offset $0E is set to 0 instead of 1, and the oh-so-important checksum is set to $0000. There’s definitely more to explore here.
  • How is Mystery Event data structured in the save file?
  • Even though the data itself is nothing special, it might be useful to disassemble the Regi doll card, because it features a basic menu system (for choosing which doll to send) that may be a helpful template for a custom interactive e-Reader program. I think it’d be neat to make programs that can do things like customizing a Battle Trainer before you send it to your game.
  • The popular conception seems to be that “e-Reader support” was removed from the Western releases of FireRed, LeafGreen, and Emerald, but there really isn’t such a thing. The e-Reader can run any program that fits in a series of dotcodes, and a program can be made to access any of the networking features that exist in the game. Trainer Tower/Trainer Hill customization may have been removed, but there’s no reason an e-Reader program couldn’t be written to distribute Wonder Cards.
As Torchickens has documented, taking a Pokémon with index number $FE in either Generation I or II into a trade or link battle with a Generation II game causes everything in the party to appear corrupted to the other game—shifted by one byte, to be more specific. Typically, this prevents trading, because everything will appear to be “abnormal” to the other game. (Note: I haven’t looked very far into exactly why this corruption happens, but the code starting at $2879E in Crystal looks extremely suspicious.)

What makes a Pokémon “abnormal”, anyway? The function at $FB57E in Crystal checks three things for Pokémon traded from Generation I:

1. The Pokémon must not be a hybrid, unless it’s an Egg. (There’s no way for a Generation I Pokémon to be seen as an Egg in Generation II, because $FD does not appear in the conversion table.)
2. The Pokémon’s level (offset $21 in the Generation I Pokémon data structure; offset $03 is ignored) must not be over 100.
3. The Pokémon’s types must be correct, unless it’s a Magnemite or Magneton (because they gained the Steel type in Generation II).

When $FE shifts the Generation I data structure, the least significant byte of the Pokémon’s remaining HP will become its species, its Type 2 will become its Type 1, its catch rate/held item will become its Type 2, and the least significant byte of its maximum HP will become its level. There are at least three ways to engineer things so that all these values will look okay after the corruption:

1. Get a Magneton with 54 HP remaining out of a total HP of 256 or higher.
2. Get any single-typed Pokémon in Generation II (except Normal or Bug type), with the same remaining HP as its index number in Generation I, and a total HP either less than 100 or between 256 and 356 (for example, a Krabby with 78/78 HP can be used, and you might be able to catch one of those by fishing in Whirl Islands 1F with a Super Rod). Give it the item with the same index number as its type: Fighting→Master Ball, Poision→BrightPowder, Ground→Great Ball, Rock→Poké Ball, Ghost→Moon Stone, Fire→Repel, Water→Max Elixer, Grass→Fire Stone, Electric→ThunderStone, Psychic→Water Stone, Dragon→HP Up, Dark→Protein. Then send it to Generation I normally (using the Johto guard glitch if necessary) before trading it back to Generation II with $FE corruption.
3. Get any Pokémon in Generation II with HP that corresponds to the Generation I index number of any single-typed Pokémon (except Normal or Bug type) which is the same as its own second type. Give it the item with the same index number as that Pokémon’s type. Send it to Generation I normally (using the Johto guard glitch if necessary), hybridize it with that Pokémon, and then trade it back to Generation II with $FE corruption.

(Normal is index $00, which corresponds with an item named ?, and Bug is $07, which corresponds with a Teru-sama. There are no pure Flying, Steel, or Ice-types in Generation II.)

When a corrupted Pokémon is received, its name and OT will be missing the first letter, its current HP will be its original level × 256, it may have multiple status conditions based on its type, it will be holding an item based on the index number of its first move, and its fourth move will be based on the least significant byte of the OT ID number and have PP based on its original level. Its stats, experience points, IVs, and EVs will probably be greatly increased, except for Special Attack and Special Defense which have to be recalculated.

Another thing I’ve noticed is that, if you put two $FE Pokémon in your party, everything will be shifted by two bytes, three $FEs will shift everything by three bytes, and so on. A three-byte shift would turn a Pokémon’s level into its species, its first two moves into its two types, and the least significant byte of its Attack stat into its level.

This might be the easiest method: get a level 54 Magneton, which should have less than 100 Attack unless its EV is too high, and corrupt it with three $FEs in the party. You can teach it TM33 Reflect as its third move so that it will be holding a GS Ball, or TM44 Rest so it will hold a Sacred Ash. (Unfortunately, Magnemite and Magneton don’t learn any moves with indices under 100 that correspond to key items, so this method won’t provide everything needed to corrupt the Balls pocket.)

It should be even easier to mess around with this in a trade between two Generation II games, if there’s a convenient way to obtain ????? ($FE). Obviously it can be done with arbitrary code execution, but I don’t know how much setup that would require.
By filling the Key Items pocket with items obtained through the Time Capsule or Celebi glitch, the duplicate key item glitch can be used to corrupt the Balls pocket, giving it access to memory beyond where that pocket is supposed to end. This allows you to use almost any item stored in your PC an unlimited number of times in the field. In Gold/Silver, it can be used to manipulate memory beyond that, but unfortunately only the PC aspect works in Crystal.

1. Deposit all of your balls into the PC, so that the Balls pocket is empty.
2. Collect enough key items that your Key Items pocket is full. If you try to take another key item from a Pokémon, it should say “Item storage space full.” The pocket holds 25 items, and in it you’ll need to have two of a key item with an index number greater than 100, and two of a key item with an index less than 100. For illustration, I’ll use two Machine Parts and two SecretPotions.
3. Move the two Machine Parts to the bottom two slots in the list, then swap them. The second item and the Cancel button will be replaced by a Blk Apricorn and Iron. (The Iron will be something else if you use a different item with index > 100. I like the idea that the remnant of a Machine Part is Iron, though. :P )
4. Swap the two SecretPotions into the bottom two slots in the list (including the slot that used to be the Cancel button), then swap them. The second SecretPotion should disappear.
5. Switch to the Balls pocket and scroll down.

Key items > 100: Card Key, Machine Part, Lost Item, Basement Key, Pass, SquirtBottle, Rainbow Wing (Crystal only: GS Ball, Blue Card, Egg Ticket)
Key items < 100: Bicycle, Coin Case, Itemfinder, Old Rod, Good Rod, Super Rod, Red Scale, SecretPotion, S.S. Ticket, Mystery Egg, Silver Wing (Crystal only: Clear Bell)

The last two item pockets in RAM are the Key Items and Balls pockets, at D5E1–D5FB and D5FC–D615 in Gold/Silver. In the first swap, the pertinent memory will look like this, if you chose Machine Part:

Code: [Select]
D5E1: $19  25 key items

(the SecretPotions are up here somewhere)

D5F9: $80  Machine Part
D5FA: $80  Machine Part   →  $1C  Iron         (×99)
D5FB: $FF  Cancel         →  $63  Blk Apricorn  (×0)
D5FC: $00  0 balls
D5FD: $FF  Cancel

In the second swap:

Code: [Select]
D5E1: $19  25 key items   →  $18  24 key items

(the Iron and Blk Apricorn are up here somewhere)

D5F9: $80  Machine Part
D5FA: $43  SecretPotion
D5FB: $43  SecretPotion   →  $43  (hidden)
D5FC: $00  0 balls        →  $FF  255 balls
D5FD: $FF  Cancel

The game tries to merge what it sees as a stack of 67 SecretPotions and a stack of 0 SecretPotions into a single stack of 67 SecretPotions, which decrements the Key Items count (hiding the second SecretPotion, because the Cancel button is supposed to be where the first SecretPotion is now) and shifts the rest of the list back one byte until an $FF is found, which is actually the Cancel button for the Balls pocket. Now the Balls pocket is thought to have 255 items in it, which gives it access to 485 bytes of memory past where the pocket is supposed to end. The first 12 items are the Cancel buttons which fill the empty spaces in your Balls pocket; as long as a Cancel button appears on the screen, any item below it will be invisible, but once you scroll far enough that the Cancel button is off-screen, the items will appear. Items 14–63 will be the items stored in your PC. I don’t know what all lies beyond item 63, but event flags start at item 222 (D7B7). The quantity of item 13 is the number of items in the PC; if you take an item with quantity 255 somewhere in the list (you should be able to find one from an event flag) and swap it into the 13th slot (making sure that the item in the 13th slot isn’t the same item), you can corrupt the PC items list in the same way, which opens up access to another 26 bytes: the list ends with the quantity of the 255th item at D7FC for the Balls pocket, and D816 for the PC.

Since all of your PC items are now accessible from the Balls pocket, you can use them anywhere you want without having to withdraw them. You can also use these items as many times as you want because, as long as they’re not any kind of Poké Ball, the quantity is never depleted. When an item is used up, and the game tries to decrement the item’s quantity, it only looks in the pocket that the item is supposed to be in; if the item is in the wrong pocket, the game won’t be able to find it and the quantity will stay the same. This is the same reason that the duplicate key item glitch allows you to use an infinite number of a regular item from the Key Items pocket. (With either glitch, if an item is in both the pocket it’s supposed to be and another pocket, using the item from either pocket will deplete the one that’s in the correct pocket—e.g., throwing a Master Ball from the Key Items pocket will use up the Master Ball in the Balls pocket if there is one; using a Rare Candy stored in your PC through the Balls pocket will use up a Rare Candy in your Items pocket if you have one there.)

In Crystal, this glitch can’t be used to its full potential because the item menu will freeze when it tries to display the item ? (index $00). Since there are lots of $00 bytes in the space after the PC item data, this makes it impossible to use this glitch to mess with event flags, which is disappointing, because I’d hoped to use it to enable the GS Ball event. With special preparation, though, it can still be used to access the PC items. This should be a safe method in Crystal:

1. Fill the 50 item slots in your PC. (I’m not 100% sure if this is a necessary precaution, since my PC was already full when I tried it, but I think it is.)
2. Fill the 12 slots of the Balls pocket, which can be done by buying multiple stacks of 99 Poké Balls, or by obtaining every type of ball in the game, including the Park Ball. Put a stack of exactly 63 Poké Balls in the first slot. (The type of ball doesn’t technically matter, but this stack will be deleted.)
3. Collect enough key items that your Key Items pocket is full. You’ll need to have three of a key item with an index number greater than 100, and three of a key item with an index less than 88 (use the same list as above; there are no key items between 88 and 100). Again, I’ll use Machine Part and SecretPotion.
4. Move the two Machine Parts to the bottom two slots in the list, then swap them. The second item and the Cancel button will be replaced by a Blk Apricorn and Iron.
5. Swap the two SecretPotions into the bottom two slots in the list (including the slot that used to be the Cancel button), then swap them. The second SecretPotion should disappear, and the contents of the Balls pocket will shift by one byte. That pocket will now appear to have 6 items (because the Poké Ball at the top had index $05, and there’s an item where the Cancel button should be). The specific items correspond to the quantities of the first 6 items that were there before; the first item should be Ether ($3F = decimal 63).
6. Take a key item from a Pokémon. Your Key Items pocket will be full again, and the Cancel button in the Key Items pocket will be restored in its proper position.
7. Repeat steps 4 and 5. This will shift the contents of the Balls pocket by one more byte. The pocket will now have 63 items: items 1–11 are the balls that were in the pocket at the start, items 12–13 are Cancel buttons, and items 14–63 are the items in your PC.

If you haven’t ever filled the Balls pocket, the last byte of the pocket (D8F0) is set to $00. Since this value becomes the 13th item when the pocket is expanded, this would normally cause a freeze if you try to scroll past it to reach the PC items. But when the pocket is filled, that byte is changed to $FF to terminate the list, and it retains that value even if you later remove items from the pocket. I’m not sure, but I believe this also happens for the PC—if you’ve never filled it, the unused bytes will be $00, but after it has been filled once, any unused item slots will be $FF. If so, this glitch would still work even if the PC hasn’t been filled, but the game would freeze if you tried to scroll down past the Cancel button at the end of the PC items in the Balls pocket.
I don’t know if this is a new discovery or just something that’s not been well-documented, but it is possible to obtain arbitrary items in Generation II by modifying a Pokémon’s catch rate/held item byte using glitches in Generation I before trading it through the Time Capsule.

The item a Generation I Pokémon holds when traded to a Generation II game is determined by the byte which stored the species’ catch rate in Generation I. The developers deliberately arranged some item index numbers in Generation II so that certain Pokémon would hold certain items when traded from Generation I—e.g., Lucky Punch, which boosts Chansey’s critical hit ratio, was given the index number 0x1E corresponding with Chansey’s unique catch rate of 30 so that Chansey traded from Generation I would hold it. However, the most common catch rate numbers correspond to item index numbers which were intentionally left blank (Teru-sama and dummy TMs/HMs), except for the Card Key, which is a key item that cannot be legitimately held. When a Generation I Pokémon with one of these catch rates is traded to Generation II, it receives a held item determined by a table which can be found at offsets 286D6–286ED in the Gold/Silver ROM and 28785–2879C in Crystal:

Catch rate 25: Leftovers (instead of 0x19 Teru-sama)
Catch rate 45: Bitter Berry (instead of 0x2D Teru-sama)
Catch rate 50: Gold Berry (instead of 0x32 Teru-sama)
Catch rate 90: Berry (instead of 0x5A Teru-sama)
Catch rate 100: Berry (instead of 0x64 Teru-sama)
Catch rate 120: Berry (instead of 0x78 Teru-sama)
Catch rate 127: Berry (instead of 0x7F Card Key)
Catch rate 135: Berry (instead of 0x87 Teru-sama)
Catch rate 190: Berry (instead of 0xBE Teru-sama)
Catch rate 195: Berry (instead of 0xC3 dummy TM04)
Catch rate 220: Berry (instead of 0xDC dummy TM28)
Catch rate 250: Berry (instead of 0xFA HM08)
Catch rate 255: Berry (instead of 0xFF HM13)

(Curiously, no Pokémon in Red/Blue/Yellow actually has a catch rate of 135, 195, 220, or 250. Maybe those catch rates exist in the Japanese Red/Green? The developers clearly thought it was necessary to reserve indices 195 and 220 by placing dummy items between the real TM04 and TM05, and between TM27 and the real TM28.)

If an item index/catch rate doesn’t appear in this table, it is left alone by the Time Capsule. This allows a Pokémon holding an item to be traded to Generation I and retain that held item when traded back to Generation II. If we use 8F or ws m to modify a Pokémon’s stored catch rate in a Generation I game, it will hold the corresponding item when traded to Generation II, even if it is a key item or Teru-sama, as long is it is not one of the items converted by the table above. This program will change the first party Pokémon’s held item to any desired value:

Code: [Select]
Lemonade      ×XX
ThunderStone ×114 [in Red/Blue] or ×113 [in Yellow]
TM09         ×119

3E XX      ld a, XX
21 7½ D1   ld hl, $D172 [in Red/Blue] or $D171 [in Yellow]
77         ld (hl), a
C9         ret

This may be an easier way to obtain key items for item duplication than using the Celebi glitch, since once the program is set up, you can quickly give several Pokémon different items that you want. It can also be used to obtain the glitch items HM10–HM12 (but not HM13, because its index 0xFF is a valid catch rate), for which the Celebi glitch would require glitch moves.
Pages: [1]