Home

Awesome

All you want to know about the Game Boy Camera save format !

Part 1: Injecting custom pictures into the save

So, despite the fact that extracting images from Game Boy Camera saves was made possible by fans since many years, it was virtually impossible in 2021 to do the inverse : inject custom pictures into saves. At least until now. What could be the interest, dear reader ? It can be usefull to mess with pixel perfect artworks, to reuse an image that was erased long ago from camera but still stored somewhere on a computer or internet or simply exchange pictures with friends if you have no friends, which is my case.

All codes given here are GNU Octave / Matlab compatible. GNU Octave is an open source version of Matlab, a langage for scientific computing. Codes are meant to be short and easy to use / modify from any of these multi OS development environments.

The small codes presented here allows injecting custom pictures in any save. Here are the steps:

The scanning code basically extracts and analyses values at addresses 0x011B2 to 0x011CF that contains the state and numbering of any image slot on the save (which I will call "State Vector" because it had no name until now). These data are also duplicated from addresses 0x011D7 to 0x011F4. Any number between 0x00 and 0x1D on this state vector represents the image number (minus one) that shows on the camera screen, FF is an unused slot (erased of never used). The number assignated to an image on camera is in consequence not related to the slot number (or physical address). Deleting an image on camera will simply write 0xFF on the vector state at the good place and all images will be renumbered dynamically, but image data stay on their respective slots as long as another image is not written on it. When a picture is taken, memory slots marked as unused on the vector state will be used by writing data in priority to the lowest address one. Next image illustrates the principle of this state vector:

Vector state

