Search › A-Z › V › VIC-20 Emulator (mwenge)
VIC-20 Emulator (mwenge)
A pure-JavaScript Commodore VIC-20 emulator (mwenge's docs/vic20 core, a Willem-Dawson-style 6502 machine). It emulates the 6502 CPU, the VIC-6560/6561 video-and-sound chip and the two 6522 VIAs, boots straight to Commodore BASIC 2.0, and takes keyboard input. On emulators.org it is wired into the shared in-browser debugger, so you can single-step the 6502, set breakpoints and inspect memory.
Runs on: Web browser
VIC-20 Emulator (mwenge) Online Emulator
Play VIC-20 Emulator (mwenge) using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| VIC-20 BASIC | VIC-20 Emulator (mwenge) | Commodore VIC-20 | grey | Open ⛶ |
Machines emulated
Chips
Notes
Embedding
mwenge's VIC-20 is a set of plain-global JavaScript modules (no bundler). Vendor them and load them in dependency order, then drive the machine yourself instead of calling vic20.execute() - its internal setTimeout loop cannot be paused or stepped from outside, which the debugger needs.
Boot. Construct the machine (it installs the CHARGEN / BASIC / KERNAL ROMs into mem and points the VIC-6560 at the <canvas id="canvas">), then run your own loop built on vic20.cycle() (one machine clock: steps both VIAs, the CPU and the VIC):
window.vic20 = new Vic20(); // must be the global 'vic20' (chip callbacks read it)
vic20.isPal = false; kerneldata = kerneldataNtsc;
vic20.init(); // builds CPU / VIAs / VIC, installs ROMs, resets
var CYCLES = 16965; // ~1.02 MHz / 60 Hz
(function loop(){
for (var i = 0; i < CYCLES; i++) vic20.cycle();
requestAnimationFrame(loop);
})();
The machine is plain objects. Everything the debugger needs is a live global, with no wasm heap to reach into:
| Member | Kind | What it does |
|---|---|---|
vic20.cycle() | method | Run one machine clock (VIAs + one CPU sub-cycle + VIC). The stepping primitive. |
vic20.cpu.isNextInst() | method | True when the next cycle() will fetch a fresh opcode, the instruction boundary used for single-step and PC breakpoints. |
vic20.cpu.getPc() | method | Live program counter (checked against the breakpoint set at each boundary). |
vic20.cpu.getRegisters() | method | Live registers {pc,sp,a,x,y,p}. |
vic20.cpu.setA/setX/setY(hex) | method | Write A/X/Y (upstream, hex-string arg). We added numeric setPc/setSp/setP so the debugger can write PC/SP/P too. |
vic20.invisibleRead(a) / invisibleWrite(a,v) | method | Side-effect-free bus access, reads VIC/VIA without clearing latches, for a live hex view. |
mem | field | The raw 64 KB memory array, under the ROM/I/O routing. |
keysdown | field | The 8-byte VIC-20 keyboard-matrix state the VIA scans; press = set a row,col bit. |
Because the CPU, bus and RAM are ordinary JavaScript, the debugger single-steps by running cycle() to the next instruction boundary, reads and writes registers straight through the CPU's get/set methods, and implements breakpoints and watchpoints as host-side checks around the loop. The only change to the core is a three-line numeric setPc/setSp/setP patch.
Debugger integration
The plug-in (mwenge-vic20-debug.js) hands the shared framework the machine surface and nothing else:
- Registers come from
vic20.cpu.getRegisters()each refresh and are written back withsetA/setX/setY(hex) and the added numericsetPc/setSp/setP; the status flags toggle bits ofP. - Memory is exposed as five chips: the side-effect-free CPU bus (
invisibleRead/invisibleWrite), the raw 64 KB RAM, and the BASIC / KERNAL / Character ROM windows. - Single step runs
cycle()untilcpu.isNextInst(), i.e. exactly one instruction. - Breakpoints and watchpoints are host-side: the boot loop checks the PC against a set at each instruction boundary, and wraps
vic20.writeto catch a watched address.
Architecture
The VIC-20 (1981) was Commodore's first colour home computer: a 6502, the VIC-6560/6561 video-and-sound chip, two 6522 VIAs for I/O, and Commodore BASIC 2.0 in ROM. mwenge's emulation keeps each as its own object, clocked in lockstep one cycle at a time:
Cpu6502- the 6502 core, driven a sub-cycle at a time via a micro-op table;cycle()advances it.Vic6560- the VIC video/sound chip, rastered into the canvas (text and the standard multicolour modes).Via6522×2, the timers, keyboard-matrix scan and joystick/tape lines.mem- the flat 64 KB array;vic20.read/writeroute reads and writes to RAM, ROM or the VIC/VIA registers.- The CHARGEN, BASIC and KERNAL ROMs are embedded (packed) in
carts.jsand copied intomemon reset.
It boots straight to **** CBM BASIC V2 **** - a complete, inspectable machine with nothing to load.