Plus/4
An in-browser Commodore Plus/4 emulator written for emulators.org in plain JavaScript. It reuses a 6502 interpreter and adds the machine's single custom chip, the TED (7360/8360), for video, interval timers, the raster interrupt and keyboard, plus the Plus/4 memory banking. The bundled BASIC 3.5 and KERNAL ROMs mean it boots straight to the Commodore READY. prompt with no downloads, and because the CPU, memory and TED are ordinary JavaScript objects the whole machine steps and inspects live in the shared debugger.
Runs on: Web browser
Plus/4 Online Emulator
Play Plus/4 using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Plus/4 BASIC | Plus/4 | Commodore Plus/4 | grey | Open ⛶ |
Machines emulated
Chips
Notes
Embedding
The Plus/4 here is a set of plain-global JavaScript modules (no bundler). Load the reused 6502 core (cpu6502.js), the base64-embedded ROMs (roms.js) and the machine (plus4-machine.js), then drive the machine from your own loop so the debugger can pause and single-step it.
Boot. Install the two 16 KB ROMs, reset (which loads PC from the $FFFC KERNAL vector), point the renderer at a <canvas>, then run your own loop built on mos6510.process() (one instruction, returns its cycle count) feeding Plus4.tick() so the TED timers and raster interrupt advance:
Plus4.setRoms(Plus4Roms.basic, Plus4Roms.kernal);
Plus4.reset();
(function frame(){
Plus4.mem._frame = false;
while (!Plus4.mem._frame) { // run one PAL frame
var c = mos6510.process(); // one 8501 instruction
Plus4.tick(c); // timers + raster IRQ
}
Plus4.renderInto(ctx, canvas.width, canvas.height);
requestAnimationFrame(frame);
})();
The machine is plain objects. Everything the debugger needs is a live global:
| Member | Kind | What it does |
|---|---|---|
mos6510.process() | method | Execute one instruction; returns its cycle count. The single-step primitive. |
mos6510.register | field | Live registers: .a .x .y .pc .sp and .status. |
Plus4.readByte(a) / writeByte(a,v) | method | The banked CPU bus (RAM under BASIC/KERNAL ROM, TED I/O at $FF00). |
Plus4.busReadSafe(a) | method | Side-effect-free read for the debugger; never toggles banking or latches. |
Plus4.tick(cycles) | method | Advance TED: the three timers plus the raster counter and its interrupt. |
Plus4.keyDown(id,shift) / keyUp(id) | method | Drive the keyboard matrix (id = col*8+bit). |
Debugger integration
Because the CPU, memory and TED are ordinary JavaScript, the debugger integrates with no changes to the core. The boot loop publishes window.EMU_BOOT with a transport the shared framework drives:
- Single-step calls
mos6510.process()once and ticks the TED by the returned cycles. - Execution breakpoints are a
Setof PC values; when non-empty the loop runs instruction-by-instruction and halts before any matchingmos6510.register.pc. - Write watchpoints hook
Plus4.mem.onWrite, so any store to a watched address pauses the machine promptly. - Registers are read and written straight off
mos6510.register; memory views read throughPlus4.busReadSafeso auto-polling never disturbs the TED.
The disassembler is the shared mos6502 decoder. The 8501 is a 6502 with an on-chip I/O port, and on the Plus/4 the banking is done through TED registers rather than that port, so the stock decoder is exact.
Architecture
The Plus/4 (Commodore 264 series, 1984) is a 6502-class machine whose single custom chip, the TED, does almost everything:
mos6510The reused 6502 interpreter standing in for the MOS 7501/8501.process()runs one instruction.Plus4memory - 64 KB RAM with BASIC ($8000-$BFFF) and KERNAL ($C000-$FFFF) ROM banked in for reads; writes always reach RAM. Reads or writes of$FF3E/$FF3Fswitch the ROM in and out.Plus4.ted- the MOS 7360/8360: three interval timers, the raster counter and raster interrupt, the interrupt status/mask registers ($FF09/$FF0A) and a 40x25 text renderer reading the video matrix at $0C00, colour RAM at $0800 and the character generator inside the KERNAL ROM.- keyboard - the 6529 column latch at
$FD30selects columns and the TED latch$FF08reads the rows of the 8x8 matrix.
Sound (the TED's two-voice tone generator) is not emulated; everything the KERNAL needs to reach BASIC and scan the keyboard is.