Chris Collins

Tools · retro

Commodore VIC-20: emulator, BASIC, assembler and debugger

A Commodore VIC-20 in your browser — PAL or NTSC, unexpanded or with 3 to 35 KB of expansion, the VIC chip's 22 × 23 screen, colours, multicolour and custom characters, its three voices and noise, both 6522 VIAs, keyboard and joystick (gamepad too). It boots Microsoft's open-source BASIC 1.1 on a KERNAL written for this site, or your own ROMs; loads PRG, D64 disks, TAP tapes and cartridges, and saves to disk and tape. Write 6502 assembly and debug it beside the code.

Added

How to use it

The VIC-20 was Commodore’s first colour home computer (1980): a 6502 at about 1 MHz, 5 KB of RAM, and the VIC chip for its chunky 22-column screen and sound. Press Power on (or Assemble & run in the Assembly tab) and it boots to READY.. Click the screen to give it the keyboard.

Commodore’s ROMs are still under copyright, so this page doesn’t ship them. Instead it runs Microsoft’s BASIC 1.1 for the 6502 — the BASIC Commodore’s own was built from, released by Microsoft under the MIT licence in 2025 — on a KERNAL written for this site. If you own the ROM dumps, load them and it’s a stock VIC-20.

How to use it

  • Type BASIC on the screen: 10 PRINT CHR$(205.5+RND(1));:GOTO 10, RETURN, RUN. RUN/STOP (Esc) breaks; the screen editor works as on the real machine, so you can move the cursor onto any line, change it and press RETURN. Type into the computer on the Run tab types a whole listing for you, and BASIC examples… has a few (the maze, colours, a scale, a bouncing ball, saving to disk). Pasting onto the screen types too.

  • Programs: drop a .PRG on the screen and it’s loaded and started (RUN for BASIC, SYS for machine code). A .D64 goes into the disk drive and a .TAP into the Datassette; with Start programs automatically the first program runs. Cartridges (.CRT from VICE, a raw 4/8 KB .A0/.BIN, or a PRG loading at $A000, $2000, $4000, $6000) start at reset.

  • Disk drive and Datassette: in BASIC, LOAD"$",8 and LIST show the directory, LOAD"NAME",8 (or ,8,1 for machine code at its own address) loads, SAVE"NAME",8 saves — onto a blank disk if none is in — and SAVE"NAME" records onto the tape. Machine code can use the KERNAL’s SETLFS, SETNAM, LOAD and SAVE the same way. The panel lists the disk and tape with Run buttons, makes a blank disk, and downloads them as .D64 and .TAP; both are kept in this browser between visits. Loading is instant.

  • Machine: PAL (6561) or NTSC (6560) — they differ in speed (1.108 / 1.023 MHz) and screen size — and the memory: unexpanded (3583 bytes free), +3 KB at $0400, +8, +16 or +24 KB from $2000 (the screen moves to $1000 and BASIC to $1201, as on the real machine), +32 KB with RAM in the cartridge area BLK5 ($A000), or everything (+35 KB). Many programs need a particular expansion.

  • Joystick: choose Arrows = joystick and the arrow keys and Space are the stick, or plug in a gamepad (the Gamepad API: Chrome, Edge, Firefox and Safari). The VIC reads it from both VIAs — the Joystick example shows how.

  • On a phone: ⌨ Keys in the toolbar opens an on-screen VIC-20 keyboard; SHIFT, C= and CTRL stay down until the next key.

Keys: Esc is RUN/STOP, Page Up RESTORE, Tab CTRL, Alt the C= key (Shift + Alt switches between the upper case / graphics and lower / upper case sets), F1–F8 the function keys, Ctrl + 1–8 the colours, Backspace DEL (Insert is INST), Home HOME (Shift: CLR). Shift + a letter gives its graphics character.

Assembly and debugging

The Assembly tab assembles 6502 code (the site’s 6502 assembler) and runs it: the VIC-20 is reset, the page waits for READY., loads the code, keeps BASIC’s memory below it, and types SYS; RTS returns to BASIC. The examples need no ROMs: hello world with CHROUT, border and background colours, screen and colour memory, the three voices and noise, GETIN, a hook on the 60 Hz interrupt, a custom character set, multicolour characters, the joystick, and a KERNAL SAVE to the disk.

