User:TimoVM/Korean GS TM22 ACE setup
This page serves as a repository for a fast ACE setup on the Korean versions of Gold & Silver. This guide can be performed once you reach Goldenrod City.
The initial entry point for ACE will be wrong pocket TM22. In the Korean version its effect pointer is $D0BE, which is located right before where the last viewed pokémon is buffered.
From there, we can redirect to box names and make the TM/HM pocket accessible for arbitrary ACE payloads.
PLEASE NOTE THAT THIS GUIDE IS OUTDATED. WRONG POCKET TM15 HAS AN EXECUTION POINTER AT THE SECOND CHARACTER OF BOX NAME 12, LEADING TO A SETUP WITHOUT REQUIRING ITEMS OR POKÉMON.
General overview
In this guide, we will steadily be building an advanced ACE program through the following process:
- Obtain a bad clone.
- Use the bad clone to obtain two additional bicycles. then use duplicate key items glitch to place TM22 (an ACE item) in the ball pocket.
- Use a box name code to set all TMs to x255.
- Sell TMs in specific quantities in order to write a program in the TM/HM pocket using TM quantities. This program allows you to build the full RAM writer by writing mail codes.
- Use another box name code to execute this program, which will allow us to write the full RAM writer using mail codes.
- After all mail codes are entered, execute the RAM writer. Running the RAM writer for the first time will also fix the side effects caused by Duplicate Key Item Glitch.
Alternatively, you can skip step 1 and step 2 if you have another game that already has an ACE setup. This can be done by trading two pokémon, each holding a bicycle, from the game that already has an ACE setup.
Preferably, make sure that you've used the Clear Save Data feature (press SELECT + UP + B on the title screen) at least once since owning the game. This will zero out all of the SRAM data, which is needed to create a bad clone.
Requirements for this guide
NOTE: There seems to be an issue with the VC version of Korean Gold & Silver that renders you unable to get proper bad clones through resetting the game during a save. At the moment, the only viable alternative is Hall of Fame SRAM glitch which requires beating the game without saving and after clearing the previous save with UP + SELECT + B
As an alternative, if you already have another copy of Korean Gold/Silver that already has ACE, you can trade two pokémon holding bicycles to bypass the bad clone requirement.
- The only hard requirement is reaching Goldenrod City to access the Day Care, along with having access to GoldenRod Dept. Store.
- Ensure that you catch a Wooper. (An alternative method is provided in case you missed catching a Wooper)
- When starting from a new game, it is recommended to start with the clock set on a Saturday.
- All other requirements can be obtained in the vicinity of Goldenrod City, we'll go over these in their respective parts of the guide.
Step 1: Obtaining a bad clone
A bad clone is created when you reset the game at a very specific time frame where:
- The game has saved that additional pokémon were deposited in the active box.
- The game has not yet saved the data of the deposited pokémon
In combination with the Day Care, we can turn this bad clone into a glitch pokémon that we'll be using to perform a variety of glitches.
Requirements
- A box that has never been full at any point in the past.
- Fill this box with 15 pokémon. You can use cloning glitch to obtain the required pokémon.
- A male pokémon (make sure that the species can be both male and female) that you can deposit to the PC.
Obtaining the bad clone
As mentioned previously, this method seems to only be usable on cartridge versions. For VC versions, you should obtain a bad clone through Hall of Fame SRAM glitch.
before checking bad clones in the PC, you should attempt to use a healing item (like a potion) up to where it brings up the party screen. This will prevent crashes caused by unterminated names.
- Deposit any party pokémon to the current active box.
- Go to "Move pokémon w/o mail", you will get a prompt to save the game.
- Reset the game shortly after the "saving... text is fully printed.
- If successful, upon restarting the game you will find a level 0 female version of the deposited pokémon with a glitched name. Make sure you only withdraw this pokémon to your party using "Move pokémon w/o mail" to keep it at lvl 0.
Please note that the timing of this is very strict (around frame perfect).
- If nothing was saved, the reset was too early. Wait a little bit longer to reset.
- If the pokémon was successfully cloned, the reset was too late. reset a little bit earlier.
- If the box ever gets to 19 pokémon in total, release pokémon from the box until there are only 15 pokémon present. Make sure to save normally after releasing them.
Use these guidelines and keep retrying until you've obtained a bad clone.
Step 2: Obtaining additional bicycles and getting TM22 in the ball pocket
This works in any language version on any generation 2 game, the method is based on a translation of a [blogpost from 任意コード]. When in the ball pocket, TM22 functions as a wrong pocket TM with its effect pointer at $D0BE (right before the last viewed pokémon buffer).
Requirements
Have the following items in the ball pocket:
- Slot 1: Poké Ball x3
- Slot 2: Great Ball x2
- Slot 3 and beyond: empty
Have the following items in the key item pocket:
- All key items you've obtained in your save thus far (withdraw all key items (if any) you previously stored from the PC)
- Bicycle at the bottom of the key item list
Have the following pokémon in the party:
- Bad clone
- Drowzee with Fire Punch in second move slot
- Drowzee with Fire Punch in second move slot
- Unwanted pokémon
- Unwanted pokémon
- Unwanted pokémon
(you can buy the TM for Fire Punch at the Goldenrod Dept. Store. To save on time and money, catch one Drowzee and teach it Fire Punch. Then clone it using cloning glitch)
Have the following pokémon in the box:
- 1 unwanted pokémon
- 1 normal pokémon
Keep in mind that we'll be corrupting both the Drowzees and the unwanted pokémon. Make sure to only use pokémon you do not wish to keep. The normal pokémon will not be corrupted at all during this process.
Obtaining duplicate bicycles
- Step 1: Deposit the bad clone in the daycare and retrieve it. It will now have turned into a glitch pokémon. Arrange your party as follows:
- Glitch pokémon
- Drowzee with Fire Punch in second move slot
- Drowzee with Fire Punch in second move slot
- Unwanted pokémon
- Unwanted pokémon
- Unwanted pokémon
- Step 2: Using "move pokémon w/o mail", add the stored unwanted pokémon to the top of your party.
- Step 3: Switch the party pokémon in the second slot (the glitch pokémon) with the pokémon in the fifth slot (an unwanted pokémon).
- Step 4: Select "Deposit pokémon" from the PC and deposit the top two pokémon in your hand.
- Step 5: Withdraw the normal pokémon from your box and add it to the party using "Withdraw pokémon".
The party will now contain two Drowzee that will both be holding a bicycle each. Take these held items to add them to the bottom of the Key Item list. It is now safe to save.
Obtaining TM22
Have the following items in the ball pocket:
- Slot 1: Poké Ball x3
- Slot 2: Great Ball x2
- Slot 3 and beyond: empty
- Go to the bottom of the key item list. The bottom of the list should consist of three separate bicycles.
- Press select on the second bicycle and swap it with the third bicycle. The number of bicycles will decrease, the "Cancel" button will change to a "?" item.
- Go to the ball pocket and toss 42 of the second item. The final quantity of the second item is a number ending in "3".
- Swap the second item in the ball pocket with the first item.
- Return to the Key Item pocket, press select on the upper bicycle and swap it with the bottommost item. This leaves you with a single bicycle, will turn the "?" item into a "Paralyz Heal" and change the first item of the Ball pocket into a TM22 x3. Make ABSOLUTELY sure that TM22's quantity is x3. If it is, it is now safe to save.
- Swap the TM22 to the second item slot of the ball pocket
- Make sure to keep TM22 in the second item slot of the ball pocket.
Do not worry about the glitch pokémon that's still in your party or the key item list that lacks a cancel button, we'll fix both at a later point.
Alternative step 2: obtaining TM49
For VC players who obtained their bad clones through Hall of Fame sram glitch, an easier alternative is provided with TM49 that only requires a pokémon with friendship and a few specific TMs (TM04 and TM27).
Have the following items in the ball pocket:
- Slot 1: Poké Ball x1
- Slot 2 and beyond: empty
- Go to the bottom of the key item list. The bottom of the list should consist of three separate bicycles.
- Press select on the second bicycle and swap it with the third bicycle. The number of bicycles will decrease, the "Cancel" button will change to a "?" item.
- Go to the ball pocket and toss 14 of the second item. The final quantity of the second item is a number ending in "1".
- Return to the Key Item pocket, press select on the upper bicycle and swap it with the bottommost item. This leaves you with a single bicycle, will turn the "?" item into a "Paralyz Heal" and change the first item of the Ball pocket into a TM49 x255.
Step 3: obtaining x255 of every TM
Now that we have obtained TM22 outside of the TM/HM pocket, we'll need to set up everything needed to actually safely use it. TM22's effect is to execute code starting from $D0BE, which is right before where the last viewed party pokémon's data is buffered. What we'd like to do is to redirect it such that box names get executed instead:
- Prepare a pokémon to ensure that code gets safely redirected to box names.
- Prepare specific box names that will give you x255 of all TMs, along with safely returning to normal game operation and automatically modifying the box code to redirect execution to TM quantities.
If you've obtained TM49 in the alternative step 2, make sure to follow alternative step 3 instead.
Preparing a Wooper
Follow this step if you previously obtained a TM22.
- Obtain the following TM:
- TM21 FRUSTRATION: obtain on sundays1 from the female clerk at Goldenrod Dept. Store by showing a pokémon with low friendship2.
- Teach Wooper TM21, make sure that FRUSTRATION is in the first move slot.
- Fill your party with Wooper in the first pary slot, 4 other pokémon and the glitchmon from the previous step. Make sure to place the glitchmon in the bottommost party slot3.
1 You can change the clock by using the date change exploit if necessary.
2 Buy a few Revival Herbs (Goldenrod Underground, saturday or sunday). Let Wooper faint in battle and revive it with the Revival Herbs. Repeat until friendship is low enough to obtain TM22 (fainting and reviving twice will usually suffice).
3 This pokémon is not needed for the setup, but is placed here in order to remove it from the party on first execution of the RAM writer. If you do not wish to remove it, replace with an unwanted pokémon.
Alternative step 3
Follow this step if you previously obtained a TM49.
- Obtain the following TMs:
- TM27 RETURN: obtain on sundays1 from the female clerk at Goldenrod Dept. Store by showing a pokémon with high friendship. - TM04 ROLLOUT: can be found north of Goldenrod City, on route 34.
- Store items in the PC as follows:
- Slot 1: any item - Slot 2: any item - Slot 3: any item - Slot 4: any item - Slot 5: TM04 x1 - Slot 6: TM27 x1
Now, any time you use TM49, execution will be redirected to $DA01, in the middle of box names.
1 You can change the clock by using the date change exploit if necessary.
Setting up box codes and using TM22
Now that you have set up either a party with Wooper , we'll rename box names to form a specific bit of code which we'll execute when we use TM17.
- Rename box codes according to the following table. Make sure to use the box names compatible with your language:
Box 1: 묻 붰 성 랴 갑 근 성 닥 Box 2: 꺌 근 성 박 같 근 성 섈 Box 3: 껭 근 앰 섈 갠 근 성 젬 Box 4: 겜 근 성 쵭 깝 근 성 튠 Box 5: 겊 긋 생 닥 깐 근 성 닥 Box 6: 겠 근 성 랴 깠 근 성 박 Box 7: 샘
- Next, name box 11: (space) (space) (space) (space) 꺽
- Finally, overwrite box 11: (space) (space) 샥 상
Finally, go through the following process to execute ACE:
- Save and reset the game.
- Check Wooper's summary.
- Use TM22 once. NOTE: this only works if TM22 is in the second slot of the item pocket you use it from.
If the code was executed successfully, switch to the TM/HM pocket. It should now contain every TM at a quantity of x255.
Info: What happened when TM22 was used?
Wrong pocket TM22 has its execution pointer in $D0BE, which is right before where the data of the last viewed party pokémon is stored. Before we can reach these areas there are a few values that we need to first pass through safely.
Relevant addresses | Function |
---|---|
D0BE | Address where the current selected item ID is buffered. Using TM22 stores D5 at this address. |
D0BF | Item slot of the current selected item, zero-indexed. Using TM22 from the second slot stores 01 at this address. |
D0C0 | Address where the current selected pokémon ID is buffered. viewing Wooper stores C2 at this address. |
D0C2 | Address related to the type of HP bar being displayed. Viewing a party pokémon's summary stores 01 at this address. |
D0C5 | Address where the current selected item quantity is buffered. Using TM22 with the current setup stores 03 at this address |
D0C6 and onward | Region where the last viewed party pokémon's data is buffered. Viewing Wooper's summary stores C2 00 DA at this address. |
This results in the game executing the following sequence:
D5 push de 01 C3 XX ld bc, XXC3 01 XX XX ld bc, XXXX 03 inc c C2 00 DA jp nc, DA00 ;middle of box names
The state of registers after using an item, along with the inc c opcode, ensure that the jump to DA00 is executed. This sequence does have one side effect in that de gets pushed on the stack. To ensure proper return, this value needs to be popped from the stack at some point.
We'll solve this by storing D1 (pop de) at the box code at address DA00. This guarantees that the game will safely return to normal execution without having to compromise on the box name codes since DA00 can't be directly written to using box names. Even when using another wrong pocket TM that doesn't push a value on the stack, D1 can safely be executed without causing a crash on return from box name execution.
This approach also means that it is safe to use TM22 in any context as long as we have fulfilled the three conditions:
- Viewing Wooper's summary.
- Using TM22 from the second slot of the item pocket it's located it.
- Having an additional pop instruction in the code that is being executed.
Info: assembly code of the box name code
Box 1: 04AF 053D 05EA 03DA 0109 01A9 05EA 02DA 50 Box 2: 01D7 01A9 05EA 04DA 0110 01A9 05EA 05DA 50 Box 3: 01E7 01A9 05EA 06DA 0115 01A9 05EA 07DA 50 Box 4: 0137 01A9 05EA 08DA 01C5 01A9 05EA 09DA 50 Box 5: 0132 01AF 05CD 02DA 01C1 01A9 05EA 02DA 50 Box 6: 013A 01A9 05EA 03DA 01C7 01A9 05EA 04DA 50 Box 7: 05C9 00 Box 11: 0BFF 0BFF 05D1 05C3 50D9 50
summary: jump to the start of box names. rewrite $DA02-$DA09 with a short sequence to call ByteFill to fill all 50 TM quantities with $FF values, then execute this sequence. Afterwards, rewrite box name 11 to set register a to $04 (required for the mail writer) and jump to the start of the TM/HM pocket.
A note on this box code
The above box code doesn't just set all TMs to x255, it also automatically alters the name of box 11 so that using TM22 will execute TM quantities from the TM/HM pocket instead. For this guide, we won't be needing to reset TM quantities to x255.
If you do wish to reset all TM quantities, simply reset the name of box 11 in the following manner:
- Name box 11: (space) (space) (space) 꺽
- Overwrite box 11: (space) (space) 상
What to do now you have 255 of every TM
At this moment, there are two main options.
- You can use the quantities in the TM/HM pocket to install a mail writer, which allows for easy installation and execution of other payloads.
- You can continue with the guide and build a RAM writer in order to achieve near-complete ACE control.
Step 4: Selling TMs to form a program in the TM/HM pocket
Now that we have obtained x255 of every TM, we'll be selling specific amounts of these in order to form a program. This program differs slightly depending on the specific language you're using. The following table displays how many TMs of each kind you need to end up with, along with the amount of money you gain by selling them.
language independent TMs
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 |
Running the newly written program
- Save and reset the game.
- Check Wooper's summary.
- Use TM22 while it's in the second item slot, this will start the mail writer and open a screen asking you to input text for a mail.
Info: assembly code of the mail writer
11 52 DE ld de, DE52 D5 push de D5 push de .loop D5 push de 21 D9 60 ld hl, ComposeMailMessage CF Farcall ;requires a = $04 to load correct ROM bank E1 pop hl D1 pop de 2A ldi a, (hl) .not@ FE 50 cp @ 30 09 jp nc, .@? ;jump if next char is a terminator/line skip 96 sub (hl) 96 sub (hl) 12 ld (de), a 13 inc de 81 add c 4F ld c, a 12 ld (de), a 2A ldi a, (hl) B4 or h 20 F0 jr nz, .not@ .@ ; jump if char is not a terminator 21 01 C4 ld hl, C401 .noInput 4D ld c, l CD CE 3A call PrintBCDNumber.loop 1B dec DE .DownPressed CD 79 37 call JoyTextDelay_ForcehJoyDown F0 AB ldh a, (hJoyLast) BD cp l ; due to PrintBCDNumber, l = $04 28 D8 jr z, .loop ; jump if a = $04 38 EE jr c, .noInput 07 rrca D0 ret nc 18 F1 jr .DownPressed
Step 5: Using the mail writer
The mail writer will open a screen that asks you to write the contents of a mail. This is where you'll need to enter mail codes. Once done, use the "END" option to finish the mail.
This will cause the mail writer to convert the newly written code into assembly. It will also print a checksum (sum of all written values) on the screen just to the right of the lower row. This can be used to verify if a code was entered correctly.
Controls
Between entering mail codes, the mail writer will ask for user input.
- Press SELECT to open a new mail and continue writing data.
- Press DOWN 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.
- Press any other button to immediately jump to and start executing the newly written program. Only use this when you've finished every mail.
Enter your mail code, then press "END". | It prints the checksum and waits for input. |
Building the full RAM writer
We will be installing the full RAM writer using a series of mail codes. These mail codes will be assembled using Scotteh's mail code tool. Copy paste the entire code in the text box on the mail code tool's page, change the language to Korean, then press "Run".
3E 03 CD 7A 31 01 CD 00 11 E1 B9 21 87 DE CD C2 31 0E 1A 11 D2 D6 D5 CD C2 31 0E 24 11 CD D4 CD C2 31 21 94 D6 34 4E 09 3E F1 22 3E FF 22 21 1F DB 35 C0 34 C9 AF 3C E0 D6 21 00 DA CD 40 CF E5 11 F8 FF 19 54 5D 01 0C 00 F0 FE 21 A9 C3 CD 7A 31 CD 6C CC 3E 7C 22 7A CD 6C CC 7B CD 6C CC 3E E3 22 1A CD 6C CC 36 7C 09 13 7D FE 13 20 E5 CD 94 31 21 50 C4 36 ED E1 18 C2 F5 CB 37 CD 73 CC F1 E6 0F C6 F6 F6 80 22 C9 CD 79 37 11 00 00 F0 AB 07 30 01 13 07 30 01 1B 07 30 03 11 F0 FF 07 30 02 1E 10 07 C9 CD 7B CC 38 41 07 30 0B 07 07 30 01 E9 F0 FE 83 E0 FE C9 07 30 03 53 1E 00 19 07 30 2A E5 F0 FE CD 7A 31 46 CD 7B CC 07 07 30 01 43 07 38 0E 78 83 47 21 50 C4 36 EC 23 CD 6C CC 18 E7 E1 70 E5 3E 05 21 FD 4D CF E1 C9 FE F1 C0 FA 92 CE FE C0 C0 3E 0D EA B5 CE C9 FA 80 CE 18 5B 3E 03 CD 7A 31 AF 21 EB CC 16 12 1E 09 0E 0B 22 1D 20 FC 09 15 20 F4 C3 CD D4 0E 71 11 27 CC D5 21 E1 B9 CD C2 31 0E 48 11 40 CF CD C2 31 0E 0F 11 EF FF CD C2 31 0E 05 11 89 FF C3 C2 31 |
After you press run, the tool will generate the mail codes that you need to enter in the mail writer.
After entering every code, a new number will appear to the right of the bottom mail row. This is a checksum and is used to verify that you've correctly entered every mail. If a checksum doesn't match the one given by the tool, that means that a code was incorrectly entered, meaning you will need to redo your mail by pressing DOWN enough times (16 times if you’ve entered a full mail code) to return to the starting byte of the last mail, then entering that same mail again.
After you're finished entering all mail codes, you can press START during the user input phase in order to start up the full RAM writer.
Using the full RAM writer
After you're finished and have verified that all checksums were valid, press any button outside of A, B or DOWN during the user input phase in order to start up the full RAM writer.
Doing this will activate the following effects:
- Save the RAM writer to the contents of box 14.
- Add TM49 to the key item pocket, along with restoring the cancel button.
- Install setup to make sure that using TM49 from the item pack will start the RAM writer.
- Remove the last pokémon in your party (except if you only have one pokémon left in your party)
- Automatically start the RAM writer.
Starting the RAM writer, either automatically or through using wrong pocket TM49, will activate the following effects:
- Copy the necessary data to memory to activate the RAM writer.
- Make the necessary modifications to screen data to properly display the RAM writer.
- Deploy OAM DMA hijack that will enable the use of TM49 during battle.
- Start the RAM writer.
After the full RAM writer has successfully started, press START to quit the RAM writer and make sure to save your game.
After exiting the RAM writer, you can restart the RAM writer by using TM33 from the item pack. In battle, you can activate the RAM writer by using TM33 and selecting "QUIT". Please note that the setup to enable the use of TM33 during battle does not persist between resets, you can reenable this function by using the RAM writer outside of battle at least once.
As you can see in the screenshots below, the RAM writer will draw various values on the screen. The leftmost 4 columns describe the addresses that are currently in view. The rightmost two columns describe the values at each of these addresses. All values on screen are represented in hexadecimal format.
For example: DA01>05 means that the address $DA01 is currently holding the value of $05.
Let's go over the controls of the full RAM writer. By default, the RAM writer will open in Read mode.
Full Writer Controls
The RAM writer uses two modes of operation. In Read mode you are able to navigate memory and view the values at specific addresses. in Write mode you'll lock in a single address and manipulate the value at that address.
RAM writer in Read mode | RAM writer in Write mode. |
Read mode controls
up: address -1 down: address +1 left: address -10 right: address +10 B + up: address -1 B + down: address +1 B + left: address -10 B + right: address +10 start: exit program A: toggle write mode select + up: sram bank -1 select + down: sram bank +1 select + left: sram bank -10 select + right: sram bank +10 select + A: start executing code from current address onwards (use with caution!)
Write mode controls
up: value -1 down: value +1 left: value -10 right: value +10 B: set current value to 0 A: exit write mode and load final value into the address