I suppose I should continue what I started now right on the point where I made some pretty big changes, make sure to read my last blog entry for the introduction of what I've started.
Last time, I left off on making a set of inputs to beat pokemon yellow in a very short time with some heavy glitches, but I did not go into any detail as to what I was actually doing, so let me do that now.
To quickly go back to the basics, the idea is to glitch out the game to gain access to a very glitched shop, this allows you to "buy" a glitch item which can be used to essentially break free of the item menu list size and just scroll down further into other parts of the games memory. Last time from there I then just modified the exit location when you exit the shop to not lead back into the town but instead lead into the hall of fame, which is the end of the game. That is all simple enough really but I wanted to much more.
At this point I was pretty close to run my own code as this broken item menu list gave a huge chunk of memory to modify, and one particular bit was the one I ended up attacking - the current map script.
This particular bit of memory points to some code that gets executed every other frame as part of whatever map you are currently in, to control all the events that happen in it. Now my idea here was to modify this to instead point to some bit of code that I can control freely - all the extra memory I can control from the item menu to be exact. To get some code into that memory though I needed to do a bit more setup, and the easiest thing I saw was to modify the rival name at the beginning of the game. You see, that name is stored right below the normal item list, so also part of what we can modify!
The thing with the item menu is that all you really do is modify 2 bytes at a time, the first byte is the item id, and the second the item quantity. All you can do with that is swap 2 byte stacks around, or subtract parts of the 2nd byte, if the item id allows to be tossed. This is often not the case and as we will learn later lead to me having to come up with some unplanned workarounds.
Because the easily controllable area - the rival name - is pretty short, not a whole lot of room for code, I decided to keep it very simple. My idea was to just read out whatever buttons are currently held on the "controller" (my inputs in an emulator), then write that byte into parts of the item menu I can control and open the start menu again so I can move that newly created bit out of the way to create another bit.
The rival name is also pretty limited on its own, you cannot create any byte below 0x7F, and also from 0x80 and up you cannot choose every single byte either, so I had to get creative. The bit of code I came up with is this:
That really is how vague my notes are, I know it does not really say anything so let me explain as to what I planned here.
The first byte, F0, is easily created by just taking a bit of empty memory, 00 00, and in the item menu "throwing" parts of it away, so this allows you to basically make anything from 00 01 up to 00 FF, so making 00 F0 was easy enough.
F5 is a valid character byte you can use in the rival name, it is "♀", so thats byte number 2.
For EA I then just took the next highest possible byte I can use for the rival name, thats "♂" which has a value of EF.
Because I now had the "item" F5 EF I can just throw some from it away in the item menu to get F5 EA.
Next up is storage, and for this I as you can see was not quite sure at first what I wanted to do, but decided to go with a huge chunk of memory very low in the item menu that was empty, in this case address D3E6. The nice thing here is how addresses are stored, you see, D3 is not a character you can use for the rival name but addresses are stored with the lower byte first and the higher second, so its stored as E6 D3. E6 just so happens to be a valid character for the rival name, "?", so I just used 2 of them to get E6 E6 and threw some of the second byte away to get E6 D3.
C3 is again not a valid character but I used a simple " " in the rival name, which is 7F, this instruction basically translates into a "do nothing" processor instruction so it made for good filler. My next character then was again, you guessed it, "?" for E6, so I could throw that away to get 7F C3.
Now 94 is also a valid character, its just a "U", so I used that, that was followed by an "end" byte, 50, so my plan was to then throw some away to get 94 02. Spoiler, this ended up not being possible because 94 just so happens to be one of those items I mentioned you cannot throw away.
Anyways, with this name I set out to start glitching:
Warning: Spoilers inside!
From this point, the game just goes on up to the point where I can finally glitch the item menu and I throw everything away and then realize, oh no, I cannot throw away the "U". This led to some questionable solution of literally selling RAM to the shop keeper. You see one of the "items" I found deep in the item menu could be sold for 9350, and the money count is within the item menu reach to modify, so I just put in a bit of free memory, 00 00 into the spot and threw some of it away to get 00 52, and then sold part of game RAM to add up to get 94 02, the instruction I originally planned to have.
So now I have some code ready, but how do I execute it? Well, in memory there was some bytes, I think it was F6 FF or something like that, well I ended up throwing enough away to get F6 D3, or in other words address D3F6, parts of memory I could modify, and moved my now built bit of code into that memory location, and then lastly replacing the current map script with that new pointer to D3F6.
So great, now I can unpause and whatever buttons were held get written to D3E6, why is that so helpful? Well I can now just always move a empty bit of memory, 00 00 into place, throw away whatever I need to get anything from 00 01 to 00 FF and when I unpause it writes the held buttons over the first 00, essentially allowing me to make any 2 bytes I want! You see, there are 8 total inputs, making up 8 bits, or in other words, 1 byte.
With this power I now was able to very slowly get more code into the game, and I made up this:
So to start with D3D1, this is basically my current "work byte" which I start with AF, it takes the base address D600 and adds that on top of it, so in this example, D6AF, then saves whatever button inputs are pressed into that and subtracts 1 from that work byte. In case you dont see whats so cool about that is that the next time I unpause it will then write to D6AE, then D6AD and so on, allowing me to really starting writing a lot in bulk.Warning: Spoilers inside!
Also after that I end up with some code opening the start menu again, but not in quite the same way as the first code did it, because I noticed that way actually crashes the game after a certain amount of pauses because of a memory corruption, so I have to add 6 to the stack before jumping to the start menu function, resulting in the last few bytes after EA D1 D3 being E8 06 C3 FD D3, basically add 6 to stack and jump to D3FD which is just the jump to the start menu from the first bit of code again that was still left over.
So now, after all that work that takes minutes and minutes to execute because the item menu moves so slow, I can now write into whatever bit of memory I want and write whatever values I want into it, all that now was left to do is generate a jump to this newly saved code at D3D2 by generating a D2 D3 "item" with the first bit of code and moving it over the map script again, before moving it over though also generate another item that THEN can jump to the big code I just wrote, in this case I generated 20 D6, which jumps to D620, meaning I have D620 up to D6AF to write whatever I want into that then gets executed.
With all that work, what did I end up writing into there? Well, I really did not have any full plan at this point, so all I did was open up a text box with some text I wrote and playing some background music track, just to have a visual confirmation that hey, all this crazy setup actually worked. All that ended up becoming this youtube video:
...and thats all for part 2! Yes, I know, I STILL have to get to actually dumping gameboy games, but that will be done in the next part, because I am still not fully done with everything for that for a proper release, thanks for reading.
You need to be logged in to comment