Commodore 64 BASIC (V2)
The 8 KB Microsoft-derived BASIC in the Commodore 64's ROM: the READY. prompt that greeted millions of users, with no commands for the machine's graphics or sound chips, so it taught a generation PEEK, POKE and memory maps.
Created by Microsoft (6502 BASIC core), adapted by Commodore Business Machines; the C64 source's change notes are signed RSR
Commodore 64 BASIC V2 is the BASIC interpreter built into the ROM of the Commodore 64. Turn the machine on and you are at its prompt:
| |
The C64 was one of the best-selling single computer models ever made; estimates run from about 12.5 million to 17 million units. That made this 8 KB interpreter the first programming language for a very large number of people. It is also one of the most criticised BASICs of its time. The C64 had the VIC-II video chip, with sprites and bitmap graphics, and the SID synthesiser chip, yet BASIC V2 has no keywords for either. Everything beyond text output meant writing numbers straight into hardware registers with POKE. So the language that introduced millions of people to programming also introduced them to memory maps, register bits and, before long, 6502 machine code.
This page covers the C64’s specific ROM: where it came from, what is in it and how it was used. The wider Commodore family, from the 1977 PET BASIC to BASIC 7.0 on the Commodore 128, is covered under CBM BASIC.
History & Origins
A Microsoft core, maintained by Commodore
All Commodore 8-bit BASICs come from Microsoft’s BASIC for the MOS 6502, which Commodore licensed in 1976 for the PET. According to Michael Steil, Commodore paid Microsoft once more for the revision that became the 1979 PET upgrade ROMs (BASIC 2), and after that developed the code itself without Microsoft’s involvement. Microsoft is not named anywhere in the C64 BASIC source. The header reads “COPYRIGHT (C) 1982 BY COMMODORE BUSINESS MACHINES”, and the hidden WAIT 6502 message that Microsoft put into that 1979 revision is reportedly not in the C64 version.
Which “version 2”?
The name “V2” is misleading. The PET also had a “BASIC 2” (the 1979 upgrade ROMs), and people often assume the VIC-20 and C64 BASIC is that PET version moved to a new machine. Michael Steil, who reassembled the early Microsoft 6502 BASICs from a single source tree, says otherwise. In a September 2008 article he wrote that “the BASIC V2 used on the VIC-20 and the C64 is actually a stripped-down version of PET BASIC 4.0 and not a ported version of PET BASIC V2”. In a follow-up he added that it has “all post-2.0 features stripped out again for space reasons”. What it inherited from the later code is mostly internal: it ends lines with a carriage return alone instead of CR/LF, and it asks the KERNAL for the memory size through the jump table instead of probing memory itself.
Commodore’s own source code, now public in Steil’s cbmsrc archive, is consistent with this. Neither listing calls itself version 2.0:
| ROM | Source header | Listing date | Sign-on |
|---|---|---|---|
| VIC-20 BASIC (901486-01) | “PET BASIC VERSION 2.1”, © 1981 | 6 March 1980 (as printed; see below) | **** CBM BASIC V2 **** |
| C64 BASIC (901226-01) | “PET BASIC VERSION 2.2”, © 1982 | 10 April 1982 | **** COMMODORE 64 BASIC V2 **** |
The VIC-20 listing date sits oddly with its 1981 copyright line and with a change note dated 6 March 1981, the same day and month. The year in the header may be a slip, but the source does not say. The C64 header lists the machines the code was meant to work with: the 2001, 4016/4032 and 8032 PETs, an unexplained “TOY”, the VIC-20, the “VIC-40”, the “COMMODORE 10/16/64” and the MAX. The disclaimer is signed “RSR”, and so are the dated change notes throughout the source. These are most likely the initials of Robert Russell, the VIC-20’s system programmer and one of the engineers who proposed the C64, although the listing never spells out the name.
From VIC-40 to Commodore 64
The C64 was designed in late 1981 as a cheaper successor to the VIC-20, under the code name VIC-40. It kept the VIC-20’s case and its BASIC. It was shown at the Consumer Electronics Show in Las Vegas on 7-10 January 1982 and went on sale in August 1982 at $595. The change notes in the C64 source record how the BASIC was adapted:
- 8 February 1982: “MODIFY FOR VIC-40 RELEASE”
- 10 April 1982: “INLINE FIX PROGRAM LOAD”, replacing the VIC-20’s March 1981 program-load fix.
- 15 April 1982: “ADD ADVERTISING SIGN-ON”. This is the
COMMODORE 64 BASIC V2banner, which replaced the VIC-20’s plainerCBM BASIC V2. - 2 July 1982: “ADD PRINT# PATCH”, a fix to the way
PRINT#calls the KERNAL to select an output channel.
Almost everything else is the VIC-20 code, moved from $C000 to $A000. That is why, decades later, a patch written for the VIC-20 ROM could be moved to the C64 by changing only its addresses.
Why not BASIC 4.0?
In 1982 Commodore already had a better BASIC. BASIC 4.0 on the PET/CBM 4000 and 8000 series added 15 disk keywords, including DLOAD, DSAVE, DIRECTORY, SCRATCH and COPY, and it is generally credited with a much faster string garbage collector. Todd Heimarck’s history of Commodore BASIC in the June 1987 COMPUTE!’s Gazette gives the reasons the C64 did not get it:
- Most VIC-20 owners had no disk drive, and Commodore “probably didn’t expect to sell many disk drives to 64 owners”.
- Many C64 buyers were expected to be VIC-20 owners. With the same BASIC, “many pure-BASIC programs (with no PEEKs or POKEs) would run as is”.
- BASIC 2.0 “was a known quantity”, and its bugs were documented. New code would bring new bugs.
- More commands would have needed a bigger ROM.
Heimarck also noted that although the C64’s operating system had seen “some very minor changes”, “its BASIC has remained the same”. Commodore’s source archive agrees. It holds three C64 KERNAL revisions (901227-01, -02 and -03) but only one C64 BASIC, 901226-01. The only later variant is for the 1990 C64GS console, and it changes a single vector (see Evolution).
Design Philosophy
BASIC V2 was not designed around the C64. It is a general-purpose interpreter that Commodore adapted for a new machine, and a few things follow from that:
- Small, and the same across machines. The whole interpreter fits in 8 KB at
$A000-$BFFF, and many programs withoutPEEKorPOKErun unchanged on a VIC-20. - BASIC is the shell. There is no separate command line. Loading, saving, listing disk directories and starting machine code are all BASIC statements, typed in direct mode.
- I/O goes through the KERNAL. BASIC calls the KERNAL’s jump table for characters, files and devices. Tape is device 1, the screen 3, printers 4 and 5, and disk drives 8 and up.
- The hardware is reached through memory.
PEEK,POKE,SYS,USRandWAITare the only way to get at the VIC-II, the SID and the CIA chips. Commodore never added colour or sound commands to the C64 ROM. It sold them later as separate cartridges.
Key Features
The keyword set
The token table in the C64 source defines 76 one-byte tokens, from END ($80) to GO ($CB). They cover 35 statements, 23 functions, the operators, the helper words TO, STEP, THEN, FN, NOT, TAB( and SPC(, and GO (so GO TO also works). The π character is handled separately as a constant.
| Group | Keywords |
|---|---|
| Program flow | FOR/TO/STEP/NEXT, GOTO, GOSUB/RETURN, ON...GOTO/GOSUB, IF...THEN, END, STOP, CONT, RUN, REM |
| Data and memory | LET, DIM, READ, DATA, RESTORE, DEF FN, CLR, NEW, LIST, FRE |
| Console I/O | PRINT, INPUT, GET, TAB(, SPC(, POS |
| Devices and files | LOAD, SAVE, VERIFY, OPEN, CLOSE, PRINT#, INPUT#, GET#, CMD |
| Hardware | PEEK, POKE, SYS, USR, WAIT |
| Math | ABS, ATN, COS, EXP, INT, LOG, RND, SGN, SIN, SQR, TAN |
| Strings | LEN, LEFT$, RIGHT$, MID$, STR$, VAL, ASC, CHR$ |
The reserved variables ST (I/O status), TI (a clock counting in 1/60-second jiffies) and TI$ (the same clock as an HHMMSS string) come from the Commodore side. The ROM also has 29 numbered error messages, from ?TOO MANY FILES to ?LOAD, plus BREAK.
Several things common in other BASICs are missing: ELSE, WHILE, CLS, LOCATE, RENUMBER, AUTO, DELETE, TRACE, and any statement for graphics, colour, sprites, sound, joysticks or disk management.
Data types and limits
- Reals: 5-byte floating point, about nine significant digits.
- Integers (
A%): -32768 to 32767, stored in two bytes. They are converted to floating point for arithmetic, so their only real benefit is saving memory in large arrays. - Strings (
A$): up to 255 characters, allocated dynamically. - Variable names: only the first two characters count, so
SCOREandSCREENare the same variable. - Program lines: at most 80 characters, which is two 40-column screen rows.
- Memory:
38911 BASIC BYTES FREEis the RAM from$0801to$9FFF. The BASIC ROM sits above it, and the 4 KB of RAM at$C000is left free for machine code.
Screen editing and abbreviations
BYTE’s otherwise harsh 1983 review called the full-screen editor “the one bright point in programming the Commodore 64”. You move the cursor anywhere on screen, type over a listed line and press RETURN to store it. Keywords can be abbreviated to a letter plus a shifted letter, for example P + SHIFT-O for POKE, or ? for PRINT. That makes it possible to fit more than 80 characters’ worth of keywords into one line, and such a line can no longer be edited once LIST expands it.
Cursor movement, colours, reverse video and clear-screen are control characters. You can type them inside quotes, where they show as reverse-video symbols, or send them with CHR$. For example, PRINT CHR$(147) clears the screen.
Programming the hardware
Here is what “graphics in BASIC V2” usually looked like. This program shows a solid square sprite:
| |
Sound works the same way, through the SID chip’s registers at 54272 ($D400):
| |
Heimarck summed up the result in 1987: “It’s not unusual to see a BASIC program that consists mainly of POKEs.”
Working with disks
BASIC V2 came from a tape-first design, so disk work is done through general commands and the drive’s own command channel:
| |
Loading the directory as a program replaces whatever BASIC program is in memory. Add-on “DOS wedge” utilities could show the directory without doing that.
The one-line maze
The best-known C64 BASIC program is one line long:
| |
Characters 205 and 206 are the two diagonal-line PETSCII graphics. Adding a random fraction to 205.5 and truncating picks one of them at random, and the result is an endless scrolling maze. The authors of the book 10 PRINT traced its printed history to a three-line variant on page 53 of the 1982 Commodore 64 User’s Guide and a one-line version in RUN magazine in July 1984.
Known Bugs and Performance
Garbage collection
The C64 does not have the faster string garbage collector that BASIC 4.0 is generally credited with. Programs that keep creating new strings, sorts in particular, can stop for long periods while BASIC reclaims memory. Heimarck described filling a C64’s memory with random strings and sorting them with a common BASIC sort routine. It took 22 hours. Asking what had held the sort back, he answered: “Mostly garbage collection.” He named BASIC’s general slowness as a second cause. That is one programmer’s account of one workload, not a controlled benchmark, but it shows why experienced C64 programmers avoided string reassignment in loops.
The multiplication bug
In December 2013, members of the Denial VIC-20 forum tracked down an arithmetic bug that had gone unnoticed for more than 30 years. The thread, “Fun with CBM arithmetics”, began on 9 December as a display oddity. On 31 December the forum member Mike traced it to multiplication. A shortcut in the floating-point multiply routine, which skips mantissa bytes that are zero, mishandles the carry flag. In some cases the result comes out halved in its low-order part. The bug depends on operand order:
| |
This should print 59 twice. On an unpatched VIC-20 the forum reported 59 in the left column and 29.5 in the right, and the same bug is in the C64 BASIC ROM. Testing in VICE, forum members found it in BASIC 2, 3.5 and 4.0 but not in the C128’s BASIC 7.0. According to Mike’s reading of the C128 ROM, Commodore had disabled the shortcut there. A patch for the VIC-20 was posted on 1 January 2014 and one for the C64 ROM on 19 January 2014.
Speed
BASIC V2 is a tokenising interpreter running on a 6510 at about 1 MHz (1.023 MHz on NTSC machines, 0.985 MHz on PAL). Every floating-point operation, including loop counters, uses 5-byte software arithmetic. For anything time-critical, C64 programmers moved to machine code, which they called with SYS.
Evolution
The C64’s BASIC never changed during the machine’s production life. The language developed around it instead:
- Commodore’s cartridges (1983). Simons’ BASIC added 114 keywords for graphics, sprites, sound and structured programming. Super Expander 64 added
GRAPHIC,DRAW,CIRCLE,PAINT, sprite and music commands. - Third-party extensions and compilers. A long list of BASIC extensions, “wedges” and BASIC compilers appeared for the C64. Many extensions worked by redirecting the RAM vectors that the V2 interpreter jumps through for things like its error handler and main loop.
- Later Commodore BASICs. BASIC 3.5 (Plus/4, C16, 1984) and BASIC 7.0 (C128, 1985) added the graphics, sound and structured-loop commands that V2 lacked. The C128 still included V2 in its C64 mode, so V2 programs kept running.
- After the hardware. The C64GS console of 1990 still had BASIC V2 in ROM. Its source, adapted by Fred Bowen in May 1990, says the only change was to point BASIC’s main-loop vector at the console’s cartridge display, so users never saw
READY.. C64 production ended in April 1994. BASIC V2 has survived mostly in emulators such as VICE, which run the original ROM image.
Current Relevance
BASIC V2 is still easy to use today:
- Emulation. VICE and other C64 emulators boot to the original
READY.prompt using the 901226-01 ROM image. - cbmbasic. Michael Steil’s 2008 project recompiles the C64 BASIC ROM into C. It runs on current operating systems as an interactive interpreter or as a
#!script interpreter, and it keeps the original interpreter’s behaviour, including its quirks. Its README says that on a 1 GHz CPU it runs about 1000 times faster than a 1 MHz 6502. That is the author’s own estimate, not a published benchmark. - Source code. Commodore’s original C64 BASIC source, with the RSR change notes, is in the
mist64/cbmsrcarchive. In September 2025 Microsoft published the source of its 6502 BASIC version 1.1, the common ancestor of the Commodore line, under the MIT License. - Retro culture. Hobbyists still write type-in listings and one-line programs in V2, using it as a deliberately limited medium. 10 PRINT made a single V2 line the subject of a book from an academic press.
Why It Matters
The Commodore 64 BASIC is a case where a limitation shaped a generation of programmers. Commodore shipped an advanced sound and graphics machine with a BASIC that could not use either chip. So beginners copied POKE statements out of the User’s Guide and magazines, then learned what the numbers meant, and many went on to assembly language. The same gap supported a large market in extension cartridges, BASIC compilers and type-in utilities.
It is also a good example of how home-computer software was built. A 1976 Microsoft licence, revised once by Microsoft and then maintained by Commodore without Microsoft’s name on it, was cut down from the PET’s BASIC 4.0 to fit a cheap machine, moved from the VIC-20 with a few months of changes signed “RSR”, and then left unchanged in ROM for twelve years. The 2013 multiplication bug shows how long code in ROM can stay in use without anyone finding its errors.
Timeline
Notable Uses & Legacy
Commodore 64 User's Guide
The manual in the box taught BASIC V2 from the READY. prompt up, including colour, sprite and sound programs built from POKE statements. According to the 10 PRINT authors, its page 53 has the first printed version of the famous maze program
Type-in programs in COMPUTE!'s Gazette and other magazines
From its first issue in July 1983, COMPUTE!'s Gazette printed BASIC V2 listings for readers to type in, often with machine code packed into DATA statements. It also printed utilities like the Automatic Proofreader to catch typing errors
Loading and launching software
The C64 boots straight into BASIC, so loading commercial software meant typing BASIC commands such as LOAD"*",8,1 and RUN. Many programs started with a one-line BASIC stub that used SYS to jump into machine code
Simons' BASIC and Super Expander 64
Both were 1983 Commodore cartridges that added keywords to BASIC V2 without replacing it. Simons' BASIC, written by 16-year-old David Simons, added 114 keywords for graphics, sprites, sound and structured programming
10 PRINT (MIT Press, 2012)
Nick Montfort, Ian Bogost, Casey Reas and seven co-authors wrote a whole book on one line of C64 BASIC V2, 10 PRINT CHR$(205.5+RND(1)); : GOTO 10, as a way into creative computing and code as culture
cbmbasic scripting interpreter
Michael Steil's cbmbasic runs the original C64 BASIC V2, statically recompiled to C, as a command-line tool with support for #! script lines