Guides:Fast 0x1500 ACE: Difference between revisions

Jump to navigation Jump to search
Content added Content deleted
Line 306: Line 306:
* If the code executes succesfully without crashing the game, the bootstrap has now been repaired.
* If the code executes succesfully without crashing the game, the bootstrap has now been repaired.


=Appendix: In-depth explanation of the setup=
=Appendix=


===Effect of Onix===
==Plain text transcripts of codes==


===Test box name===
Defeating the provided list of pokémon and viewing Onix's summary will result in the following values starting from the buffered species ID at $D10E, assuming the pokémon is in party slot #2:

{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
! Language !! Box name content !! Language !! Box name content !! Language !! Box name content
|-
! scope="row"| English
|| <pre>Box 14: Pk Pk h 'd</pre>
! scope="row" | Italian
|| <pre>Box 14: Pk Pk Í</pre>
! scope="row"| Spanish
|| <pre>Box 14: Pk Pk Í</pre>
|}
Note: "..." refers to one ellipsis character, “pk” refers to the one pk character, "$" refers to the pokédollar sign, "*" refers to the multiplication symbol. Make sure to pay careful attention to upper/lowercase letters.

===Setup box name===

{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
! Language !! Box name content !! Language !! Box name content !! Language !! Box name content
|-
! scope="row"| English
|| <pre>Box 1: 0 ♀ ♀ Pk ? ♂ E ♀
Box 2: Pk 5 'd 'v z é B 5
Box 3: 'v 9 é [SPACE] 5 'v , F
Box 4: 's [SPACE] 5 ? E 's [SPACE] 5
Box 5: 'v 's é J 5 'v 8 5
Box 6: é F 5 'v * é I 5
Box 7: 0 C 's [SPACE] 5 é H 5
Box 8: p é G 5 ♀ 'v h h
Box 9: 's [SPACE] 5 é C 5 'v B
Box 10: h 's [SPACE] 5 é D 5 *
Box 11: 'v 9 é E 5 Pk 0 9
Box 12: 's B 5 é C 5 Pk 'v
Box 13: 'v Pk é T 2 h 'd 5
Box 14: p 0 5 ♀ Pk 'v G 1</pre>
! scope="row" | Italian
|| <pre>Box 1: 0 ♀ ♀ Pk ? ¡ E ♀
Box 2: Pk 5 ì ° z é B 5
Box 3: ° 9 é [SPACE] 5 ° , F
Box 4: ó [SPACE] 5 ? E ó [SPACE] 5
Box 5: ° ú é I 5 ° 9 5
Box 6: é J 5 ° 8 é F 5
Box 7: È R ó [SPACE] 5 é H 5
Box 8: p é G 5 ♀ ° h h
Box 9: ó [SPACE] 5 é C 5 ° B
Box 10: h ó [SPACE] 5 é D 5 *
Box 11: ° 9 é E 5 Pk 0 9
Box 12: ó B 5 é C 5 Pk °
Box 13: ° Pk é T 2 h ì 5
Box 14: p 0 5 ♀ Pk ° G 1</pre>
! scope="row"| Spanish
|| <pre>BBox 1: 0 ♀ ♀ Pk ? ¡ E ♀
Box 2: Pk 5 ì ° z é B 5
Box 3: ° 9 é [SPACE] 5 ° , F
Box 4: ó [SPACE] 5 ? E ó [SPACE] 5
Box 5: ° ó é J 5 È 5 5
Box 6: é I 5 ° 3 é F 5
Box 7: È R ó [SPACE] 5 é H 5
Box 8: p é G 5 ♀ ° h h
Box 9: ó [SPACE] 5 é C 5 ° B
Box 10: h ó [SPACE] 5 é D 5 *
Box 11: ° 9 é E 5 Pk 0 9
Box 12: ó B 5 é C 5 Pk °
Box 13: ° Pk é T 2 h ì 5
Box 14: p 0 5 ♀ Pk ° G 1</pre>
|}
Note: "..." refers to one ellipsis character, “pk” refers to the one pk character, "$" refers to the pokédollar sign, "*" refers to the multiplication symbol. Make sure to pay careful attention to upper/lowercase letters.

