My Glitched Jolteon

Screenshot - Jolteon's stats, with the 'IDNo/' label, 'OT/' label, and OT name missing.

On my old Yellow version save file - the one I loved, the one I started shortly after beating the game for the first time when I was ten years old because I didn't know you could just continue after beating the Champion - I had a glitched Jolteon.

Specifically, when you tried to view his stats, the screen would just go blank. It really freaked me out the first time it happened; I thought the game had crashed somehow. But when I pressed A after that, the stats did appear - only some of what was meant to be on the status screen was missing. (In particular I remember vividly that the IDNo/ and OT/ labels were missing.) The second status page was perfectly normal. This happened consistently, exactly like this, every time I viewed this one Pokémon's stats. There was nothing wrong with any other Pokémon I had, or anything else on the game, and in every other respect he was just a normal Jolteon. But he was glitched, so he was different, so he was awesome.

Jolteon hadn't been one of my original team members on that save file. But after beating the Champion (by this time I knew I could continue afterwards), I had set about training up other Pokémon off my PC, both to complete my Pokédex and just for fun, and one day I took out my Eevee, the one I'd gotten from Celadon Mansion during my playthrough. I'm pretty sure I discovered the glitch the first time I viewed his stats after withdrawing him. I remember being torn about evolving him; I had the thought that maybe evolving him would fix him, reset whatever was going on, and while on the one hand I didn't want this weird glitch to mess up my game somehow, on the other hand this was something weird and unique and kind of cool. But as luck would have it, he stayed exactly as glitched after I’d used the Thunderstone. If not for the glitch, I would probably have just put him back on the PC after training him up to catch up with my team at the time, like all the other Pokémon around that time that I trained to high levels just because I felt like it. But as it was, Jolteon was special, so I just had to keep him on, even though having a second Electric-type alongside my Pikachu was kind of redundant. He became a permanent team member, and I showed him off to anyone who would care (mostly my cousins).

I never knew why my Jolteon was glitched. It was a genuine cartridge, bought new, and I'd never used a cheating device or exploited glitches of any kind. (One time, I'd attempted to perform the classic Old Man Missingno. trick after reading about it online - but of course it hadn't worked, much to my disappointment, because I was playing Yellow, which had fixed that particular glitch.) At the time, I only had the vaguest idea of a "glitch" as being when something just randomly happened wrong on the game; I didn't question what was actually going on here that was making this consistently happen for this one Jolteon, and I didn't have the knowledge or mental capacity to properly assess exactly how weird it was. For all I knew, maybe this just happened sometimes.

