Search › A-Z › V › Virtual Boy
Virtual Boy
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.
Runs on: Web browser
Virtual Boy Online Emulator
Play Virtual Boy using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Red Stripe Framebuffer Demo | Virtual Boy | Nintendo Virtual Boy | open | Open ⛶ |
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:
| Member | Kind | What it does |
|---|---|---|
vb.step() | method | Execute exactly one V810 instruction. The single-step primitive. |
vb.r | field | The 32 general registers as an Int32Array (r0 is hard-wired to zero). |
vb.pc | field | The program counter (32-bit). |
vb.sr, vb.Z/S/OV/CY | field | System registers (EIPC, ECR, PSW…) and the four PSW condition flags. |
vb.peek8(addr) | method | A side-effect-free byte read of the full 32-bit address space (region-decoded). |
vb.write8/16/32(a,v) | method | Write the bus; wrapping onWrite around this is how watchpoints work. |
vb.pad | field | The 16-bit game-pad word (a set bit means pressed), read back at 0x02000010. |
vb.render(ctx,img) | method | Blit 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-operandMOVEA/ADDI/ORI/ANDI/XORI/MOVHIforms, andLD/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 at0x00000000, sound at0x01000000, hardware registers (game pad, timer) at0x02000000, 64 KB WRAM at0x05000000, save RAM at0x06000000, and the game-pak ROM at0x07000000(the reset vector0xFFFFFFF0mirrors 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 at0x02000010/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.