Thomas (boggyb) wrote,

Gameboy Printer Simulator part 2: the software

Before I completely forget about it, here's the rest of that Gameboy Printer emulator post. This time, it's about the software.

There's two pieces of software that needed to be written for this: the Bus Pirate needed enough brains to pretend to be a Gameboy Printer, and a PC program needed to be written to actually turn the "printout" into an image. While the interface is slow enough that it could probably all be done on the computer, having the Bus Pirate do some of the work means that there's no timing issues.

The traditional way to do this sort of protocol emulation is to bit-bang it, by directly controlling a GPIO pin. But that's a rather brute-force way of doing things, and modern microcontrollers have a shedload of hardware units for speaking all sorts of different protocols. In the case of the PIC used on the Bus Pirate, it has a pair of SPI modules. These are perfectly capable of running as a SPI slave, which means all my code needs to do is take each byte as it arrives and display it. It also needs to track enough state to be able to send the necessary responses.

I started with the existing SPI sniffer code, and hacked it around until it could send as well as receive. I then added a pair of state machines: one to handle decoding the packets sent by the Gameboy and send the status/acknowledgement replies, and a second to ensure that the right status was sent. If I was writing this from scratch I'd need to come up with some way of getting the data to the computer, but the SPI sniffer mode in the Bus Pirate already has a set of functions for buffering data and feeding it to the serial UART as hex characters. This made it a lot easier to write, as the only really new bits were the state machines.

Once these were written and debugged (with thanks to Tros of #jj2 for spotting that I'd forgotten to actually turn on the output pin), I then just "printed" all the photos to the Bus Pirate and captured the output with a terminal client. This spat out a bunch of hex looking rather like the output from one of the earlier teaser posts. Except this time, I'll tell you how to understand it:


This is the basic packet format from my code. The code uses a mix of square [] and curly {} braces to mark certain things, and a vertical bar | to separate each byte. The curly braces contain the command and flags bytes - a command code of 0x01 is a status request.

The next four lines show the last few bytes of the packet. In each of those lines, the first byte shows what the Gameboy sent and the second shows what the Bus Pirate transmitted (which was actually sampled using the second SPI unit so I could check the bytes were being transmitted at the right time). The first two pairs show the checksum bytes from the Gameboy (which we ignore). For the final two pairs, the Gameboy sends a dummy 0x00 byte and reads in an acknowledgement byte (0x81) followed by a status byte. Simples!

Oh, the actual packet also includes a pair of synchronisation bytes (0x88, 0x33) at the start and two bytes of length immediately after the flags, but my code doesn't bother printing that.


Here the command code is 0x0F, which is a signal to prepare for printing. I've no idea what significance this actually has, if any.

[0xFF|0xFF|0xFF|0xFF| ... |0xFF|0xFF|0xFF|0xFF]

This one is slightly different, as this packet has actual data (which is much longer that what I've put there). The 0x04 command tells the printer that the Gameboy is sending it a chunk of image data, and my code displays this inside the square brackets. More about this image data later.


Finally we get a print command (0x02), which includes in the payload the margins and a value controlling how dark the resulting print is. At this point a real printer would go away and actually print stuff, and the Gameboy would send status commands every so often until the flags byte shows that the printer has finished. My emulation code just waits for about a second - I had some issues with reporting immediate success.

And now you know what the gibberish means.

The next stage is to turn said gibberish into actual pictures. The way the Gameboy encodes the images requires a bit of thought to decode. Rather than sending the data a line at a time, it splits the image into 8 pixel by 8 pixel tiles and sends these a row at a time. Within a tile, each successive pair of bytes encodes a row of pixels, starting with the topmost row in the tile. The first byte has the least significant bit of each pixel and the second byte the most significant bit. I'm sure this format makes perfect sense for the graphics hardware in the Gameboy, but it's rather unfriendly to decode on a PC.

I wrote a decoder in Java that runs through that log and extracts the images from it. It basically extract the image data from the log and does scary bit-mangling to decode the pixel values and draw them on screen, at which point it can be saved as a GIF or whatever. I need to modify it to split out multiple images in the same log - once I've done that, I'll post it online along with my Bus Pirate modifications (or if you can't wait for that - it'll be later rather than sooner - then feel free to ask me for the code). Then I can get started on Mystery Project number 2...
Tags: bus pirate adventures, gameboy, hardware

  • NaBloPoMo!

    It's November, which means it's time for anther month of semi-coherent ramblings! Ironically, despite the current Covid insanity today was much like…

  • End of the Year meme 2019

    Welcome all to a new decade! What did you do in 2019 that you'd never done before? I'm... not sure there was anything new in 2019. Does seeing…

  • NaBloPoMo!

    Yes, it's that time of year where I try to create an entire month's worth of random ramblings! Today ended with a surprise games evening, courtesy…

  • Post a new comment


    default userpic
    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 1 comment