In 2003, when I was thirteen, I let a visiting cousin from Denmark play my Yellow version for a bit, and she started a new game and saved. (It wasn't really her fault - she had little reason to know that an innocuous-looking menu option in an unfamiliar game would just delete my own progress with little warning, and I sort of realized that but didn't know how to communicate that to her with my limited Danish.) I was absolutely devastated - for all the hundreds upon hundreds of hours I'd sunk into it, completing my Pokédex and training up so many Pokémon, but mostly because I was very emotionally attached to my team: the Pikachu that I'd trained to level 100 (I'd done it in a frantic, desperate bid to make him happy again after I'd deposited him on the PC once to try a dumb rumour about how you could get into Bill's secret garden if you had six specific Pokémon in your party), the Charizard that had made me love Charizard, Blastoise, Pidgeot, Dragonite - and, of course, my glitched Jolteon. When it happened, I'd been in the process of training up the rest of the team to level 100 through repeated rounds through the Elite Four, but they never made it there. In the intense way that only kids can feel, it was like losing friends.

After a while, I started a new file and tried my best to recreate my old save: I named myself TRAINER (something I'd done when I was ten because it felt more official, somehow), I caught the same Pokémon, I put together the same team as before. I got Eevee from the Celadon Mansion with bated breath: maybe some sort of production error on my cartridge meant that the Celadon Eevee would always have the same glitch? But no: my new Eevee was just a normal Eevee. In a very definitive, tangible way, it would never be the same.

Back then, I mainly just grieved my lost partner. The glitch only mattered because it had made him special. But years later, by the time I had a degree in computer science and had personally dug into some of the games' programming, my thoughts began to wander back to my Jolteon. Glitches in video games aren't just something being weird at random by magic: there had to be a concrete explanation for what was happening there. And yet, in all those years since, as fans discovered and documented everything from exactly why Missingno. has the stats it does to ways to completely break the game and make it blissfully execute arbitrary code, I had never, ever seen another person describe the same glitch that had happened with my Jolteon or anything like it. I knew it was real - it wasn't something that'd happened once that I could have been dreaming or imagining, but something that had happened consistently, every time - but now I didn't have that save anymore to verify it, or even so much as a video of it (video recording devices weren't anywhere near as ubiquitous back in the early 2000s as they are today).

I burned with curiosity: what was actually wrong with my Jolteon? Why would it cause these weirdly specific effects? I made a post about it on my Tumblr in 2015, and at some point I went and dug through the pret disassembly of the Pokémon status screen code (effectively a recreation of what the the original source code might have looked like, based on the published cartridge, that functions identically to the real thing), just to see if anything stuck out to me that might explain it. But nothing really did, and I ended up giving up on that line of inquiry and moving on to other things.

Investigating the Glitch

Eventually, in early 2024, I happened to go on a big nostalgia binge about the first-generation games and their glitches, and once again I thought of Jolteon, this time from a slightly different angle. Since the glitch happened consistently to Jolteon and only Jolteon, there had to be something unusual in Jolteon's data structure. Pokémon data structures in the Game Boy games were simple, small pieces of data, just 64 bytes total per Pokémon, with each of those bytes designated to hold a particular piece of information about that Pokémon: stuff like current stats, IVs, stat experience, species, moves, nickname, ID number and original trainer. Something must have happened to one or more of those bytes, somehow - something that had caused this, but hadn't caused anything else weird.

And how could something have happened to my Jolteon that seemingly had never happened to anyone else's Pokémon, as far as I'd heard anywhere on the internet, in the twenty-plus years since? It probably wasn't some kind of thing I'd inadvertently done in-game to cause it - I'd never toyed around with memory corruption or anything of the like, and if it had just been something I'd done by accident during normal gameplay, surely other people would have bumped into and described this issue over the years. Instead, my thoughts began to drift to a rare kind of glitch, where a cell in a memory chip erroneously flips from 0 to 1 or vice versa due to one-off hardware interactions, such as from charged particles set off by cosmic rays. What if what had happened to my Jolteon was unique because it really was caused by a one in a million sort of event - something like a charged particle that happened to hit the bit of memory storing the Pokémon on my PC in just the right place?

This was just speculation, but it gave me a theoretical place to start: a brute-force approach could be to just take a regular Jolteon and see what would happen if I flipped a bit at a time, emulating the hypothetical cosmic ray bit flip. In 2023, I had bought a device to back up my Game Boy saves, so I had my new Yellow save (the one I'd started in 2003) with my new, regular Jolteon on my computer, where I could load it up in an emulator with debugging features that would let me override individual bytes in memory on the fly.

Something else I realized, once I was actually looking at the Pokémon data structure organization, was that the brute-force approach would be overkill. It was actually fairly easy to rule out, or just about rule out, that Jolteon had had weird bit flips in most of the Pokémon data fields. For instance, if there'd been a bit flip in his species number - well, then he wouldn't have been a Jolteon; either he'd have just turned into a different valid Pokémon, or into a glitch species. That obviously wasn't what had happened. The level was obviously perfectly normal and he'd leveled up normally dozens of times without it affecting the glitch. A stat? Well, stats are recalculated every time a Pokémon levels up, and Jolteon had stayed glitched as I'd trained him, so clearly not. And even fields like the stat experience or ID number still wouldn't make any sense, once I thought about it: both of those are two-byte numbers (0-65535), and every possible two-byte value is a perfectly valid normal value for the stat experience or ID number, so a bit flip in a number like that would have just made it a different, equally valid number; why would that cause anything glitchy? (Besides, stat experience changes every time you battle, and his ID number had shown up on the status screen, and I would definitely have noticed if it wasn't 22166 like for all my other Pokémon.)

Instead, I managed to pretty much narrow it down to the two fields that stored text: the nickname and original trainer name.

Text, on a computer, is really just a series of numbers, of course. A character encoding defines what numbers correspond to which character; when a program is dealing with a bit of data that it expects to be text, it will reference the character encoding to look up what character corresponds to each number, and thus what glyph should be shown on the screen. Pokémon Red, Blue and Yellow use their own character encoding, which is how the games encode both dialogue text shown in text boxes, Pokémon names and nicknames, character names, Pokédex entries, and other UI text; the number 128, for example, corresponds to capital A, 129 to capital B, and 130 to capital C, while the lowercase letters start at 160 for lowercase a.

I figured initially that maybe a bit flip could have turned a character in the nickname or OT name into an invalid character - a number that doesn't actually correspond to any character, according to the character encoding - or some special character that might be used in other places in the game, but that the status screen UI didn't know how to handle properly because normally it was never meant to be able to appear in a nickname or OT name. In a case like that, I could picture the game choking on trying to show that character, which could perhaps explain the blank screen. It didn't immediately explain why the A press then resulted in most of the status screen showing up fine minus some labels, but at least it was a theory.

So I looked up the character encoding used in the games on Bulbapedia... and realized that the games' character encoding includes a bunch of control characters that will just straight-up execute some code whenever the game tries to render them anywhere. Control characters are used for things like marking where a line ends and the text should go to the next line, or where a text string or dialogue ends; most weren't obviously relevant to my Jolteon. But there were also control characters like "page" (used to denote the end of the first page of a Pokédex entry and start of the next) or "paragraph" (used to denote where a 'paragraph' of dialogue ends), which as it turns out cause the game to wait until the player presses a button before continuing. And that immediately rang very, very relevant to a glitch that manifested in waiting for a button press before displaying something. Finally, after more than two decades, I had a real clue as to what could have been going on with my Jolteon.

I loaded up my Yellow save in the bgb emulator, located my Jolteon's data in memory, and overwrote the "end string" character of his OT name with the page character (chosen mainly because it was the first character of interest on the list). I opened the menu and went to Jolteon's stats. And lo and behold, there was the familiar blank screen! I pressed A and...

Screenshot - Jolteon's stats, with the type, 'IDNo/' label, 'OT/' label, and OT name missing.

Okay, okay, this wasn't quite what I thought I remembered. I was pretty sure the type had shown up. I also thought the OT name itself had shown up. But the missing labels were definitely correct, exactly like I remembered it. The ID number being there even though the label wasn't was correct. Something like this was definitely it. A single control character in the OT name really could cause both an initial blank screen and subsequent missing labels on the first status screen.

I tried some other likely culprit control characters and quickly discovered that overwriting the end string character (number 80) with the paragraph character (number 81, exactly one bit flip away from the original end string character) resulted in something even closer to my memory of my Jolteon:

Screenshot - Jolteon's stats, with the 'IDNo/' label, 'OT/' label, and OT name missing.

I tried a few more control characters, but this was the closest matching result I got. I also tried putting these control characters in the nickname field - but when I did that, that resulted in an initial blank screen when I viewed the Pokémon menu itself, too. In hindsight, it was pretty obvious why: the Pokémon's nickname is displayed on the Pokémon menu, too, so of course if rendering the nickname is interrupted to wait for a button press, that will happen there too. And while that's also an interesting effect, that definitely wasn't anything that had happened with my Jolteon (thankfully - that would have been really annoying any time he was on the team, whereas the real Jolteon only required me to press A one more time when viewing his particular stats). So I could rule out the nickname.

In other words, my Jolteon, back in 2001-2003, was glitched because he had a control character in his OT name - possibly caused by an errant cosmic ray whose byproducts just so happened to hit an Eevee's PC data in a way that simply made him very special, with no other ill effects.

The Fallibility of Memory

Technically, what I thought I remembered - what I'd written down in my Tumblr post in 2015 - was that the OT name had still showed up fine alongside the ID number. I wrote that very confidently into the post. But I couldn't get my experiments to match that part of the description, and the more I thought about it, the more I concluded I'd probably misremembered that particular detail. When I wrote the Tumblr post I was basing the description on my recollections of previous times I'd described it - my Jolteon had been wiped from existence more than a decade before I made that post, after all - but human brains are fallible, and I think at one point or another over those twelve years my squishy human brain could pretty easily have gotten slightly mixed up about the OT name, given that for the ID number it was indeed the case that the label was missing but the ID number itself showed up. I was certain about the missing labels, with a very specific memory from the time of thinking to myself about how those labels were supposed to be there and they weren't; I was certain that the ID number had been there, that the whole area hadn't just been blank; but I was not actually that kind of certain about the OT name.

I went on a bit of an adventure digging through all my old files and old forum posts for any mention of my glitched Jolteon from the time I still had him, or at least a time closer to when I'd still had him, to see if I could find an older description. But unfortunately, while I did find various times I'd offhandedly mentioned my glitched Jolteon, I failed to find any surviving accounts from earlier than 2015 where I'd actually described exactly what the status screen had looked like (very frustrating; I truly want to shake my teen self by the shoulders and tell her that this Jolteon thing was really interesting and I should have been documenting it in detail everywhere).

I could not really tell you for sure from memory whether the type was missing, like in the first screenshot above, or not, like in the second screenshot. But I think it was almost certainly like the second screenshot - it feels more familiar off gut feeling, and by far the simplest possible bit flip that could have caused it would result in that one. To see why, let's look at the actual data representing the normal OT for my Pokémon. The OT name data consists of ten bytes, each of which can represent a number from 0 to 255 inclusive; the byte sequence for my OT name, TRAINER, was 147 145 128 136 141 132 145 80 0 0. In binary, these bytes are written as follows:

1001 0011
1001 0001
1000 0000
1000 1000
1000 1101
1000 0100
1001 0001
0101 0000
0000 0000
0000 0000

The page control character is number 73, which is 0100 1001 in binary; the paragraph control character is number 81, which is 0101 0001. The only possible single bit flip that would turn any character in Jolteon's OT name into one of these control characters is turning the 80 (end string, 0101 0000) byte into 81 (paragraph, 0101 0001). Meanwhile, to get the page character, you would need to flip at least three different bits somewhere. This seems vanishingly unlikely compared to the former possibility - and when the former feels like a better match for my memory anyway, I think we can pretty much conclude that was it. The end string character turned into a paragraph character.

Why the Glitch Happens

So what is really happening when Jolteon's status screen is rendered? How come the initial screen is fully blank, even though it's the character at the end of the OT name that waits for a button prompt? Why are these particular elements missing?

Well, it took until September 2024 before I fully managed to sit down to get to the bottom of it, but with the context of knowing that the glitch was almost certainly caused by a button confirmation character in the OT name, I was able to look at the status screen disassembly again and figure out exactly what's going on there.

For the purposes of displaying graphics, the games use a set of tiles, each 8x8 pixels, and then set which tile should be displayed in each 8x8 area on the screen. The character encoding is really a mapping of numbers to tiles, because text characters here are just tiles, too! This is why glitches in these games will sometimes result in letters or numbers being shown as background elements, or something that looks like background tiles being displayed where you'd expect text.

What the paragraph and page control characters effectively do is the following:

  1. Overwrite the tile that would be on the bottom right side of the text box with a down arrow tile.
  2. Wait for a button press.
  3. Once a button is pressed, blank out a portion of the screen (i.e. set all of it to show a blank tile).
  4. Set the location where we will write the next character to a set pair of coordinates.

This is because when we finish one page of dialogue or Pokédex text, the player needs to confirm when they've read it and want to move on to the next page, with the arrow serving as a prompt - and the game obviously wants the previous bit of text to be cleared away before it begins writing out the next bit of text. And the next bit of text should then start at the start of the appropriate text box, not where the previous text left off. Since these control characters are intended only to be used in dialogue boxes or Pokédex entries respectively, they just hardcode what bit of the screen should be erased and where the next bit of text will start. For the paragraph character (used in dialogue boxes), it erases the content of the bit of the screen containing the two lines of dialogue and sets the next text to start at the start of that box, while Pokédex entries are shown in a bigger box that displays three lines of text at once, so the page character erases a somewhat bigger area and starts the following text a bit higher.

Screenshot - in-game dialogue, with the area erased by the paragraph character highlighted. Screenshot - Jolteon's Pokédex entry, with the area erased by the page character highlighted.

(On both of these screenshots, the game is genuinely waiting for button input because it's encountered a paragraph/page character being used normally as intended! The arrow you see in the bottom right is the one that's rendered in step one for both of these characters.)

Meanwhile, here's what a regular status screen looks like:

Screenshot - Pikachu's status screen.

The game renders this screen in a pretty haphazard and counterintuitive order, which looks like this (somewhat simplified):

  1. Set the current palette to be all white. The game can swap between different palettes to be used to render tiles; a given tile will define each of its 64 pixels to be one of four different color designations, but which four colors they correspond to varies based on the palette. With the white palette, all the colors are white, so everything will simply appear blank, regardless of what tiles have been set where; this means the whole screen blanks out briefly while the game is loading the status screen in, and then it pops in all at once when everything is ready and the game resets the palette back to normal.
  2. Clear the current tiles on the whole screen.
  3. Load in the appropriate set of tiles for the status screen.
  4. Draw (i.e. set the tiles for) the 'box' (vertical line on the right and horizontal line at the bottom ending in an 'arrow') that surrounds the name, HP and status.
  5. Write out the "No." text that goes next to the Pokédex number.
  6. Draw the 'box' around the type, ID number and OT.
  7. Write out the "TYPE1/", "TYPE2/", "IDNo/" and "OT/" labels on the right side.
  8. Draw the HP bar.
  9. Write out the Pokémon's status.
  10. Write out the "STATUS/" label.
  11. Write out the Pokémon's level.
  12. Write out the Pokémon's Pokédex number.
  13. Write out the Pokémon's type (this step includes blanking out the "TYPE2/" label if the Pokémon only has one type).
  14. Write out the Pokémon's nickname.
  15. Write out the Pokémon's Original Trainer name.
  16. Write out the Pokémon's ID number.
  17. Draw the box with the Pokémon's stats and write the stat labels and values into it.
  18. Set the palette back to normal.
  19. Draw the Pokémon's flipped sprite.
  20. Play the Pokémon's cry.
  21. Wait for a button press.

This means that by the time we get to writing the Pokémon's Original Trainer name onto the screen, we've already written out the labels, but not the ID number or the stats box... and the palette is still set to the all-white palette. If the OT name contains a character that waits for a button press, well - we'll wait for a button press then and there, while the palette is still white. Hence, even though we've already set the tiles for most of the status screen, the screen stays blank!

Once the button press happens, we then dutifully clear out the designated area of the screen. On the status screen, here's how those blanked-out areas line up for the paragraph and page characters:

Screenshot - Pikachu's status screen, with the area erased by the paragraph character highlighted. Screenshot - Pikachu's status screen, with the area erased by the page character highlighted.

So, if we encounter the paragraph character in the OT name, we'll blank out area in the left screenshot. This will erase the IDNo/ and OT/ labels that we already placed, as well as the OT name itself. However, we don't draw the ID number or the stats box until afterwards, so those will still show up fine!

Meanwhile, if we encounter the page character in the OT name, we'll blank out an even bigger portion of the screen, now wiping out the type as well, though the TYPE1/ label is spared since it's just outside the affected area. Again, though, the ID number and the stats box are drawn afterwards, so they're still shown as normal.

This explains everything about the funny status screen, and it also proves pretty conclusively that there's pretty much no way the OT name ever showed up for Jolteon. It's simply part of the area that gets blanked out once we press the button.

Fun with Control Characters

There are actually four control characters that wait for button input, which are as follows:

Name Number (decimal) Binary representation
page 73 0100 1001
_cont 75 0100 1011
paragraph 81 0101 0001
prompt 88 0101 1000

The prompt character does not blank out a whole area of the screen - instead, it displays a down arrow in the bottom right, waits for button input, and then once a button is pressed, it just blanks out the arrow tile again and then exits (this character is meant to be used to prompt the player to close a piece of text, so in theory, nothing should come after it). This means that for my seven-character OT name, the final letter is blanked out, because it happens to be located in the bottom right where the arrow would go:

Screenshot - Jolteon's status screen, with the final letter of the OT name 'TRAINER' missing.

However, if the prompt character appears earlier in the name, the name will cut off there, as with here, where I overwrote the second letter with it:

Screenshot - Jolteon's status screen, with everything after the initial 'T' of the OT name missing.

What happens in the hypothetical where something like a paragraph or page character appears earlier in the OT name? Well, then what comes after that character does get printed onto the screen after we've cleared out the "textbox" - but because the paragraph or page character will also have reset the coordinates of where the next bit of text is meant to appear, it will write it out starting from the left side of the screen, and then after that the whole name simply gets covered up by the stat box when that is rendered, so the OT name still does not appear. Just for fun, it is possible with memory manipulation to artificially insert other control characters into the name that will print multiple characters (for instance, there's a control character that actually prints the entire word TRAINER); if we take advantage of this to extend the OT name beyond the normal maximum of ten characters, then you can see the part of the name that isn't covered by the stat box (though for the paragraph character the ID number ends up also getting rendered on top of it):

