Glitch City Laboratories Archives

Glitch City Laboratories closed on 1 September 2020 (announcement). This is an archived copy of a thread from Glitch City Laboratories Forums.

You can join Glitch City Research Institute to ask questions or discuss current developments.

You may also download the archive of this forum in .tar.gz, .sql.gz, or .sqlite.gz formats.

Emulation & ROM Hacking

Anatomy of an e-Reader Mystery Event - Page 1

Anatomy of an e-Reader Mystery Event

Posted by: Háčky
Date: 2014-11-21 05:24:47
For a long time, I didnt 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, Ive really wanted to find out how it works and how to make my own cards for it.

Ive 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.

Prologue
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.

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 didnt know what their companys name was; its 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 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.


Header
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 20005000 bytes after the end of the data, including the cards entire Z80 program. Its almost a quine!

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:

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:

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. Heres a C translation:

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;
else
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; its 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 [tt]setbyte[/tt] command ($0E):



Both the Eon Ticket and the Japanese Decoration Present card (which gives the Regirock, Regice, and Registeel Dolls) use [tt]setbyte 2[/tt] or [tt]setbyte 3[/tt] to display custom messages, so The event was safely loaded. is never seen. The Eon Tickets 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.

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:

[img]http://i.imgur.com/vyV61jU.png[/img][img]http://i.imgur.com/TM2bLyz.png[/img]
[img]http://i.imgur.com/jqLPvHp.png[/img][img]http://i.imgur.com/1obUZCK.png[/img]

The [tt]killscript[/tt] 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:

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 (4848 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 couldnt find information on that. The known values for offset $528 are:

$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 its actually the Yago Berry that does. Too bad its been closed to editing because of some new game that isnt 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:

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. Furlocks Forest previously documented this data structure, but Ive learned a couple of new things about it.

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 dont know if this list is used for anything other than e-Reader cards.

$00: *AQUA LEADER
$01: *TEAM AQUA    ()
$02: *TEAM AQUA    ()
$03:  AROMA LADY
$04:  RUIN MANIAC
$05: *INTERVIEWER
$06:  TUBER        ()
$07:  TUBER        ()
$08:  COOLTRAINER
$09:  COOLTRAINER
$0A:  HEX MANIAC
$0B:  LADY
$0C:  BEAUTY
$0D:  RICH BOY
$0E:  POKéMANIAC
$0F:  SWIMMER
$10:  BLACK BELT
$11:  GUITARIST
$12:  KINDLER
$13:  CAMPER
$14:  BUG MANIAC
$15:  PSYCHIC      ()
$16:  PSYCHIC      ()
$17:  GENTLEMAN
$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      ()
$24:  YOUNGSTER
$25: *CHAMPION
$26:  FISHERMAN
$27:  TRIATHLETE  ( cycling)
$28:  TRIATHLETE  ( cycling)
$29:  TRIATHLETE  ( running)
$2A:  TRIATHLETE  ( running)
$2B:  TRIATHLETE  ( swimming)
$2C:  TRIATHLETE  ( swimming)
$2D:  DRAGON TAMER
$2E:  BIRD KEEPER
$2F:  NINJA BOY
$30:  BATTLE GIRL
$31:  PARASOL LADY
$32:  SWIMMER
$33:  PICNICKER
$34: *TWINS
$35:  SAILOR
$36: *BOARDER      (Youngster)
$37: *BOARDER      (Youngster)
$38:  COLLECTOR
$39: *PKMN TRAINER (Wally)
$3A: *PKMN TRAINER (Brendan)
$3B: *PKMN TRAINER (Brendan)
$3C: *PKMN TRAINER (Brendan)
$3D: *PKMN TRAINER (May)
$3E: *PKMN TRAINER (May)
$3F: *PKMN TRAINER (May)
$40:  PKMN BREEDER ()
$41:  PKMN BREEDER ()
$42:  PKMN RANGER  ()
$43:  PKMN RANGER  ()
$44: *MAGMA LEADER
$45: *TEAM MAGMA  ()
$46: *TEAM MAGMA  ()
$47:  LASS
$48:  BUG CATCHER
$49:  HIKER
$4A: *YOUNG COUPLE
$4B: *OLD COUPLE
$4C: *SIS AND BRO


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:

[img]http://i.imgur.com/7eaWivN.png[/img]

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:

Offset Len  Description
$00    2    Species
$02    2    Held item
$04    8    Moves
$0C    1    Level
$0D    1    Its 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 Stuarts 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 isnt), 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 Natashas 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