===Reset box name===

{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
! Language !! Box name content !! Language !! Box name content !! Language !! Box name content
|-
! scope="row"| English
|| <pre>Box 1: p 0 Mn ♀ Pk p 0 2
Box 2: E ♀ Pk 'v y é h 5
Box 3: F 'v , h 's h 5 p
Box 4: 'v 6 h 's h 5 p p
Box 5: 0 'm 's h 5 'v M F
Box 6: 's h 5 'v B A 'd Pk
Box 7: Pk h 'd

Box 14: p 0 5 ♀ Pk 'v G 1</pre>
! scope="row" | Italian
|| <pre>Box 1: p 0 Mn È 2 ♀ Pk 5
Box 2: ° y é f 5 F ° ,
Box 3: Ù f 5 È È Ù f 5
Box 4: È Á Ù f 5 5 È W
Box 5: Ù f 5 È [SPACE] Ù f 5
Box 6: Pk Pk Í Í Í

Box 14: p 0 5 ♀ Pk ° G 1 </pre>
! scope="row"| Spanish
|| <pre>Box 1: p 0 Mn È 2 ♀ Pk 5
Box 2: ° y é f 5 F ° ,
Box 3: Ù f 5 È È Ù f 5
Box 4: È Á Ù f 5 5 È W
Box 5: Ù f 5 È [SPACE] Ù f 5
Box 6: Pk Pk Í Í Í

Box 14: p 0 5 ♀ Pk ° G 1 </pre>
|}
Note: "..." refers to one ellipsis character, “pk” refers to the one pk character, "$" refers to the pokédollar sign, "*" refers to the multiplication symbol. Make sure to pay careful attention to upper/lowercase letters.

==In-depth explanation of the setup==

===Explanation on the 0x1500 ACE setup===

This setup uses [[0x1500 control code arbitrary code execution|0x1500 control code ACE]]. Since the page already contains an explanation on how it works, this page will focus on what the setup does to achieve its effect.

Relevant addresses for this explanation:

{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
! Address !! Function
|-
| $D002 || Address where the last read mail is stored.
|-
| $D073 || Address where the names of pokémon are buffered.
|-
| $D086 || Address where the names of used items are buffered.
|-
| $D108 || Address where the current selected party pokémon’s species is buffered.
|-
| $D109 || Address where the current selected party pokémon’s party slot is buffered.
|-
| $D10C || Address where the amount of items tossed is buffered.
|-
| $D10D || Address where the amount of the last selected item is buffered.
|-
| $D10E || Address where the data of the last viewed pokémon is buffered.
|}

* Attempting to toss 21 items will buffer $15 at $D10C.
* For a list at the highest size it has ever been, the "Quantity" of the CANCEL button will be $00, which will be buffered at $D10D when the CANCEL button is used with A. This forms the required $1500 to start executing ACE.
* By opening the start menu and moving one step up at the specified location, the game will load in a $C0 (ret nz) at $CD70, allowing safe return from the effects of $1500. The game will resume executing from $D10E onward.
* The last pokémon viewed is buffered from $D10E onward. Setting Tackle ($21) as its first move allows safe passage over Screech ($67).
* Rocky’s trainer ID is fixed and will be $BF (cp a, which resets the carry flag) and $1E. Both values are safe to pass.
* Rocky’s XP total will end up between 326 and 350. This is always interpreted as $01 and $XX. since the high HP stat exp byte is always $00, the total is interpreted as ld bc, $00XX. This means that exp is always safe to pass.
* Due to the specific pokémon defeated, the data in the stat experience fields will be read as $D2 $00 $F0. This is interpreted as jp nc $F000, due to echo ram this will redirect execution to $D000, which is where the last read mail was buffered. The nc condition is always fulfilled thanks to the previous $BF (cp a) in Onix’s Trainer ID.
* At this point, the mail will redirect execution to $FB75. Due to echo ram, this will effectively redirect execution to $DB75, the start of box name 1. Please note that $D003 and $D004 are overwritten by opening the withdraw screen to the values of the current box and slot of the currently selected stored pokémon. These values are taken care of by setting the first character of the mail to $FA, which is interpreted along with the next two values as ld a, (YYXX).
* Afterwards, the game will simply execute the box name code.

