This project was to try and dump out all the images that I got from two gameboy cameras that I purchased off the internet.

For convenience and also considering that other people may want to construct their own extractor in an accessible manner, I opted to extract the images via the gameboy link cable to an arduino pretending to be a gameboy printer.

This is by no means a reverse engineering of the gameboy link protocol, as that has already been done. But rather it is just an implementation to allow for people with an arduino and a gameboy link cable to get their images out of their gameboy for archival purpose.

This is important, as the gameboy camera is battery backed up. If the battery dies, the images stored within it is lost forever.

What I hope to see in the future is a way to organise a way to retreive all the images from second hand gameboy cameras and display it online.

Project Source Code

If you are interested in replicating the project, then all the source code is placed in this repository:

Project Makeup

This projects consist of two parts:

  • Arduino sketch emulating a gameboy printer to a computer via a serial link.
  • Javascript gameboy printer hex stream rendering to image in browser.
    • Part of the code is based on the gameboy tile decoder tutorial at http://www.huderlem.com/demos/gameboy2bpp.html

You can decode your own gameboy printer hex stream at the bottom of this page.


Images Extracted

For privacy reasons, I have not released all the images that I had extracted from the gameboy camera carts. But I would love to get back in touch with whomever originally took this image and hand over the images.

Hope you enjoy the images. I don’t know when it was taken however.

Cart 1

  • cart_one_A01.png
  • cart_one_A02.png
  • cart_one_A03.png - A girl and her mother?
  • cart_one_A04.png - A woman
  • cart_one_A05.png - Black Image
  • cart_one_A06.png
  • cart_one_A07.png
  • cart_one_A08.png
  • cart_one_A09.png
  • cart_one_A10.png
  • cart_one_A11.png
  • cart_one_A12.png
  • cart_one_A13.png - White Image
  • cart_one_A14.png
  • cart_one_A16.png
  • cart_one_A17.png
  • cart_one_A18.png - A girl hand signing V
  • cart_one_A19.png - A toddler sticking out her tounge
  • cart_one_A20.png - A pouting toddler
  • cart_one_A21.png - A mother holding up her toddler?
  • cart_one_A22.png - Same girl hand signing V elsewhere
  • cart_one_A23.png
  • cart_one_A24.png
  • cart_one_A26.png
  • cart_one_A27.png - A grandmother
  • cart_one_A28.png - A guy and a girl
  • cart_one_A29.png
  • cart_one_A30.png

Cart 2

Not as many images in this cart

  • cart_two_A01.png
  • cart_two_A02 - A girl
  • cart_two_A03 - A father?
  • cart_two_A04 - A toddler? With various gameboy stickers.
  • cart_two_A05 - Same as A04 but different sticker and expression
  • cart_two_A06 - A older girl holding up a victory sign

Protocol In Summary

Protocol

Below is also documented in the arduino sketch, but is formatted here for easier readbility.

| BYTE POS :   |     0     |     1     |     2     |     3     |     4     |  4 + X    | 4 + X + 1 | 4 + X + 2 | 4 + X + 3 | 4 + X + 4 |
|--------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
| SIZE         |        2 Bytes        |  1 Bytes  |  1 Bytes  |  1 Bytes  | Variable  |        2 Bytes        |  1 Bytes  |  1 Bytes  |
| DESCRIPTION  |       SYNC_WORD       | COMMAND   |     DATA_LENGTH(X)    | Payload   |       CHECKSUM        |    ACK    |  STATUS   |
| FROM PRINTER |    0x88   |    0x33   | See Below | Low Byte  | High Byte | See Below |       See Below       |    0x00   |    0x00   |
| TO PRINTER   |    0x00   |    0x00   |    0x00   |    0x00   |    0x00   |    0x00   |    0x00   |    0x00   |    0x81   | See Below |
  • Command may be either Initialize (0x01), Data (0x04), Print (0x02), or Inquiry (0x0F).
  • Payload byte count size depends on the value of the DATA_LENGTH field.
  • Checksum is a simple sum of bytes in command, data length, and the data payload.
  • Status byte is a bitfield byte indicating various status of the printer itself. (e.g. If it is still printing)