Re: Anatomy of an e-Reader Mystery Event

Posted by: Torchickens
Date: 2014-11-21 11:48:55
Wow. Excellent work. Keep it up.


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


What does the Kuo Berry actually do? Might the effects differ if you hacked it in the English version somehow? Does it really have an English bag description? "A hold item that heals a burn in battle."

Sorry for so many questions. I'm inexperienced with the e-Reader.

You might want to send a tweet to SnorlaxMonster. He's a Bulbapedia admin who incidentally has an account here. He could edit the article for you.

Re: Anatomy of an e-Reader Mystery Event

Posted by: Háčky
Date: 2014-11-21 13:12:41

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


What does the Kuo Berry actually do? Might the effects differ if you hacked it in the English version somehow? Does it really have an English bag description? "A hold item that heals a burn in battle."

The Kuo Berry is only a Pokéblock ingredient (offsets $51652B are all 00), same as the other five berries I didnt list.

All e-Reader berries have the Enigma Berrys bag description, POKéBLOCK ingredient. Plant in loamy soil to grow a mystery. In Japanese, its のつちのなにとななみそだつ.

Re: Anatomy of an e-Reader Mystery Event

Posted by: Torchickens
Date: 2014-11-21 13:51:18
I see, thanks. I wonder where that English description (here for bag description) came from?

You made a minor typo. It should be: の つちのなに と なな み そだつ

Re: Anatomy of an e-Reader Mystery Event

Posted by: Stackout
Date: 2014-11-21 18:30:38

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.


So.. let's find the others.

Any chance we could find the other Mystery Event data by searching the ROM for the byte sequence [tt]04 00 04 00 00 00 04 00 80 00 00 00[/tt] ?

Re: Anatomy of an e-Reader Mystery Event

Posted by: Háčky
Date: 2014-11-21 19:05:14


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.


So.. let's find the others.

Any chance we could find the other Mystery Event data by searching the ROM for the byte sequence [tt]04 00 04 00 00 00 04 00 80 00 00 00[/tt] ?

Definitely. Heres an index:

$45DAE1 (type $10, Eon Ticket)
$45DDB2 (type $0F)
$45E306 (type $05 script)
$45E3E0 (type $10, first embedded chunk is type $08)
$45E402 (type $10, first embedded chunk is type $09)
$45E422 (type $10, first embedded chunk is type $0A)
$45E443 (type $10, first embedded chunk is type $0C)
$45E4EF (type $0D Battle Trainer)
$45E606 (type $0E)
$45E619 (type $0F)
$45E712 (type $10, type $05 script + type $02 data)
$45E797 (type $10, type $0B mixing records item + empty type $02 data)

TOURNAMENT, the nickname for the Unown distribution, appears at $42E248. I dont see any obvious pointers into that neighborhood from the $45xxxx region.

Its interesting that theres a naked type $05 script pointer; I guess thats only possible because the pointer is to a ROM address, so the actual script doesnt need to be sent with it in a type $02 chunk?

Re: Anatomy of an e-Reader Mystery Event

Posted by: Háčky
Date: 2014-11-21 23:10:07
I sloppily merged the German Eon Ticket into my disassembly of the English one so I could try to build it into a working e-Reader program (with $02000000 as the base address, so it would work with any old non-debug Rubin/Saphir cartridge). My first attempt succeeded in making contact with the game, but resulted in Fehler beim Laden! Vorgang wird abgebrochen. (Loading error. Ending session.)