* For the alternative method, selecting Spearow to read its mail will buffer both its species and party slot to $D108 and $D109. By putting a Spearow in the topmost party slot, this will buffer a $15 and $00 respectively. One drawback of this approach is that these RAM values are more volatile and are immediately overwritten after executing ACE. Luckily, Onix’s species ID ($5F) acts as a text terminator, preventing users from accidentally crashing the game if they forget to reset these values.

Additional note: $D086 isn’t actually relevant to the setup. The reason it’s mentioned here is because using an item buffers the item’s name to this location, placing a $50 terminator just a bit after where the pokémon’s name is normally buffered. Having this terminator in place will allow you to safely view an unterminated pokémon’s name.

===Effect of the test box name===

Box name data starts from $D8BF onward. Converting the provided mail code to assembly results in the following:

====English====


<pre>
<pre>
F6 FF or $FF ; a = $FF, reset carry flag
5F ld e, a
D0 ret nc ; Safely return to normal game operation
00 nop
21 67 00 ld hl, $0067 ; Determined by Onix's moves, Tackle and Screech
00 nop
BF cp a, a
1E 00 ld e, $00 ; $BF1E corresponds to Onix's OTID of 48926
01 XX 00 ld bc, $00XX ; $XX is determined by the exact level of the opponents fought
D2 00 F0 jp nc, $F000
</pre>
</pre>


====French====
After the effect of 0x1500 ACE is triggered and execution is redirected to $D10E, execution slides harmlessly through move, OTID and experience data before jumping to $F000, which is echo RAM for $D000 and is located two bytes before the last buffered mail.


<pre>
===Effect of Sandshrew===
21 80 80 ld hl, $8080
C9 ret ; Safely return to normal game operation
</pre>


====German====
Defeating the provided list of pokémon and viewing Sandshrew's summary will result in the following values starting from the buffered species ID at $D10E, assuming the pokémon is in party slot #2:


<pre>
<pre>
21 80 80 ld hl, $8080
1B dec de
F6 FF or $FF ; a = $FF, reset carry & zero flag
30 0A jr .jump
C0 ret nz ; Safely return to normal game operation
XX XX XX XX XX XX XX XX XX 73 ; Move, OTID and experience is skipped over by the jr instruction
</pre>
00 nop ; .jump

C3 00 F0 jp $F000
====Italian & Spanish====

<pre>
C9 ret ; Safely return to normal game operation
</pre>
</pre>


===Effect of the setup box name code===
After the effect of 0x1500 ACE is triggered and execution is redirected to $D10E, execution jumps over move, OTID and experience data, followed by another jump to $F000, which is echo RAM for $D000 and is located two bytes before the last buffered mail.


Converting the characters from box names to assembly results in the following code. Please note that the box name code overwrites part of itself, the translated assembly assumes the code was already used once.
===Effect of the mail===


The code overwrites part of itself to call the byteFill function. This will fill the area between $D859 and $D88A with $FF values, setting all 50 TM quantities to 255. Separately, this code writes five bytes from $DA10 onward, the effect pointer of TM15, installing a TM15 bootstrap that redirects execution to the Mail Writer. Lastly, when combined with the mail code, it will convert the first item in the main item pocket to a TM15.
The last read mail is buffered from $D002 onward. Please note that viewing the bad clone in box #1 will write the value $01 to $D003 and $D004. Converting the characters from the mail to assembly results in the following, ordered by language:


====English====
====English====


<pre>
<pre>
Box 1: $DB75
FA 01 01 ld a, ($0101) ; a = $C3
A7 and a, a ; Reset carry flag
AF xor a ; a = $00
D6 FF sub $FF ; a = $01
D4 75 FB call nc, wBoxNames
EA D0 FB ld ($FBD0), a
A7 and a, a ; Reset carry flag
D6 F1 sub $F1 ; a = $10
E1 pop hl ; After returning from 0x1500 ACE, this prevents the print function from printing text in WRAM.
D0 ret nc
50 ld d; b
</pre>


Box 2: $DB7E
====French====
EA 87 FB ld ($FB87), a
D6 EF sub $EF ; a = $21
EA 86 FB ld ($FB87), a
21


Box 3: $DB87
<pre>
FA 01 01 ld a, ($0101) ; a = $C3
10 FA ld hl, $FA10 ; Execution pointer of wrong pocket TM15
EA AC FB ld ($F8AC), a
D6 F5 sub $F5 ; a = $CE, TM15's item ID
EA 93 F8 ld (wItems), a ; Main item pocket, first item ID
D6 F3 sub $F3 ; a = $DB
EA 86 FB ld ($FB86), a
EA E9 FB ld ($FBE9), a
4E ld a, a
D6 BA sub $BA ; a = $21
EA 75 FB ld (wBoxNames), a
D6 FF sub $FF ; a = $22
D6 FF sub $FF ; a = $22
FB ei
EA B7 FB ld ($FBB7), a
50 ld d, b
AF xor a ; a = $00, set zero flag

CC 75 DB call z, wBoxNames
Box 4: $DB90
E1 pop hl ; After returning from 0x1500 ACE, this prevents the print function from printing text in WRAM.
EA AA FB ld ($FBAA), a
85 add a, l ; a = $32
EA D1 FB ld ($FBD1), a
85 add a, l ; a = $42
50 ld d, b

Box 5: $DB99
F6 81 or $81 ; a = $C3, reset carry flag
D4 D6 FB call nc, .setupBootStrap
B4 or a, h ; a = $FB
D6 A2 sub $A2 ; a = $59, reset carry flag
50 ld d, b

Box 6: $DBA2
EA AD FB ld ($FBAD), a
D4 AA FB call nc, .writeBootstrap
D6 81 sub $81 ; a = $D8, set carry flag
22 ldi (hl), a ; .writeBootstrap

Box 7: $DBAB
D0 ret nc
D0 ret nc
21 59 F8 ld hl, $F859 ; $59 will later be overwritten to $41 to prevent crashing when viewing the newly written name
AF xor a ; a = $00
EA D2 FB ld ($FBD2), a
50 ld d, b

Box 8: $DBB4
D6 D0 sub $D0 ; a = $30
EA D5 FB ld ($FBD5), a
D6 EF sub $EF ; a = $41
FB ei
50 ld d, b

Box 9: $DBBD
EA D4 FB ld ($FBD4), a
EA AD FB ld ($FBAD), a ; Overwrites part of box #7 to prevent a crash
B5 or a, l ; a = $59
FB ei
50 ld d, b

Box 10: $DBC6
D6 8B sub $8B ; a = $CE
EA 93 F8 ld (wItems), a ; Main item pocket, item #1's ID
F6 FF or $FF ; a = $FF, reset carry flag
FB ei
50 ld d, b

Box 11: $DBCF
FB ei
01 32 00 ld bc, 0032
D2 41 30 jp nc, byteFill
F5 push af ; .SetupBootStrap
50 ld d, b

Box 12: $DBD8
D6 85 sub $85 ; a = 3E, reset carry flag
D4 AA FB call nc, .writeBootstrap
85 add a, l ; a = $4F
E6 84 and $84 ; a = $04, reset carry flag
50 ld d, b

