Mail writer
The Mail writer is an arbitrary code execution program for pokémon Gold, Silver and Crystal, created by TimoVM.
It is a 50 byte program, installed in the TM/HM pocket by having specific TM quantities, that allows the user to quickly and accurately write and execute arbitrary code payloads of up to a maximum size of 428 bytes. Payloads are written from wOtPartyCount onward, where enemy trainer's parties are usually buffered. Using the Mail writer requires an ACE setup that both redirects execution to the start of the TM/HM pocket and sets the value of register a to $04.
The Mail writer is currently supported for all language releases of Gold, Silver and Crystal, both VC and cartridge, with the exception of the Japanese releases.
How the mail writer works
Upon execution, the Mail writer will open the mail character entry screen where the player can write up to 32 different characters. After the player has confirmed the mail, the following actions take place:
- The Mail writer will take pairs of characters and convert them into a single combined value. These values are then sequentially written, converting the 32 letter mail into a 16 byte long line of code.
- Next, the Mail writer will display a checksum calculated from the combined value of all written bytes for the player to verify. Then the program enters a waiting state where they can either choose to write another mail, go back and correct previously written values or stop the mail writer and execute the newly written payload.
- If the player has chosen to write a new mail, the Mail writer will open a new mail entry screen. The new mail is then also converted into a 16 byte lond line of code and placed right after the code written by the previous mail(s), allowing the player to write arbitrarily long payloads.
Mail codes can be automatically calculated using Scotteh's mail code tool. This tool will accept a code written in hexadecimal values and automatically convert them to mail codes. These mails are optimized to require the least amount of button presses possible. The following values were determined from converting a 288 byte long RAM writer code:
Language | Button presses |
---|---|
English | 5.0 |
German | 4.9 |
French | 4.3 |
Spanish | 4.2 |
Italian | 4.2 |
Korean | 10.7 |
Installation
Prior to installation, the player should use an ACE code that sets the quantities of all TMs in the TM/HM pocket to x255. Then, the player can simply sell TMs until desired quantities are reached. The amount of TMs sold of each kind depends between versions and different languages.
Quantities for EN/FR/DE/IT/SP versions of pokémon Gold & Silver
Language independent TM quantities
TM | Final Quantity | Sell value |
---|---|---|
TM01 DYNAMICPUNCH | x17 | 357000 |
TM02 HEADBUTT | x85 | 170000 |
TM03 CURSE | x221 | 51000 |
TM04 ROLLOUT | x213 | 42000 |
TM05 ROAR | x213 | 21000 |
TM06 TOXIC | x213 | 63000 |
TM07 ZAP CANNON | x33 | 222000 |
TM08 ROCK SMASH | LANGUAGE DEPENDENT, SEE NEXT TABLE | |
TM09 PSYCH UP | x98 | 78500 |
TM10 HIDDEN POWER | x207 | 72000 |
TM11 SUNNY DAY | x225 | 30000 |
TM12 SWEET SCENT | x209 | 23000 |
TM13 SNORE | x42 | 106500 |
TM14 BLIZZARD | x254 | 1500 |
TM15 HYPER BEAM | x80 | 262500 |
TM16 ICY WIND | x56 | 298500 |
TM17 PROTECT | x251 | 6000 |
TM18 RAIN DANCE | x40 | 215000 |
TM19 GIGA DRAIN | x10 | 367500 |
TM20 ENDURE | x135 | 180000 |
TM21 FRUSTRATION | x134 | 60500 |
TM22 SOLARBEAM | x18 | 355500 |
TM23 IRON TAIL | x19 | 354000 |
TM24 DRAGONBREATH | x35 | 330000 |
TM25 THUNDER | x129 | 126000 |
TM26 EARTHQUAKE | x79 | 264000 |
TM27 RETURN | x18 | 118500 |
TM28 DIG | x24 | 231000 |
TM29 PSYCHIC | x239 | 16000 |
TM30 SHADOW BALL | x33 | 333000 |
TM31 MUD-SLAP | x1 | 381000 |
TM32 DOUBLE TEAM | x196 | 59000 |
TM33 ICE PUNCH | x77 | 267000 |
TM34 SWAGGER | x205 | 25000 |
TM35 SLEEP TALK | LANGUAGE DEPENDENT, SEE NEXT TABLE | |
TM36 SLUDGE BOMB | x58 | 98500 |
TM37 SANDSTORM | x27 | 228000 |
TM38 FIRE BLAST | x205 | 50000 |
TM39 SWIFT | LANGUAGE DEPENDENT, SEE NEXT TABLE | |
TM40 DEFENSE CURL | x55 | 100000 |
TM41 THUNDERPUNCH | x189 | 99000 |
TM42 DREAM EATER | x40 | 322500 |
TM43 DETECT | x217 | 19000 |
TM44 REST | x56 | 298500 |
TM45 ATTRACT | x240 | 22500 |
TM46 THIEF | x254 | 1500 |
TM47 STEEL WING | x8 | 370500 |
TM48 FIRE PUNCH | x200 | 32500 |
TM49 FURY CUTTER | x24 | 346500 |
TM50 NIGHTMARE | x243 | 13000 |
Language specific TM quantities
! rowspan="2" | TM !! colspan="2" | English !! colspan="2" | French !! colspan="2" | German !! colspan="2" | Italian !! colspan="2" | Spanish |- ! Final amount !! Amount sold for !! Final amount !! Amount sold for !! Final amount !! Amount sold for !! Final amount !! Amount sold for !! Final amount !! Amount sold for |- | TM08 || x66 || 94500 || x43 || 106000 || x34 || 110500 || x118 || 68500 || x153 || 51000 |- | TM35 || x239 || 8000 || x144 || 55500 || x231 || 12000 || x222 || 16500 || x162 || 46500 |- | TM39 || x144 || 111000 || x59 || 196000 || x135 || 120000 || x127 || 128000 || x77 || 178000 |}
Quantities for KOR versions of pokémon Gold & Silver
TM | Final amount | Amount sold for |
---|---|---|
TM01 | 17 | 357000 |
TM02 | 82 | 173000 |
TM03 | 222 | 49500 |
TM04 | 213 | 42000 |
TM05 | 213 | 21000 |
TM06 | 213 | 63000 |
TM07 | 33 | 222000 |
TM08 | 217 | 19000 |
TM09 | 96 | 79500 |
TM10 | 207 | 72000 |
TM11 | 225 | 30000 |
TM12 | 209 | 23000 |
TM13 | 42 | 106500 |
TM14 | 254 | 1500 |
TM15 | 80 | 262500 |
TM16 | 48 | 310500 |
TM17 | 9 | 369000 |
TM18 | 150 | 105000 |
TM19 | 150 | 157500 |
TM20 | 18 | 355500 |
TM21 | 19 | 118000 |
TM22 | 129 | 189000 |
TM23 | 79 | 264000 |
TM24 | 18 | 355500 |
TM25 | 42 | 213000 |
TM26 | 180 | 112500 |
TM27 | 32 | 111500 |
TM28 | 240 | 15000 |
TM29 | 33 | 222000 |
TM30 | 01 | 381000 |
TM31 | 196 | 88500 |
TM32 | 77 | 178000 |
TM33 | 205 | 75000 |
TM34 | 206 | 24500 |
TM35 | 58 | 98500 |
TM36 | 27 | 114000 |
TM37 | 205 | 50000 |
TM38 | 121 | 134000 |
TM39 | 55 | 200000 |
TM40 | 240 | 7500 |
TM41 | 171 | 126000 |
TM42 | 189 | 99000 |
TM43 | 40 | 107500 |
TM44 | 216 | 58500 |
TM45 | 56 | 298500 |
TM46 | 238 | 25500 |
TM47 | 07 | 372000 |
TM48 | 208 | 70500 |
TM49 | 24 | 346500 |
TM50 | 241 | 14000 |
Quantities for EN/DE/FR/IT/SP versions of pokémon Crystal
TM | Final Quantity | Sell value |
---|---|---|
TM01 DYNAMICPUNCH | x17 | 357000 |
TM02 HEADBUTT | x128 | 127000 |
TM03 CURSE | x210 | 67500 |
TM04 ROLLOUT | x213 | 42000 |
TM05 ROAR | x213 | 21000 |
TM06 TOXIC | x213 | 63000 |
TM07 ZAP CANNON | x33 | 222000 |
TM08 ROCK SMASH | LANGUAGE DEPENDENT, SEE NEXT TABLE | |
TM09 PSYCH UP | x94 | 80500 |
TM10 HIDDEN POWER | x207 | 72000 |
TM11 SUNNY DAY | x225 | 30000 |
TM12 SWEET SCENT | x209 | 23000 |
TM13 SNORE | x42 | 106500 |
TM14 BLIZZARD | x254 | 1500 |
TM15 HYPER BEAM | x80 | 262500 |
TM16 ICY WIND | x56 | 298500 |
TM17 PROTECT | x251 | 6000 |
TM18 RAIN DANCE | x40 | 215000 |
TM19 GIGA DRAIN | x10 | 367500 |
TM20 ENDURE | x135 | 180000 |
TM21 FRUSTRATION | x134 | 60500 |
TM22 SOLARBEAM | x18 | 355500 |
TM23 IRON TAIL | x19 | 354000 |
TM24 DRAGONBREATH | x35 | 330000 |
TM25 THUNDER | x129 | 126000 |
TM26 EARTHQUAKE | x79 | 264000 |
TM27 RETURN | x18 | 118500 |
TM28 DIG | x24 | 231000 |
TM29 PSYCHIC | x239 | 16000 |
TM30 SHADOW BALL | x33 | 333000 |
TM31 MUD-SLAP | x1 | 381000 |
TM32 DOUBLE TEAM | x197 | 58000 |
TM33 ICE PUNCH | x77 | 267000 |
TM34 SWAGGER | x205 | 25000 |
TM35 SLEEP TALK | LANGUAGE DEPENDENT, SEE NEXT TABLE | |
TM36 SLUDGE BOMB | x56 | 99500 |
TM37 SANDSTORM | x27 | 228000 |
TM38 FIRE BLAST | x205 | 50000 |
TM39 SWIFT | LANGUAGE DEPENDENT, SEE NEXT TABLE | |
TM40 DEFENSE CURL | x53 | 101000 |
TM41 THUNDERPUNCH | x189 | 99000 |
TM42 DREAM EATER | x40 | 322500 |
TM43 DETECT | x217 | 19000 |
TM44 REST | x56 | 298500 |
TM45 ATTRACT | x240 | 22500 |
TM46 THIEF | x254 | 1500 |
TM47 STEEL WING | x8 | 370500 |
TM48 FIRE PUNCH | x200 | 32500 |
TM49 FURY CUTTER | x24 | 346500 |
TM50 NIGHTMARE | x243 | 13000 |
Language specific TM quantities
! rowspan="2" | TM !! colspan="2" | English !! colspan="2" | French !! colspan="2" | German !! colspan="2" | Italian !! colspan="2" | Spanish |- ! Final amount !! Amount sold for !! Final amount !! Amount sold for !! Final amount !! Amount sold for !! Final amount !! Amount sold for !! Final amount !! Amount sold for |- | TM08 || x117 || 69000 || x122 || 66500 || x99 || 78000 || x197 || 29000 || x232 || 11500 |- | TM35 || x204 || 25500 || x175 || 40000 || x182 || 36500 || x186 || 34500 || x172 || 41500 |- | TM39 || x75 || 180000 || x56 || 199000 || x53 || 202000 || x57 || 198000 || x53 || 202000 |}
General assembly
11 XX XX ld de, wOTPartyCount D5 push de .loop D5 push de D5 push de 21 XX XX ld hl, _ComposeMailMessage CF Farcall ; requires a = $04 E1 pop hl D1 pop de .nextChar 2A ldi a, (hl) FE 50 cp 50 38 FB jr c, .nextchar 28 0A jp z, .@ 87 add a 86 add (hl) 12 ld (de), a 13 inc de 23 81 add c 4F ld c, a 12 ld (de), a 18 EF jr nz, .nextChar .@ 21 01 C4/C5 ld hl, C401/C501 ; corresponds to a screen tile location. C401 for Gold/Silver, C501 for Crystal. 4D ld c, l CD XX XX call PrintBCDNumber.loop (-$01) ; if language ends BCD with $, jump to PrintBCDNumber.loop. else, jump to one byte before PrintBCDNumber.loop .DownPressed 1B dec DE CD XX XX call JoyTextDelay_ForcehJoyDown BD cp l; Due to the effects of PrintBCDNumber.loop, l = $04 28 D9 jr z, .loop 38 F0 jr c, .@ FE 08 cp 08 C8 ret z 18 F2 jr .DownPressed