When I first looked at the debug version data, I was surprised that the region codes were $04, since the Pokémon data structure uses $04 for Italian and $05 for German. So, I tried changing all three region codes to $05, and

[img]http://i.imgur.com/8zcRZPR.png[/img][img]http://i.imgur.com/iAp91VB.png[/img]
[img]http://i.imgur.com/bwu1P6X.png[/img][img]http://i.imgur.com/a5261ZW.png[/img]
[img]http://i.imgur.com/wG6q9zN.png[/img][img]http://i.imgur.com/8yUId8o.png[/img]

Setting offset $0E of the header to 0 or 1 doesnt seem to have any effect.

As far as I know, this is the first e-Reader dotcode created to be compatible with a European localization of the game.

Re: Anatomy of an e-Reader Mystery Event

Posted by: Bent`
Date: 2014-11-22 00:25:45
How is emulation of the eReader these days? Does it work well? Does it still need custom builds?

Re: Anatomy of an e-Reader Mystery Event

Posted by: Háčky
Date: 2014-11-22 00:43:03

How is emulation of the eReader these days? Does it work well? Does it still need custom builds?

no$gba does a fine job of it.

Re: Anatomy of an e-Reader Mystery Event

Posted by: hpoké_coloradohugge
Date: 2014-11-22 05:25:58
sometimes if feel like im actually the only one who owns a e-reader…

Re: Anatomy of an e-Reader Mystery Event

Posted by: Stackout
Date: 2014-11-22 08:22:29
I'm also interested in the gen 3 distribution ROMs, though I doubt we'll see those until hell freezes over. The only one known to exist outside of Nintendo is in the hands of a collector who paid like £200 for it on ebay. It's also bolted inside the GBASP it came with.

Re: Anatomy of an e-Reader Mystery Event

Posted by: Sanqui
Date: 2014-11-23 17:50:29

I'm also interested in the gen 3 distribution ROMs, though I doubt we'll see those until hell freezes over. The only one known to exist outside of Nintendo is in the hands of a collector who paid like £200 for it on ebay. It's also bolted inside the GBASP it came with.

One of my friends owns a Gen 3 distribution cartridge or two.  I didn't realize they weren't dumped - I could totally borrow them and dump them with my DS.

Re: Anatomy of an e-Reader Mystery Event

Posted by: Háčky
Date: 2014-11-24 02:24:29
I spent some quality time with the German debug ROM, and learned quite a bit more.

First, I was slightly wrong about the structure of Mystery Event data: anything after the 17-byte header is read as a series of chunks. The Battle Trainer and Enigma Berry chunks eah consist only of the four-byte pointer to the data, and the following $02 byte terminates the chunk list. The $00 byte after that is unnecessary padding.

The type $10 chunk, consisting of a checksum and the start and end addresses for it (12 bytes), is not required to make a card with multiple chunks. You can bypass the need to calculate that checksum by just deleting that chunk. (Its still a good idea to include it if youre making an actual card to be printed, to ensure that transmission errors are detected. Its less necessary for Battle Trainer/Enigma Berry cards because that data includes its own checksum, albeit a childish one.)

A type $0F is the same as type $10 except that the checksum is merely bytewise addition. Why choose this when you have a good checksum option sitting right next to it?

Several of the Mystery Event packets stored in the debug ROM have empty data sections, which are filled in by the Mimic e-Card code before it transmits them. You can see the actual packet thats transmitted by viewing RAM starting at $02000000. In particular, the checksums for type $0F or $10 chunks are filled in automatically, with one exception noted below.


$45DAE1: Eon Ticket
This is a German translation of the American Eon Ticket event, except that the distribution limit for mixing records is 5 in this version, whereas it was 30 in the American release. The Mimic e-Card modes ticket function sends this script.


$45DDB2: Template for Enigma Berry
This is blank Enigma Berry data with a type $0F checksum.

The RAM seed function uses this template and sends a berry based on the Cheri Berrys stats (soft, 2.0 cm, yields 23, et cetera), but overwrites its name with 「」 (part of the German name AMRENA remains after the $FF string terminator). The Cheri Berrys tag sprite is used. The tag description is 「そとききのみだまはつち」. The usage-by-trainer structure is set to 40 00 00 00 44 00 FF, which gives this berry the effect of Sacred Ash (revives and fully heals all fainted Pokémon). Offsets $520527 contain the text 「\v2っ」 (no terminator; \v2 is a variable). The last four bytes before the checksum are 00, indicating it has no use as a held item.


$45E306: Luvdisc event
This data has a type $05 script which gives the player a level 15 Luvdisc holding Berry Juice, or fails if the players party is full. It also has two type $03 chunks, which appear to define the messages that appear when the script succeeds or fails. The Eon Ticket does this by calling [tt]virtualloadpointer[/tt] within the script itself.

None of the functions on the Mimic e-Card menu access this data. I guess nobody actually wants a Luvdiscnot even the developers

db $05 ; instant script
GBAPTR ScriptData

db $03 ; loading message
db $02 ; success
GBAPTR AddedToYourTeam

db $03 ; loading message
db $03 ; failure
GBAPTR YourPartyIsFull

db $02 ; end of chunks

ScriptData:
setvirtualaddress ScriptData
countpokemon
compare LASTRESULT, 6
virtualgotoif 1, .party_full

givepokemon LUVDISC, 15, BERRY_JUICE, $00000000, $00000000, $00
setbyte 2 ; success; will display AddedToYourTeam
end

.party_full
setbyte 3 ; failure; will display YourPartyIsFull
end

AddedToYourTeam:
Text_DE "Ein POKéMON wurde in das Team des\n"
Text_DE "Spielers aufgenommen.@"

YourPartyIsFull:
Text_DE "Das Team des Spielers ist vollständig.\n"
Text_DE "Es kann kein weiteres POKéMON\l"
Text_DE "aufgenommen werden.@"



$45E3E0: Gives ribbon to party Pokémon
A type $08 chunk awards a ribbon to each of the party Pokémon. The ribbon function uses this data to award a Marine Ribbon with the text REGIONAL TURNIER 2003 BAND des CHAMPS. The first byte represents the type of ribbon, and the second represents the description.

db $08 ; award ribbon
db $00 ; Marine Ribbon
db $01 ; 2003 REGIONAL TOURNEY CHAMPION RIBBON

db $02 ; end of chunks


The possible ribbon types are:

$00: Marine Ribbon
$01: Land Ribbon
$02: Sky Ribbon
$03: Country Ribbon
$04: National Ribbon
$05: Earth Ribbon
$06: World Ribbon


The descriptions are taken from this list, $01 being the first. $00 results in a blank description.

If a ribbon of type > $06 or description > $40 is specified, no ribbons will be attached to the Pokémon, although the Mystery Events screen will say they were.


$45E402: Upgrades Pokédex to National Mode
The type $09 chunk has zero bytes of data, and upgrades the recipients Pokédex to National Mode.


$45E422: Adds a rare word?
The type $0A chunk contains one byte. This data is used by the message function, and the receiving game displays Ein seltenes Wort wurde hinzugefügt. (A rare word has been added.) Does this have something to do with the easy chat system?

db $0A ; adds a rare word?
db $01

db $02 ; end of chunks



$45E443: Template for gift Pokémon
Gift Pokémon are defined using a type $0C chunk, which consists of a pointer to a 136-byte structure. The first 100 bytes of that are a complete Pokémon data structure. I have no idea what the last 36 bytes are for.

The PKMN function sends a level 21 Unown with nickname TOURNAMENT, OT 09999 ENGLISH, caught in a Great Ball in Petalburg City, game of origin 14 (is that normal for event Pokémon?), holding a Full Restore.

The wrong PKMN function sends the same Pokémon, but clears the checksum at offset $1C to create a Bad Egg. (IVs are randomized, so there may be a 1/65536 chance that the checksum really would be $0000 and this wouldnt become a Bad Egg.)

For both PKMN and wrong PKMN, the 36 unknown bytes are: 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 00 BF C8 C1 C6 C3 CD C2 FF 0F 27 00 00 4A 75 82 00 00 03. This notably includes the string ENGLISH.

The egg function tries to send a Pikachu egg. It leaves the checksum in the type $10 chunk blank, so it fails with a loading error. (This could also have a 1/65536 chance of working.) For egg, the 36 unknown bytes are: 00 31 00 03 49 6A 00 03 30 06 00 00 00 31 00 03 DF 8F 00 08 F0 17 00 03 A3 07 00 08 17 00 00 00 8C 1D 00 03.


$45E4EF: Template for Battle Trainer
This is just blank Battle Trainer data.

The trainer function fills in this template to place a PKMN Ranger named 「」 (Card e) in the house in Mossdeep City:

BT_Level 0 ; Mossdeep only
Class PKMN_RANGER_M
BT_Floor 0 ; Mossdeep only
db $03 ; unknown value, which is $00 on all Battle e cards
OT_Name ""
OT_ID 09999, 00000

; these easy chat words are invalid; all display as ???
Introduction $0000, $0000, $0000, $0000, $0000, $0000
After_Win    $0007, $0008, $0009, $000A, $000B, $000C
After_Loss  $000D, $000E, $000F, $0010, $0011, $0012

Pokemon CHARMELEON
Holds QUICK_CLAW
Moves SCARY_FACE, FLAMETHROWER, SLASH, DRAGON_RAGE
Level 50
PP_Ups 0,0,0,0
EVs 0,0,0,0,0,0
OT_ID 09999, 00000
IVs 21,13,11,23,14,22, CHARMELEON_BLAZE
PV $93788551 ; Lonely
Nickname "TOURNAMENT"
Friendship 70

Pokemon WARTORTLE
Holds FOCUS_BAND
Moves RAPID_SPIN, PROTECT, RAIN_DANCE, SKULL_BASH
; lol, Rain Dance is your only Water move
Level 50
PP_Ups 0,0,0,0
EVs 0,0,0,0,0,0
OT_ID 09999, 00000
dd $67817E1E ; bit 30 identifies this Pokémon as an egg!
            ; but that doesnt actually make it one
; IVs 30,16,31,2,24,19, WARTORTLE_TORRENT
PV $6BE2D612 ; Hardy
Nickname "TOURNAMENT"
Friendship 70

Pokemon IVYSAUR
Holds LUM_BERRY
Moves RAZOR_LEAF, SWEET_SCENT, GROWTH, SYNTHESIS
Level 50
PP_Ups 0,0,0,0
EVs 0,0,0,0,0,0
OT_ID 09999, 00000
IVs 24,1,2,3,4,8, IVYSAUR_OVERGROW
PV $6222CB3B ; Rash
Nickname "TOURNAMENT"
Friendship 70




$45E606: In-game clock adjustment?
The type $0E chunk has zero bytes of data, and results in the message Das spielinterne Zeiteingabe-System ist jetzt verfügbar. (The in-game clock adjustment system is now useable.)

Does anyone know what the in-game clock adjustment system is? It didnt enable me to change the time on the clock in my bedroom.

The clock function sends this. Im not convinced of TCRFs claim that this is related to the berry glitch.


$45E619: Ganlon Berry event
This is similar to the Eon Ticket event, with Norman giving you the Ganlon Berry at his Gym. The difference is that instead of the Eon Tickets type $05 script which checks whether the Southern Island event has already beenplayed [sic] and whether theres space in the Key Items pocket, this data appears to have a type $03 chunk which points to the Go see your father text, and a type $04 chunk with the single byte $02. The $FF byte in the type $03 chunk might indicate a message that is always displayed, and the $02 byte in the type $04 chunk might indicate success, allowing the type $06 script to be saved without needing to run a type $05 script.

The item function sends this script.

db $06 ; in-game script
db 8,1 ; Petalburg Gym
db 1  ; Norman
GBAPTR NormanScriptStart
GBAPTR NormanScriptEnd

db $03 ; loading message
db $FF
GBAPTR GoSeeYourFather

db $04 ; sets script return value?
db $02

db $02 ; end of chunks

GoSeeYourFather:
Text_DE "Besuche deinen Vater in der ARENA\n"
Text_DE "von BLTENBURG CITY.@"

NormanScriptStart:
setvirtualaddress NormanScriptStart

; cant get this berry if you have one in your bag or PC
checkitem GANLON_BERRY, 1
compare LASTRESULT, 1
virtualgotoif 1, .ineligible
checkpcitem GANLON_BERRY, 1
compare LASTRESULT, 1
virtualgotoif 1, .ineligible

lock
faceplayer
virtualmsgbox FoundARareBerry
waitmsg
waitkeypress

copyvarifnotzero $8000, GANLON_BERRY
copyvarifnotzero $8001, 1
callstd 0 ; give item
release
killscript

.ineligible
jumpram ; does this cause Normans default script to run?

FoundARareBerry:
Text_DE "VATER: Hi, \v1!\p"
Text_DE "Ich habe gerade diese seltene BEERE\n"
Text_DE "erhalten. Ich schenke sie dir!@"



$45E712: Registeel Doll event
This is a German translation of one of the three events on the Japanese Decoration Present card. The goods function sends this script.


$45E797: Mixing records item
This enables you to give a Potion to up to three other games when you mix records.

The potion function sends this verbatim. ball replaces the Potion with a Poké Ball, and cheri berry and TM01 likewise do what youd expect.

An item will only be sent by mixing records if the recipient does not already have the item in question. (I think that was my problem when I was trying to send non-Key Items in this manner before.)

db $0B ; mixing records gift item
db $01 ; unknown, same value as for Eon Ticket
db 3  ; distribution limit
dw POTION

db $02 ; end of chunks

Re: Anatomy of an e-Reader Mystery Event

Posted by: Torchickens
Date: 2014-11-24 10:05:11

$45DDB2: Template for Enigma Berry
This is blank Enigma Berry data with a type $0F checksum.

The RAM seed function uses this template and sends a berry based on the Cheri Berrys stats (soft, 2.0 cm, yields 23, et cetera), but overwrites its name with 「」 (part of the German name AMRENA remains after the $FF string terminator). The Cheri Berrys tag sprite is used. The tag description is 「そとききのみだまはつち」. The usage-by-trainer structure is set to 40 00 00 00 44 00 FF, which gives this berry the effect of Sacred Ash (revives and fully heals all fainted Pokémon). Offsets $520527 contain the text 「\v2っ」 (no terminator; \v2 is a variable). The last four bytes before the checksum are 00, indicating it has no use as a held item.


Interesting. Is that Berry data in the final game too? I'm going to have a go at interpreting this as I'm studying Japanese. I don't know much though.

「そとききのみだまはつち」 probably reads like: "This external Berry is in development right now."

そと = External?
き = Ta form of verb く, which means come/arrive.
きのみ= Fruit/Berry.
だま = Right now.
はつ = Development.
-ち = in (and apparently other prepositions).

probably means "external" here too (as in real data is supposed to be written from the e-Reader).

I don't know what \v2っ means; however, as well as floor, can be "times" (e.g. '2 times'), "world", etc. "っ" means effect, but I don't know if it's the same as っ.

Re: Anatomy of an e-Reader Mystery Event

Posted by: Háčky
Date: 2014-11-24 11:30:57
Interesting. Is that Berry data in the final game too?

No. It doesnt even exist coherently in the debug ROMits pieced together at runtime from the actual Cheri Berry data and a few scattered stringsbut those strings arent in the final Japanese ROM.

I don't know what \v2っ means; however, as well as floor, can be "times" (e.g. '2 times'), "world", etc. "っ" means effect, but I don't know if it's the same as っ.

The string 「\v2っ\v3ひ」 occurs at $39B6D8 of the debug ROM, directly after the usage-by-trainer data for this berry that makes it work like Sacred Ash. The first eight bytes of it are probably copied into the berry data by accident.