Wed 02 May 2018 — Wed 02 May 2018

Commodore Basic

I used to write small programs in on my Commodore 64 as a child.

I thought I'd take another look at it. VICE is a good C64 emulator, and is already packaged for NixOS.

nix-env -iA nixos1803.vice
x64sc # This is the Commodore 64 emulator in accurate mode

C64 programmers' reference

Getting Started

The first thing to notice is that everything is capitalized. If you hold the shift key and press a character, intending to type a capital, you'll instead get some weird character, so don't do that.

The Commodore 64 functions as a REPL. You can interactively enter commands to execute them immediately. Usually you need to put PRINT before them to make them not a syntax error, however.

PRINT "OY OY SAVALOY."

If you want to instead store a command in memory, so that you can run it later, you write a line number in front of it. If you need to erase a line, just put in that line number with no code after it.

Having stored some commands in memory, you can view them using LIST, run them using RUN, and save them to your output device (usually a cassette tape) using SAVE.

Comments use the REM command, which stands for remark.

0  REM A PROGRAM, STORED IN MEMORY
10 PRINT "OY OY SAVALOY."
15 REM THE END OF THE PROGRAM

LIST
RUN

Line numbers must be integers from 0 to 63999, so make sure to leave some gaps between them in case you need to write more than you thought.

Variables

You don't need to declare variables. You can just assign them using =. There is an optional LET keyword you can use here.

The manual recommends omitting LET, because it takes up unnecessary memory. However, = is also overloaded to mean equality, so you might sometimes find it useful.

10 X = 5
20 PRINT X
RUN

You can allocate fixed length arrays using DIM(10, 10). These can be multi-dimensional.

There are three functions to allow you to keep some data inside the program code:

DATA
constants inside the program code
READ
set variable from data statements
RESTORE
go back to start of data

Number Operations

Negative numbers are represented in two's complement.

The standard number comparison operators =>< work.

There are three bitwise operations AND, OR and NOT. They also act as logical operators.

0 is false, other numbers evaluate to true. Similarly, "" is false, while other strings evaluate to true.

Built in number functions:

ABS
absolute value
EXP
e to the power of number
INT
round downwards
LOG
natural logarithm
RND
random uniform float
SGN
sign of number
SQR
square root

Trigonometry:

SIN
sine
COS
cosine
ATN
arctangent
TAN
tangent

Text Manipulation

ASC/CHR$
character to ASCII code and back
LEFT$/MID\(/RIGHT\)
substring
STR$/VAL
convert number to text and back
LEN
length of a string
SPC
characters of whitespace

Control Flow

RUN starts from the first line number you have stored.

If you want to use a different entry point, you can use GOTO instead GOTO 1000. This is probably more useful inside your programs, however.

There is a multiple jump variant of GOTO which switches on a variable to choose the target ON X GOTO 1000, 2000, 3000.

Execution continues in ascending order by line number, until you reach some sort of jump or branch command.

The GOSUB command lets you be a bit more structured in your programming. It puts the calling line on the stack, jumps and continues executing until it reaches a RETURN command, then jumps back to the line from the stack (there is a limited stack depth).

There isn't any built-in support for jumping named labels, just line numbers.

Functions

GOSUB isn't the same as a proper function call, because the stack frame doesn't include local variables.

You can define functions using DEF FN: DEF FN MyFunction(X) = X + 1} You can only use this inside your program code.

Functions can return numbers or strings. They only take one parameter, but can look at other variables.

Branching and Looping

There is IF-THEN, but no else statement. There are FOR loops which work a bit like a range.

0  REM FIZZBUZZ IN C64 BASIC
10 GOSUB 100
20 FOR X = 0 TO 100: GOSUB 200: NEXT
30 END

200 REM Print FizzBuzz
210 LET BUZZ = X / 3
215 LET BUZZ = BUZZ = INT(BUZZ)
220 LET FIZZ = X / 5
225 LET FIZZ = FIZZ = INT(FIZZ)
230 IF BUZZ AND FIZZ THEN PRINT "FIZZBUZZ"
240 IF BUZZ AND NOT FIZZ THEN PRINT "BUZZ"
250 IF FIZZ AND NOT BUZZ THEN PRINT "FIZZ"
260 IF NOT FIZZ AND NOT BUZZ THEN PRINT X
299 RETURN

The next command says which loop variable to move (if omitted, it increments the innermost loop). There's a limit of 9 levels of loop nesting.

Input/Output

OPEN/CLOSE
open or close a device
CMD
choose output device
GET
read keypresses from the user
GET#
read keypresses from somewhere else
INPUT
prompt user for input
INPUT#
fetch data from somewhere else
LOAD/SAVE
read program from storage device, or save it onto the device
VERIFY
compare program on storage to program in memory
POS
current cursor position
PRINT
write to screen
TAB
spacing when using print
PRINT#
write somewhere else
STATUS
what happened to the last file operation
TIME
time since power on
TIME$
real time

Special Printing

It's possible to incorporate coloured text in your program using key sequences, which you can print out.

You can also print out cursor key movements.

Memory

PEEK/POKE
get or set an integer at a memory address
CLR
erase memory
NEW
erase program
FRE
list free memory