Box 13: $DBE1
D4 AA FB call nc, .writeBootstrap
F1 pop af ; a = $C3, reset carry flag
D2 AA FB jp nc, .writeBootstrap
FB
50

Bootstrap: $DA10
3E 04 ld a, $04
C3 59 D8 jp wTMsHMs
</pre>
</pre>


====German====
====Italian====


<pre>
<pre>
Box 1: $DB75
FA 01 01 ld a, ($0101) ; a = $C3
87 add a, a ; a = $86
EA A3 FB ld ($FBA3), a ; Due to mail, a = $00
C6 9C add $9C ; a = $22
D6 FF sub $FF ; a = $01
EA A9 FB ld ($FBA9), a
EA A1 FB ld ($FBA1), a
50 ld d, b
C6 FF add $FF ; a = $21

EA 75 FB ld (wBoxNames), a
Box 2: $DB7E
D6 CF sub $CF ; a = $32
EA A2 FB ld ($FBA2), a
C6 EF add $EF ; a = $21
FB ei
50 ld d, b

Box 3: $DB87
EA 9E FB ld ($FB9E), a
D6 C8 sub $C8 ; a = $59
EA 9F FB ld ($FB9F), a
50 ld d, b

Box 4: $DB90
C6 D6 add $D6 ; a = $2F
EA A5 FB ld ($FBA5), a
D6 FF sub $FF ; a = $30
FB ei
50 ld d, b

Box 5: $DB99
EA A6 FB ld ($FBA6), a
F6 FF or $FF
21 59 F8 ld hl, wTMsHMs ; $59 gets overwritten to $D8 to prevent a crash upon viewing the newly written box name
01

Box 6: $DBA2
32 00 ld bc, $0032
CD 2F 30 call byteFill
AF xor a ; a = $00
AF xor a ; a = $00
F6 4E or $4E ; a = $4E
F6 E2 or $E2 ; a = $E2
50 ld d, b
F6 80 or $80 ; a : $CE

EA 93 F8 ld (wItems), a ; Main item pocket, first item ID
Box 7: $DBAB
F0 F0 ld a, ($FFF0) ; a = 0, zero flag is NOT reset
84 add a, h ; af = $DA10
C4 75 FB call z, wBoxNames
F5 push af
E1 pop hl ; After returning from 0x1500 ACE, this prevents the print function from printing text in WRAM.
C0 ret nz
E1 pop hl
D6 9C sub $9C ; a = $3E
CD C8 FB call .write
50 ld d, b

Box 8: $DBB4
E6 84 and $84 ; a = $04
CD C8 FB call .write
C6 BF add $BF ; a = $C3
BF cp a
50 ld d, b

Box 9: $DBBD
CD C8 FB call .write
C6 96 add $96 ; a = $59
CD C8 FB call .write
50 ld d, b

Box 10: $DBC6
D6 81 sub $81 ; a = $D8
22 ldi (hl), a ; .write
C9 ret

Bootstrap: $DA10
3E 04 ld a, $04
C3 59 D8 jp wTMsHMs
</pre>
</pre>


====Italian & Spanish====
====Spanish====


<pre>
<pre>
Box 1: $DB75
FA 01 01 ld a, ($0101) ; a = $C3
D6 A1 sub $A1 ; a = $22
EA A3 FB ld ($FBA3), a ; Due to mail, a = $00
D6 FF sub $FF ; a = $01
EA C8 FB ld ($FBC8), a
EA A1 FB ld ($FBA1), a
50 ld d, b

Box 2: $DB7E
D6 CF sub $CF ; a = $32
EA A2 FB ld ($FBA2), a
C6 EF add $EF ; a = $21
FB ei
50 ld d, b

Box 3: $DB87
EA 9E FB ld ($FB9E), a
D6 C8 sub $C8 ; a = $59
EA 9F FB ld ($FB9F), a
50 ld d, b

