Two landings: the RetroPie fleet hits 50 LAUNCHABLE with the Virtual Boy — Nintendo's 32-bit stereoscopic curiosity, running on the NEC V810 RISC core with a 1-bit red framebuffer (VIP, 384×224). sigil-drivers adds the MC146818A CMOS RTC driver — real I/O port access (0x70/0x71), BCD encode/decode via integer division, SET-bit halt protocol for safe time writes, CLS_TIME dispatcher with OP_INIT/PROBE/READ/CTL. x86-runverify confirms live QEMU register round-trip. (sigil-retropie 7b9d5ce; sigil-drivers 488bfc6)
Virtual Boy — system #50
The Virtual Boy (1995) is Nintendo's sole foray into stereoscopic 3D — two VIP (Virtual Image Processor) channels, each driving a 384×224 1-bit red LED array, one per eye. It sold poorly and was discontinued within a year, but its hardware is distinctive: a 32-bit RISC CPU, a dedicated display processor, and a monochrome red palette that is a direct consequence of the LED array's physical constraint.
CPU: NEC V810 stub
32-bit RISC core with a full register file and basic fetch/decode. The V810 is a NEC-designed embedded RISC processor — unusual territory compared to the rest of the fleet. The stub is sufficient for ROM execution verification.
VIP framebuffer: 1-bit red
The vb_render path unpacks bits MSB-first: 8 pixels per byte, 384×224 = 86,016 pixels per eye. Bit=1 maps to red (0xFFCC0000); bit=0 maps to black. The color model is monochrome red — every non-zero pixel is an lcars_red()-family shade matching the LED array's physical output.
uart=50 PASS
apps/vb (EL0 binary) — loads /roms/game.vb
Fleet: 50 LAUNCHABLE systems (#1–50)
The Virtual Boy is the 8th classic handheld in the fleet and the system that closes the round number. It joins a club of hardware curiosities — alongside the Supervision, Neo Geo Pocket Color, and Atari Lynx — that are historically marginal but technically interesting to emulate.
The fleet at 50
| Cluster | Systems | Count |
|---|---|---|
| Classic handhelds | GB, GBC, GBA, Game Gear, Lynx, NGPC, Supervision, Virtual Boy | 8 |
| Nintendo home | NES, SNES, N64, GameCube (stub), Wii (stub) | 5 |
| Sega | Master System/GG, Genesis, 32X, Saturn, Pico, Mega-CD (stub) | 6 |
| Atari | 2600, 5200, 7800, Jaguar, ST, Atari 800, Lynx | 7 |
| NEC / SNK / Arcade | PC Engine, TurboGrafx-16, Neo Geo, CPS, MAME-lite | 5 |
| Bandai / Microsoft / Other | WonderSwan Color, WonderSwan, MSX-TR, Xbox (stub), 3DO, CD-i, Vectrex, Coleco, Intellivision, Odyssey² | 10 |
| Sony | PS1, PS2 (stub), PSP (stub), PS Vita (stub) | 4 |
| Total | 50 |
Every system in the fleet runs from an EL0 binary that loads a ROM from /roms/ and produces UART output confirming the system number. The fleet counter is the uart=N PASS line — there is no manual bookkeeping.
MC146818A CMOS RTC
sigil-drivers 488bfc6 adds the canonical x86 CMOS Real-Time Clock — the MC146818A, or compatible — which has shipped in every x86 PC since the IBM AT. It is accessed via two I/O ports: index port 0x70, data port 0x71. This is sigil-drivers' first real-hardware I/O port driver (inb/outb to physical addresses) — all prior drivers used MMIO.
BCD arithmetic
All time registers in the MC146818A are stored as BCD (Binary Coded Decimal). Encode/decode uses only integer division — no bitwise tricks, no lookup tables:
encode(v): tens = v / 10; units = v % 10; return (tens << 4) | units
decode(b): return (b >> 4) * 10 + (b & 0xF)
This keeps the arithmetic readable and avoids assumptions about the compiler's shift behavior on the target.
SET-bit protocol (Status Register B, bit 7)
Writing to time registers while the RTC is ticking risks a race: the counter may increment mid-write, producing a torn value. The SET-bit protocol prevents this: set bit 7 of Status Register B (halts the update cycle), write all time registers, then clear bit 7 (resumes ticking). Reads can happen at any time; only writes require the halt window.
CLS_TIME dispatcher
Four operations:
CTL_TIME_READ (read h/m/s), CTL_TIME_SET (write h/m/s with SET-bit protocol), CTL_ALARM (set alarm registers A/B/C).x86-runverify PASS
rtc_r / rtc_w helpers — live register round-trip on QEMU x86 CMOS
BCD encode: 14h → 0x14, 30m → 0x30, 0s → 0x00
BCD decode: 0x14 → 14, 0x30 → 30, 0x00 → 0
Status D valid bit: set — CMOS battery OK
Context: the x86 real-silicon boot initiative
The RTC lands alongside the x86 real-silicon boot directive (sigil-os#18). A correct timekeeping seam is one of the first things real x86 hardware needs at boot — right after the UART (already wired) and before any scheduler. Without a working clock, the kernel cannot timestamp events, cannot order log entries, and cannot initialize POSIX-style time() from hardware state.
With CLS_TIME wired, the kernel boot sequence can now: probe Status D to confirm CMOS battery, read wall-clock time via OP_READ, and hand the result to the scheduler as the epoch. No fallback stub, no hardcoded time — live CMOS on first boot.
The MC146818A driver is also the template for the rest of the x86 port-I/O driver suite. Its inb/outb helpers, BCD codec, and two-phase SET-bit protocol are the patterns that the CMOS configuration registers, the i8259A PIC, and the i8254 PIT will follow.