Until this step, everything was fine and easy, tricky enough to occupy my brain for an evening but not much. Here came some very bad undocumented surprise. There is an undocumented checksum system at addresses 0x011D5-0x011D6 and 0x011FA-0x011FB that precludes any possibility of un-erasing a single picture or activating a new memory slot by simply manipulating the state vector (except as a whole as in this case the checksum is known). Doing this simply forces the camera to replace any value on state vector by 0xFF (means you've basically fucked your precious images in case you just own original hardware in 1998).

This is why I wrote slot_activator.m, which activates all slots (an unerases all pictures). This was the only operation that I was initially able to perform, knowing the checksum of this particular state vector. For doing this, I simply stuff addresses 0x011B2 to 0x011CF with a fake "camera full" state vector (0x00, 0x01, 0x02 ...0x1C, 0x1D) and addresses 0x011D5-0x011D6 with the corresponding checksum (0xE2, 0x14). Et voilĂ  ! This means that range 0x011D7 to 0x011F4 and addresses 0x011FA-0x011FB are just echos. Activating the 30 slots of a camera after a factory reset gives you 30 white images.

Hexadecimal codes to unerase all picture

unerase pictures

Hopefully, I've found that an active image could be replaced bytewise without activating any suicide code. In consequence, the image injection code just substitutes the data corresponding to the image tiles (address range : 0xXX000-0xXXDEF for the image, address range : 0xXXDF0-0xXXEFF for the thumbnail, XX ranging from 02 to 1F). Additionnal data (range 0xXXF00-0xXXFFF), are not modified. Apart from that, data are arranged in Game Boy tile format, tile after tile, in reading order, so nothing particular for you Nintendo nerds.

Funfact, the thumbnail is dynamically rewritten each time the image is saved into the Game Boy Camera, even if just one pixel is changed. So I just provide a generic image thumbnail that will soon disappear. Invigorated by my half-a-success, I took a look around the state vector in search for any minigame score to manipulate (that damn mole is too fast !), following the word "Magic" into the save signing the presence of interesting stuff. This is where another form of pain begins.

This was the easy part, now began the tricky one

Time for creativity

Part 2: breaking the data encoding system just for science

I loosely continued collecting data to understand how bytes are arranged into the savestate (see research folder). The principle reason is that it seems that there is not any single cheating codes on the whole planet Earth for this device (except the CoroCoro save hack that targets one of the rare unprotected range), even more than 25 years after the camera was released, which is quite annoying when you know the requirement to unlock the full B album (Yes, accomplish 1000 points at Ball, 7000 points at Space Fever II and less that 16 seconds at Run! Run! Run! means you were at some point of your life stuck at home with two broken legs and only a Game Boy to entertain yourself, believe me). So my motivation to crack the thing was rather strong.

My general (tedious) strategy was to compare different dumped savesates with some accomplishments made (not all, I'm not mad nor stuck at home with broken legs), byte per byte, to understand where were the targeted addresses. I systematically compared with a blank savestate (all data erased). Everything was made on real hardware (Game Boy Camera and Pocket Camera in parallel). So here are my conclusions:

So I can now propose a revised structure of the Game Boy Camera save format since Jeff Frohwein proposed the first one in the early 2000's.

Game Boy Camera save ram format by increasing adresses

Images are then repeated from 0xXX000 to 0xXXFFF with XX ranging from 03 to 1F.

Image slot 5 (range 0x04FF2-0x04FFF) contains calibration data for camera, echoed in image slot 18 (range 0x11FF2-0x011FFF). To trigger auto-calibration, fill these ranges with 0xAA and boot the camera in the dark. The function of these calibration bytes is not fully understood today. They change camera sensor register O for sure (fine voltage tuning) and maybe some other settings. I did not investigate that much for the moment as it requires lot of datalogging and calculations for basically no reward (I honestly doubt anybody would give a shit of the result). At this point, camera rom disassembly will be more relevant than reverse engineering.

General comment: any extended 0xAA range is a remnant of the initial factory sram tests, never erased since camera release. Other value means that backup battery has been replaced one time in the camera life. By extension, these ranges are never included into any checksums as they are never used by the camera code in writing mode.

Visual representation of data at the beginning of the sram

Visual representation of data at the beginning of save ram

Now let's finally reverse engineer this damn checksum system !

OK, at this point I was curious to understand how the checksum system worked (it was even a matter of honor). It was not a two bytes checksum like the Game Boy Printer protocol for sure, But some savestates comparisons showed that increasing values of scores or pictures taken always increased the left byte of the cheksum (low address). So this one was just a sum on 8 bits. The right byte (high address) had a weird behavior. I've tried all the common operators available in assembly and XOR was (of course) the good one. So left byte is a 8-bit sum and right byte a 8 bit XOR of values considered in the checksum. The rule to modify any byte in an area protected by checksum is the following:

And that's all ! The checksum could be calculated from scratch from always the same seed: "Magic" followed by 0x2F, 0x15 (starting checksum when all data are 0x00). Each new data entering a protected area modifies the values of its corresponding checksum according to the rules. "Magic" is a mandatory keyword (its absence triggers the suicide code even if the checksum is correct).

Starting seed for ALL camera checksums

Starting seed

If "Magic" is included into the checksum and replaced by 5x 0x00, it becomes simply 0x4E, 0x54 ("NT" in Ascii).

Well enough to enjoy all the crappy images of the B album of the camera (At least in the international version, Gold and Japanese are a bit better). This folder contains self-explanatory code to transform any 128 kB file in legit save. This folder contains a code that generate an universal save unlocking all the features of all the camera versions starting from any of your prefered save.

Example of state vector checksum attack

State vector

Example of Minigame checksum attack

Minigames

Examples of score attack on real hardware

Scores you will never get in real That damn mole finally beaten by brute force.

Part 3: Calibrating the sensor

A secret factory menu have been discovered in december 2021 independently by me and Cristofer Cruz: by pressing all inputs (4 directions included, I know this is completely stupid) at the same time when booting, or by filling the sram with 0xAAs on real device, the camera enters a factory reset mode saying "STORE PLEASE WAIT", then "STORE END" and playing a Run!Run!Run jingle. The exact purpose of this menu have been discovered by serendipity the 7 august 2022 from a glitched save of my own (lost since, sadly) that changes the sensor auto-exposure rules: this is a calibration menu.

During this procedure, the camera sensor is activated and the game stores data in the range 0x04FF2-0x04FFF, echoed at the range 0x11FF2-0x011FFF. By comparing this vector extracted from new cameras (new old stocks) and cameras placed in different lightning conditions during this calibration procedure, it has been established that these data are probably setpoints or offsets for guiding the auto-exposure of the camera calculated from activating the sensor in the dark in different conditions.

So for calibrating the camera, you must proceed as following:

Method 1:

Method 2:

This should be made after battery loss/replacement as non-calibrated cameras can behave weirdly.

Secret menu

Part 4: some random stuff for camera nerds

2021-07-01 Update: structure of the Hello Kitty Pocket Camera save

Thanks to Cristofer Cruz who built a real Hello Kitty Pocket Camera from the dead body of a Pocket Camera and a MX27C8000 EPROM, we were able to explore the SRAM structure from various dumps. The save format is about the same than the Game Boy Camera with some exceptions:

The counter for images is followed by a nice flower meter just below. I think that the game save data are not protected just because the game is not finished. Indeed, the "Magic" word exists but without checksum after and the game save data are not echoed contrary to the state vector that may originate from the old Game Boy Camera code the Hello Kitty is based on. Moreover, game save data are written in address range 0x01000-0x0102E wich corresponds to animation settings in the regular Game Boy Camera (so it will mess all minigames data if you change the rom as checksum won't be updated properly).

These minor ram save format inconsistencies mean that switching from regular rom to HK rom with the same save is OK, but switching back will probably wipe your records if you catch any "kitt", the rom "currency". Images are anyway always conserved.

Save functionality of the leaked rom was probably enough for running and testing the game but not "polished" for antipiracy and public release. Structure of the sram, very similar to the Game Boy Camera, reinforces the idea that this version is more a port of the GB Camera than a complete reboot.

It was also observed that the image is overall "smoother" (in a not pleasant way I should admit) with this camera rom (hardware being the same) which probably involves some subtle modifications of sensor registers or dithering tables compared to regular roms. I've never investigated more on this point as I guess that nobody (included me) cares of that in fact.

Funfact: as the number of borders in HK rom is higher than in regular roms (and checksum correctly updated for this entry in HK rom), you can save a value from HK rom not supported by regular rom. This leads to an incorrect address to tilemap and very interesting glitched borders appear.

Byte attack on HK Pocket Camera (Created by Cristofer Cruz)

Byte attack on Hello Kitty Byte attack on Hello Kitty

2023-05-20 Update: structure of the Debagame Tester - Second Impact

A prototype of Game Boy Camera has been found on Ebay in may 2023. Images of the device are archived here. It has a main menu very similar with the MBC5 mapper chip test program linked in 2020. Most intersting things are within the rom as it contains quite a lot of hidden features like programmer faces, unused graphics and pieces of assembly code with comments. I rapidely checked the save format:

Summary of some tests made on real hardware:

My overall impression is that the 10.24 version (the only known to date) lacks several key features as some menus lead to dead end and/or have no effects (printing, data protection, etc.). It was probably an early version used to validate the quite definitive hardware into the real battlefield (messy kid room and car rear shelf in full sun), the main dev being probably continued on a test board with EPROMs. It's still surprising to have such a close-to-definitive hardware design equipped with a mask ROM of such a primitive camera version.

The Debagame Tester

Debagame_Tester

Aknowledgments