Glitch City Laboratories Archives

Glitch City Laboratories closed on 1 September 2020 (announcement). This is an archived copy of a thread from Glitch City Laboratories Forums.

You can join Glitch City Research Institute to ask questions or discuss current developments.

You may also download the archive of this forum in .tar.gz, .sql.gz, or .sqlite.gz formats.

Generation I Glitch Discussion

CoolTrainer (and non hex:00 Super Glitch) yields documentation thread - Page 3

Re: CoolTrainer (and non hex:00 Super Glitch) yields documentation thread

Posted by: Torchickens
Date: 2015-05-21 12:33:56
I'm not sure. Yeah, if a Yellow user cannot use CoolTrainer; then their only options other than save corruption glitch to activate arbitrary code or get 255 items without GameShark might be the Cable Club escape glitch with Missingno. (using the Safari Zone glitch to escape instead of Poison) or without linking Pikachu off-screen glitch arbitrary code, which is a pain to set up as it stands.

You're right; there are a selection of sources; however, I don't know what determines the selection. At the moment for me on a save that won't work (link) the source is always around D2A5 and since this is Trainer name for party Pokémon data there would be 0x50 here. So if the source is not going to change you would have to use arbitrary code execution or maybe get over six Pokémon and swap some with un-terminated names up (with Q above to prevent a freeze) to get it to work.

In BGB, if you set a breakpoint on write to CD6D via Debug>Access breakpoints; you can see that hl is copied into CD6D (where CD6D is 'de'); and this way you can check the source of the name each time.

I got a different selection of hl pointers for another save where the glitch works.

I think it's important to know, so I have just asked TheZZAZZGlitch on Youtube if he can look into where the pointer comes from.

Re: CoolTrainer (and non hex:00 Super Glitch) yields documentation thread

Posted by: Krys3000
Date: 2015-05-22 05:03:57
Alright ! Let me know if he gets something.

I honestly forgot about that cable club glitch, yes it's a good solution. However I did not know that new arbitrary code execution method in yellow using pikachu. You publish too many videos for me to have the time to watch them all  :P it's a very interesting glitch, I hope I will have the time to work on it soon so I could add it to PRAMA.

Thanks again !

Re: CoolTrainer (and non hex:00 Super Glitch) yields documentation thread

Posted by: TheZZAZZGlitch
Date: 2015-05-23 10:38:01
I think it's important to know, so I have just asked TheZZAZZGlitch on Youtube if he can look into where the pointer comes from.


I decided to leave my answer here, since it may be useful for some people.

Move name table in Gen I has an unusual structure - instead of using fixed-width fields (which would have been a lot more stable), programmers decided to store move names one after another, separated with an end string character (0x50):
[tt]
004000  8F 8E 94 8D 83 50 8A 80 91 80 93 84 7F 82 87 8E  POUND#KARATE CHO
004010  8F 50 83 8E 94 81 8B 84 92 8B 80 8F 50 82 8E 8C  P#DOUBLESLAP#COM
004020  84 93 7F 8F 94 8D 82 87 50 8C 84 86 80 7F 8F 94  ET PUNCH#MEGA PU
004030  8D 82 87 50 8F 80 98 7F 83 80 98 50 85 88 91 84  NCH#PAY DAY#FIRE 
[/tt]
To get the name pointer for a move with index number X, the game finds the Xth 0x50 character starting from address $4000 (this is where the table is loaded during the process), and returns the address to the string that's located before it.

So for move 0x01, it returns $4000, for move 0x02 returns $4006, etc.
It works OK, until we try to get the name pointer for an out of bounds move, be it Super Glitch or Cooltrainer. Cooltrainer move is index 0x00, but because a standard "subtract one, check if zero" loop is used in the subroutine, the move index that the procedure actually searches for is 256.

The last valid move, with index number 0xA5, is Struggle. After that, the entire ROM page is filled with 0x00 bytes:
[tt]
004600  88 93 94 93 84 50 92 93 91 94 86 86 8B 84 50 00  ITUTE#STRUGGLE#.
004610  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  …………….
*snip*
007FF0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  …………….
[/tt]

We can already predict that the Super Glitch move 0xA6 will have it's name pointer at $460F, right after Struggle. This makes 0xA6 the only Super Glitch move that will cause memory corruption every time, since its name points to a constant ROM location.

If the index number is greater than 0xA6, we enter the territory of undefined behavior. The entire memory space following the ROM sections (VRAM, SRAM, WRAM in order) will be searched as if it was the move name table. Where the pointer lands is dependent on the number of 0x50 bytes in the RAM.

Our journey starts at VRAM. On real console it would be very unlikely to find too many 0x50 characters there, because VRAM is only accessible for short periods of time (during the vBlank interrupt to be exact) and any attempt of blindly reading VRAM contents will most commonly return a 0xFF byte, regardless of what is actually there.

