NinBendo – circuit bending by corrupting 8-bit game code.

Yeah, back in junior high I had not enough friends and too much time, and discovered that keying in random Game Genie codes would sometimes cause a NES game to (harmlessly) glitch out in interesting ways. :-p Some codes just locked up the game (drat!), while others caused screen glitches, messed with colors, and rearranged levels. Still others would screw up the game music or sound effects. I was always strangely mesmerized by the bleepy sonic barf of a good sound loop crash.

Of course, now that I’m all old and exposed to the Internets, I come to find out there are entire groups devoted to pretty much exactly this–glitching out electronic toys to produce interesting sound effects (circuit bending). So for those folks, here is some info and samples from codebending on the original NES. Hardcore circuit benders might consider this software-bending stuff cheating since the case never comes off ;-)

Some WAV files:
Recorded long-long-ago (possibly in Nesticle for Win95), stumbling across them on my HDD the other day is what got me playing with it again.

_0_ / _1_ / _2_ / _3_ / _4_ / _5_ / _6_ / _7_ / _8_ /

Videos:
Before & After – lest you think the game just has really bizarre sound effects to begin with
Crunchy – this effect would make a great sample in some industrial song.
SMB3 World Map pointer crash – my guess is this value indexes a jump table whose entries point to the start of the World map for that world, ranging from 0 (world 1) to 8 (Warp zone). Setting it to a non-existent world (past the end of the jump table) causes arbitrary data to be parsed as a world map, with deliciously (un)predictable results.

For these videos I used the emulator’s speedup key to fast-forward through some of the boring bits, but the vids themselves are unedited.

How Game Genie (and other patch devices) work:

The Game Genie and its various successors for cartridge-based game consoles are realtime code patchers that sit between the cartridge (a set of ROMS containing the game’s executable code and data) and the CPU that is reading and executing the instructions. A Game Genie code tells it to overwrite a small portion (up to a whopping 3 bytes [codes] on the NES) of the program on the cartridge with new contents, for example, replace a subtraction opcode (the one that runs on Mario’s life counter just after he falls into a pit of lava) with a dummy instruction, granting infinite lives. Of course nothing is actually overwritten (it’s a ROM after all*); the device intercepts read commands to the game cartridge and substitutes the replacement values on the fly, kind of like a sneaky foreign-language interpreter with an axe to grind. (Ace: “War is hell, the last thing we want is a fight.” Translator: “White devil say, I want to fight you… so go to Hell!”)

So in its simplest form, a Game Genie Code represents (ROM address: new byte value). Why they took such pains to hide this behind scrambled letter codes for the NES is anyones guess…some suggest it was to make the codes seem more ‘magical’, mysterious and hard to guess. (A complete description of how to decipher GG letter codes is here.) I suppose the fact that its manufacturer’s secondary revenue stream was in selling updated code books could have played a role, too ;-)

On the NES, this biz of replacing data based on its address gets hairy because the NES only really supports ROMs up to 16K. Developers soon found this limiting and wanted to develop much larger games, so to work around this limitation, many games include memory-mapper logic that lets the game code being run on the NES instruct the cartridge to swap different 16K banks of ROM in and out on the fly. The Game Genie can’t know if and when the game has performed such a switch, so they try to solve the “but what if they swap banks on us and the data address we think we’re intercepting actually points to completely different data from the new bank?” problem by adding a key value to the Game Genie code. The key byte is the expected value of the ROM byte you’re replacing. In this case, when the NES requests data from the cartridge and there is a substitution on file, the Game Genie reads the cartridge data and compares it to the expected value, substituting the new data only if the value from the current cartridge bank matches (indicating it is probably the correct bank). This is not perfect (there is roughly an n in 256 chance that another bank contains the same data byte at that address, where n is the number of banks), but in practice works well enough that *most* substitutions are possible.

The key byte is indicated in 8-letter GG codes, which resolve to (ROM address: new value: if old value = xxx)

Finding Codes for noise glitching:

The old-skool way:
Set up a real live console with a game and patch device (Game Genie / Gameshark / Pro Action Replay), then start plugging away with random codes until it glitches out. For the original Game Genie, 6-letter codes have a much better chance of having some effect than 8-letter codes (bankswitch keying). Maybe set up a gamepad with turbo so that the A (select a letter) and B (delete a letter) fire at very slightly different speeds, and rapidly waggle the stick around over the letters. Have a VCR (remember those?) recording continuously so that when something interesting does happen, you can back up the tape and see the winning code.

