BASIC V2 Reference
Complete command reference
Complete command reference for Commodore 64 BASIC V2
BASIC V2 Reference
Commodore 64 BASIC V2 is Microsoft’s 6502 BASIC interpreter with Commodore-specific extensions. Released in 1982, it’s deliberately simple—no sprite commands, no sound commands, no disk commands beyond LOAD and SAVE. You’ll use POKE and SYS for anything interesting.
This reference covers every BASIC V2 command, organised by category. For game programming, you’ll spend most of your time in I/O, Control Flow, and Memory Access.
I/O Commands
Display text or numbers on screen.
print "hello world"
print x
print x;y;z
print "x=";x;" y=";y
Separators:
;— No space between items,— Tab to next column (10-character intervals)- Nothing — Adds RETURN after output
Special uses:
print chr$(147) rem clear screen
print chr$(19) rem home cursor
print tab(10);"text" rem position text
print spc(5);"text" rem add spacing
Performance: PRINT is slow. Filling the screen takes ~18 seconds. Use POKE for speed.
INPUT
Wait for user to type a value.
input a rem shows ? prompt
input "name";n$ rem custom prompt
input "age";a rem stores in variable
Behaviour:
- Pauses program completely
- Displays
?unless you provide prompt text - Expects number for numeric variables, text for string variables
- Pressing RETURN without input gives
?REDO FROM STARTerror
Game development note: INPUT blocks. Games need non-blocking input—use GET or read joystick/keyboard directly via PEEK.
GET
Read single keypress without waiting.
10 get k$
20 if k$="" then goto 10
30 print "you pressed ";k$
Critical difference from INPUT:
- Doesn’t wait for RETURN
- Returns empty string if no key pressed
- Reads one character only
- Ideal for real-time game controls
GET#, INPUT#
Read from open files.
open 1,8,2,"data,seq,r"
input#1,a$
get#1,b$
close 1
See File Commands section for full disk I/O.
Control Flow
FOR…TO…STEP…NEXT
Repeat commands a set number of times.
for i=1 to 10
print i
next i
for i=0 to 100 step 10
print i
next i
for i=10 to 1 step -1
print i
next i
Details:
- Loop variable can be any numeric variable
- STEP defaults to 1 if omitted
- STEP can be negative for countdown
- Can nest up to 10 levels deep
- NEXT without variable name allowed but slower
Performance: FOR loops are relatively fast. Nested loops slow down significantly beyond 3 levels.
GOTO
Jump to line number.
10 print "hello"
20 goto 10
Uses:
- Main game loop:
GOTO 20 - Error recovery
- Menu systems
Avoid: Spaghetti code. Use GOSUB for repeated sections.
GOSUB…RETURN
Call a subroutine, then return.
10 gosub 1000
20 print "done"
30 end
1000 print "subroutine"
1010 return
Details:
- Can nest up to 10 levels deep
- RETURN jumps back to line after GOSUB
- Use for repeated code blocks
- Essential for structured programs
IF…THEN
Make decisions based on conditions.
if a=5 then print "yes"
if a=5 then print "yes":goto 100
if a<>5 then print "no"
if a>5 then print "big" else print "small"
Comparison operators:
=equal to<>not equal to>greater than<less than>=greater than or equal<=less than or equal
Multiple commands: Use : to chain commands after THEN.
IF…THEN…ELSE: Handle both true and false in one line.
ON…GOTO / ON…GOSUB
Jump to different lines based on value.
10 input "choice 1-3";c
20 on c goto 100,200,300
30 print "invalid choice"
100 print "option 1":end
200 print "option 2":end
300 print "option 3":end
Details:
- Value must be 1 to number of destinations
- If value is 0 or > number of destinations, continues to next line
- Ideal for menus and state machines
Operators
Arithmetic
| Operator | Operation | Example | Result |
|---|---|---|---|
+ | Addition | 5+3 | 8 |
- | Subtraction | 5-3 | 2 |
* | Multiplication | 5*3 | 15 |
/ | Division | 15/3 | 5 |
^ | Power | 2^3 | 8 |
Integer division: Use INT(A/B) for whole number results.
Modulo: Not built-in. Use A-INT(A/B)*B for remainder.
Logical
| Operator | Operation | Example |
|---|---|---|
AND | Both true | if a=5 and b=10 |
OR | Either true | if a=5 or b=10 |
NOT | Invert | if not(a=5) |
Bitwise operations: AND, OR, NOT also work on numbers bitwise.
a=15 and 3 rem result: 3 (binary: 1111 AND 0011 = 0011)
a=12 or 3 rem result: 15 (binary: 1100 OR 0011 = 1111)
a=not 0 rem result: -1 (all bits set)
Game use: Collision detection, flag checking, bit masking.
Math Functions
INT()
Convert to integer (truncate decimals).
print int(3.7) rem 3
print int(-3.7) rem -4 (rounds down, not toward zero)
Common use: Random number generation.
dice=int(rnd(1)*6)+1 rem 1-6
ABS()
Absolute value (remove negative sign).
print abs(-5) rem 5
print abs(5) rem 5
Game use: Distance calculations, collision detection.
SQR()
Square root.
print sqr(16) rem 4
print sqr(2) rem 1.41421356
Game use: Pythagoras distance: d=sqr((x2-x1)^2+(y2-y1)^2)
Performance warning: Very slow. Avoid in tight loops.
RND()
Random number generator.
print rnd(1) rem 0.0 to 0.999999
print rnd(0) rem repeat last number
print rnd(-1) rem reseed from clock
Practical patterns:
rem 0-9
n=int(rnd(1)*10)
rem 1-10
n=int(rnd(1)*10)+1
rem 1-6 (dice)
n=int(rnd(1)*6)+1
rem 50-99
n=int(rnd(1)*50)+50
Formula: INT(RND(1)*RANGE)+START
Reseeding: RND sequence is predictable. Use RND(-TI) at program start for variation.
Trigonometry
sin(x) rem sine
cos(x) rem cosine
tan(x) rem tangent
atn(x) rem arctangent
Units: Radians, not degrees. Convert: radians = degrees * 3.14159 / 180
Game use: Circle movement, projectile arcs, rotation.
Performance warning: Extremely slow. Precompute or use lookup tables.
String Functions
LEN()
String length.
a$="hello"
print len(a$) rem 5
LEFT$(), RIGHT$(), MID$()
Extract substrings.
a$="hello world"
print left$(a$,5) rem "hello"
print right$(a$,5) rem "world"
print mid$(a$,7,5) rem "world" (start at position 7, 5 chars)
Position: 1-based indexing (first character is position 1).
CHR$()
Character from code.
print chr$(65) rem "A"
print chr$(147) rem clear screen
print chr$(13) rem return/newline
See PETSCII Chart for complete code list.
ASC()
Code from character.
print asc("a") rem 65
print asc("0") rem 48
Input validation:
10 get k$:if k$="" then 10
20 if asc(k$)<48 or asc(k$)>57 then print "numbers only":goto 10
STR$()
Convert number to string.
a=123
a$=str$(a)
print a$ rem " 123" (note leading space for positive numbers)
Quirk: Positive numbers get leading space. Use MID$(STR$(A),2) to remove.
VAL()
Convert string to number.
a$="123"
a=val(a$)
print a rem 123
Error handling: Invalid strings return 0.
print val("abc") rem 0
print val("12abc") rem 12 (stops at first non-digit)
Memory Access
PEEK()
Read memory location.
a=peek(53280) rem read border colour
b=peek(1024) rem read first screen position
Address range: 0-65535
Common locations:
- Screen RAM: 1024-2023
- Colour RAM: 55296-56295
- VIC-II registers: 53248-53294
- SID registers: 54272-54296
- CIA registers: 56320-56335, 56576-56591
See Screen Memory and VIC-II Chip for complete maps.
POKE
Write to memory location.
poke 53280,0 rem black border
poke 1024,1 rem "A" at top-left of screen
poke 53265,59 rem blank screen
Power: POKE controls everything. Sprites, sound, colours, hardware registers.
Danger: Wrong POKE can crash the system. Addresses 0-1 control memory banking—change these carefully.
Performance: POKE is 9× faster than PRINT for screen updates.
Variables
Types
Numeric variables:
a=5 rem floating-point (default)
a%=5 rem integer (NOT supported in BASIC V2)
String variables:
a$="hello" rem string ($ suffix required)
Arrays:
dim a(10) rem 0-10 (11 elements)
dim a$(10) rem string array
dim a(10,10) rem 2D array (11×11)
Naming Rules
- 1-2 characters:
A,X,A1,XY - First character must be letter
- Second character can be letter or digit
- Case insensitive:
Aandaare same variable - Reserved words: Don’t use
TO,IF,OR, etc.
Longer names allowed but only first 2 characters matter:
score=10
scrap=20
print score rem 20! (both are "SC")
Best practice: Use single letters or letter+digit for clarity.
DIM
Define array dimensions.
dim a(100) rem 101 elements (0-100)
dim grid(20,20) rem 21×21 grid
dim names$(50) rem 51 string array
Default: Arrays without DIM limited to 0-10.
Memory: Arrays consume significant RAM. Each numeric element = 5 bytes, each string = 3 bytes + string length.
Program Control
RUN
Start program from beginning.
run rem start at lowest line number
run 100 rem start at line 100
Effect: Clears all variables (like NEW but keeps program).
END
Stop program.
100 print "done"
110 end
Effect: Returns to READY prompt. Variables preserved.
STOP
Pause program.
100 stop
Effect: Shows BREAK IN LINE 100. Type CONT to continue.
Debug use: Insert STOP to inspect variables mid-program.
CONT
Continue after STOP.
cont rem resume from STOP
Limitation: Can’t continue after changing program or some errors.
File Commands
LOAD
Load program from disk/tape.
load "game",8 rem load from disk drive 8
load "game",8,1 rem load to address in file
load "*",8,1 rem load first program
Parameters:
- Filename (15 chars max)
- Device (1=tape, 8=disk)
- Secondary address (0=BASIC, 1=absolute)
SAVE
Save program to disk/tape.
save "game",8 rem save to disk
save "game",1 rem save to tape
Overwrite: Use @0: prefix to replace existing file.
save "@0:game",8 rem overwrite "game"
VERIFY
Check if file matches memory.
verify "game",8 rem verify against disk
Use: Confirm tape/disk recording successful.
OPEN
Open file for reading/writing.
open 1,8,2,"data,seq,r" rem read sequential
open 1,8,2,"data,seq,w" rem write sequential
open 15,8,15 rem command channel
Parameters:
- Logical file number (1-255)
- Device (8=disk)
- Secondary address
- Filename and mode
CLOSE
Close open file.
close 1 rem close file 1
Important: Always close files to flush buffers.
CMD
Redirect output to file.
open 1,8,2,"output,seq,w"
cmd 1
print "this goes to file"
close 1
System Commands
SYS
Call machine language routine.
sys 64738 rem clear screen (same as PRINT CHR$(147))
sys 49152 rem call ML program at $C000
Common addresses:
- 64738 ($FCE2): Clear screen
- 58260 ($E394): Initialize screen
- 58640 ($E570): Initialize I/O
Game use: ML routines for sprites, sound, fast graphics.
WAIT
Pause until memory condition met.
wait 53265,128 rem wait for raster bit 8
wait 53265,128,128 rem wait for bit clear
Syntax: WAIT address, mask [, invert]
Use: Synchronize with raster, wait for hardware events.
USR()
Call machine language function.
a=usr(0) rem call USR function
Setup required: POKE address into 785-786 first.
poke 785,0:poke 786,192 rem point to $C000
a=usr(0) rem call $C000
Screen Control
CLR
Clear all variables.
clr rem reset all variables to 0 or ""
Effect: Arrays deallocated, strings freed, all values reset.
Use: Program initialization, resetting game state.
NEW
Delete program and clear variables.
new rem erase everything
Warning: Can’t undo. Program gone forever unless saved.
LIST
Display program.
list rem list all lines
list 100 rem list line 100
list 100-200 rem list range
REM
Comment (ignored by computer).
10 rem this is a comment
20 rem setup game variables
Shortcuts: Can abbreviate commands but REM stays as REM for clarity.
Special Characters in Listings
BASIC V2 tokenizes keywords. When you LIST, you see:
- Lowercase: Your typed text (strings, variable names)
- Uppercase: BASIC keywords
Screen codes: Colour changes and cursor controls appear as reversed characters in listings but work correctly when run.
Performance Considerations
Slow commands:
- PRINT (especially with scrolling)
- String operations (concatenation, MID$, etc.)
- Trigonometry (SIN, COS, TAN)
- SQR
- Division and exponentiation
Fast commands:
- POKE
- PEEK
- Integer arithmetic (+, -, AND, OR)
- FOR…NEXT (within reason)
- Variable assignment
Optimization tips:
- Use POKE instead of PRINT for graphics
- Precompute math-heavy values
- Keep loops simple
- Use integer arithmetic where possible:
A=A+1notA=A+1.0 - Minimize string operations in loops
- Use single-letter variables (marginally faster)
Common Patterns
Game loop
10 rem initialize
20 gosub 1000
30 rem main loop
40 gosub 2000
50 gosub 3000
60 goto 40
1000 rem setup
1010 return
2000 rem input
2010 return
3000 rem update
3010 return
Collision detection
if abs(x1-x2)<8 and abs(y1-y2)<8 then gosub 5000
Screen position to memory
addr=1024+(y*40)+x
poke addr,81 rem character
poke 55296+(y*40)+x,1 rem colour
Delay loop
for i=1 to 500:next i
Joystick read
j=peek(56320)
if j and 1=0 then rem up
if j and 2=0 then rem down
if j and 4=0 then rem left
if j and 8=0 then rem right
if j and 16=0 then rem fire
Limitations
What BASIC V2 doesn’t have:
- Sprite commands (use POKE to VIC-II)
- Sound commands (use POKE to SID)
- DO…WHILE or REPEAT…UNTIL loops
- ELSE IF or CASE statements
- Local variables
- Procedures with parameters
- Structured data types
- Built-in sort or search
- Disk directory commands (use
LOAD"$",8then LIST)
String handling:
- Maximum 255 characters per string
- Concatenation very slow
- No string buffer control (garbage collection unpredictable)
Memory:
- ~38KB available for BASIC programs
- Variables stored at top of BASIC memory
- Arrays consume significant space
- Stack depth limited (10 levels GOSUB/FOR)
See Also
- PETSCII Chart — character codes for PRINT and CHR$()
- Screen Memory — direct screen access with POKE
- VIC-II Chip — graphics registers
- Random Numbers — RND() internals and techniques
- Variables and Memory — how variables work internally
BASIC V2 is your gateway to the C64. Master these commands, then learn when to abandon them for machine language.