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
.PRGon the screen and it’s loaded and started (RUNfor BASIC,SYSfor machine code). A.D64goes into the disk drive and a.TAPinto the Datassette; with Start programs automatically the first program runs. Cartridges (.CRTfrom 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"$",8andLISTshow the directory,LOAD"NAME",8(or,8,1for machine code at its own address) loads,SAVE"NAME",8saves — onto a blank disk if none is in — andSAVE"NAME"records onto the tape. Machine code can use the KERNAL’sSETLFS,SETNAM,LOADandSAVEthe same way. The panel lists the disk and tape with Run buttons, makes a blank disk, and downloads them as.D64and.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$1000and 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 (
TXTTABat 43/44, soPEEK(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 —
1000shows a byte,1000.103Fdumps,1000: A9 01stores,1000Gruns. From BASIC,SYS 65280enters it andXgoes back. -
My ROMs: Load my ROM files… takes the 8 KB KERNAL (
kernal.901486-07.binfor PAL,-06for 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,15command channel and no printer. Only the KERNAL’s own tape format is decoded from.TAPfiles. -
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 |
|---|---|---|
|
Tab: |
|
|
|
|
|
|
|
|
Expansion in KB: |
|
|
|
|
|
Open the screen full-window and run the program |
|
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.
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser; nothing you type leaves this page.