Box 4: $DB90
C6 D2 add $D2 ; a = $2B
EA A5 FB ld ($FBA5), a
D6 FB sub $FF ; a = $30
FB ei
50 ld d, b

Box 5: $DB99
EA A6 FB ld ($FBA6), a
F6 FF or $FF
21 59 F8 ld hl, wTMsHMs ; $59 gets overwritten to $D8 to prevent a crash upon viewing the newly written box name
01

Box 6: $DBA2
32 00 ld bc, $0032
CD 2B 30 call byteFill
AF xor a ; a = $00
AF xor a ; a = $00
F6 E2 or $E2 ; a = $E2
CD 75 FB call wBoxNames
50 ld d, b
EA 9F FB ld ($FB9F), a ; Prevent a game crash when viewing the box name

F6 4E or $4E ; a = $DE
Box 7: $DBAB
C6 F0 add $F0 ; a = $CE
84 add a, h ; af = $DA10
EA 93 F8 ld (wItems), a ; Main item pocket, first item ID
F5 push af
E1 pop hl ; After returning from 0x1500 ACE, this prevents the print function from printing text in WRAM.
E1 pop hl
D6 9C sub $9C ; a = $3E
CD C8 FB call .write
50 ld d, b

Box 8: $DBB4
E6 84 and $84 ; a = $04
CD C8 FB call .write
C6 BF add $BF ; a = $C3
BF cp a
50 ld d, b

Box 9: $DBBD
CD C8 FB call .write
C6 96 add $96 ; a = $59
CD C8 FB call .write
50 ld d, b

Box 10: $DBC6
D6 81 sub $81 ; a = $D8
22 ldi (hl), a ; .write
C9 ret
C9 ret

Bootstrap: $DA10
3E 04 ld a, $04
C3 59 D8 jp wTMsHMs
</pre>
</pre>


===Effect of the box name===
===Effect of the TM code===


Converting the TM quantities to assembly results in the following code. Please note that this code requires a value of $04 in register a in order to properly work.
Box name data starts from $D8BF onward. Converting the provided mail code to assembly results in the following:


====English====
====English====


<pre>
<pre>
11 80 D2 ld de, $D280
F6 FF or $FF ; a = $FF, reset carry flag
D5 push de
D0 ret nc ; Safely return to normal game operation
D5 push de ; .nextMail
D5 push de
21 75 5E ld hl, _ComposeMailMessage
CF rst08h, FarCall a:hl
E1 pop hl
D1 pop de
2A ldi a, (hl) ; .continue
FE 50 cp $50
38 FB jr c, .continue
28 0A jr z, .terminator
87 add a, a
86 add a, (hl)
12 ld (de), a
13 inc de
23 inc hl
81 add a, c
4F ld c, a
12 ld (de), a
18 EF jr .continue
21 01 C5 ld hl, $C501 ; .screenLoop
4D ld c, l
CD CC 38 call PrintBCDNumber.loop - 1
1B dec de ; .goBack
CD 4B 35 call JoyTextDelay_ForcehJoyDown
BD cp a, l ; l = $04
28 D9 jr z, .nextMail
38 F0 jr c, .displayLoop
FE 08 cp $08
C8 ret z
18 F2 jr .goBack
</pre>
</pre>


====French====
====Italian====


<pre>
<pre>
21 80 80 ld hl, $8080
11 80 D2 ld de, $D280
D5 push de
C9 ret ; Safely return to normal game operation
D5 push de ; .nextMail
D5 push de
21 C5 5E ld hl, _ComposeMailMessage
CF rst08h, FarCall a:hl
E1 pop hl
D1 pop de
2A ldi a, (hl) ; .continue
FE 50 cp $50
38 FB jr c, .continue
28 0A jr z, .terminator
87 add a, a
86 add a, (hl)
12 ld (de), a
13 inc de
23 inc hl
81 add a, c
4F ld c, a
12 ld (de), a
18 EF jr .continue
21 01 C5 ld hl, $C501 ; .screenLoop
4D ld c, l
CD BA 38 call PrintBCDNumber.loop
1B dec de ; .goBack
CD 39 35 call JoyTextDelay_ForcehJoyDown
BD cp a, l ; l = $04
28 D9 jr z, .nextMail
38 F0 jr c, .displayLoop
FE 08 cp $08
C8 ret z
18 F2 jr .goBack
</pre>
</pre>


