Jump to content

Mail writer: Difference between revisions

6,688 bytes added ,  10 months ago
 
(8 intermediate revisions by the same user not shown)
Line 3:
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=
Line 45:
* '''Press START''' to immediately jump to and start executing the newly written program. '''Only use this when you've finished every mail.'''
* '''Press any button on the D-pad''' to go back one byte at a time to correct errors. '''If the printed checksum doesn't match the expected checksum, press DOWN 16 times to retry the last mail.''' This will also overwrite the printed checksum with the value at the currently selected address, giving you a method to check how far back you're going.
 
Due to limitations, the Japanese version of the mail writer has slightly different controls:
* '''Press A''' to open a new mail and continue writing data.
* '''Press B''' to immediately jump to and start executing the newly written program. '''Only use this when you've finished every mail.'''
* '''Press any other button''' to go back one byte at a time to correct errors. '''If the printed checksum doesn't match the expected checksum, press DOWN 16 times to retry the last mail.''' This will also overwrite the printed checksum with the value at the currently selected address, giving you a method to check how far back you're going.
 
{| class="wikitable"
Line 60 ⟶ 65:
The Mail writer only uses relatives jumps and can, theoretically, be installed at any address.
 
==Quantities for EN/FR/DE/IT/SP versions of pokémon Gold & Silver==
 
Gold & Silver: installed at D57E onward, writes bytes from DD55 onward.
 
Crystal: installed at D852 onward, writes bytes from D280 onward.
 
For Crystal only: while you can call the mail writer using 0x1500 arbitrary code execution, it is preferable to call it using Wrong Pocket TM ACE so that the tiles printed by PrintBCDNumber.loop are fully consistent with the tiles displayed by [https://scotteh.me/ace/mail/ Scotteh's mail code tool].
Installed at D57E onward, writes bytes from DD55 onward.
 
===Language/version independent TM quantities===
 
{| class="wikitable"
! TM !! Final Quantity !! Sell value
|-
|TM01 DYNAMICPUNCH ||x17 ||357000
|-
|TM02 HEADBUTT ||x85Colspan = "2" | SEE NEXT TABLE ||170000
|-
|TM03 CURSE ||x221 Colspan = "2" ||51000 SEE NEXT TABLE
|-
|TM04 ROLLOUT ||x213 ||42000
|-
|TM05 ROAR ||x213 ||21000
|-
|TM06 TOXIC ||x213 ||63000
|-
|TM07 ZAP CANNON ||x33 ||222000
|-
|TM08 ROCK SMASH ||Colspan = "2" | LANGUAGE DEPENDENT, SEE NEXT TABLE
|-
|TM09 PSYCH UP ||x98 Colspan = "2" ||78500 SEE NEXT TABLE
|-
|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 ||x196Colspan = "2" | SEE NEXT TABLE ||59000
|-
|TM33 ICE PUNCH ||x77 ||267000
|-
|TM34 SWAGGER ||x205 ||25000
|-
|TM35 SLEEP TALK ||Colspan = "2" | LANGUAGE DEPENDENT, SEE NEXT TABLE
|-
|TM36 SLUDGE BOMB ||x58Colspan = "2" | SEE NEXT TABLE ||98500
|-
|TM37 SANDSTORM ||x27 ||228000
|-
|TM38 FIRE BLAST ||x205 ||50000
|-
|TM39 SWIFT ||Colspan = "2" | LANGUAGE DEPENDENT, SEE NEXT TABLE
|-
|TM40 DEFENSE CURL ||x55Colspan = "2" | SEE NEXT TABLE ||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 ||x8x08 ||370500
|-
|TM48 FIRE PUNCH ||x200 ||3250082500
|-
|TM49 FURY CUTTER ||x24 ||346500
|-
|TM50 NIGHTMARE ||x243x242 ||13000
|}
 
===LanguageGold/Silver specific TM quantities===
 
{| class="wikitable"
Line 177 ⟶ 186:
! 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
|-
|TM02 TM08 HEADBUTT || x66 x85 || 94500 170000 || x43 x85 || 106000 170000 || x34 x85 || 110500 170000 || x118 x85 || 68500 170000 || x153 x85 || 51000170000
|-
|TM03 TM35CURSE || x239 x221 || 8000 51000 || x144 x221 || 55500 51000 || x231 x221 || 12000 51000 || x222 x221 || 16500 51000 || x162 x221 || 4650051000
|-
|TM08 TM39ROCK SMASH || x144 x66 || 111000 94500 || x59x43 || 196000106000 || x135x34 || 120000110500 || x127x118 || 12800068500 || x77x153 || 17800051000
|-
|TM09 PSYCH UP ||x98 ||78500||x98 ||78500||x98 ||78500||x98 ||78500||x98 ||78500
|-
|TM32 DOUBLE TEAM ||x196 ||59000 ||x196 ||59000 ||x196 ||59000 ||x196 ||59000 ||x196 ||59000
|-
|TM35 SLEEP TALK ||x239 ||8000 || x144 || 55500 || x231 || 12000 || x222 || 16500 || x162 || 46500
|-
|TM36 SLUDGE BOMB ||x58 ||98000||x58 ||98000||x58 ||98000||x58 ||98000||x58 ||98000
|-
|TM39 SWIFT ||x144 ||111000 || x59 || 196000 || x135 || 120000 || x127 || 128000 || x77 || 178000
|-
|TM40 DEFENSE CURL ||x55 ||100000||x55 ||100000||x55 ||100000||x55 ||100000||x55 ||100000
|}
 
===Crystal specific TM quantities===
 
{| class="wikitable"
! 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
|-
|TM02 HEADBUTT ||x128 ||127000||x128 ||127000||x128 ||127000||x128 ||127000||x128 ||127000
|-
|TM03 CURSE ||x210 ||67500||x210 ||67500||x210 ||67500||x210 ||67500||x210 ||67500
|-
|TM08 ROCK SMASH ||x117 ||69000|| x122 || 66500 || x99 || 78000 || x197 || 29000 || x232 || 11500
|-
|TM09 PSYCH UP ||x94 ||80500||x94 ||80500||x94 ||80500||x94 ||80500||x94 ||80500
|-
|TM32 DOUBLE TEAM ||x197 ||58000||x197 ||58000||x197 ||58000||x197 ||58000||x197 ||58000
|-
|TM35 SLEEP TALK ||x204 ||25500|| x175 || 40000 || x182 || 36500 || x186 || 34500 || x172 || 41500
|-
|TM36 SLUDGE BOMB ||x56 ||99500 ||x56 ||99500 ||x56 ||99500 ||x56 ||99500 ||x56 ||99500
|-
|TM39 SWIFT ||x75 ||180000|| x56 || 199000 || x53 || 202000 || x57 || 198000 || x53 || 202000
|-
|TM40 DEFENSE CURL ||x53 ||101000||x53 ||101000||x53 ||101000||x53 ||101000||x53 ||101000
|}
 
Line 294 ⟶ 341:
|}
 
==Quantities for EN/DE/FR/IT/SPJP versions of pokémon Crystal==
 
Unlike the others, the Japanese versions are able to use the Mail writer as a box code instead. Both are intended to be used with a wrong pocket TM ACE setup that redirects execution to the first box name ($D8B2 for Gold & Silver, $DB68 for Crystal). For Crystal, an additional setup using 0x1500 control code ACE is required to finish the box codes.
While you can call the mail writer using 0x1500 arbitrary code execution, it is preferable to call it using Wrong Pocket TM ACE so that the tiles printed by PrintBCDNumber.loop are fully consistent with the tiles displayed by [https://scotteh.me/ace/mail/ Scotteh's mail code tool].
 
===Gold & Silver===
Installed at D852 onward, writes bytes from D280 onward.
 
Write the following box codes, then use the wrong pocket TM ACE:
{| class="wikitable"
! 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 ||Colspan = "2" | 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 ||Colspan = "2" | LANGUAGE DEPENDENT, SEE NEXT TABLE
|-
|TM36 SLUDGE BOMB ||x56 ||99500
|-
|TM37 SANDSTORM ||x27 ||228000
|-
|TM38 FIRE BLAST ||x205 ||50000
|-
|TM39 SWIFT ||Colspan = "2" | 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
|}
 
<pre>Box 1: ヅ に わ ゆ ゆ ゾ ュ ぼ
===Language specific TM quantities===
Box 2: ゆ に ヂ ぺ な に ヨ プ
Box 3: ゅ ま む ゅ ご き き よ
Box 4: ぐ デ だ ガ ご き き よ
Box 5: キ デ ド ア ぺ デ ご ?
Box 6: だ ! ズ が と ぜ ォ ギ
Box 7: ビ ヘ ば で が ブ ブ ぜ
Box 8: げ ぜ ォ ま き ぐ ァ プ
Box 9: ダ れ か リ ダ リ だ ゥ</pre>
 
===Crystal===
{| class="wikitable"
 
! rowspan="2" | TM !! colspan="2" | English !! colspan="2" | French !! colspan="2" | German !! colspan="2" | Italian !! colspan="2" | Spanish
First, write the following box codes.
|-
 
! 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
<pre>Box 1: ヅ に わ ゆ ゆ が ぜ ぜ
|-
Box 2: ゆ げ ぜ ェ ぼ ガ べ プ
| TM08 || x117 || 69000 || x122 || 66500 || x99 || 78000 || x197 || 29000 || x232 || 11500
Box 3: き ま む ゅ ご き き よ
|-
Box 4: ぐ デ だ ガ ご き き よ
| TM35 || x204 || 25500 || x175 || 40000 || x182 || 36500 || x186 || 34500 || x172 || 41500
Box 5: キ デ ド ア ぺ デ ご ?
|-
Box 6: だ ! ズ が な ぜ ォ ギ
| TM39 || x75 || 180000 || x56 || 199000 || x53 || 202000 || x57 || 198000 || x53 || 202000
Box 7: ビ ヘ チ チ が ビ ブ ギ
|}
Box 8: ぜ セ げ ま き ぐ ァ プ
Box 9: ダ ダ け パ ダ リ だ ゥ</pre>
 
Then, give a pokémon the following mail to hold. Execute 0x1500 control code ACE redirecting to $D000 (where the mail is buffered in memory). This code will modify two bytes from the above box code, along with replacing the first item in the main item pocket with TM15 and adding the required bootstrap to redirect execution to the start of box names.
 
<pre>ぼ ほ ほ セ ル が れ ぜ デ オ づ イ づ チ づ 0
ゥ キ リ よ ヌ ゥ モ ろ ゥ あ ろ ゅ の</pre>
 
Afterwards, you can use TM15 anytime outside of battle to start up the mail writer.
 
=General assembly=
Line 497 ⟶ 459:
D0 ret nc
18 F1 jr .DownPressed</pre>
 
==JP Gold & Silver versions==
 
<pre>11 C6 DC ld de, DCC6
D5 push de
.newMail
D5 push de
0E AE ld c, AE
3E 50 ld a, 50
 
D5 push de
C6 10 sub A0 ; a = 60
47 ld b, a ; bc = 60AE
C5 push bc
C6 A4 add a, A4 ; a = 04
42 ld b, d
50 ld d, b
 
E1 pop hl ; hl = 60AE
CF rst08H ; Farcall _ComposeMailMessage (a:hl = 04:60AE)
D1 pop de
E1 pop hl ; set both hl and dc to the start of the newly written mail
.loop
2A ldi a, (hl)
B7 or a, a
B7 or a, a
D6 50 sub 50
 
28 13 jr, .terminator
30 05 jr, .character
2A ldi a, (hl) ; if terminator, escape loop. if newline, get new value for a and continue
B7 or a, a
B7 or a, a
D6 50 sub 50 ; ensures that new character will result in the same value when combined with the next
 
.character
86 add (hl)
12 ld (de), a
13 inc de
80 add a, b
47 ld b, a ; responsible for generating checksum
12 ld (de), a
2A ldi a, (hl) ; inc hl is not available, so this will do
E6 50 or 50 ; ensures that carry flag is not set
 
30 E7 jr nc, .loop
.terminator
0C inc c ;_ComposeMailMessage sets bc to 0000, so c = 00 when we reach this part
26 C4 ld h, C4
2E F4 ld l, F4 ; hl = C4F4, bottom left screen tile
06 50 and 50 ; Ensures that b is consistent for the next call
1A ld a, (de)
CD 3A 33 call PrintBCDNumber.loop + 01h ; PrintBCDNumber.loop itself can't be reached, so we skip forward one byte.
.errorCorrection
26 1B ld h, 1B
1B dec de ; calling PrintBCDNumber.loop with c = 01 advances de by 01.
2E 50 ld l, 50 ; hl = 1B50
 
 
29 add hl, hl ; hl = 36A0
2E F4 ld l, F4 ; hl = 36F4 (address of JoyTextDelay_ForcehJoyDown)
CF rst08H ; Farcall JoyTextDelay_ForcehJoyDown set a = current button state
B7 or a, a ; is no button pressed? if yes, ask for new button states
28 E9 jr z, .terminator
42 ld b, d
50 ld d, b
 
0F rlca ; is the a button pressed? If yes, start a new mail
DA B6 D8 jp c, .loop
0F rlca ; is the b button pressed? If yes, return and execute newly written program. if not, decrement de to allow user to correct errors
D8 ret c
30 EA jr nc, .errorCorrection
50 ld d, b</pre>
 
==JP Crystal versions==
 
<pre>mail
 
3E 01 ld a, 01
01 8D A6 ld bc, A68D ; will be used for arithmetic operations
26 DA ld h, DA
2E 12 ld e, 12
84 add a, h ; a = DB
32 ldd (hl), a ; hl = DA11
81 add a, c ; a = 68
32 ldd (hl), a ; hl = DA10
90 sub a, b ; a = C2
32 ldd (hl), a ; hl = DA0F
F6 4E or 4F ; a = CE (TM15 item ID)
 
EA 86 D8 ld (D886), a; Item pocket, item #1 ID
D6 96 sub a, 96 ; a = 38
EA A1 DB ld (DBA1), a
EA B1 DB ld (DBB1), a
E1 pop hl ; required for proper exit out of 0x1500
C9 ret
50 ld d, b
 
*Bytes 2 and 3 get overwritten when viewing the unterminated name pokémon in the box
 
Mail writer
 
11 B1 D2 ld de, D2B1
D5 push de
.newMail
D5 push de
26 2E ld h, 2E
2E 50 ld l, 50
 
D5 push de
29 add hl, hl ; hl = 5CA0
2E EB ld l, EB ; hl = 5CEB
3E 05 ld a, 05
3D dec a ; a = 04
42 ld b, d
50 ld d, b
 
B7 or a, a
CF rst08H ; Farcall _ComposeMailMessage -01h (a:hl = 04:5CEB)
D1 pop de
E1 pop hl ; set both hl and dc to the start of the newly written mail
.loop
2A ldi a, (hl)
B7 or a, a
B7 or a, a
D6 50 sub 50
 
28 13 jr, .terminator
30 05 jr, .character
2A ldi a, (hl) ; if terminator, escape loop. if newline, get new value for a and continue
B7 or a, a
B7 or a, a
D6 50 sub 50 ; ensures that new character will result in the same value when combined with the next
 
.character
86 add (hl)
12 ld (de), a
13 inc de
80 add a, b
47 ld b, a ; responsible for generating checksum
12 ld (de), a
2A ldi a, (hl) ; inc hl is not available, so this will do
E6 50 or 50 ; ensures that carry flag is not set
 
30 E7 jr nc, .loop
.terminator
0C inc c ;_ComposeMailMessage sets bc to 0000, so c = 00 when we reach this part
26 C5 ld h, C5
2E F4 ld l, F4 ; hl = C4F4, bottom left screen tile
06 50 and 50 ; Ensures that b is consistent for the next call
1A ld a, (de)
CD 90(38) call PrintBCDNumber.loop
.errorCorrection
26 1A ld h, 1A
1B dec de ; calling PrintBCDNumber.loop with c = 01 advances de by 01.
06 50 ld b, 50
 
 
2E 8D ld l, F4 ; hl = 1A8D
29 add hl, hl ; hl = 351A (address of JoyTextDelay_ForcehJoyDown -01h)
CF rst08H ; Farcall JoyTextDelay_ForcehJoyDown -01h set a = current button state
B7 or a, a ; is no button pressed? if yes, ask for new button states
28 E9 jr z, .terminator
42 ld b, d
50 ld d, b
 
0F rlca ; is the a button pressed? If yes, start a new mail
(38)B9 jr c, .loop
40 ld b, b
0F rlca ; is the b button pressed? If yes, return and execute newly written program. if not, decrement de to allow user to correct errors
D8 ret c
30 EA jr nc, .errorCorrection
50 ld d, b</pre>
1,516

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.