Older versions of VBA do not emulate VRAM inaccessiblity, so on VBA move 0xA7's name is "qq", because of this pattern in VRAM at address $83C5:
[tt]
0083C0  00 00 E0 E0 50 B0 B0 50 58 A8 AC 54 56 AA 0E F6 …
        ————– ******** —————————
        0xA6's name    0xA7's  0xA8's name
                      name
[/tt]

On BGB (and real console), the finishing 0x50 byte at $83C7 is not read, causing Super Glitch effects:

[img]http://i.imgur.com/6OPqcFH.png[/img]

Besides 0xA7, almost no moves have their pointers in VRAM, since most of the bytes in VRAM are read as 0xFF.

From now on, I will be specifically focusing on Cooltrainer move's name pointer, and how to predict its location.

Next, the search passes through SRAM. In battle, this block of memory is used to decompress sprites. So where the search ends is also slightly determined by the opposing Pokemon's sprite. This is why Cooltrainer sometimes does not work against a specific Pokemon, but happens to work in a different battle against a different Pokemon.

The biggest influence on Cooltrainer's name pointer comes from the game's RAM, and the number of 0x50 bytes in there. Statistically, the search has the biggest chance of stopping in a RAM block which contains a lot of text strings, as every text string in RAM has to end with a 0x50. This explains why Cooltrainer move's name pointer often lands in memory blocks responsible for storing Pokemon or trainer names. Probably the biggest memory block with lots of text strings is $DD00 - $DF00, which contains nicknames and OT names for Pokemon in the current PC box. Which is why I suggest changing around the PC box if the Cooltrainer move does not work.

Of course, every action which will lead to increasing/decreasing the number of 0x50 bytes in memory will change the name pointer and increase the likelyhood of the Cooltrainer move working. You could fill your inventory with Ethers x80, have a full team of level 80 Slowbros, give all your Pokemon 10-letter names, and so on.

Because the memory blocks at $D300 and $DD00 have the biggest concentration of 0x50 bytes, the name pointer will probably land between those two locations. Here are some ways to predict and control where the pointer will land (note that this is all derived from fuzzy logic and may not apply every time):

- If you didn't ever nickname any Pokemon in your party, the pointer will probably be at your party Pokemon data. If the Pokemon is never nicknamed, its name is fully padded with 0x50 bytes to 10 characters (unnamed MEW is in fact named "MEW[x50][x50][x50][x50][x50][x50][x50]"), and the excess 0x50 characters cause the name pointer search to end earlier. If you nicknamed all Pokemon in your party, the pointer will probably be at boxed Pokemon data.

- If you fought a trainer before encountering a wild Pokemon, the pointer will probably land somewhere between $D900 - $DB00. This is because in a trainer battle addresses $D9AC - $DA2F are populated with Pokemon names and trainer names, increasing the number of 0x50 characters between $D300 and $DD00.

- If you want the Cooltrainer move memory corruption to work, my idea is: fill your box with a good amount of hex 0x50 Missingnos, and give a nickname to all Pokemon in your party. Hopefully the name pointer will then land somewhere in the $DA00 range, and then the 0x50 characters are separated from each other by 20 bytes, so the invalid name doesn't get terminated too early.

- Another (way easier) way would be renaming all Pokemon in your party, and switching your box to an empty, never used one. This will cause the pointer to slide all the way down to echo RAM ($E000+).

To see how the name pointer behaves, I wrote a small LUA script for use on VBA. It calculates the name pointer for the Cooltrainer move and displays it to the screen every frame. I included it as an attachment.

Re: CoolTrainer (and non hex:00 Super Glitch) yields documentation thread

Posted by: Torchickens
Date: 2015-05-23 12:11:07

Alright ! Let me know if he gets something.

I honestly forgot about that cable club glitch, yes it's a good solution. However I did not know that new arbitrary code execution method in yellow using pikachu. You publish too many videos for me to have the time to watch them all  :P it's a very interesting glitch, I hope I will have the time to work on it soon so I could add it to PRAMA.

Thanks again !


You're welcome. I wish you good luck for when you get around to it.

TheZZAZZGlitch: Thank you very much. That looks very helpful.

Re: CoolTrainer (and non hex:00 Super Glitch) yields documentation thread

Posted by: Crystal_
Date: 2015-05-24 04:19:25
Next, the search passes through SRAM. In battle, this block of memory is used to decompress sprites. So where the search ends is also slightly determined by the opposing Pokemon's sprite. This is why Cooltrainer sometimes does not work against a specific Pokemon, but happens to work in a different battle against a different Pokemon.


Wouldn't the SRAM be closed (i.e. 0xFF) when you are attempting to use/view cooltrainer's name?

Re: CoolTrainer (and non hex:00 Super Glitch) yields documentation thread

Posted by: Krys3000
Date: 2015-05-24 06:50:48
Hello TheZZAZZGlitch !

Thank you for those very clear explanations. I now understand well how the glitch works, and how to maximize the chances to make it work.

If it's ok for you, I'd like to publish your script on the article I am currently writing for my website (http://prama-initiative.com/). I think it might help the readers to understand where the problem is, if they couldn't get the corruption to occur. :)