Arduboy
This runs the Arduboy open-source handheld in your browser. A real ATmega32u4 (AVR) drives a 128x64 OLED, six buttons and a piezo speaker, running real MIT-licensed homebrew game .hex files. The AVR core is Wokwi's avr8js, and it is wired to a full AVR debugger for single-stepping the machine code, reading and writing the registers, and watching flash, SRAM and I/O.
Runs on: Web browser
Arduboy Online Emulator
Play Arduboy using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Dash (Arduboy Edition) | Arduboy | Arduboy | open | Open ⛶ | |
| Minesweeper | Arduboy | Arduboy | open | Open ⛶ | |
| Dot (Arduboy Edition) | Arduboy | Arduboy | open | Open ⛶ | |
| Crate Confusion | Arduboy | Arduboy | open | Open ⛶ |
Machines emulated
Chips
Notes
Embedding
The Arduboy is an Atmel ATmega32u4 (8-bit AVR at 16 MHz) with a 128x64 1-bit OLED, six buttons and a piezo. It runs on avr8js — Wokwi's TypeScript AVR simulator, bundled once to a browser global (window.avr8js) with esbuild; nothing in the core is patched. We build the Arduboy board around the core and own the run loop so the debugger can drive it.
Boot. Parse the game's Intel-HEX into a little-endian Uint16Array of flash words, construct a CPU with 2560 bytes of SRAM (so SP resets to 0x0AFF, the real 32u4 RAMEND), build the peripherals, then run avrInstruction(cpu) + cpu.tick() to exactly 16 MHz worth of cycles per video frame:
var cpu = new avr8js.CPU(flashWords, 2560); // SP -> 0x0AFF (32u4 RAMEND)
var board = ARDUBOY.buildBoard(cpu, avr8js); // ports B-F, SPI, Timer0/1/3, OLED, speaker
var CYCLES = 16000000 / 60; // one video frame of AVR time
for (var s = 0; s < SAMPLES; s++) { // SAMPLES = round(sampleRate/60)
var target = start + Math.round((s + 1) * CYCLES / SAMPLES);
while (cpu.cycles < target) { avr8js.avrInstruction(cpu); cpu.tick(); }
buf[s] = board.speakerLevel(); // sample the piezo pins at audio rate
}
Everything is plain JavaScript state — no wasm heap. cpu.pc is a flash word index; cpu.data is the whole data space (R0-R31 at 0x00-0x1F, I/O registers, SP at 0x5D/0x5E, SREG at 0x5F, then SRAM); cpu.progBytes is flash as bytes. Interrupts (Timer0 millis, Timer3 audio, SPI) are serviced inside cpu.tick(), so a plain instruction+tick loop runs the whole machine, and the debugger single-steps it with one avrInstruction.
Debugger integration
The plug-in (arduboy-debug.js) describes the ATmega32u4 to the shared debugger and reuses the AVR disassembler added for the Arduino build:
- Decoder. Reuses
/debugger/src/cpus/avr.js(decoder'avr') — the full 8-bit AVR set: ALU ops, theLDI/CPI/SUBIimmediates,MOV/MOVW, the X/Y/ZLD/STforms andLDD/STD, the 2-wordLDS/STS/JMP/CALL, theBRxxfamily,IN/OUT, the bit/skip ops and the SREG ops. - Registers read live each refresh: R0-R31, the pointer pairs X/Y/Z, SP, PC (as a flash byte address so it lines up with the disassembly + breakpoints) and SREG broken out into
I T H S V N Z C. Each has aset()writing straight back intocpu.data. - Memory is three side-effect-free chips: Flash (
cpu.progBytes, disassembled), the Data space (regs + I/O + SRAM) and a focused I/O-register window over0x20-0xFF. - Single step is one
avrInstruction(cpu). Breakpoints are host-side checks ofcpu.pc*2against a set of flash byte addresses. Write-watchpoints wrapcpu.writeDataand pause the loop the moment a watched data-space address (e.g.PORTCat0x28, the speaker) is written.
Architecture
The Arduboy (2015, Kevin Bates) is a credit-card-sized open-source handheld built on a single microcontroller — no external logic. This build models it faithfully:
- ATmega32u4 — 8-bit AVR at 16 MHz, 32 KB flash (word-addressed), 2.5 KB SRAM (
SPresets to0x0AFF). avr8js ships 328P peripheral configs; the 32u4's GPIO ports (B,C,D,E,F) and SPI sit at the same addresses, so those are reused — but the interrupt vectors differ, so the timer configs are cloned and re-vectored, and a Timer3 config the 328P lacks is built for the audio timer. - SSD1306 128x64 OLED over hardware SPI (SCK=PB1, MOSI=PB2, CS=PD6, DC=PD4, RST=PD7). The command/data protocol is decoded from the SPI byte stream (DC selects command vs data); the Arduboy streams the whole 1024-byte page buffer each frame in horizontal-addressing mode, and the framebuffer is rendered 1:1 to the canvas.
- Six buttons on their real port pins — LEFT=PF5, RIGHT=PF6, UP=PF7, DOWN=PF4, A=PE6, B=PB4 — active-low with pull-ups (released = high, pressed = low), driven from the keyboard / on-screen pad.
- Piezo speaker on PC6 (OC3A) + PC7, driven by Timer3 (ArduboyTones' CTC compare-match ISR, or Arduboy2's hardware OC3A toggle). A small EEPROM and avr8js's ADC are added so score-saves and random-seed reads behave.
The pin map is taken directly from the open-source Arduboy2 library (Arduboy2Core.h). Because the games are real AVR machine code, every instruction single-steps in the debugger.
Sound
Pattern S (authored chip, from the pins). The Arduboy has no sound chip — the piezo is toggled directly, either by Timer3 in CTC mode driving the OC3A hardware pin (Arduboy2 beep) or by the Timer3 compare-match ISR toggling the port in software (the ArduboyTones library). Both are emulated: a 32u4 Timer3 config (register block at 0x90, OC3A = PC6, compare/overflow vectors re-mapped to the 32u4 table) is added to avr8js, so the CPU actually toggles the speaker pins.
Sound is captured straight off those pins: each audio sample, the machine is run to the corresponding cycle count (real 16 MHz timing, so pitch is exact — no resampling) and the differential level of PC6 vs PC7 is read as -1 / 0 / +1 and scaled to an Int16. Exactly round(EmuAudio.sampleRate/60) interleaved-stereo samples are EmuAudio.push()-ed per video frame.
The mute contract is the standard one: transport.setMute / transport.isMuted delegate to EmuAudio, and it starts muted until the Sound button's real click. Caveat: the piezo is silent until a game plays a tone (many Arduboy games beep on menu / jump / collision events), and single-pin square-wave audio is intentionally buzzy — that is how the hardware sounds.