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:
- Github Repo: arduino-gameboy-printer-emulator
This projects consist of two parts:
- Arduino sketch emulating a gameboy printer to a computer via a serial link.
- 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.
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_one_A03.png - A girl and her mother?
- cart_one_A04.png - A woman
- cart_one_A05.png - Black Image
- cart_one_A13.png - White Image
- 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_A27.png - A grandmother
- cart_one_A28.png - A guy and a girl
Not as many images in this cart
- 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
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
- 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
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.
- https://github.com/gism/GBcamera-ImageSaver - Eventally found that someone else has already tackled the same project.
- However was not able to run this sketch, and his python did not run. So there may have been some code rot.
- Nevertheless I was able to get some ideas on using an ISR to capture the bits fast enough.
- http://gbdev.gg8.se/wiki/articles/Gameboy_Printer - Main gb documentation on gb protocol, great for the inital investigation.
- http://furrtek.free.fr/?a=gbprinter&i=2 - Previous guy who was able to print to a gameboy printer
- http://playground.arduino.cc/Main/Printf - printf in arduino
- Backup if above link is dead here
- Most detailed writeup on the protocol I found online.
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.
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.