The fast modern way:
Use an emulator with integrated cheat (and ideally debugger) features. This makes it much faster to set, clear and save codes, and the straight (address:value or address:value:if oldvalue) format supported by most emulators is far more intuitive than those nonsense letter codes when trying to home in on a good substitution. If you know a bit of assembler (or are willing to learn), a builtin debugger/disassembler makes homing in on the sound-specific code much faster than just plugging away at random. For example, the NES sound chip is controlled by memory-mapped registers in the range 0x4000 ~ 0x4015 (see NES APU reference for details). Have it search for code that writes to these addresses, or polls the APU status register (0x4015)…better yet, have it trap writes to these locations and show you exactly when and where it occurs.

The FCEUX emulator provides some pretty advanced reverse engineering features designed for homebrew developers and game hackers. In particular, a Trace feature dumps out a running, disassembled list of address:value data fetched from the cartridge throughout any time. This feature, working together with a Code/Data logger (which incrementally determines which parts of the ROM are executable code vs. data by the way they are accessed), can be used to narrow down the location of certain code fragments and/or data structures of interest.

Example video: Using FCEUX features to bend SMB3’s World 1 map music. No knowledge of 6502 assembly language needed, but it never hurts.

Modifying one (or maximum three) bytes doesn’t sound like a lot, but even these small changes can be used to produce far-ranging consequences. A 6502 CPU instruction is of variable length, consisting of a 1-byte opcode followed by 0 – 3(?) bytes of arguments. Overwriting an opcode byte with one that takes a different number of arguments will affect how the following instructions are decoded – e.g. some subsequent CPU opcodes will be interpreted as arguments, or argument data will be interpreted as opcodes. Also, executable code and data such as text, level data, sound files etc. are intermixed throughout the code (most disassemblers will not be smart enough to tell which is which, making reverse engineering a giant pain). Corrupting data or pointers to the data can be just as effective as modifying the executable code. Say for the purpose of example, there is a track of music data in there stored as a sequence of (frequency, duration) byte pairs, and the code to initialize a level sets a pointer to the start of this data. Bumping the pointer value by 1 (so that it starts on a duration byte) would cause a music decoding loop to be interpreting the duration byte as a frequency and vice versa, with very interesting results. Likewise if you corrupted this pointer to point to level data instead of sound data, or simply corrupt some data structure in such a way as to goof up a parser somewhere.

Some general considerations:

1) No emulator is a perfect replica of a real console, or other emulators for that matter. You may not get exactly the same result from the same code modifications on different emulators, or between emulators and a real console. In particular, your emulator may try to transparently trap/handle bad opcodes (which come with the territory of overwriting game code with random data!) while your console happily runs them with undefined results, or your modification causes the game to read from uninitialized memory (whereas the emulator may have gotten its memory pre-initialized to 0’s when the OS allocated it).

2) Related to the above (uninitialized memory, etc.), codebending results are not guaranteed to be deterministic or repeatable, even for the same code on the same console / emulator. Keep this in mind if you incorporate codebending in any sort of live performance! Results may depend on uninitialized memory/register contents, or whatever state those contents are left in after a warm reset, or user input, or ESD / EMI / cosmic rays / El Nino. If your results are input-dependent, look into TAS (Tool-Assisted Speedrun) tools present on some emulators. These will allow you to feed the game scripted or pre-recorded gamepad input with timing accurate to single television frames.

3) Finally – Although some old games often have One True Version, many others may have a couple different minor revisions floating around, either to fix bugs discovered after initial release, or to accommodate NTSC vs. PAL, etc. The end result is even a 1-byte addition to the game code means all the address locations are shifted by one, so the same code on two revisions will be modifying an entirely different piece of code.

* Unfortunately for them, there is no way to insert a device between the CPU and RAM in order to modify RAM contents directly, so they had to be content with e.g. nopping out CPU instructions to produce the desired effects. Kind of an art form to replace opcodes from a limited pool of same-length opcodes in such a way that they perform the intended function without side effects. But luckily for you, the modern emulators let you meddle around with RAM contents directly, too.


Posted

in

by

Comments

2 responses to “NinBendo – circuit bending by corrupting 8-bit game code.”

  1. […] bookmarks tagged circuit bending Outguessing the machine » NinBendo – circuit bend… saved by 1 others     jimmynutz bookmarked on 05/17/09 | […]

  2. Jesse Avatar

    Thank you! This is all very useful info, as it was beginning to seem like I wasn’t going to find an easy solution outside of actually bending my console. That would take a lot of time that I could be using on other projects, though. I was beginning to wonder about bending cartridges rather than the actual system, and that’s basically what the Game Genie is doing, virtual bending if you will. I wouldn’t worry about benders thinking this is cheating. Its actually quite brilliant.*****!

Leave a Reply

Your email address will not be published. Required fields are marked *