SearchA-ZV › Virtual Boy

Virtual Boy

2026 Open source · MIT Online

This is a compact NEC V810 core written from scratch for emulators.org so the Nintendo Virtual Boy (1995) has a live, single-steppable debugger target. It faithfully executes the V810 integer instruction set and renders one eye's framebuffer in the console's signature red-on-black, booting a bundled public-domain homebrew ROM directly in the browser, no plugins, no wasm.

Visit the official site ↗

Runs on: Web browser

Virtual Boy Online Emulator

Play Virtual Boy using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
Red Stripe Framebuffer DemoVirtual BoyNintendo Virtual BoyopenOpen ⛶

Machines emulated

Chips

Notes

Embedding

The Virtual Boy here is a small, self-contained core written for this site: vb-core.js exposes a plain-global VirtualBoy constructor - no bundler, no wasm. Because the CPU, memory and framebuffer are ordinary JavaScript fields, the host page reaches straight into the machine; nothing is hidden behind a wasm heap.

Boot. Construct the machine, install a ROM, then run your own loop that advances the V810 and blits one eye's framebuffer:

var vb = new VirtualBoy();
vb.loadRom(romBytes);                // game-pak ROM (reset vector 0xFFFFFFF0 mirrors into it)
vb.reset();                          // r0..r31 = 0, PC = 0xFFFFFFF0
(function loop(){
  for (var n = 0; n < 250000; n++) vb.step();  // step() = one V810 instruction
  vb.render(ctx, img);                 // left framebuffer -> red on black
  requestAnimationFrame(loop);
})();

The machine is plain objects. Every part the debugger needs is a live field:

MemberKindWhat it does
vb.step()methodExecute exactly one V810 instruction. The single-step primitive.
vb.rfieldThe 32 general registers as an Int32Array (r0 is hard-wired to zero).
vb.pcfieldThe program counter (32-bit).
vb.sr, vb.Z/S/OV/CYfieldSystem registers (EIPC, ECR, PSW…) and the four PSW condition flags.
vb.peek8(addr)methodA side-effect-free byte read of the full 32-bit address space (region-decoded).
vb.write8/16/32(a,v)methodWrite the bus; wrapping onWrite around this is how watchpoints work.
vb.padfieldThe 16-bit game-pad word (a set bit means pressed), read back at 0x02000010.
vb.render(ctx,img)methodBlit the left eye's 384×224 framebuffer as red intensity on black.

Debugger integration

The plug-in virtualboy-debug.js reads the live core from window.EMU_BOOT and hands the shared debugger a description of it; the core itself is untouched.

Own the loop. The boot script runs its own requestAnimationFrame loop. With no breakpoints set it runs a fast batch of vb.step() calls per frame; once a breakpoint exists it checks the program counter before each instruction and pauses on a hit:

while (n-->0) {
  if (bps.has(vb.pc >>> 0)) { running = false; break; }  // PC breakpoint
  vb.step();
  if (!running) break;                                // watchpoint tripped in onWrite
}

Registers. vb.r is read live each refresh and written back through each register's set() (r0 is read-only). PSW is shown as a word plus the individual Z S OV CY ID flags, alongside PC, ECR and the exception shadow registers EIPC/EIPSW.

Watchpoints. The boot sets vb.onWrite, a hook the bus calls on every guest write; a write to a watched address pauses the loop. Memory is exposed as one chip per VB region (game-pak ROM, WRAM, VIP display RAM, save RAM, hardware registers), each read through vb.peek8 - side-effect-free. Disassembly uses the shared v810 decoder added for this machine, covering the V810's Format I–VI integer ISA (reg-reg, imm5/system, Bcond, JR/JAL, 3-operand-imm16 and load/store); unknown encodings show as .word.

Architecture

The Virtual Boy (1995) is Nintendo's stereoscopic 3-D console. Its CPU is the NEC V810 (the Nintendo variant is the "NVC"), a clean 32-bit RISC with 32 general registers, a fixed 16-/32-bit little-endian encoding, and a red-only vibrating-mirror display driven by the VIP (Virtual Image Processor).

This core models what a debugger target needs and no more:

  • V810 CPU - an interpreter of the integer instruction set (Formats I–VI): reg-reg ALU, immediate and system ops, conditional branches, JR/JAL, the 3-operand MOVEA/ADDI/ORI/ANDI/XORI/MOVHI forms, and LD/ST/IN/OUT. Floating-point and bit-string ops are decoded but not executed.
  • Memory map - region-decoded by address bits 26..24: VIP display RAM at 0x00000000, sound at 0x01000000, hardware registers (game pad, timer) at 0x02000000, 64 KB WRAM at 0x05000000, save RAM at 0x06000000, and the game-pak ROM at 0x07000000 (the reset vector 0xFFFFFFF0 mirrors into it).
  • Display - the left framebuffer is 384×224, 2 bits per pixel, stored column-major (64 bytes per column). The renderer maps the four brightness levels to red intensity on black, the real Virtual Boy look; the right eye is emulated identically but only one is shown.
  • Game pad - the 16-bit controller word (two D-pads, A/B, L/R triggers, Start, Select) is read back at 0x02000010/0x02000014.

The bundled ROM is a public-domain homebrew demo authored for this site: its V810 code fills the framebuffer with graded red stripes and polls the pad, so it is a guaranteed non-black, single-steppable target. A full commercial Virtual Boy game would additionally need the VIP world/BGMap compositor and VSU audio, which this minimal core does not implement.