Click a line number beside the code for a breakpoint (F9 toggles the cursor line); F5 continue, F6 pause, F11 step, F10 step over, Shift+F11 step out, Ctrl+F10 run to the cursor. Registers, flags, the stack, the disassembly (with the KERNAL’s jump-table names and chip registers such as CHROUT, VIA2_T1CL, VIC_COLOUR), memory and watches sit beside the editor. The Debugger tab adds the VIC’s registers decoded (screen, characters and colour addresses, origin, raster, colours, each voice in Hz), both VIAs (ports, timers, shift register, interrupt flags) and the memory map with BASIC’s pointers.

Firmware

Firmware on the Run tab chooses what the VIC-20 boots:

  • Open BASIC (the default): Microsoft BASIC 1.1 (source, MIT), assembled by this site’s build script in its Commodore PET configuration with a few marked changes so it runs on the stub KERNAL and keeps its pointers where the VIC-20’s BASIC does (TXTTAB at 43/44, so PEEK(43) works). It is the direct ancestor of Commodore BASIC 2 and has the same keywords and tokens, so VIC-20 BASIC programs load, list and run; what it lacks are Commodore’s later fixes and quirks.

  • Monitor only: the stub KERNAL with its hex monitor — 1000 shows a byte, 1000.103F dumps, 1000: A9 01 stores, 1000G runs. From BASIC, SYS 65280 enters it and X goes back.

  • My ROMs: Load my ROM files… takes the 8 KB KERNAL (kernal.901486-07.bin for PAL, -06 for NTSC), the 8 KB BASIC (basic.901486-01.bin) and the 4 KB character ROM (chargen.901460-03.bin) — VICE’s names, or any dump of the right size. Commodore’s chips are recognised by CRC-32 and named. They stay in this browser (IndexedDB).

The stub KERNAL is this site’s own code (MIT; its source is on the References tab): the jump table’s CHROUT, CHRIN, GETIN, PLOT, SCNKEY, SETLFS, SETNAM, MEMTOP, MEMBOT, RDTIM and friends at Commodore’s addresses, a screen editor with the VIC-20’s 88-character logical lines, the keyboard scan on the 60 Hz interrupt into the real KERNAL’s buffer ($0277), and RUN/STOP + RESTORE. LOAD and SAVE ($FFD5, $FFD8) are done by the emulator, which is also how the Datassette and 1541 work with your own ROMs: the KERNAL’s calls are caught and the file comes straight from the disk image or tape.

The screen font is the free MEGA65 Open ROMs character set (LGPL; the same file the C64 emulator boots with — the VIC-20 uses the C64’s layout), with this site’s own glyphs where it has none; This site’s font switches to the one drawn here.

Limits

  • The CPU runs instruction by instruction with the documented cycle counts, not cycle by cycle; the screen is drawn a line at a time, so changes in the middle of a line don’t show.

  • VIC sound is a square-wave model (Φ2 / n / (255 − X) with n = 256, 128, 64, 32) with a 15-bit noise generator, not the real chip’s filtering.

  • Tape and disk work at the KERNAL level: programs with their own fast loaders, turbo tapes and copy-protected disks don’t load, and there is no drive CPU, no OPEN 15,8,15 command channel and no printer. Only the KERNAL’s own tape format is decoded from .TAP files.

  • Light pen, paddles and bank-switched cartridges aren’t emulated. The colours are an approximation; no two published VIC-20 palettes agree.

  • With the open BASIC: no OPEN/PRINT# files and BASIC 1’s error texts and behaviour in places. Programs that call undocumented ROM routines need Commodore’s ROMs.

Linking to an example

Parameter Meaning Example

mode

Tab: run, asm, debug, refs

mode=asm

example

hello, colours, screen, sound, keys, irq, chars, multicolour, joystick, save

example=chars

video

pal or ntsc

video=ntsc

mem

Expansion in KB: 0, 3, 8, 16, 24, 32, 35

mem=8

firmware

basic, monitor or roms

firmware=monitor

present=1, autostart=1

Open the screen full-window and run the program

autostart=1

For example: ?mode=asm&example=chars&autostart=1, ?mode=asm&example=joystick. Share links never carry programs, disks or ROMs.

Browser support and privacy

It runs in any current browser; sound starts after the first click (browsers require it), and a gamepad works where the Gamepad API does (Chrome, Edge, Firefox, Safari). Everything happens on this page: the first time it fetches the open BASIC and the font from this site (about 30 KB). Programs, disks, tapes and ROMs you open stay in your browser (IndexedDB) and are never sent anywhere. The program library below the Run tab only fetches what you ask it to.

Runs entirely in your browser; nothing you type leaves this page.