Jump to content

Guides:Fast 0x1500 ACE: Difference between revisions

m
no edit summary
mNo edit summary
 
(25 intermediate revisions by 2 users not shown)
Line 7:
If you encounter any issues when going through this guide or would like to provide feedback, please contact TimoVM on the [https://discord.gg/EA7jxJ6 Glitch City Research Institute Discord].
 
'''When playing on cartridge or emulator, it is requiredrecommended to have previously cleared an old save by pressing SELECT + UP + B simultaneously on the start screen at least once since obtaining the cart. Otherwise you willrisk not bebeing able to obtain a bad clone or an unterminated name pokémon.'''
 
The contents of this guide are demonstrated in the following video:
 
{{youtube|iJRb3PwUrkg|TimoVM}}
 
=Setting up initial ACE=
Line 73 ⟶ 77:
 
Finally, in order to execute ACE, do the following actions:
 
{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
|
[[File:EN Fast ACE PokeSen.png]]
||
[[File:EN Fast ACE Spearow.png]]
|}
 
# Stand in front of the PC on the second floor of any pokémon center. Take one step down, take one step left until you end up at the location indicated by the above screenshot on the left. '''Save the game here and reset.'''
Line 95 ⟶ 106:
# Sell TMs in specific quantities so that the amount of TMs in the TM/HM pocket spell out a small mail writer program.
 
==Step 4: settingSetting all TM quantities to x255<span id="{{anchorencode:Box name payload}}"></span>==
 
* Rename box names to form the following language dependent codes. '''Please mind the differences between uppercase X ([[File:Character UCX.png]]), lowercase x ([[File:Character lcx.png]]) and multiplication symbol ([[File:Character mul.png]]).'''
Line 112 ⟶ 123:
|}
 
