Commodore BASIC
Commodore BASIC, also known as PET BASIC, is the dialect of the BASIC programming language used in Commodore International's 8-bit home computer line, stretching from the PET of 1977 to the C128 of 1985. The core was based on 6502 Microsoft BASIC, and as such it shares most of the core code with other 6502 BASICs of the time, such as Applesoft BASIC.
History
Commodore licensed the BASIC from the young, cash-strapped Microsoft on a "pay once, no royalties" basis. It remains unclear if Microsoft actually believed that Commodore would come back for new BASIC editions for their follow-on computer projects. Instead, Commodore took the source code of the flat-fee BASIC and developed it further internally for all their other 8-bit home computers. It wasn't until the Commodore 128 (with V7.0) that a Microsoft copyright notice was displayed. However, Microsoft had built an easter egg into the original Commodore Basic that proved its provenance: typing the (obscure) command WAIT 6502, 1
would result in Microsoft!
appearing on the screen. (The easter egg was well concealed - the message did not show up in any disassembly of the interpreter.)
Technical details
A very convenient feature of Commodore's ROM-resident BASIC interpreter and KERNAL was the full-screen editor, which allowed users to input, edit, and enter direct commands as well as program lines anywhere on the screen—simply by pressing the RETURN
key whenever the cursor happened to be on a line containing a valid BASIC statement. This marked a significant change in program entry interfaces compared to other common home computer BASICs at the time, which typically used line editors, invoked by a separate EDIT
command, a "copy cursor," Escape sequences, or the like.
Another interesting feature was its ability to save named files to any device, including the cassette, initially a popular storage device in the days of the PET. Most systems of the era only supported filenames on diskette, which made saving multiple files on other devices more difficult, requiring making note of the recorder's counter display at the location of the file, which was inaccurate and prone to error. Most non-Commodore users solved the problem by only recording one file per tape. With the PET, when one loaded a file by name from the cassette, the cassette would start to be read and the computer would examine the filenames as they came up, skipping over the ones the user was not looking for. The file system was also supported by a powerful RECORD
structure that could be loaded or saved to files. Another difference between Commodore and other platforms' cassette transfer implementations was that Commodore tapes were encoded digitally, where other manufacturers usually used a less expensive analog interface which enabled the use of a standard tape recorder, but was much less reliable.
Like the original Microsoft BASIC interpreter, which it is based on, Commodore BASIC is known to be woefully slow compared to machine code. Test results have shown that copying 16 kilobytes of memory from ROM to RAM takes less than a second in machine code, but over a minute in BASIC. To try to make up for the slowness of the interpreter, programmers started using various tricks to speed up execution. One idea was to store often-used integer values into variables rather than using them as literal values, as interpreting a variable name was faster than interpreting a literal number. Programmers also often wrote speed-critical sections of a program in 6502 assembly language and executed them from BASIC using the SYS
command.
Commodore BASIC keywords could be abbreviated by entering at least one letter, and then a shifted version of the next letter on. In the default text mode, this shifted character appeared as a graphics symbol; e.g. the GOTO
command could be abbreviated G{Shift-O}
(which resembled GΓ
onscreen). In cases of ambiguity, more unshifted letters of the command were needed, such as GO{Shift-S}
(GO♥
) being required for GOSUB
since G{Shift-O}
was already taken. This system was by no means perfect – among other problems, the command INPUT
had no abbreviation because its spelling collided with a separate, arguably unnecessary INPUT#
keyword. The latter was unavoidably identified by all possible abbreviations of the former simply because it was located nearer the beginning of the keyword lookup table.
By abbreviating keywords however, it was possible to use less memory to store more code in a program line (line lengths were usually limited to 2 or 4 screen lines, depending on the specific machine). This allowed for a slight saving on the overhead to store otherwise necessary extra program lines, but nothing more.
In the rare situation when commercial BASIC software was meant to be LIST
-ed, each token's keyword was spelled out in full, leading to a line that extended over more screen lines than could be handled by the Logical Line Link Table. If the author of the program had intended editing of his software by users, the user might nevertheless have found it daunting to edit with the on-screen editing capabilities. Commodore 64 users (but not C-128 users) might find LIST
ing such a line near the bottom of the screen to trigger a bug in the 40 column screen editor, causing the machine to crash or return an OUT OF MEMORY error. Thus some Commodore 64 came under the impression that such a kind of "expanded" program line on a C-64 might occupy more memory.
Commodore BASIC lines did not need any spaces except where omitting one would be ambiguous, and in fact most Commodore BASIC programs were written with no spaces, e.g., 100IFA=5THENPRINT"YES":GOTO160
. Omitting spaces as such would lead to a more compact program, since the tokenizer never removes any space inserted between keywords: the presence of spaces results in extra 0x20
bytes in the tokenized program which are merely skipped during execution.
The order of execution of Commodore BASIC lines was not determined by line numbering; instead, it followed the order in which the lines were linked in memory: much like a modern singly linked list, each program line was stored in memory as a line number, a pointer, and then the tokenized code for the line. The pointer contained address in memory of the next program line. While a program was being entered, BASIC would constantly reorder program lines in memory so that the line numbers and pointers were all in ascending order. However after a program was entered, manually altering the line numbers and pointers with the POKE commands could allow for out-of-order execution or even give each line the same line number.
Variable names were only significant to 2 characters; thus the variable names VARIABLE1
, VARIABLE2
and VA
all referred to the same variable.
The native number format of Commodore BASIC, like that of its parent MS BASIC, was floating point. Most of the contemporary BASIC implementations used one byte for the characteristic (exponent) and three bytes for the mantissa. This led to problems in business applications since the accuracy of a floating point number using a three-byte mantissa is only about 6.5 decimal digits, and round-off error is common. Commodore, however, used MS BASIC's four-byte mantissa, which made their BASIC much more adapted for business than most other BASICs of the era.
Also akin to MS BASIC, 16-bit signed integers (i.e. in the range -32768 to 32767) were available by postfixing a variable name with a percent symbol, and string variables were represented by postfixing the variable name with a dollar sign. Despite the 2 character limit on variable names, the variables AA$
, AA
, and AA%
would each be understood as distinct.
Many BASIC extensions were released for the Commodore 64, due to the relatively limited capabilities of its native BASIC 2.0. One of the most popular extensions was the DOS Wedge, due to its inclusion on the Commodore 1541 Test/Demo Disk. This 1 KB extension to BASIC added a number of disk-related commands, including the ability to read a disk directory without destroying the program in memory. Its features were subsequently incorporated in various third-party extensions, such as the popular Epyx FastLoad cartridge. Other BASIC extensions added additional keywords to make it easier to code sprites, sound, and high-resolution graphics.
Versions and features
A list of CBM BASIC versions in chronological order, with successively added features:
Released versions
- V1.0: PET 2001 with chiclet keyboard and built-in Datassette (original PET)
- arrays limited to 256 elements
- PEEK command explicitly disabled over BASIC ROM locations above $C000
- V4.0: PET/CBM 4000/8000 series (and late version PET 2001s)
- disk operations:
DLOAD,DSAVE,COPY,SCRATCH,
etc (15 in all) - disk error-channel variables:
DS,$DS
- disk operations:
- V4+ : CBM-II series (aka B, P range)
- memory management:
BANK
- more disk operations:
BLOAD,BSAVE,DCLEAR
- formatted printing:
PRINT USING,PUDEF
- error trapping:
DISPOSE
- alternative branching:
ELSE
- dynamic error handling:
TRAP,RESUME,ERR$()
- flexible
DATA
read:RESTORE [
linenumber]
- string search function:
INSTR
- memory management:
- V3.5: C16/116, Plus/4
- sound and graphics commands
- joystick input:
JOY
- decimal ← → hexadecimal conversion:
DEC(),HEX$()
- structured looping:
DO,LOOP,WHILE,UNTIL,EXIT
- function key assignment:
KEY
(also direct mode) - program entry/editing:
AUTO,DELETE,RENUMBER
- debugging (tracing):
TRON,TROFF
- MLM entry command:
MONITOR
- C(1)16, Plus/4 Easter egg – enter
SYS 52650
- V7.0: C128
- more sound and graphics commands, including sprite handling
- built-in sprite editor:
SPRDEF
- multi-statement blocks for
IF THEN ELSE
structures:BEGIN,BEND
- paddle, lightpen input:
POT,PEN
- exclusive or function:
XOR
- get variable address:
POINTER
- text mode windowing:
WINDOW
- controlled time delay:
SLEEP
- memory management:
SWAP,FETCH,STASH
- more disk operations:
BOOT,DVERIFY
- CPU speed adjustment:
FAST,SLOW
(2 vs 1 MHz) - enter C64 mode:
GO64
- undocumented, working:
RREG
(read CPU registers after aSYS
) - unimplemented commands:
OFF,QUIT
- C128 Easter egg – enter
SYS 32800,123,45,6
Unreleased versions
- V10 : Commodore 65 (unreleased prototype)
- graphics/video commands:
PALETTE,GENLOCK
- mouse input:
MOUSE,RMOUSE
- text file (
SEQ
) utility:TYPE
- program editing:
FIND,CHANGE
- memory management:
DMA
,FRE(
<0
>|<1
>|<2
>)
- unimplemented commands:
PAINT,LOCATE,SCALE,WIDTH,SET,VIEWPORT
PASTE,CUT
- graphics/video commands:
Notable extension packages
- Super Expander (VIC-20; delivered on cartridge) (Commodore)
- Super Expander 64 (C64; cartridge) (Commodore)
- Simons' BASIC (C64; cartridge) (Commodore)
- Graphics BASIC (C64; floppy disk) (Hesware)
- BASIC 8 (C128; floppy disk and optional internal ROM chip) (Walrusoft)
References
BASIC 2.0:
- Angerhausen et.al. (1983). The Anatomy of the Commodore 64 (for the full reference, see the C64 article).
BASIC 3.5:
- Gerrard, Peter; Bergin, Kevin (1985). The Complete COMMODORE 16 ROM Disassembly. Gerald Duckworth & Co. Ltd. ISBN 0-7156-2004-5.
BASIC 7.0:
- Jarvis, Dennis; Springer, Jim D. (1987). BASIC 7.0 Internals. Grand Rapids, Michigan: Abacus Software, Inc. ISBN 0-916439-71-2.