Screenshot - Jolteon's status screen, with 'RA' shown between the stat box and the ID number. Screenshot - Jolteon's status screen, with 'RAINER' shown extending out from the edge of the stat box.

Meanwhile, the _cont character may be the most amusing one. It's normally used to scroll text up so that we can write the next line below, so what it does is it displays a down arrow in the bottom right, waits for button input, blanks out the down arrow again, and then moves the text currently in the dialogue textbox area up, so that the bottom half of the textbox ends up in the top. If the end string character gets turned into that, this is what we get:

Screenshot - Jolteon's status screen, showing OT/51402E.

What has happened here is that first we write out TRAINER, then the down arrow replaces the final R, then after the button press the arrow gets blanked out so we're left with "TRAINE". We then move "OT/" and "TRAINE" upwards where they replace the "IDNo/" label, and then the five-character ID number gets written in its normal location which is now right on top of the OT name, replacing TRAIN and leaving only the E. (This was one of the more inexplicable effects I got when first experimenting, so it's very gratifying to be able to explain it.)

Conclusion

My original glitched Jolteon was a dear, special teammate now lost forever to time - but two decades later, I have finally worked out what was going on with his strange status screen and how it probably happened, and there's a big sense of catharsis in that. I haven't made the artificial bit flip permanent for my new Jolteon, but I hypothetically could do that and then write the save back to the cartridge, where I could watch it happen on my Game Boy Color for the first time in twenty years. I don't think I will, at this point - it still would never be quite the same. But solving Jolteon's mystery feels like an appropriate way to honor his memory.

Goodbye, Jolteon. You were very, very special.

Page last modified September 18 2024 at 19:31 UTC