* Then, execute 0x1500 control code ACE using the method described in thesection [[https://glitchcity1.wiki/wiki/Guides:Fast_0x1500_ACE#Using_the_ACE_setup|previous section here]]4.1
 
* If the code was successfully executed, the TM/HM pocket should now be completely filled with 255 copies of every TM. Additionally, the first item in the main item pocket will have changed into a TM15. Using it will execute code in the TM/HM pocket. Make sure to save after verifying that the code worked.
Line 123 ⟶ 134:
 
{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
! English !! French !! German !! Italian !! Spanish
|-
|
[[File:TM English C.png]]
||
[[File:TM French C.png]]
||
[[File:TM German C.png]]
||
[[File:TM Italian C.png]]
Line 246 ⟶ 253:
 
{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
! 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 ROCK SMASH || x117 ||69000 || x122 || 66500 || x99 || 78000 || x197 || 29000 || x232 || 11500
|-
| TM35 SLEEP TALK ||x204 ||25500 || x175 || 40000 || x182 || 36500 || x186 || 34500 || x172 || 41500
|-
| TM39 SWIFT ||x75 ||180000 || x56 || 199000 || x53 || 202000 || x57 || 198000 || x53 || 202000
|}
 
Line 294 ⟶ 301:
In case something happens with the TM15 bootstrap that causes it to no longer function, you can repair bootstrap without having to reset TM quantities using the following procedure:
 
* Enter the following language-specific box names. '''Please mind the differences between uppercase X ([[File:Character UCX.png]]), lowercase x ([[File:Character lcx.png]]) and multiplication symbol ([[File:Character mul.png]])'''. For English, boxes 8 through 13 are irrelevant for the setup and do not need to be renamed. For Italian & Spanish, boxes 7 through 13 are irrelevant for the setup and do not need to be renamed.
 
{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
! English !! French !! German !! Italian !! Spanish
|-
|
[[File:Box English C Reset V2.png]]
||
[[File:Box FrenchItalian C Reset V2.png]]
||
[[File:Box GermanSpanish C Reset V2.png]]
||
[[File:Box Italian C Reset.png]]
||
[[File:Box Italian C Reset.png]]
|}
* Then, execute 0x1500 control code ACE using the method described in section 1.4.1
 
* Execute 0x1500 ACE using the usual steps.
* If the code executes succesfully without crashing the game, the bootstrap has now been repaired.
 
=Appendix: In-depth explanation of the setup=
 
===EffectPlain text transcripts of Onix=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;"
<pre>
! Language !! Box name content !! Language !! Box name content !! Language !! Box name content
5F ld e, a
|-
00 nop
! scope="row"| English
21 67 00 ld hl, $0067 ; Determined by Onix's moves, Tackle and Screech
|| <pre>Box 14: Pk Pk h 'd</pre>
00 nop
! scope="row" | Italian
BF cp a, a
|| <pre>Box 14: Pk Pk Í</pre>
1E 00 ld e, $00 ; $BF1E corresponds to Onix's OTID of 48926
! scope="row"| Spanish
01 XX 00 ld bc, $00XX ; $XX is determined by the exact level of the opponents fought
|| <pre>Box 14: Pk Pk Í</pre>
D2 00 F0 jp nc, $F000
|}
</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===
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.
 
{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
===Effect of Sandshrew===
! Language !! Box name content !! Language !! Box name content !! Language !! Box name content
|-
! scope="row"| English
|| <pre>Box 1: 0 ♀ ♀ Pk ? ♂ E Pk
Box 2: ♀ Pk '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 p F 1
Box 14: p 0 5 ♀ Pk 'v G 1</pre>
! scope="row" | Italian
|| <pre>Box 1: 0 ♀ ♀ Pk ? ¡ E Pk
Box 2: ♀ Pk ì ° 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 p F 1
Box 14: p 0 5 ♀ Pk ° G 1</pre>
! scope="row"| Spanish
|| <pre>Box 1: 0 ♀ ♀ Pk ? ¡ E Pk
Box 2: ♀ Pk ì ° 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 p F 1
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===
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:
 
{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
<pre>
! Language !! Box name content !! Language !! Box name content !! Language !! Box name content
1B dec de
|-
30 0A jr .jump
! scope="row"| English
XX XX XX XX XX XX XX XX XX 73 ; Move, OTID and experience is skipped over by the jr instruction
|| <pre>Box 1: p 0 Mn ♀ Pk p 0 2
00 nop ; .jump
Box 2: E ♀ Pk 'v y é h 5
C3 00 F0 jp $F000
Box 3: F 'v , h 's h 5 p
</pre>
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 Pk p F 1
 
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 é i 5 F ° ,
Box 3: Ù i 5 È È Ù i 5
Box 4: È Á Ù i 5 5 È W
Box 5: Ù i 5 È [SPACE] Ù i 5
Box 6: Pk Pk Pk p F 1 Í Í
 
Box 14: p 0 5 ♀ Pk ° G 1 </pre>
! scope="row"| Spanish
|| <pre>Box 1: p 0 Mn È 2 ♀ Pk 5
Box 2: ° y é i 5 F ° ,
Box 3: Ù i 5 È È Ù i 5
Box 4: È Á Ù i 5 5 È W
Box 5: Ù i 5 È [SPACE] Ù i 5
Box 6: Pk Pk Pk p F 1 Í Í
 
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
|-
| $C4A0 || Starting address of wTilemap
|-
| $C4BE || Address of the tilemap where the name of the current active box will be printed when viewing the withdraw screen.
|-
| $CD70 || Starting address of wBGMapBufferPointers
|-
| $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.
|}
 
* The specific movement pattern used will buffer C2 9B C4 (jp nz $C49B) at $CD70.
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.
* Selecting Spearow in the party screen will buffer 15 00 at $D108.
* Viewing the unterminated name pokémon in the withdraw screen will cause the game to attempt to print its name. Since the name doesn't contain a terminator, the game will continue printing text until it find and executes the $15 control character at $D108.
* The presence of the $00 at $D109 will erroneously cause the game to call $CD52. Due to the specific movement pattern and location used, the area between $CD52 and $CD70 is filled with $00 values, allowing safe passage.
* Thanks to the jump buffered at $CD70, the game will jump to $C49B. Since we're in the withdraw screen, the area between $C49B and $C4A0 is filled with $00 values, allowing safe passage. The jump will always pass, since both the carry and zero flags are reset when the game calls $CD52.
* Between $C4A0 and $C4BE are a bunch of screen tiles that are either blank ($7F) or edges of text boxes ($79, $7A, $7B and $7C). These opcodes are all harmless and simply load register values to other registers, allowing safe passage.
* $C4BE holds the text characters of the current active box, allowing us to form arbitrary jumps to other locations in memory.
 
===Effect of the mailtest box name===
 
The lastcurrent readactive mailbox is bufferedprinted from $D002 onward. Please note that viewingon the badtilemap clonestarting in box #1 will write the valuefrom $01C4BE to $D003 and $D004onward. Converting the charactersprovided frombox thename mailcode to assembly results in the following, ordered by language:
 
====English====
 
<pre>
E1 pop hl
FA 01 01 ld a, ($0101) ; a = $C3
E1 pop hl ; popping hl twice then returning will cause the game to continue printing from de to hl. The second pop ensures hl will point to the $7000 region, allowing safe exit.
A7 and a, a ; Reset carry flag
A7 and a ; reset carry flag
D4 75 FB call nc, wBoxNames
D0 ret nc ; Safely return to normal game operation
A7 and a, a ; Reset carry flag
E1 pop hl ; After returning from 0x1500 ACE, this prevents the print function from printing text in WRAM.
D0 ret nc
</pre>
 
====FrenchItalian & Spanish====
 
<pre>
E1 pop hl
FA 01 01 ld a, ($0101) ; a = $C3
E1 pop hl ; popping hl twice then returning will cause the game to continue printing from de to hl. The second pop ensures hl will point to the $7000 region, allowing safe exit.
D6 F5 sub $F5 ; a = $CE, TM15's item ID
C9 ret ; Safely return to normal game operation
EA 93 F8 ld (wItems), a ; Main item pocket, first item ID
</pre>
D6 F3 sub $F3 ; a = $DB
 
EA 86 FB ld ($FB86), a
===Effect of the setup box name code===
EA E9 FB ld ($FBE9), a
 
4E ld a, a
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.
D6 BA sub $BA ; a = $21
 
EA 75 FB ld (wBoxNames), a
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
F6 F5 or $F5 ; a = $F5
F5 push af
E1 pop hl ; hl = $F500
E6 EF and $EF ; a = $E5
84 add a, h ; af = $DA10
E1 pop hl
50 ld d, b
 
Box 2: $DB7E
F5 push af
E1 pop hl ; hl = $DA10, overwritten to $22, ldi (hl), a
D0 ret nc ; On first pass, ignored. Taken whenever $DB7F is called
D6 B9 sub $B9 ; a = $21
EA 81 FB ld ($FB81), a
50 ld d, b
 
Box 3: $DB87
D6 FF sub $FF ; a = $22
EA B77F FB ld ($FBB7FB7F), a
AFD6 F4 xorsub a$F4 ; a = $00, set zero flag2E
85 add a, l ; a = $3E, reset carry flag
CC 75 DB call z, wBoxNames
50 ld d, b
E1 pop hl ; After returning from 0x1500 ACE, this prevents the print function from printing text in WRAM.
 
D0 ret nc
Box 4: $DB90
D4 7F FB call nc, $FB7F
E6 84 and $84 ; a = $04
D4 7F FB call nc, $FB7F
50 ld d, b
 
Box 5: $DB99
D6 D4 sub $D4 ; a = $30
EA 89 FB ld ($FB89), a
D6 FE sub $FE ; a = $32
FB ei
50 ld d, b
 
Box 6: $DBA2
EA 85 FB ld ($FB85), a
D6 F1 sub $F1 ; a = $41
EA 88 FB ld ($FB88), a
50 ld d, b
 
Box 7: $DBAB
F6 82 or $82 ; a = $C3, reset carry flag
D4 7F FB call nc, $FB7F
EA 87 FB ld ($FB87), a
50 ld d, b
 
Box 8: $DBB4
AF xor a ; a = $00
EA 86 FB ld ($FB86), a
F5 push af
D6 A7 sub $A7 ; a = $59
A7 and a ; Reset carry flag
50 ld d, b
 
Box 9: $DBBD
D4 7F FB call nc, $FB7F
EA 82 FB ld ($FB82), a
D6 81 sub $81 ; a = $D8
50 ld d, b
 
Box 10: $DBC6
A7 and a ; Reset carry flag
D4 7F FB call nc, $FB7F
EA 83 FB ld ($FB83), a
F1 pop af ; a = $00
50 ld d, b
 
Box 11: $DBCF
D6 FF sub $FF ; a = $01
EA 84 FB ld ($FB84), a
E1 pop hl
F6 FF or $FF ; a = $FF
50 ld d, b
 
Box 12: $DBD8
D4 81 FB call nc, $FB81 ; $FB81 was rewritten to 21 59 D8 01 32 00 C3 41 30
EA 82 FB ld ($FB82), a ; Replace $59 by $FF to prevent possible crash when viewing $59 as text
E1 pop hl
D6 50 sub $50 ; a = $AF
 
Box 13: $DBE1
D6 E1 sub $E1 ; a = $CE
EA 93 F8 ld (wItems), a ; Replace first item in item pocket with TM15
AF xor a ; a = $00
85 add a, l
F7 rst30h ; Resume text function, immediately hit terminator
50 ld d, b
 
Box 14: displayed as screen tiles at $C4BE
AF xor a ; a = $00
F6 FB or $FB ; a = $FB
F5 push af
E1 pop hl ; h = $FB
D6 86 sub $86 ; a = $75
F7 rst30h ; hl = $FB75, de = $C4C5, jump to hl
 
Bootstrap: $DA10
3E 04 ld a, $04
C3 59 D8 jp wTMsHMs
</pre>
 
====GermanItalian====
 
<pre>
Box 1: $DB75
FA 01 01 ld a, ($0101) ; a = $C3
87F6 F5 addor a, a$F5 ; a = $86F5
F5 push af
C6 9C add $9C ; a = $22
E1 pop hl ; hl = $F500
EA A9 FB ld ($FBA9), a
C6E6 FFE5 addand $FFE5 ; a = $21E5
84 add a, h ; af = $DA10
EA 75 FB ld (wBoxNames), a
E1 pop hl
50 ld d, b
 
Box 2: $DB7E
F5 push af
E1 pop hl ; hl = $DA10, overwritten to $22, ldi (hl), a
D0 ret nc ; On first pass, ignored. Taken whenever $DB7F is called
D6 B9 sub $B9 ; a = $21
EA 81 FB ld ($FB81), a
50 ld d, b
 
Box 3: $DB87
D6 FF sub $FF ; a = $22
EA 7F FB ld ($FB7F), a
D6 F4 sub $F4 ; a = $2E
85 add a, l ; a = $3E, reset carry flag
50 ld d, b
 
Box 4: $DB90
D4 7F FB call nc, $FB7F
E6 84 and $84 ; a = $04
D4 7F FB call nc, $FB7F
50 ld d, b
 
Box 5: $DB99
D6 D5 sub $D5 ; a = $2F
EA 88 FB ld ($FB88), a
D6 FF sub $FF ; a = $30
FB ei
50 ld d, b
 
Box 6: $DBA2
EA 89 FB ld ($FB89), a
D6 FE sub $FE ; a = $32
EA 85 FB ld ($FB85), a
50 ld d, b
 
Box 7: $DBAB
C6 91 add $91 ; a = $C3, reset carry flag
D4 7F FB call nc, $FB7F
EA 87 FB ld ($FB87), a
50 ld d, b
 
Box 8: $DBB4
AF xor a ; a = $00
F6EA 4E86 FB orld ($4E ;FB86), a = $4E
F5 push af
F6 80 or $80 ; a : $CE
D6 A7 sub $A7 ; a = $59
EA 93 F8 ld (wItems), a ; Main item pocket, first item ID
F0 F0A7 ldand a, ($FFF0) ; aReset = 0, zerocarry flag is NOT reset
50 ld d, b
C4 75 FB call z, wBoxNames
 
E1 pop hl ; After returning from 0x1500 ACE, this prevents the print function from printing text in WRAM.
Box 9: $DBBD
C0 ret nz
D4 7F FB call nc, $FB7F
EA 82 FB ld ($FB82), a
D6 81 sub $81 ; a = $D8
50 ld d, b
 
Box 10: $DBC6
A7 and a ; Reset carry flag
D4 7F FB call nc, $FB7F
EA 83 FB ld ($FB83), a
F1 pop af ; a = $00
50 ld d, b
 
Box 11: $DBCF
D6 FF sub $FF ; a = $01
EA 84 FB ld ($FB84), a
E1 pop hl
F6 FF or $FF ; a = $FF
50 ld d, b
 
Box 12: $DBD8
D4 81 FB call nc, $FB81 ; $FB81 was rewritten to 21 59 D8 01 32 00 C3 2F 30
EA 82 FB ld ($FB82), a ; Replace $59 by $FF to prevent possible crash when viewing $59 as text
E1 pop hl
D6 50 sub $50 ; a = $AF
 
Box 13: $DBE1
D6 E1 sub $E1 ; a = $CE
EA 93 F8 ld (wItems), a ; Replace first item in item pocket with TM15
AF xor a ; a = $00
85 add a, l
F7 rst30h ; Resume text function, immediately hit terminator
50 ld d, b
 
Box 14: displayed as screen tiles at $C4BE
AF xor a ; a = $00
F6 FB or $FB ; a = $FB
F5 push af
E1 pop hl ; h = $FB
D6 86 sub $86 ; a = $75
F7 rst30h ; hl = $FB75, de = $C4C5, jump to hl
 
Bootstrap: $DA10
3E 04 ld a, $04
C3 59 D8 jp wTMsHMs
</pre>
 
====Italian & Spanish====
 
<pre>
Box 1: $DB75
FA 01 01 ld a, ($0101) ; a = $C3
D6F6 A1F5 subor $A1F5 ; a = $22F5
F5 push af
EA C8 FB ld ($FBC8), a
E1 pop hl ; hl = $F500
E6 E5 and $E5 ; a = $E5
84 add a, h ; af = $DA10
E1 pop hl
50 ld d, b
 
Box 2: $DB7E
F5 push af
E1 pop hl ; hl = $DA10, overwritten to $22, ldi (hl), a
D0 ret nc ; On first pass, ignored. Taken whenever $DB7F is called
D6 B9 sub $B9 ; a = $21
EA 81 FB ld ($FB81), a
50 ld d, b
 
Box 3: $DB87
D6 FF sub $FF ; a = $22
EA 7F FB ld ($FB7F), a
D6 F4 sub $F4 ; a = $2E
85 add a, l ; a = $3E, reset carry flag
50 ld d, b
 
Box 4: $DB90
D4 7F FB call nc, $FB7F
E6 84 and $84 ; a = $04
D4 7F FB call nc, $FB7F
50 ld d, b
 
Box 5: $DB99
D6 D4 sub $D4 ; a = $30
EA 89 FB ld ($FB89), a
C6 FB add $FB ; a = $2B
FB ei
50 ld d, b
 
Box 6: $DBA2
EA 88 FB ld ($FB88), a
D6 F9 sub $F9 ; a = $32
EA 85 FB ld ($FB85), a
50 ld d, b
 
Box 7: $DBAB
C6 91 add $91 ; a = $C3, reset carry flag
D4 7F FB call nc, $FB7F
EA 87 FB ld ($FB87), a
50 ld d, b
 
Box 8: $DBB4
AF xor a ; a = $00
CDEA 7586 FB callld wBoxNames($FB86), a
F5 push af
EA 9F FB ld ($FB9F), a ; Prevent a game crash when viewing the box name
F6D6 4EA7 orsub $4EA7 ; a = $DE59
C6 F0A7 addand $F0a ; aReset =carry $CEflag
50 ld d, b
EA 93 F8 ld (wItems), a ; Main item pocket, first item ID
 
E1 pop hl ; After returning from 0x1500 ACE, this prevents the print function from printing text in WRAM.
Box 9: $DBBD
C9 ret
D4 7F FB call nc, $FB7F
EA 82 FB ld ($FB82), a
D6 81 sub $81 ; a = $D8
50 ld d, b
 
Box 10: $DBC6
A7 and a ; Reset carry flag
D4 7F FB call nc, $FB7F
EA 83 FB ld ($FB83), a
F1 pop af ; a = $00
50 ld d, b
 
Box 11: $DBCF
D6 FF sub $FF ; a = $01
EA 84 FB ld ($FB84), a
E1 pop hl
F6 FF or $FF ; a = $FF
50 ld d, b
 
Box 12: $DBD8
D4 81 FB call nc, $FB81 ; $FB81 was rewritten to 21 59 D8 01 32 00 C3 2B 30
EA 82 FB ld ($FB82), a ; Replace $59 by $FF to prevent possible crash when viewing $59 as text
E1 pop hl
D6 50 sub $50 ; a = $AF
 
Box 13: $DBE1
D6 E1 sub $E1 ; a = $CE
EA 93 F8 ld (wItems), a ; Replace first item in item pocket with TM15
AF xor a ; a = $00
85 add a, l
F7 rst30h ; Resume text function, immediately hit terminator
50 ld d, b
 
Box 14: displayed as screen tiles at $C4BE
AF xor a ; a = $00
F6 FB or $FB ; a = $FB
F5 push af
E1 pop hl ; h = $FB
D6 86 sub $86 ; a = $75
F7 rst30h ; hl = $FB75, de = $C4C5, jump to hl
 
Bootstrap: $DA10
3E 04 ld a, $04
C3 59 D8 jp wTMsHMs
</pre>
 
===Effect of the boxTM namecode===
 
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====
 
<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>
 
====FrenchItalian====
 
<pre>
2111 80 80D2 ld hlde, $8080D280
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>
 
====GermanSpanish====
 
<pre>
2111 80 80D2 ld hlde, $8080D280
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>
 
===Effect of the reset box name code===
====Italian & Spanish====
 
Converting the characters from box names to assembly results in the following code. This code writes the required bootstrap to $DA10, the entrance point of Wrong Pocket TM15. This area of memory is unused but is preserved during saves.
 
====English====
 
<pre>
Box 1: $DB75
C9 ret ; Safely return to normal game operation
AF xor a ; a = $00, reset carry flag
</pre>
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
===Explanation on the 0x1500 ACE setup===
84 add a, h ; af = $DA10
F5 push hl
E1 pop hl ; hl = $DA10
D6 B8 sub $B8 ; a = $22
EA A7 FB ld (.write), a
50 ld d, b
 
Box 3: $DB87
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.
85 add a, l ; a = $33
D6 F4 sub $F4 ; a = $3E
A7 and a ; Reset carry flag
D4 A7 FB call nc, .write
AF xor a ; a = $00
50 ld d, b
 
Box 4: $DB90
Relevant addresses for this explanation:
D6 FC sub $FC ; a = $04
A7 and a ; Reset carry flag
D4 A7 FB call nc, .write
AF xor a ; a = $00
AF xor a
50 ld d, b
 
Box 5: $DB99
{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
F6 D2 or $D2 ; a = $D2
! Address !! Function
D4 A7 FB call nc, .write
|-
D6 8C sub $8C ; a = $46
| $D002 || Address where the last read mail is stored.
85 add a, l ; a = $59
|-
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 6: $D8A2
* Attempting to toss 21 items will buffer $15 at $D10C.
D4 A7 FB call nc, .write
* 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.
D6 81 sub $81 ; a = $D8, carry flag set
* 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.
22 ldi (hl), a ; .write
* The last pokémon viewed is buffered from $D10E onward. Setting Tackle ($21) as its first move allows safe passage over Screech ($67).
D0 ret nc ; Skip on last pass
* 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.
E1 pop hl
* 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.
50 ld d, b
* 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 7: $D8AC
* 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.
E1 pop hl
E1 pop hl
AF xor a ; a = $00
85 add a, l
F7 rst30h ; Resume text function, immediately hit terminator
 
Box 14: displayed as screen tiles at $C4BE
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.
AF xor a ; a = $00
F6 FB or $FB ; a = $FB
F5 push af
E1 pop hl ; h = $FB
D6 86 sub $86 ; a = $75
F7 rst30h ; hl = $FB75, de = $C4C5, jump to hl
</pre>
 
====Italian & Spanish====
=Plain text transcript for codes=
 
<pre>
* Mail
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
{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
D6 B8 sub $B8 ; a = $22
! Language !! Mail content
EA A8 FB ld (.write), a
|-
85 add a, l ; a = $32
! scope="row"| English
D6 F4 sub $F4 ; a = $3E
| <pre>4 4 4 h ‘s … 5 h Pk ‘d </pre>
50 ld d, b
|-
! scope="row"| French
| <pre>4 4 4 j' ♀ é T 2 j' / é G 5 é & 5
j' à é ... 5 j' 9 é x 5 p î ... s' Pk ô </pre>
|-
! scope="row"| German
| <pre>4 4 4 H ë : é j 5 ë 9 é ... 5 p 0
0 A é T 2 $ $ ö ... 5 Pk Ä</pre>
|-
! scope="row"| Italian
| <pre>4 4 4 ° b é Ì 5 p Ù ... 5 é ] 5 0
È $ é T 2 Pk Í</pre>
|-
! scope="row"| Spanish
| <pre>4 4 4 ° b é Ì 5 p Ù ... 5 é ] 5 0
È $ é T 2 Pk Í</pre>
|-
| colspan = "2"| "..." refers to a single ellipsis character, “pk” refers to a single pk symbol.
|}
 
Box 3: $DB87
* Test box code
CD A8 FB call .write
C6 C6 add $C6 ; a = $04
CD A8 FB call .write
50 ld d, b
 
Box 4: $DB90
{| class="wikitable" style="margin-left: auto; margin-right: auto; border: none;"
C6 BF add $BF ; a = $C3
! English !! French !! German !! Italian !! Spanish
CD A8 FB call .write
|-
FB ei
| <pre>0 9 'd</pre> || <pre>A A A ô</pre> || <pre>A A A 0 9 Ä</pre> || <pre>Í</pre> || <pre>Í</pre>
C6 96 add $96 ; a = $59
|}
50 ld d, b
 
Box 5: $DB99
CD A8 FB call .write
C6 7F add $7F ; a = $D8
CD A8 FB call .write
50 ld d, b
 
Box 6: $DBA2
E1 pop hl
E1 pop hl ; Prevent side effects when returning to text printer
E1 pop hl
AF xor a ; a = $00
85 add a, l
F7 rst30h ; Resume text function, immediately hit terminator
22 ldi (hl), a ; .write
C9 ret
 
Box 14: displayed as screen tiles at $C4BE
AF xor a ; a = $00
F6 FB or $FB ; a = $FB
F5 push af
E1 pop hl ; h = $FB
D6 86 sub $86 ; a = $75
F7 rst30h ; hl = $FB75, de = $C4C5, jump to hl
</pre>
 
[[Category:Guides]]
1,540

edits

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