devlog.

Glitch · Gen 1 cartridge

The name that becomes a Pokémon

A Pokémon's evolution table is looked up by species index with no bounds check. Feed it an index the game never assigns on purpose and it reads past the table into whatever else lives in that ROM bank, and evolves the Pokémon into whatever that garbage happens to decode as. There are two real ways to feed it that index. One is entirely the player's own choice: pick a trainer name with a digit in the right place, watch a scripted demo in Viridian City, and catch a specific wild Pokémon on one coastal tile. The other doesn't need the player's cooperation at all — a modified link partner can hand it over in an ordinary, visible trade, and the Pokémon looks completely normal until the next battle it wins.

10
species indices a name can choose (246–255)
2
confirmed outcomes — SLOWPOKE, GROWLITHE
2
independent delivery routes proven
7
real battle wins to the traded-in evolution

Reproduced 27–28 Sep 2026 on a retail image, Pokemon - Blue Version (USA, Europe) (SGB Enhanced).gb, SHA-1 d7037c83e1ae5b39bde3c30787637ba1d4c48ce2.

The sequel to the hooked Dragonite

The hooked Dragonite is one buffer overflow with one outcome, reached one way. This is a different bug in the same cartridge — the evolution-table lookup at TryEvolvingMon — and it has two completely different, independently real ways in. Both were traced to source, both were run on TerminalGB's own CPU rather than assumed from the disassembly, and one of them was proven end to end across two linked emulator cores over a real link-cable protocol.

The mechanism

One lookup, one missing check, in a table that's fine for every species the game actually uses.

The table

EvosMovesPointerTable, bank 0E:$705C

Every species has a two-byte pointer in this table, indexed by (species − 1) × 2, into its own evolution-and-move-learn data. For the 190 real species in the game this is a completely ordinary lookup. Nothing checks that species is one of those 190 before doing the arithmetic.

What happens past the edge

Garbage entries, then a real one

Feed the lookup a species index above 190 and the pointer it computes lands somewhere else in bank 0E — not a crash, just a different address, holding whatever bytes were already there. Evolution_PartyMonLoop reads that address as a stream of evolution-table entries anyway: a byte for the entry type, then whatever that type's format calls for. Most of the stream decodes as entries with no real meaning and gets skipped; sooner or later — sometimes never, sometimes after dozens of skipped "entries" — the parser hits a byte pattern that happens to look like a valid LEVEL entry, and evolves the Pokémon into whatever species byte follows it.

Why this is predictable, not random

The garbage is fixed ROM data

The bytes past the table's real end are ordinary ROM bytes — code and data belonging to whatever else lives in that bank. They never change between runs. Every out-of-range species index has exactly one predicted outcome, and it can be worked out in advance by walking the same bytes the real CPU would read, without ever running the game.

Route one: the player's own name

The community's own "Old Man"/Cinnabar MissingNo. glitch family, walked all the way to a specific, chosen evolution.

The copy that shouldn't matter

The Old Man's catching demo writes over the wild-encounter table

Viridian City's Old Man runs a scripted catching demonstration through the same battle-menu routine every other battle uses. For that one battle type, the routine copies the player's own 11-byte name into wLinkEnemyTrainerName — which the game's own memory layout overlaps with wGrassRate and the 20-byte wGrassMons wild-encounter table. Loading a new map is supposed to overwrite that table with real data, but a town with zero wild encounters skips the overwrite entirely — it only ever clears the rate byte. Cinnabar Island and Route 21 are exactly that kind of map, so the table keeps whatever the Old Man's demo last wrote into it: the player's name.

The tile that reads it

One specific "left shore" half-block

A wild encounter rolls its odds against one tile check and reads its species data from a second, independent tile check. On a "left shore" half-block — the game's own disassembly names Cinnabar Island's east coast as the example — those two checks disagree: the odds are rolled as a water tile, but the species comes from the grass table. So a wild encounter on that one tile reads species data out of a table that, on Cinnabar or Route 21, still holds the player's own name.

Which byte lands where

The 3rd, 5th and 7th letters become species bytes