====German====
====Spanish====


<pre>
<pre>
21 80 80 ld hl, $8080
11 80 D2 ld de, $D280
D5 push de
F6 FF or $FF ; a = $FF, reset carry & zero flag
D5 push de ; .nextMail
C0 ret nz ; Safely return to normal game operation
D5 push de
21 E8 5E ld hl, _ComposeMailMessage
CF rst08h, FarCall a:hl
E1 pop hl
D1 pop de
2A ldi a, (hl) ; .continue
FE 50 cp $50
38 FB jr c, .continue
28 0A jr z, .terminator
87 add a, a
86 add a, (hl)
12 ld (de), a
13 inc de
23 inc hl
81 add a, c
4F ld c, a
12 ld (de), a
18 EF jr .continue
21 01 C5 ld hl, $C501 ; .screenLoop
4D ld c, l
CD AC 38 call PrintBCDNumber.loop - 1
1B dec de ; .goBack
CD 35 35 call JoyTextDelay_ForcehJoyDown
BD cp a, l ; l = $04
28 D9 jr z, .nextMail
38 F0 jr c, .displayLoop
FE 08 cp $08
C8 ret z
18 F2 jr .goBack
</pre>
</pre>


===Effect of the reset box name code===
====Italian & Spanish====

Converting the characters from box names to assembly results in the following code. This code overwrites the latter half of party pokémon #3's stat experience data, allowing it to function as a TM25 bootstrap that redirects execution to the Mail Writer.

====English====


<pre>
<pre>
Box 1: $DB75
C9 ret ; Safely return to normal game operation
AF xor a ; a = $00, reset carry flag
F6 E2 or $E2 ; a = $E2
F5 push af
E1 pop hl
AF xor a ; a = $00, reset carry flag
F6 F8 or $F8 ; a = $F8
50 ld d, b

Box 2: $DB7E
84 add a, h ; af = $DA10
F5 push hl
E1 pop hl ; hl = $DA10
D6 B8 sub $B8 ; a = $22
EA A8 FB ld (.write), a
50 ld d, b

Box 3: $DB87
85 add a, l ; a = $33
D6 F4 sub $F4 ; a = $3E
A7 and a ; Reset carry flag
D4 A8 FB call nc, .write
AF xor a ; a = $00
50 ld d, b

Box 4: $DB90
D6 FC sub $FC ; a = $04
A7 and a ; Reset carry flag
D4 A8 FB call nc, .write
AF xor a ; a = $00
AF xor a
50 ld d, b

Box 5: $DB99
F6 D2 or $D2 ; a = $D2
D4 A8 FB call nc, .write
D6 8C sub $8C ; a = $46
85 add a, l ; a = $59
50 ld d, b

Box 6: $D8A2
D4 A8 FB call nc, .write
D6 81 sub $81 ; a = $D8
A7 and a ; Reset carry flag
22 ldi (hl), a ; .write
D0 call nc

Party pokémon #3's stat experience, starting from $DA9A
3E 04 ld a, $04
D2 59 D8 jp nc, wTMsHMs
</pre>
</pre>


====Italian & Spanish====
===Explanation on the 0x1500 ACE setup===


<pre>
This setup uses [[0x1500 control code arbitrary code execution|0x1500 control code ACE]]. Since the page already contains an explanation on how it works, this page will focus on what the setup does to achieve its effect.
Box 1: $DB75
AF xor a ; a = $00
F6 E2 or $E2 ; a = $E2
C6 F8 add $F8 ; af = $DA10
F5 push af
E1 pop hl ; hl = $DA10
FB ei
50 ld d, b


