Guides:Fast 0x1500 ACE: Difference between revisions
m
→Appendix: In-depth explanation of the setup
Line 306:
* If the code executes succesfully without crashing the game, the bootstrap has now been repaired.
=Appendix
==
===Test 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 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>
F6 FF or $FF ; a = $FF, reset carry flag
D0 ret nc ; Safely return to normal game operation
</pre>
====French====
<pre>
21 80 80 ld hl, $8080
C9 ret ; Safely return to normal game operation
</pre>
====German====
<pre>
21 80 80 ld hl, $8080
F6 FF or $FF ; a = $FF, reset carry & zero flag
C0 ret nz ; Safely return to normal game operation
</pre>
====Italian & Spanish====
<pre>
C9 ret ; Safely return to normal game operation
</pre>
===Effect of the setup box name code===
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.
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.
====English====
<pre>
Box 1: $DB75
D6 FF sub $FF ; a = $01
EA D0 FB ld ($FBD0), a
D6 F1 sub $F1 ; a = $10
Box 2: $DB7E
EA 87 FB ld ($FB87), a
D6 EF sub $EF ; a = $21
EA 86 FB ld ($FB87), a
21
Box 3: $DB87
EA AC FB ld ($F8AC), a
D6 FF sub $FF ; a = $22
FB ei
50 ld d, b
Box 4: $DB90
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
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>
Box 1: $DB75
EA
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 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
F6
50 ld d, b
Box 7: $DBAB
84 add a, h ; af = $DA10
F5 push af
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>
Box 1: $DB75
D6 FF sub $FF ; a = $01
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
F6 E2 or $E2 ; a = $E2
50 ld d, b
Box 7: $DBAB
84 add a, h ; af = $DA10
F5 push af
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>
===Effect of the
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.
====English====
<pre>
11 80 D2 ld de, $D280
D5 push de
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>
D5 push de
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>
D5 push de
D5 push de ; .nextMail
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>
===Effect of the reset box name code===
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>
Box 1: $DB75
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>
====Italian & Spanish====
<pre>
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
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
CD 9F FB call .write
C6 C6 add $C6 ; a = $04
CD 9F FB call .write
50 ld d, b
Box 4: $DB90
C6 BF add $BF ; a = $C3
CD 9F FB call .write
FB ei
C6 96 add $96 ; a = $59
50 ld d, b
Box 5: $DB99
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
3E 04 ld a, $04
C3 59 D8 jp wTMsHMs
</pre>
=Plain text transcript for codes=
|