Sync Word (2 Bytes)

// Sync Word
#define GBP_SYNC_WORD_0       0x88    // 0b10001000
#define GBP_SYNC_WORD_1       0x33    // 0b00110011
#define GBP_SYNC_WORD         0x8833  // 0b1000100000110011

Command Bytes (1 Byte)

// Command Byte Values
#define GBP_COMMAND_INIT      0x01 // 0b00000001 // Typically 10 bytes packet
#define GBP_COMMAND_DATA      0x04 // 0b00000100 // Typically 650 bytes packet (10byte header + 640byte image)
#define GBP_COMMAND_PRINT     0x02 // 0b00000010 // Typically 14 bytes (10 + 4 printer setting)
#define GBP_COMMAND_INQUIRY   0x0F // 0b00001111 // Always reports current status. Typically 10 bytes packet

Ack Byte (1 Byte)

// ACKNOWLEGEMENT BYTE VALUE
#define GBP_ACK               0x81 // 0b10000001 // Recommended by "GB Printer interface specification"
#define GBP_ACK_2             0x80 // 0b10000000 // Used by esp8266-gameboy-printer

Status Byte (1 Byte) (As bit flags)

// GAMEBOY PRINTER STATUS BYTE BIT POSITION
#define GBP_STATUS_TEMP_WARN_BIT_POS          7
#define GBP_STATUS_PAPER_JAM_BIT_POS          6
#define GBP_STATUS_TIMEOUT_BIT_POS            5
#define GBP_STATUS_BATTERY_LOW_BIT_POS        4
#define GBP_STATUS_READY_TO_PRINT_BIT_POS     3
#define GBP_STATUS_PRINT_REQUESTED_BIT_POS    2
#define GBP_STATUS_CURRENTLY_PRINTING_BIT_POS 1
#define GBP_STATUS_CHECKSUM_ERROR_BIT_POS     0

Timing

Below measurements was obtained via digilent ANALOG DISCOVERY

                       1.153ms
        <--------------------------------------->
         0   1   2   3   4   5   6   7             0   1   2   3   4   5   6   7
     __   _   _   _   _   _   _   _   ___________   _   _   _   _   _   _   _   _
CLK:   |_| |_| |_| |_| |_| |_| |_| |_|           |_| |_| |_| |_| |_| |_| |_| |_|
DAT: ___XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX____________XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX_
       <-->                           <---------->
       127.63 us                         229.26 us

  • Clock Frequency: 8kHz (127.63 us)
  • Transmission Speed: 867 baud (1.153ms per 8bit symbol)
  • Between Symbol Period: 229.26 us

Here below is the signal captured from the gameboy link cable, with nothing connected to the other side. I was doing this to just understand the general structure of the communication packet, based on existing documentation.


Resources


Findings

Some of the issues I am having with the current project is that there appears to be no flow control between the gameboy and the gameboy printer.

This means I had to increase the speed of the serial link between the arduino and the PC to 115200baud to keep up with the gameboy link speed.

Also I was not able to correctly decode the CRC.


Future

Some things I would certainly like to see improved upon, via other people improving on this project. Is…

  • Get crc working
  • Document the gameboy printer protocol so future hardware hackers can better understand the protocol
  • Provide a consistent C header file for future people to write their own implementation
  • Investigate if there is a way to force flow control
  • Making the js decoder a lib in node.js so it can decode directy from the arduino
  • Creating a proper pcb to make a cleaner gameboy to pc link cable.

Embedded JS Gameboy Printer Decoder

For your convenience, I have also included the decoder below. An example stream is also provided of a blank image.




Your browser doesn't support the HTML5 canvas. :(