Search › A-Z › A › Acorn Archimedes
Acorn Archimedes
The Acorn Archimedes was the first desktop computer built around the ARM, Acorn's own 32-bit RISC processor. This is Sarah Walker's Arculator emulator compiled to WebAssembly, running an A3000 (Acorn ARM2, 4 MB) and booting RISC OS 3.11 straight to the desktop in your browser.
Runs on: Web browser
Acorn Archimedes Online Emulator
Play Acorn Archimedes using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| RISC OS 3 | Acorn Archimedes | Acorn Archimedes | Acorn RISC OS | grey | Open ⛶ |
Machines emulated
Operating systems
Chips
Notes
Embedding
Arculator is a C emulator that uses SDL2 for video, sound and input. We compiled it to WebAssembly with Emscripten (-sUSE_SDL=2 -sUSE_WEBGL2=1); the emulator owns its own emscripten_set_main_loop, and we drive/inspect it from JavaScript through exported EMSCRIPTEN_KEEPALIVE functions. We self-host everything (no CDN): arculator.js (Emscripten glue), arculator.wasm (the emulator), and arculator.data (a preloaded MEMFS image holding the RISC OS 3.11 ROM, the extension ROM and CMOS).
// Module is configured BEFORE the glue loads; the canvas MUST have id="canvas"
// for Emscripten SDL2. The preloaded arculator.data.js is loaded first, then the
// glue auto-runs main() -> arc_init() -> RISC OS boots on the default arc.cfg.
var Module = {
canvas: document.getElementById('canvas'),
onRuntimeInitialized: function () { publishEmuBoot(Module); } // wire the debugger
};
| Exported hook | What it does |
|---|---|
arc_pause_main_thread() / arc_resume_main_thread() | Stock Arculator hooks: set/clear the flag the main loop checks once per frame. |
arc_dbg_step(n) | Run the ARM core for exactly n instructions (true single step), then stop. |
arc_dbg_run_ms(ms) | Advance one ~50 Hz frame (the debugger "step frame" control). |
arc_key_set(scancode, down) | Set/clear a host key (SDL scancode) for the on-screen keyboard. |
arc_do_reset() | Reset the machine. |
The physical keyboard and mouse need no extra wiring: Emscripten's SDL2 port maintains SDL_GetKeyboardState from the browser's key events, and the mouse runs in RISC OS's absolute-pointer mode over the canvas.
Debugger integration
This is a Tier-4 "WASM core, full debugger" integration: Arculator keeps the ARM state inside the wasm module, so we rebuilt the core with tiny state-export hooks (a new emscripten_debug.c plus four one-line edits). The golden rule holds - the getters only sample state when the debugger asks (~10×/s and once per step); the per-instruction path pays one predictable branch (if (dbg_trap)), and only when a breakpoint, watchpoint or step is actually armed.
| What the debugger needs | How the hook provides it |
|---|---|
| R0-R15 (r15 = PC + PSR on this 26-bit core) | arc_dbg_get_reg(i) / arc_dbg_set_reg(i,v) read & write the core's uint32_t armregs[16] directly - fully writable. |
| Disassembly origin (current PC) | arc_dbg_pc() = (PC-8)&0x3fffffc, matching Arculator's own debugger. |
| Memory (side-effect-free) | arc_dbg_read(addr) wraps the core's readmemf_debug(), which reads RAM/ROM only and never touches an I/O latch. |
| Single step | arc_dbg_step(n) runs the real ARM core for exactly n instructions - a true per-instruction advance, not a time-slice. |
| Execution breakpoints | An address set checked at the end of each instruction (only while armed); on a hit the main loop pauses. |
| Write watchpoints | The core's inline CPU store path (writememb/writememl in arc.h - the fast path RAM writes actually take) flags a hit when a watched word is written; the loop stops after that instruction. |
Exactly what we changed. One new file src/emscripten_debug.c (the exports + the break/watch/step logic) and one header src/emu_dbg.h, plus four minimal edits guarded by #ifdef ARCWEB:
// src/arm.c - end of the execarm() instruction loop
if (dbg_trap && dbg_post_execute()) { total_cycles = 0; break; } // bp/wp/step halt
// src/arc.h - the inline writememb()/writememl() CPU store path
if (dbg_trap) dbg_on_write(a); // watchpoint check
// src/emscripten_main.c - arcloop(), after arc_run()
if (arc_dbg_take_halt()) pause_main_thread = 1; // pause on halt
// src/input_sdl2.c - keyboard_poll_host(), so on-screen keys survive
key[c] = state[c] | vkey[c]; // OR in the overlay
What is real vs approximate. Registers, the PC+PSR word, memory, disassembly, play/pause, single-step, execution breakpoints and write watchpoints are all real and come from Arculator's own core. Register write-back covers the full r0-r15 file and the PSR flag bits. Memory is shown through the MEMC logical map (the addresses the ARM sees); I/O windows read back as 0xff rather than perturbing hardware.
Architecture
The Acorn Archimedes (1987) was the first desktop computer built around the ARM - Acorn's own 32-bit RISC processor. Arculator models the A305-A5000 family; the default here is an A3000: an Acorn ARM2 (ARMv2, a 26-bit machine where r15 holds both the program counter and the processor status), the MEMC1a memory controller, the VIDC video controller and the IOC I/O controller, with 4 MB of RAM, running RISC OS 3.11 from ROM.
arculator.wasm/arculator.js- Arculator 2.2 (Sarah Walker) compiled with Emscripten + our debug hooks.arculator.data- preloaded MEMFS:roms/riscos311/ros311(RISC OS 3.11, 2 MB),roms/arcrom_ext(extension ROM), and CMOS defaults.
How to rebuild from scratch (reproducible).
# toolchain: Homebrew emscripten 6.0.3 on PATH (/opt/homebrew/bin), python3, node
# 1. clone the Emscripten Arculator port (powers archi.medes.live)
git clone https://github.com/pdjstone/arculator-wasm.git && cd arculator-wasm
# 2. fetch the grey RISC OS ROMs from Sarah Walker's official distribution
curl -Ls https://b-em.bbcmicro.com/arculator/Arculator_V2.2_Linux.tar.gz | tar xz roms
# 3. add src/emscripten_debug.c + src/emu_dbg.h and the four #ifdef ARCWEB edits
# (arm.c, mem.c, emscripten_main.c, input_sdl2.c); add emscripten_debug to OBJS.
# 4. modern-clang fixes: CFLAGS += -std=gnu17 -Wno-error; guard hostfs.c bool
# typedef with #ifndef bool; point the file_packager rule at Homebrew's copy.
# 5. build the wasm target (FULL_FAT bundles ROMs + cmos into arculator.data):
make -j8 FULL_FAT=1 wasm
# artefacts: build/wasm/arculator.{js,wasm,data,data.js} -> emulator/archimedes/src/