The 11-byte copy lands as five (level, species) pairs. The first pair — the most heavily weighted encounter slot — takes its species byte from the trainer name's 3rd character. Gen 1's text encoding maps the digits 0–9 directly onto internal species indices 246–255. A name with a digit in that position is a direct, deliberate choice of which out-of-range species shows up in the grass.

Confirmed on TerminalGB's real CPU

Two names, two predicted evolutions, both correct

The name copy itself was run on the real CPU at the exact instruction (bank 0F:$4EDD): a name with '6' as its 3rd character produced species byte $FC (252) in the wild-encounter table after 82 real instructions, byte for byte. Walking the evolution table for each of the ten name-reachable indices and then running the real evolution routine on the two most interesting of them confirmed both: species 252 evolves into SLOWPOKE after 317 real instructions, and species 255 evolves into GROWLITHE after 461 — both landing exactly where the static walk of the real ROM bytes predicted.

Route two: a modified trade partner

No name, no coastal tile, no cooperation from the player at all — just an ordinary trade, both sides visible, over a real link-cable wire.

The other way in

A trade copies the offered species byte with no check

AddEnemyMonToPlayerParty copies a traded-in Pokémon's species byte from whatever the other console sent — the link-cable protocol is unencrypted and has been reverse-engineered end to end, so a real, buildable modified device can offer any byte it likes. Nothing on the receiving side validates it against the real species list before writing it into the party.

Proven, not modeled

Two full Game Boy cores, one real Cable Club trade

Two complete TerminalGB cores were joined over the project's own real link cable implementation and driven through an actual Cable Club trade — walk to the receptionist, take the link menu, select the party slot, confirm — with one side offering a hand-built Pokémon carrying species byte 0xC1 (193). Reading the receiving console's live memory straight after "Trade completed!" confirmed the byte survived the real wire intact: species 193, level 8, exactly as sent.

The genuinely interesting part

It doesn't evolve at the trade — and the reason is a real timing detail

The game forces an evolution check on the traded-in Pokémon immediately, as part of the trade animation, before "Trade completed!" even prints. But at that exact instant the game's own link-state flag still reads LINK_STATE_TRADING, and the evolution parser skips any entry that isn't a same-instant trade evolution while that flag is set. Species 193's table entry is the ordinary LEVEL kind, not a trade evolution, so the mid-trade check waves it through untouched. The forced flag survives the trade and takes effect for real at the next battle the receiving player wins — by which point the link-state flag has been cleared, and nothing stops the evolution any more. The traded-in Pokémon looks completely ordinary in its new owner's party until then.

Confirmed by the game's own text

Seven real battle wins to the evolution

After the trade, the receiving console fought seven real wild battles with the traded-in Pokémon, over real game frames rather than scripted turns. On the seventh, the moment its level crossed the table's own predicted threshold, the game printed "SPECOP evolved into SPEAROW!" — matching, byte for byte, both the species the static table walk predicted for 193 and the exact level it predicted the evolution would require. The party structure's own species byte read 0x05 immediately after, confirming the on-screen text against a direct memory read of the same event.

What's proven, and what isn't yet

Honest about the gap this page still has.


Where these numbers come from

Every address, byte value and table walk above was read from a retail cartridge image, Pokemon - Blue Version (USA, Europe) (SGB Enhanced).gb, SHA-1 d7037c83e1ae5b39bde3c30787637ba1d4c48ce2, cross-referenced against the pret/pokered disassembly. The name-copy and evolution-overflow reproductions ran on TerminalGB's own CPU core executing the real routines directly; the trade reproduction joined two independent TerminalGB cores over the project's real link cable implementation and drove an actual Cable Club trade through the existing trade-bot tooling, reading both consoles' live memory and on-screen text rather than assuming the wire behaved as documented.

The underlying "Old Man"/Cinnabar Island MissingNo. glitch is long-documented community lore, not a discovery made here; what's new on this page is walking it all the way to two specific, predicted evolutions and proving the same overflow is independently reachable through a modified link partner, with the trade-timing detail confirmed by direct reproduction rather than assumed from either mechanism alone.

← All glitches