
I built physics-model-based RetroArch shaders for the original Game Boy and AGS-101 LCDs
I recently built a pair of RetroArch shaders that try to recreate the original display characteristics of the first-generation Game Boy and the backlit GBA SP AGS-101.
Many handheld shaders begin with an imagined “retro screen” color and then blend a few previous frames to create ghosting. That can look nostalgic, but nostalgia is not always accuracy.
Some Game Boy shaders become extremely bright green. Others look more like a generic calculator or electronic-organizer LCD than an original Game Boy. Both may feel old, but they are still interpretations of what people remember an old screen looking like.
I wanted to approach the problem differently.
Here are two screenshots with my Game Boy shader enabled. The first scene exposes row and column crosstalk, while the falling piece in the second image makes the LCD response and ghosting easier to see.
My approach can be summarized in four words:
Measure first, then calculate.
For color, I used measured and color-managed reference data for the original displays, including their color, grayscale and black-level behavior. That data is then converted correctly to sRGB instead of being approximated with a green tint.
On a reasonably accurate sRGB display, the result should therefore be much closer to the original screen colors—not simply someone’s memory of what a Game Boy looked like.
The second part is the display model itself.
A real LCD does not create ghosting by blending several complete frames. Each liquid-crystal pixel has a previous state, receives an electrical drive signal and takes time to move toward its next state. Bright-to-dark and dark-to-bright transitions do not necessarily happen at the same speed.
My shader first converts the game image into simulated electrical drive values. It then calculates how the virtual liquid-crystal pixels respond over time while preserving their previous states.
For the original Game Boy, the model also accounts for the shared row and column drive structure of its passive-matrix screen. This means ghosting, crosstalk and residual images are produced by the evolving display state rather than being painted over the final image as a blur effect.
The GBA SP AGS-101 uses a very different type of LCD, so I built a separate model for it. Its pixels respond faster, but different color and brightness transitions still have different response characteristics. Its measured color behavior, black level, scanning and pixel structure are handled separately from the Game Boy model.
The comparison below shows raw emulator output on the left and the AGS-101 shader on the right. The difference is not only saturation: the color balance, black level, tonal depth and pixel appearance all change.
The models were not tuned only by eye. During development, I used original display measurements, drive and timing information, historical LCD research, and experimental data from similar materials and panels from the same era.
Where complete original panel data no longer exists, I used historically appropriate research to constrain the model instead of inventing values based on appearance alone.
All screenshots in this post were rendered in RetroArch on a KONKR Pocket Advance and captured directly from its 960×640 framebuffer:
- GBA content uses an exact 4× mapping from 240×160 to 960×640.
- Game Boy content uses an exact 4× mapping from 160×144 to a 640×576 viewport.
These are direct captures of the shader’s GPU output on the handheld, not photographs of its physical panel.
The project is now open source and can be used with RetroArch. Download it, extract it into the RetroArch shaders directory, and load the appropriate preset. Any frame-mixing option inside the emulator core should be disabled so the temporal response is not calculated twice.
GitHub and download: https://github.com/JohnnySun/retro-display-lab