20 December 2022
I present to you: The GB Interceptor. It is an adapter that goes between an unmodified Game Boy and the cartridge and offers a video stream of the game via USB.

The video above should give you a good overview of what it does, how it works and what its limitations are. This article here goes more into the technical details of how it works. If you are interested in how to order and build your own GB Interceptor, check out github and the order and build video.
Why do we need this?
The best way to explain why1 I developed and built the GB Interceptor is to explain which problem I tried to solve with it. A few months ago a Tetris enthusiast got in touch with me about this problem: An online Tetris tournament during which the contestants stream their gameplay.
Today, there is nothing unusual about streaming footage from a Game Boy. Emulators can easily do it and modern Game Boy variants like the Analogue Pocket offer HDMI output that could be captured. There also are some mods to add HDMI out to original Game Boy hardware, so getting a video stream from a Game Boy is a challenge that has long been solved.
The unusual detail about doing it for a Tetris tournament is that the players have to rely on their muscle memory which they trained on their personal Game Boys. Switching them for an unfamiliar modern device or an emulator will significantly impede their ability to play competitively. Also, you can imagine that a tournament that asks each contestant to first mod the hell out of their beloved Game Boys just to stream a video would not be well received.
So, we need a way to get a video from unmodified Game Boys also without modifying the game that is being played. Ideally in a form that can be used by anyone without complicated software or additional hardware like an HDMI grabber.
Basic concept of how it works
Well, in the end, the only connector with game data that is accessible on a Game Boy without a mod is the cartridge slot2. After all, the entire game data has to go through there. So, the idea is to create an adapter that connects the cartridge to the Game Boy directly and only adds the capability to intercept a copy of the transferred data.
However, this means that we cannot randomly access data of interest and we cannot see the data in RAM that the Game Boy’s CPU put together from the raw instructions from the cartridge. Especially, we cannot see the Video RAM, which would have been very nice as it would contain everything3 required to draw the image on screen. Instead, we need to create our own copy of VRAM.
To do so, I had to write an emulator to which I feed the data from the cartridge memory bus. For this I use an rp2040 (the Raspberry Pi Pico’s microcontroller) and split its cores to the two main processing parts of the Game Boy. One core emulates the CPU to recreate a copy of VRAM and the other core emulates the Game Boy’s graphics unit, the PPU4.
The CPU emulation actually is the trickiest part here, because it has to keep up with the memory bus that is pushing out events at a rate of about 1 MHz. If the PPU emulation falls behind, it would cause a short glitch like a flicker, but if the CPU emulation falls behind, it will eventually miss an event on the memory bus. Not only would the simulated copy of the RAM possibly get out of synch forever, but the emulator would not even be able to interpret the following instructions. An event on the bus is not always the next instruction, because the Game Boy’s CPU may take several cycles to execute some instructions while others are completed within a single cycle. So, the emulator has to keep track of how many cycles have to be ignored after a specific instruction before an event should be considered to be an instruction again. If we miss only one of them it becomes nearly impossible to get this right again.
This together with the overhead of emulating an 8-bit CPU on a 32-bit CPU made it necessary to overclock the rp2040 from its default 125 MHz5 to 225 MHz. The rp2040 can usually handle this without any problems, but still I would love to see if someone can improve the efficiency of my code to dial this back a bit.
Since the PPU emulation is not that critical and actually periodically gets some free time during the Game Boy’s vblank period when no image is being drawn, it also handles USB communication.
The hardware
The actual hardware to implement this is pretty much a Raspberry Pi Pico with some bus transceivers to connect its GPIO ports to the cartridge bus. From the 32 pins of this bus, two are used for +5V and ground, one is used for analog audio6 and one is used to control the reset state of the Game Boy. The other 28 pins are connected to the rp2040, which therefore gets access to 16 address pins, 8 data pins and the four bus control pins clock, read, write and chip select. Since these use 5V logic I use the same bus transceivers that already served me well in the WiFi Game Boy cartridge to convert the signals to 3.3V for the rp2040.
This leaves two GPIOs unused. One observes the voltage on the +5V line to check if the Game Boy is turned on or not and the other one controls a status LED and reads a mode button.
The rest of the cartridge is based on the minimal hardware design example for the rp2040 by the Raspberry Pi Foundation. This includes an oscillator, flash memory, a voltage converter and a USB port, which I replaced by a Type C variant.
That’s pretty much it. A Raspberry Pi Pico in Game Boy cartridge format hooked up to the Game Boy’s memory bus. The schematics and PCB designs can of course be found in the project’s github repository.
Implementation
What really let’s the GB Interceptor do what it does is its software, which can of course also be found on github. In the following I will write about some of its details.
USB video class
The GB Interceptor streams the resulting image using the USB video class implementation of TinyUSB, so in theory no drivers are needed and it should just show up as a webcam. Well, in theory. Unfortunately, this only works as expected on Linux, where I can directly use the GB Interceptor in VLC, OBS, Zoom or ffmpeg. On Windows and Android many apps seem to have trouble with the format of the video stream. On Windows, for example, VLC (despite working on Linux) complains that no suitable format could be found while OBS works perfectly fine without any settings or drivers required. On Windows this is good news because you can use OBS as a virtual webcam to forward the GB Interceptor stream to any software that is picky about the format. A list of tested host software can be found on github.
Unfortunately, at the time of this writing I was not able to get any video on MacOS and I am not yet sure why. For some reason it does not even trigger TinyUSB to enable the video stream, so I am not entirely convinced that it is the format. Keeping in mind that I have not yet done many tests on MacOS and that the video class implementation in TinyUSB is very recent and experimental, I hope that I can fix this in the future. Even if I could not get the video class to work here, it should be possible to pump the images through UART on the USB bus and use a simple Python script to convert it to a video stream on the system. You can check the curren