Recreating the Game Boy Color Boot Animation as an 88Ă31 Web Button with ImageMagick
This article walks through extracting the 175âframe boot animation from the Game Boy Color ROM, converting it into a webâfriendly 88Ă31 button, and seamlessly integrating a custom grey background while preserving the original fade transition. Using the SameBoy emulator, a detailed breakpoint strategy, and a full ImageMagick command pipelineâincluding colour remappingâauthors can reproduce a polished GIF button suitable for modern personal sites.
## Background
The Game Boy Colorâs boot animation is a classic example of tight, frameâaccurate sprite work. Over the past few years the retro webâbutton style has resurfaced, and a 88Ă31 button featuring the classic "+Game Boy+" logo is a popular choice for personal sites.
Rather than design the logo from scratch, the goal here is to extract the original animation from the boot ROM, scale it accurately, and wrap it in the standard greyâborder button frame that matches the ubiquitous 88Ă31 design.
## Extracting the Raw Frames
The boot animation is embedded in the official Nintendo boot ROM, a 32âŻkB binary. The easiest way to capture each frame is to run the ROM in an emulator that supports breakâpoints on the Game Boy Color. SameBoy is a lightweight, wellâdocumented option.
### Identifying the VBlank Loop
The animation is paced by the hardware VBlank interrupt. The disassembly of the ROM (e.g. the communityâdumped, labelled source) shows a routine called `Wait_for_next_VBLANK` (addressâŻ$0211). By setting a breakpoint here and stepping through, each return to the routine corresponds to the completion of one frame.
### Capturing Screenshots
SameBoy exposes an `âS` hotâkey that outputs the current LCD framebuffer to disk as a PNG at the native 160Ă144 resolution, independent of the host display.
> **Scripted workflow**
> 1. Reset and set a breakpoint on `sub_0291` (the routine that calls `Wait_for_next_VBLANK`).
> 2. Continue execution until the breakpoint.
> 3. Capture a screenshot.
> 4. Repeat until the animation restarts.
>
This produces 175 singleâframe PNGs. ImageMagick can then be used to assemble these into a GIF:
```bash
magick -delay 1.6742706299 -loop 0 *.png animation.gif
```
The delay value is derived from the hardware clock (â0.0167âŻs per frame).
## Resizing & Framing the Logo
The raw animation contains the full 127âŻĂâŻ22 pixel âGame Boyâ text logo at coordinates (16,âŻ48). To reuse it in a standard 88Ă31 button we need to:
1. **Crop** the logo out of the full 160Ă144 frames.
2. **Scale** it to fit the 88Ă31 area while preserving the aspect ratio.
3. **Embed** it in a grey border and pad the remainder of the frame.
4. **Replace** any white background with the chosen grey color.
Each step is performed in a single ImageMagick pipeline:
```bash
magick animation.gif \
-crop 127x22+16+48 +repage \
-fill #C0C0C0 -opaque #FFFFFF \
-resize 82x \
-gravity center \
-background #C0C0C0 \
-extent 88x31 \
-coalesce null:frame.png \
-layers composite \
button.gif
```
Explanation:
- `-crop` isolates the logo.
- The `-opaque` replace removes the white background.
- `-resize 82x` respects the aspect ratio (82Ă14).
- `-gravity center` and `-extent` pad the image within an 88Ă31 canvas.
- `-coalesce null:frame.png` applies the classic 2âpixel grey border.
## Handling FadeâtoâWhite Artefacts (âGhostingâ)
The original boot animation fades the logo from deep blue to pure white. When the background is replaced with grey (#C0C0C0), the transition produces a faint ghostâlike halo.
### Extracting Transition Colours
A histogram of the final frames reveals a tidy list of 26 colours that form the blueâtoâwhite gradient:
```text
#006BFF ⊠#FAFBFF, #FFFFFF
```
The fade can be remapped to transition from the same blue start to grey end. A Python helper converts each hex colour into an equivalent in the new range:
```python
from math import lerp
# Example mapping for one colour
start_old = (0x00, 0x6B, 0xFF)
end_old = (0xFF, 0xFF, 0xFF)
start_new = (0x00, 0x6B, 0xFF)
end_new = (0xC0, 0xC0, 0xC0)
def remap(c):
r,g,b = c
t = (r - start_old[0]) / (end_old[0] - start_old[0])
return tuple(int(lerp(a,b,t)) for a,b in zip(start_new,end_new))
```
The script outputs a sequence of `-fill/-opaque` pairs that replace each original colour with its new counterpart.
### OneâShot ImageMagick Replacement
Inserting those pairs into the earlier pipeline achieves the remapped fade in a single command:
```bash
magick animation.gif \
-crop 127x22+16+48 +repage \
-fill #006BFF -opaque #006BFF \
-fill #056DFE -opaque #066CFF \
... \
-fill #C0C0C0 -opaque #FFFFFF \
-resize 82x \
-gravity center \
-background #C0C0C0 \
-extent 88x31 \
-coalesce null:frame.png \
-layers composite \
button.gif
```
(The `...` represents the full list of 26 colour pairs.)
## Result & Integration
The final `button.gif` is an 88Ă31 animated GIF with a classic 2âpixel grey border, the Game Boy logo rendered in its original style, and a clean grey background that eliminates ghosting.
Embedding is straightforward:
```html
```
Feel free to host the GIF locally or integrate it into your preferred static site generator.
## Takeaways
* **Extracting ROM assets** can be done reliably with an emulator and a small debugging workflow.
* **ImageMagickâs pipeline** handles cropping, scaling, colour remapping, padding, and framing in a single command chain, showcasing its power for complex webâgraphics transformations.
* **Colour remapping** is critical when adjusting legacy hardwareâspecific visuals for modern color palettes: a handful of RGB conversions can eliminate visual artefacts.
This process illustrates how classic retro graphics can be harvested, sanitized, and repurposed for contemporary web design, while staying true to the original artwork.