The "(Enemy) learned " effect.
Posted by: Spoink
Date: 2016-06-25 19:17:12
[youtube]https://www.youtube.com/watch?v=njs98Ulf7gc[/youtube]
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.
I think this may be related to the sound bank addresses C0EF, C0F0 becoming corrupted (corrupted by the decompression of the glitch Pokémon's sprite). When experimenting with the "stable unstable" Missingno. trick (the first unstable Missingno. you encounter is believed to never freeze the game unless you encounter further), I noticed that a value of 01 would give a "learned"/"trying to learn" effect.
What I want to know is why and how this occurs, as well as where the name comes from. I know the stack pointer decreases significantly for every textbox. Here is the video:
[youtube]https://www.youtube.com/watch?v=njs98Ulf7gc[/youtube]
I think this may be related to the sound bank addresses C0EF, C0F0 becoming corrupted (corrupted by the decompression of the glitch Pokémon's sprite). When experimenting with the "stable unstable" Missingno. trick (the first unstable Missingno. you encounter is believed to never freeze the game unless you encounter further), I noticed that a value of 01 would give a "learned"/"trying to learn" effect.
So you mean it's corrupted to a infinite 01 loop?
It corrupted the enemy Pokemon value?
I think this may be related to the sound bank addresses C0EF, C0F0 becoming corrupted (corrupted by the decompression of the glitch Pokémon's sprite). When experimenting with the "stable unstable" Missingno. trick (the first unstable Missingno. you encounter is believed to never freeze the game unless you encounter further), I noticed that a value of 01 would give a "learned"/"trying to learn" effect.
So you mean it's corrupted to a infinite 01 loop?
It corrupted the enemy Pokemon value?
It can get changed to 01 but I don't know if it is an infinite loop, and if you put a halt to the message you may be able to return the sound banks to normal. The sprite decompression causes corruption of the memory, so one of the C0EF/C0F0 (sound bank) addresses may have been corrupted to 01.
All tunes in the game use sound banks: 02 (overworld music), 08 (battle music) 1F (dungeon music) and 20 in English Yellow/28 in Japanese Yellow (special music). But bank 01 is invalid and can lead to the game executing the "learned"/"trying to learn" message for unknown reasons. When some people try the 0120EFC0 0120F0C0 019F5AD3 code to play the Pokémon Yellow unused track, the nurse in the Pokémon Center can disappear and it seems the cause is related to the sound bank being forced to 20 where there are limited valid sounds.
I don't know if invalid sprites can corrupt the enemy Pokémon, except possibly Missingno. in Japanese Yellow who can turn the battle into a Trainer battle if I remember correctly (but I may be wrong).
That's right. You can access 256 with the code 01xxEFC0, 01xxF0C0. I don't know if any are effectively duplicates, however.
Sometimes these invalid sound banks will cause the game to freeze.
It actually takes the back sprite from 0xFAC9, which is in RAM. It reads this, and draws too many bytes, corrupting some stuff, and then… I don't know.
Nice~
I accidentally found the answer while investigating the behavior of glitch sound banks.
It is known that encountering unstable Missingno. on Yellow will corrupt sound-related RAM. The "(Enemy) learned"/"(Enemy) is trying to learn" effect occurs if the current sound bank at $C0EF gets corrupted to the value 0x01. Being more exact, the effect activates when the game tries to play any sound from this invalid sound bank.
Sound banks are essentially ROM banks. Before playing a sound, the game switches to the appropriate ROM bank to play the sound from there. Every sound bank has its own handler - a piece of code which tells the game how to actually play the sounds. The game runs through a long list of comparisons to see which bank is currently loaded and execute the correct handler.
Because the programmers never accounted for sound banks other than 0x02, 0x08, 0x0F or 0x20, the game will jump to $6BD4 every time a sound is played from a bank other than 0x02, 0x08 or 0x0F:
[tt]; check if current bank is 02
cp $2
jr nz, .checkForBank08
(…)
.checkForBank08
; check if current bank is 08
cp $8
jr nz, .checkForBank1F
(…)
.checkForBank1F
; check if current bank is 1F
cp $1F
jr nz, .bank20
(…)
; if we got here, the current bank must be 20… right?
.bank20
ld a, b
call Handler_6BD4[/tt]
This causes the game to execute code at $6BD4 every time a sound from an invalid sound bank is played.
What is at this address? It depends on the loaded ROM bank, which depends on the loaded sound bank. It just so happens $6BD4 at ROM bank 0x01 will land in the middle of the LearnMove subroutine:
[tt]LearnMove:
call SaveScreenTilesToBuffer1
ld a, [wWhichPokemon]
ld hl, wPartyMonNicks
call GetPartyMonName
; 6BD4 is here
ld hl, wcd6d
ld de, wLearnMoveMonName
ld bc, NAME_LENGTH
call CopyData
(…)[/tt]
And suddenly, the game will attempt to teach a move!
The move name will depend on the last string loaded into memory, which can be an item (MISSINGNO. learned POTION), a move (MISSINGNO. learned HYPER BEAM), a Pokemon (MISSINGNO. learned CHARIZARD), player's name or rival's name (MISSINGNO. learned ASSFART).
The Pokemon that the move is taught to depends on the wWhichPokemon address ($CF91). The subroutine which calculates poison damage in the overworld (which runs every 4 steps) changes this address, and sets it to the last Pokemon it considered. So, most likely, if you don't go out of your way to manipulate this value, the game will actually attempt to teach a move to the last Pokemon in the player's party.
Which textbox is displayed depends on whether the player's last party Pokemon already has 4 moves ("trying to learn" text) or has less than 4 moves ("learned" text).
Trying to click through the textbox will play a sound, which will trigger another textbox, since the invalid sound bank is still loaded. This causes the game to fall into an infinite loop. After clicking through a lot of textboxes, the stack will eventually overflow, and the game will crash.
TheZZAZZGlitch, did you investigate what code other banks yield ? Otherwise, it might be cool to write a tool that looks through ROM to find whether or not we get cool instructions… and, hopefully, a jp / call somewhere in RAM ?