Box 2: $DB7E
Relevant addresses for this explanation:
D6 B8 sub $B8 ; a = $22
EA 9F FB ld (.write), a
85 add a, l ; a = $32
D6 F4 sub $F4 ; a = $3E
50 ld d, b


Box 3: $DB87
{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
CD 9F FB call .write
! Address !! Function
C6 C6 add $C6 ; a = $04
|-
CD 9F FB call .write
| $D002 || Address where the last read mail is stored.
50 ld d, b
|-
| $D073 || Address where the names of pokémon are buffered.
|-
| $D086 || Address where the names of used items are buffered.
|-
| $D108 || Address where the current selected party pokémon’s species is buffered.
|-
| $D109 || Address where the current selected party pokémon’s party slot is buffered.
|-
| $D10C || Address where the amount of items tossed is buffered.
|-
| $D10D || Address where the amount of the last selected item is buffered.
|-
| $D10E || Address where the data of the last viewed pokémon is buffered.
|}


Box 4: $DB90
* Attempting to toss 21 items will buffer $15 at $D10C.
C6 BF add $BF ; a = $C3
* For a list at the highest size it has ever been, the "Quantity" of the CANCEL button will be $00, which will be buffered at $D10D when the CANCEL button is used with A. This forms the required $1500 to start executing ACE.
CD 9F FB call .write
* By opening the start menu and moving one step up at the specified location, the game will load in a $C0 (ret nz) at $CD70, allowing safe return from the effects of $1500. The game will resume executing from $D10E onward.
FB ei
* The last pokémon viewed is buffered from $D10E onward. Setting Tackle ($21) as its first move allows safe passage over Screech ($67).
C6 96 add $96 ; a = $59
* Rocky’s trainer ID is fixed and will be $BF (cp a, which resets the carry flag) and $1E. Both values are safe to pass.
50 ld d, b
* Rocky’s XP total will end up between 326 and 350. This is always interpreted as $01 and $XX. since the high HP stat exp byte is always $00, the total is interpreted as ld bc, $00XX. This means that exp is always safe to pass.
* Due to the specific pokémon defeated, the data in the stat experience fields will be read as $D2 $00 $F0. This is interpreted as jp nc $F000, due to echo ram this will redirect execution to $D000, which is where the last read mail was buffered. The nc condition is always fulfilled thanks to the previous $BF (cp a) in Onix’s Trainer ID.
* At this point, the mail will redirect execution to $FB75. Due to echo ram, this will effectively redirect execution to $DB75, the start of box name 1. Please note that $D003 and $D004 are overwritten by opening the withdraw screen to the values of the current box and slot of the currently selected stored pokémon. These values are taken care of by setting the first character of the mail to $FA, which is interpreted along with the next two values as ld a, (YYXX).
* Afterwards, the game will simply execute the box name code.


Box 5: $DB99
* For the alternative method, selecting Spearow to read its mail will buffer both its species and party slot to $D108 and $D109. By putting a Spearow in the topmost party slot, this will buffer a $15 and $00 respectively. One drawback of this approach is that these RAM values are more volatile and are immediately overwritten after executing ACE. Luckily, Onix’s species ID ($5F) acts as a text terminator, preventing users from accidentally crashing the game if they forget to reset these values.
CD 9F FB call .write
C6 7F add $7F ; a = $D8
7F ld a, a
22 ldi (hl), a ; .write
C9 ret


Party pokémon #3's stat experience, starting from $DA9A
Additional note: $D086 isn’t actually relevant to the setup. The reason it’s mentioned here is because using an item buffers the item’s name to this location, placing a $50 terminator just a bit after where the pokémon’s name is normally buffered. Having this terminator in place will allow you to safely view an unterminated pokémon’s name.
3E 04 ld a, $04
C3 59 D8 jp wTMsHMs
</pre>


=Plain text transcript for codes=
=Plain text transcript for codes=