Commodore 64 Programmer's Reference Guide
Commodore 64 Programmer's Reference Guide
PROGRAMMER’S
REFERENCE GUIDE
REPRODUCED – 2022
BASED ON ORIGINAL DOCUMENTATION:
FIRST PUBLISHED – 1982
THIS REVISION: R221216-01
ii
TABLE OF CONTENTS
INTRODUCTION............................................................................................................................ ix
What's Included? ........................................................................................................................................ x
How To Use This Reference Guide ......................................................................................................... xi
Commodore 64 Applications Guide ..................................................................................................... xii
Commodore Information Network ....................................................................................................... xvii
1. BASIC PROGRAMMING RULES ................................................................................................. 1
Introduction.................................................................................................................................................. 2
Screen Display Codes (BASIC Character Set) ....................................................................................... 2
The Operating System (OS) ............................................................................................................... 2
Programming Numbers and Variables ................................................................................................... 4
Integer, Floating-Point snd String Constants .................................................................................... 4
Integer, Floating-Point and String Variables ................................................................................... 7
Integer, Floating-Point and String Arrays ........................................................................................ 8
Expressions and Operators ...................................................................................................................... 9
Arithmetic Expressions ...................................................................................................................... 10
Arithmetic Operations ...................................................................................................................... 10
Relational Operators........................................................................................................................ 12
Logical Operators............................................................................................................................. 13
Hierarchy of Operations.................................................................................................................. 15
String Operations ............................................................................................................................. 16
String Expressions ............................................................................................................................. 17
Programming Techniques ....................................................................................................................... 18
Data Conversions .............................................................................................................................. 18
Using the INPUT Statement .............................................................................................................. 18
Using the GET Statement ................................................................................................................. 22
How to Crunch BASIC Programs ..................................................................................................... 24
2. BASIC LANGUAGE VOCABULARY.......................................................................................... 29
Introduction............................................................................................................................................... 30
BASIC Keywords, Abbreviations, and Function Types ....................................................................... 31
Description of BASIC Keywords ............................................................................................................ 35
The Commodore 64 Keyboard and Features..................................................................................... 93
Screen Editor............................................................................................................................................ 94
iii
3. PROGRAMMING GRAPHICS ON THE COMMODORE 64........................................................ 99
Graphics Overview............................................................................................................................... 100
Character Display Modes.............................................................................................................. 100
Bitmap Modes.................................................................................................................................. 100
Sprites ............................................................................................................................................... 100
Graphics Locations ................................................................................................................................ 101
Video Bank Selection...................................................................................................................... 101
Screen Memory ............................................................................................................................... 102
Color Memory.................................................................................................................................. 103
Character Memory ......................................................................................................................... 103
Standard Character Mode .................................................................................................................. 107
Character Definitions ...................................................................................................................... 107
Programmable Characters .................................................................................................................. 108
Multicolor Mode Graphics ................................................................................................................... 115
Multicolor Mode Bit......................................................................................................................... 115
Extended Background Color Mode .................................................................................................... 120
Bitmapped Graphics ............................................................................................................................ 121
Standard High-Resolution Bitmap Mode ..................................................................................... 122
How It Works ................................................................................................................................... 122
Multicolor Bitmap Mode ....................................................................................................................... 127
Smooth Scrolling .................................................................................................................................... 128
Sprites ..................................................................................................................................................... 131
Defining a Sprite ............................................................................................................................. 131
Sprite Pointers ................................................................................................................................. 133
Turning Sprites On .......................................................................................................................... 134
Turning Sprites Off ......................................................................................................................... 135
Colors ................................................................................................................................................ 135
Multicolor Mode .............................................................................................................................. 135
Settlng a Sprite to Multicolor Mode............................................................................................. 136
Expanded Sprites ........................................................................................................................... 136
Sprite Positioning ............................................................................................................................ 137
Vertical Positioning ......................................................................................................................... 138
Horizontal Positioning ..................................................................................................................... 139
Sprite Positioning Summary ........................................................................................................... 143
Sprite Display Priorities ................................................................................................................. 144
Collision Detects .............................................................................................................................. 144
Sprite to Sprite Collisions............................................................................................................... 145
Sprite to Data Collisions ................................................................................................................ 145
Other Graphics Features ..................................................................................................................... 150
Screen Blanking ............................................................................................................................... 150
Raster Register ................................................................................................................................ 150
Interrupt Status Register................................................................................................................. 151
Suggested Screen and Character Color Combinations............................................................. 152
iv
Programming Sprites – Another Look ................................................................................................ 153
Making Sprites in BASIC – A Short Program .............................................................................. 153
Crunching Your Sprite Programs................................................................................................... 156
Positioning Sprites on the Screen .................................................................................................. 157
Sprite Priorities ................................................................................................................................ 161
Drawing A Sprite ............................................................................................................................ 162
Creating A Sprite… Step by Step ............................................................................................... 163
Moving Your Sprite on the Screen ................................................................................................ 165
Vertical Scrolling ............................................................................................................................. 166
The Dancing Mouse – A Sprite Program Example ..................................................................... 166
Easy Spritemaking Chart ............................................................................................................... 176
Sprite Making Notes....................................................................................................................... 177
4. PROGRAMMING SOUND AND MUSIC ON YOUR COMMODORE 64 ................................. 183
Introduction............................................................................................................................................. 184
Volume Control ................................................................................................................................ 186
Frequencies of Sound Waves........................................................................................................ 186
Using Multiple Voices ........................................................................................................................... 187
Controlling Multiple Voices ............................................................................................................ 191
Changing Waveforms .......................................................................................................................... 192
Understanding Waveforms ........................................................................................................... 194
The Envelope Generator ...................................................................................................................... 196
Filtering ................................................................................................................................................... 199
Advanced Techniques ........................................................................................................................... 202
Synchronization and Ring Modulation................................................................................................ 207
5. BASIC TO MACHINE LANGUAGE ......................................................................................... 209
What Is Machine Language? ............................................................................................................... 210
What Does Machine Code Look Like? ......................................................................................... 211
Simple Memory Map of the Commodore 64 ............................................................................. 212
The Registers Inside the 6510 Microprocessor ........................................................................... 213
How Do You Write Machine Language Programs? ......................................................................... 214
64MON ............................................................................................................................................ 215
Hexadecimal Notation ......................................................................................................................... 215
Your First Machine Language Instruction ..................................................................................... 218
Writing Your First Program ........................................................................................................... 220
Addressing Modes ................................................................................................................................ 221
Zero Page ........................................................................................................................................ 221
The Stack .......................................................................................................................................... 222
v
Indexing .................................................................................................................................................. 223
Indirect Indexed .............................................................................................................................. 223
Indexed Indirect .............................................................................................................................. 224
Branches And Testing...................................................................................................................... 226
Subroutines ............................................................................................................................................. 228
Useful Tips for the Beginner ................................................................................................................ 229
Approaching a Large Task .................................................................................................................. 230
MCS6510 Microprocessor Instruction Set – Alphabetic Sequence ................................................ 232
Instruction Addressing Modes and Related Execution Times .......................................................... 254
Memory Management on the Commodore 64 ................................................................................. 260
The KERNAL............................................................................................................................................ 268
KERNAL Power-Up Activities ............................................................................................................... 269
How to Use The KERNAL ................................................................................................................ 270
User Callable KERNAL Routines .................................................................................................... 272
Error Codes ...................................................................................................................................... 306
Using Machine Language From BASIC ............................................................................................... 307
Where to Put Machine Language Routines ................................................................................. 309
How to Enter Machine Language.................................................................................................. 309
Commodore 64 Memory Map ............................................................................................................ 310
Commodore 64 Input/Output Assignments ................................................................................. 320
6. INPUT/OUTPUT GUIDE...........................................................................................................335
Introduction............................................................................................................................................. 336
Output to the TV.................................................................................................................................... 336
Output to Other Devices ...................................................................................................................... 337
Output to Printer ............................................................................................................................. 338
Output to Modem............................................................................................................................ 339
Working With Cassette Tape ....................................................................................................... 340
Data Storage On Floppy Diskettes .............................................................................................. 342
The Game Ports..................................................................................................................................... 343
Paddles............................................................................................................................................. 346
Light Pen ........................................................................................................................................... 348
RS-232 Interface Description .............................................................................................................. 348
General Outline .............................................................................................................................. 348
Opening an RS-232 Channel ........................................................................................................ 349
Getting Data from an RS-232 Channel ...................................................................................... 352
Sending Data to an RS-232 Channel .......................................................................................... 353
Closing an RS-232 Data Channel................................................................................................. 354
Sample BASIC Programs................................................................................................................ 356
vi
Receiver/Transmitter Buffer Base Location Pointers .................................................................. 357
Zero-Page Memory Locations and Usage .................................................................................. 358
Nonzero-Page Memory Locations and Usage............................................................................ 358
The User Port ......................................................................................................................................... 359
Port Pin Description ......................................................................................................................... 359
The Serial Bus ........................................................................................................................................ 362
Serial Bus Pinouts ............................................................................................................................ 363
The Expansion Port................................................................................................................................ 366
Z-80 Microprocessor Cartridge .......................................................................................................... 368
Using Commodore CP/M®............................................................................................................ 369
Running Commodore CP/M®........................................................................................................ 369
APPENDICES .............................................................................................................................. 373
A. Abbreviations For BASIC Keywords .............................................................................................. 374
B. Screen Display Codes ...................................................................................................................... 376
C. ASCII And CHR$ Codes................................................................................................................... 379
D. Screen and Color Memory Maps................................................................................................... 382
E. Music Note Values ............................................................................................................................ 384
F. Bibliography ...................................................................................................................................... 388
G. VIC Chip Register Map................................................................................................................... 391
H. Deriving Mathematical Functions.................................................................................................... 394
I. Pinouts for Input/Output Devices..................................................................................................... 395
J. Converting Standard BASIC Programs to Commodore 64 BASIC............................................. 398
K. Error Messages ................................................................................................................................. 400
L. 6510 Microprocessor Chip Specifications ..................................................................................... 402
M. 6526 Complex Interface Adapter (CIA) Chip Specifications ................................................... 419
N. 6566/6567 (VIC-II) Chip Specifications ...................................................................................... 436
O. 6581 Sound Interface Device (SID) Chip Specifications ........................................................... 457
P. Glossary ............................................................................................................................................. 482
INDEX ........................................................................................................................................................... 483
vii
INTRODUCTION
The COMMODORE 64 PROGRAMMER'S REFERENCE GUIDE has been
developed as a working tool and reference source for those of you who want to
maximize your use of the built-in capabilities of your COMMODORE 64. This
manual contains the information you need for your programs, from the simplest
example all the way to the most complex. The PROGRAMMER'S REFERENCE
GUIDE is designed so that everyone from the beginning BASIC programmer to
the professional experienced in 6502 machine language can get information to
develop his or her own creative programs. At the same time this book shows you
how clever your COMMODORE 64 really is.
INTRODUCTION ix
What you can do with this book is to find a considerable amount of valuable
programming reference information written in easy to read, plain English with
the programmer's jargon explained. On the other hand the programming
professional will find all the information needed to use the capabilities of the
COMMODORE 64 effectively.
WHAT'S INCLUDED?
Our complete "BASIC dictionary" includes Commodore BASIC language
commands, statements and functions listed in alphabetical order. We've
created a "quicklist" which contains all the words and their
abbreviations. This is followed by a section containing a more detailed
definition of each word along with sample BASIC programs to illustrate
how they work.
You can also enter the world of music synthesis and create your
own songs and sound effects with the best built-in synthesizer
available in any personal computer.
x INTRODUCTION
HOW TO USE THIS REFERENCE GUIDE
Throughout this manual certain conventional notations are used to describe the
syntax (programming sentence structure) of BASIC commands or statements and
to show both the required and optional parts of each BASIC keyword. The rules
to use for interpreting statement syntax are as follows:
1. BASIC keywords are shown in capital letters. They must appear where
shown in the statement, entered and spelled exactly as shown.
2. Items shown within quotation marks (" ") indicate variable data which
you must put in. Both the quotation marks and the data inside the quotes
must appear where shown in each statement.
5. Items inside angle brackets (<>) indicate variable data which you
provide. While the slash (/) indicates that you must make a choice
between two mutually exclusive options.
When you actually apply the syntax conventions in a practical situation, the
sequence of parameters in your statements might not be exactly the same as the
sequence shown in syntax examples. The examples are not meant to show every
possible sequence. They are intended to present all required and optional
parameters.
INTRODUCTION xi
Programming examples in this book are shown with blanks separating words and
operators for the sake of readability. Normally though, BASIC doesn't require
blanks between words unless leaving them out would give you an ambiguous or
incorrect syntax.
Shown below are some examples and descriptions of the symbols used for
various statement parameters in the following chapters. The list is not meant to
show every possibility, but to give you a better understanding as to how syntax
examples are presented.
When you first thought about buying a computer you probably asked yourself,
"Now that I can afford to buy a computer, what can I do with it once I get one?"
The great thing about your COMMODORE 64 is that you can make it do what
YOU want it to do! You can make it calculate and keep track of home and
business budget needs. You can use it for word processing. You can make it play
arcade-style action games. You can make it sing. You can even create your own
animated cartoons, and more. The best part of owning a COMMODORE 64 is
that even if it did only one of the things listed below it would be well worth the
price you paid for it. But the 64 is a complete computer and it does do
EVERYTHING listed and then some!
xii INTRODUCTION
By the way, in addition to everything here you can pick up a lot of other creative
and practical ideas by signing up with a local Commodore User’s Club,
subscribing to the COMMODORE and POWER/PLAY magazines, and joining the
COMMODORE INFORMATION NETWORK on CompuServe™.
APPLICATION COMMENT/REQUIREMENTS
ACTION PACKED You can get real Bally Midway arcade games
GAMES like Omega Race, Gorf, Wizard of Wor, as well
as “play and learn” games like Math Teacher 1,
Home Babysitter and Commodore Artist.
INTRODUCTION xiii
Not only that, if you join the COMMODORE
INFORMATION NETWORK on CompuServe™
you can get the latest news and updates on all
Commodore products, financial information, shop
at home services, you can even play games with
the friends you make through the information
systems you join.
xiv INTRODUCTION
all the different graphics and character display
modes.
INTRODUCTION xv
SIMULATIONS Computer simulations let you conduct dangerous
or expensive experiments at minimum risk and
cost.
These are just a few of the many applications for you and your COMMODORE
64. As you can see, for work or play, at home, in school or the office, your
COMMODORE 64 gives you a practical solution for just about any need.
Commodore wants you to know that our support for users only STARTS with your
purchase of a Commodore computer. That's why we've created two publications
with Commodore information from around the world, and a "two-way" computer
information network with valuable input for users in the U.S. and Canada from
coast to coast.
POWER/PLAY
The Home Computer Magazine
xvi INTRODUCTION
COMMODORE
The Microcomputer Magazine
The magazine of the future is here. To supplement and enhance your subscription
to POWER/PLAY and COMMODORE magazines, the COMMODORE
INFORMATION NETWORK – our "paperless magazine" – is available now over
the telephone using your Commodore computer and modem.
Join our computer club, get help with a computing problem, "talk" to other
Commodore friends, or get up-to-the-minute information on new products,
software and educational resources. Soon you will even be able to save yourself
the trouble of typing in the program listings you find in POWER/PLAY or
COMMODORE by downloading direct from the Information Network (a new
user service planned for early 1983). The best part is that most of the answers
are there before you even ask the questions. (How's that for service?)
To call our electronic magazine you need only a modem and a subscription to
CompuServe™, one of the nation's largest telecommunications networks. (To
make it easy for you Commodore includes a FREE year's subscription to
CompuServe™ in each VICMODEM package.) Just dial your local number for
the CompuServe™ data bank and connect your phone to the modem. When the
CompuServe™ video text appears on your screen type G CBM on your
computer keyboard. When the COMMODORE INFORMATION NETWORK'S
table of contents, or "menu," appears on your screen choose from one of our
sixteen departments, make yourself comfortable, and enjoy the paperless
magazine other magazines are writing about.
INTRODUCTION xvii
For more information, visit your Commodore dealer or contact CompuServe™
customer service at 800-848-8990 (in Ohio, 614-457-8600).
xviii INTRODUCTION
CHAPTER 1
BASIC
PROGRAMMING
RULES
Introduction
Screen Display Codes (BASIC
Character Set)
Programming Numbers and
Variables
Expressions and Operators
Programming Techniques
INTRODUCTION
This chapter talks about how BASIC stores and manipulates data. The topics
include:
The Operating System is contained in the Read Only Memory (ROM) chips and
is a combination of three separate, but interrelated, program modules:
2. The KERNAL handles most of the interrupt level processing in the system
(for details on interrupt level processing, see Chapter 5). The KERNAL
also does the actual input and output of data.
3. The Screen Editor controls the output to the video screen (television set)
and the editing of BASIC program text. In addition, the Screen Editor
intercepts keyboard input so that it can decide whether the characters
1. DIRECT Mode
2. PROGRAM Mode
1. When you're using the DIRECT mode, BASIC statements don't have line
numbers in front of the statement. They are executed whenever the
RETURN key is pressed.
NOTE: Always type NEW and hit RETURN before starting a new program.
The Commodore 64 has two complete character sets that you can use, either
from the keyboard or in your programs.
In SET 1, the upper case alphabet and the numbers 0-9 are available without
pressing the SHIFT key. If you hold down the SHIFT key while typing, the
graphics characters on the RIGHT side of the front of the keys are used. If you
hold down the key while typing, the graphics characters on the LEFT side of
the front of the key are used. Holding down the SHIFT key while typing any
character that doesn't have graphic symbols on the front of the key gives you
the symbol on the top most part of the key.
In SET 2, the lower case alphabet and the numbers 0-9 are available without
pressing the SHIFT key. The upper case alphabet is available when you hold
down the SHIFT key while typing. Again, the graphic symbols on the LEFT side
of the front of the keys are displayed by pressing the key, while the symbols
on the top most part of any key, without graphics characters, are selected when
you hold down the SHIFT key while typing.
To switch from one character set to the other press the and the SHIFT keys
together.
Constants are the data values that you put in your BASIC statements. BASIC uses
these values to represent data during statement execution. CBM BASIC can
recognize and manipulate three types of constants:
1. INTEGER NUMBERS
2. FLOATING-POINT NUMBERS
3. STRINGS
-12
8765
-32768
+44
0
-32767
NOTE: Do NOT put commas inside any number. For example, always type 32,000 as 32000. If
you put a comma in the middle of a number you will get the BASIC error message: ?SYNTAX
ERROR.
1. SIMPLE NUMBER
2. SCIENTIFIC NOTATION
Floating-point constants will show you up to nine digits on your screen. These
digits can represent values between -999999999 and +999999999. If you
enter more than nine digits the number will be rounded based on the tenth digit.
If the tenth digit is greater than or equal to 5 the number will be rounded
upward. Less than 5 the number will be rounded downward. This could be
important to the final totals of some numbers you may want to work with.
Floating-point numbers are stored (using five bytes of memory) and are
manipulated in calculations with ten places of accuracy. However, the numbers
are rounded to nine digits when results are printed. Some examples of simple
floating-point numbers are:
Numbers smaller than .01 or larger than 999999999 will be printed in scientific
notation. In scientific notation a floating-point constant is made up of three parts:
1. THE MANTISSA
2. THE LETTER E
3. THE EXPONENT
The mantissa is a simple floating-point number. The letter E is used to tell you that
you're seeing the number in exponential form. In other words E represents *10
(eg., 3E3=3*10↑3=3000). And the exponent is what multiplication power of
10 the number is raised to.
Both the mantissa and the exponent are signed (+ or –) numbers. The exponent's
range is from –39 to +38 and it indicates the number of places that the actual
decimal point in the mantissa would be moved to the left (–) or right (+) if the
value of the constant were represented as a simple number.
There is a limit to the size of floating-point numbers that BASIC can handle, even
in scientific notation: the largest number is +1.70141183E+38 and calculations
which would result in a larger number will display the BASIC error message
?OVERFLOW ERROR. The smallest floating-point number is +2.93873588E–39
and calculations which result in a smaller value give you zero as an answer and
NO error message. Some examples of floating-point numbers in scientific
notation (and their decimal values) are:
235.988E–3 (.235988)
2359E6 (2359000000.)
–7.09E–12 (–.00000000000709)
–3.14159E+5 (–314159.)
A string constant can contain blanks, letters, numbers, punctuation and color or
cursor control characters in any combination. You can even put commas between
numbers. The only character which cannot be included in a string is the double quote
mark ("). This is because the double quote mark is used to define the beginning
and end of the string.
A string can also have a null value – which means that it can contain no character
data. You can leave the ending quote mark off of a string if it's the last item on
a line or if it's followed by a colon (:). Some examples of string constants are:
Variables are names that represent data values used in your BASIC statements.
The value represented by a variable can be assigned by setting it equal to a
constant, or it can be the result of calculations in the program. Variable data,
like constants, can be integers, floating-point numbers, or strings. If you refer to
a variable name in a program before a value has been assigned, the BASIC
Interpreter will automatically create the variable with a value of zero if it's an
integer or floating-point number. Or it will create a variable with a null value if
you're using strings.
Variable names can be any length but only the first two characters are
considered significant in CBM BASIC. This means that all names used for variables
must NOT have the same first two characters. Variable names may NOT be the
same as BASIC keywords and they may NOT contain keywords in the middle of
variable names. Keywords include all BASIC commands, statements, function
names and logical operator names. If you accidentally use a key word in the
middle of a variable name, the BASIC error message ?SYNTAX ERROR will
show up on your screen.
Array names can be integers, floating-points or string data types and all
elements in the array have the same data type as the array name. Arrays can
have a single dimension (as in a simple list) or they can have multiple dimensions
(imagine a grid marked in rows and columns or a Rubik's Cube®). Each element
of an array is uniquely identified and referred to by a subscript (or index
variable) following the array name, enclosed within parentheses ( ).
The maximum number of dimensions an array can have in theory is 255 and the
number of elements in each dimension is limited to 32767. But for practical
purposes array sizes are limited by the memory space available to hold their
A(5)=0 (sets the 5th element in the 1 dimensional array called “A”
equal to zero)
1. ARITHMETIC
2. STRING
Expressions are normally thought of as having two or more data items called
operands. Each operand is separated by a single operator to produce the
desired result. This is usually done by assigning the value of the expression to a
variable name. All of the examples of constants and variables that you've seen
so far, were also examples of expressions.
ARITHMETIC EXPRESSIONS
ARITHMETIC OPERATIONS
ADDITION (+): the plus sign (+) specifies that the operand on the right is added
to the operand on the left.
2+2
A+B+C
X%+1
BR+10E–2
SUBTRACTION (–): The minus sign (–) specifies that the operand on the right is
subtracted from the operand on the left.
EXAMPLES:
4–1
100–64
A–B
55–142
The minus can also be used as a unary minus. That means that it is the minus sign in
front of a negative number. This is equal to subtracting the number from zero (0).
EXAMPLES:
–5
–9E4
–B
4–(–2) same as 4+2
MULTIPLICATION (*): An asterisk (*) specifies that the operand on the left is
multiplied by the operand on the right.
EXAMPLES:
100*2
50*0
A*X1
R%*14
DIVISION (/): The slash (/) specifies that the operand on the left is divided by
the operand on the right.
EXAMPLES:
10/2
6400/4
A/B
AE2/XR
EXAMPLES:
RELATIONAL OPERATORS
The relational operators (<, =, >, <=, >=, <>) are primarily used to compare
the values of two operands, but they also produce an arithmetic result. The
relational operators and the logical operators (AND, OR, and NOT), when used
in comparisons, actually produce an arithmetic true/false evaluation of an
expression. If the relationship stated in the expression is true the result is assigned
an integer value of –1 and if it's false a value of 0 is assigned. These are the
relational operators:
EXAMPLES:
Numeric data items can only be compared (or assigned) to other numeric items.
The same is true when comparing strings, otherwise the BASIC error message
?TYPE MISMATCH will occur. Numeric operands are compared by first
converting the values of either or both operands from integer to floating-point
form, as necessary. Then the relationship of the floating-point values is evaluated
to give a true/false result.
At the end of all comparisons, you get an integer no matter what data type the
operand is (even if both are strings). Because of this, a comparison of two
operands can be used as an operand in performing calculations. The result will
be –1 or 0 and can be used as anything but a divisor, since division by zero is
illegal.
LOGICAL OPERATORS
The logical operators (AND, OR, NOT) can be used to modify the meanings of
the relational operators or to produce an arithmetic result. Logical operators can
produce results other than –1 and 0, though any nonzero result is considered true
when testing for a true/false condition.
The logical operators (sometimes called Boolean operators) can also be used to
perform logic operations on individual binary digits (bits) in two operands. But
when you're using the NOT operator, the operation is performed only on the
single operand to the right. The operands must be in the integer range of values
(–32768 to +32767) (floating-point numbers are converted to integers) and
logical operations give an integer result.
1 AND 1 = 1
0 AND 1 = 0
1 AND 0 = 0
0 AND 0 = 0
1 OR 1 = 1
0 OR 1 = 1
1 OR 0 = 1
0 OR 0 = 0
NOT 1 = 0
NOT 0 = 1
1 XOR 1 = 0
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0
The logical operators AND, OR and NOT specify a Boolean arithmetic operation
to be performed on the two operand expressions on either side of the operator.
In the case of NOT, ONLY the operand on the RIGHT is considered. Logical
operations (or Boolean arithmetic) aren't performed until all arithmetic and
relational operations in an expression have been completed.
EXAMPLES:
HIERARCHY OF OPERATIONS
When you use parentheses in expressions, they must be paired so that you
always have an equal number of left and right parentheses. Otherwise, the
BASIC error message ?SYNTAX ERROR will appear.
A+B
C↑(D+E)/2
((X–C↑(D+E)/2)*10)+1
GG$>HH$
JJ$+"MORE"
K%=1 AND M<>X
K%=2 OR (A=B AND M<X)
NOT (D=E)
OR Logical OR PQ OR 15
STRING OPERATIONS
Strings are compared using the same relational operators (=, <>, <=, >=, <,
>) that are used for comparing numbers. String comparisons are made by taking
one character at a time (Ieft-to-right) from each string and evaluating each
character code position from the PET/CBM character set. If the character codes
are the same, the characters are equal. If the character codes differ, the
character with the lower code number is lower in the character set. The
comparison stops when the end of either string is reached. All other things being
Regardless of the data types, at the end of all comparisons you get an integer
result. This is true even if both operands are strings. Because of this a comparison
of two string operands can be used as an operand in performing calculations.
The result will be –1 or 0 (true or false) and can be used as anything but a
divisor since division by zero is illegal.
STRING EXPRESSIONS
Expressions are treated as if an implied "<>0" follows them. This means that if
an expression is true then the next BASIC statements on the same program line
are executed. If the expression is false the rest of the line is ignored and the
next line in the program is executed.
Just as with numbers, you can also perform operations on string variables. The
only string arithmetic operator recognized by CBM BASIC is the plus sign (+)
which is used to perform concatenation of strings. When strings are concatenated,
the string on the right of the plus sign is appended to the string on the left,
forming a third string as a result. The result can be printed immediately, used in
a comparison, or assigned to a variable name. If a string data item is compared
with (or set equal to) a numeric item, or vice-versa, the BASIC error message
?TYPE MISMATCH will occur. Some examples of string expressions and
concatenation are:
10 A$="FILE": B$="NAME"
20 NAM$ = A$ + B$ (gives the string: FILENAME)
30 RES$ = "NEW " + A$ + B$ (gives the string: NEW FILENAME)
DATA CONVERSIONS
When necessary, the CBM BASIC Interpreter will convert a numeric data item
from an integer to floating-point, or vice-versa, according to the following rules:
Now that you know what variables are, let's take that information and put it
together with the INPUT statement for some practical programming applications.
Type the word NEW on your Commodore 64. Hit the RETURN key, and try this
example:
1. NUMERIC
2. STRING
You probably remember from the earlier sections that numeric variables are
used to store number values such as 1, 100, 4000, etc. A numeric variable can
be a single letter (A), any two letters (AB), a letter and a number (A1), or two
letters and a number (AB1). You can save memory space by using shorter
variables. Another helpful hint is to use letters and numbers for different
categories in the same program (A1, A2, A3). Also, if you want whole numbers
for an answer instead of numbers with decimal points, all you have to do is put
a percent sign (%) at the end of your variable name (AB%, A1%, etc.)
Now let's look at a few examples that use different types of variables and
expressions with the INPUT statement:
NOTE: Example 3 shows that MESSAGES or PROMPTS are inside the quotation marks (" ") while
the variables are outside. Notice, too, that in line 20 the variable A was printed first, then the
message "TIMES 5 EQUALS", and then the calculation, multiply variable A by 5 (A*5).
Calculations are important in most programs. You have a choice of using "actual
numbers" or variables when doing calculations, but if you're working with
numbers supplied by a user you must use numeric variables. Begin by asking the
user to type in two numbers like this:
SHIFT CLR/HOME
5 PRINT ""
10 PRINT "MONTHLY INCOME": INPUT IN
20 PRINT
30 PRINT "EXPENSE CATEGORY 1": INPUT E1$
40 PRINT "EXPENSE AMOUNT": INPUT E1
50 PRINT
60 PRINT "EXPENSE CATEGORY 2": INPUT E2$
70 PRINT "EXPENSE AMOUNT": INPUT E2
80 PRINT
90 PRINT "EXPENSE CATEGORY 3": INPUT E3$
100 PRINT "EXPENSE AMOUNT": INPUT E3
110 PRINT "" SHIFT CLR/HOME
120 E=E1+E2+E3
130 EP=E/IN
140 PRINT "MONTHLY INCOME: $"IN
150 PRINT "TOTAL EXPENSES: $"E
160 PRINT "BALANCE EQUALS: $"IN-E
170 PRINT
180 PRINT E1$"="(E1/E)*100"% OF TOTAL EXPENSES"
190 PRINT E2$"="(E2/E)*100"% OF TOTAL EXPENSES"
200 PRINT E3$"="(E3/E)*100"% OF TOTAL EXPENSES"
210 PRINT
220 PRINT "YOUR EXPENSES ="EP*100"% OF YOUR TOTAL
INCOME"
230 FOR X=1TO5000:NEXT:PRINT
240 PRINT "REPEAT? (Y/N)":INPUT Y$:IF Y$="Y" THEN 5
250 PRINT "":END
SHIFT CLR/HOME
NOTE: IN can NOT = 0, and E1, E2, E3 can NOT all be 0 at the same time.
Line(s) Description
5 Clears the screen.
10 PRINT/INPUT statement.
20 Inserts blank line.
30 Expense Category 1 = E1$.
40 Expense Amount = E1.
50 Inserts blank line.
60 Expense Category 2 = E2$.
70 Expense Amount = E2.
80 Inserts blank line.
90 Expense Category 3 = E3$.
100 Expense Amount = E3.
110 Clears the screen.
120 Add Expense Amounts = E.
130 Calculate Expense/Income%
140 Display Income.
150 Display Total Expenses.
160 Display Income – Expenses.
170 Inserts blank line.
180-200 Calculate % each Expense Amount is of Total Expenses
210 Inserts blank line.
220 Display E / IN %
230 Time delay loop.
Now multiply those two numbers together to create a new variable C as shown
in line 20 below:
20 C=A*B
Enter these 3 lines and RUN the program. Notice that the messages are inside
the quotes while the variables are not.
40 PRINT "$" C
The dollar sign goes in quotes because the variable C only represents a number
and can't contain a $. If the number represented by C was 100 then the
Commodore 64 screen would display $ 100. But, if you tried to PRINT $C without
using the quotes, you would get a ?SYNTAX ERROR message.
One last tip about $$$: You can create a variable that represents a dollar sign
which you can then substitute for the $ when you want to use it with numeric
variables. For example:
10 Z$="$"
Now whenever you need a dollar sign you can use the string variable Z$. Try
this:
10 Z$="$":INPUT A
20 PRINT Z$A
Line 10 defines the $ as a string variable called Z$, and then INPUTs a number
called A. Line 20 PRINTs Z$ ($) next to A (number).
You'll probably find that it's easier to assign certain characters, like dollar signs,
to a string variable than to type "$" every time you want to calculate dollars or
other items which require " " like %.
Most simple programs use the INPUT statement to get data from the person
operating the computer. When you're dealing with more complex needs, like
protection from typing errors, the GET statement gives you more flexibility and
your program more "intelligence." This section shows you how to use the GET
statement to add some special screen editing features to your programs.
NEW
10 TI$="000000"
20 IF TI$ < "000015" THEN 20
Now type RUN, hit RETURN and while the program is RUNning type in the word:
HELLO.
Notice that nothing happened for about 15 seconds when the program started.
Only then did the message HELLO appear on the screen.
Imagine standing in line for a movie. The first person in the line is the first to get
a ticket and leave the line. The last person in line is last for a ticket. The GET
statement acts like a ticket taker. First it looks to see if there are any characters
"in line." In other words, have any keys been typed? If the answer is yes then
that character gets placed in the appropriate variable. If no key was pressed
then an empty value is assigned to a variable.
At this point it's important to note that if you try to put more than 10 characters
into the buffer at one time, all those over the 10th character will be lost.
Since the GET statement will keep going even when no character is typed, it is
often necessary to put the GET statement into a loop so that it will have to wait
until someone hits a key or until a character is received through your program.
Below is the recommended form for the GET statement. Type NEW to erase your
previous program.
Notice that there is NO SPACE between the quote marks ("") on this line. This
indicates an empty value and sends the program back to the GET statement in
a continuous loop until someone hits a key on the computer. Once a key is hit the
program will continue with the line following line 10. Add this line to your
program:
There are many things you can do with a screen editor. You can have a flashing
cursor. You can keep certain keys like CLR/HOME from accidentally erasing the
whole screen. You might even want to be able to use your function keys to
represent whole words or phrases. And speaking of function keys, the following
program lines give each function key a special purpose. Remember this is only
the beginning of a program that you can customize for your needs.
The CHR$ numbers in parentheses come from the CHR$ code chart in Appendix
C. The chart lists a different number for each character. The four function keys
are set up to perform the tasks represented by the instructions that follow the
word THEN in each line. By changing the CHR$ number inside each set of
parentheses you can designate different keys. Different instructions would be
performed if you changed the information after the THEN statement.
You can pack more instructions – and power – into your BASIC programs by
making each program as short as possible. This process of shortening programs
is called "crunching."
Most programmers start their programs at line 100 and number each line at
intervals of 10 (i.e., 100, 110, 120). This allows extra lines of instruction to be
added (111, 112, etc.) as the program is developed. One means of crunching
the program after it is completed is to change the line numbers to the lowest
numbers possible (i.e.,1, 2, 3) because longer line numbers take more memory
than shorter numbers when referenced by GOTO and GOSUB statements. For
instance, the number 100 uses 3 bytes of memory (one for each number) while
the number 1 uses only 1 byte.
You can put more than one instruction on each numbered line in your program
by separating them by a colon. The only limitation is that all the instructions on
each line, including colons, should not exceed the standard 80-character line
length. Here is an example of two programs, before and after crunching:
USING VARIABLES
Large amounts of data can be typed in as one piece of data at a time, over
and over again… or you can print the instructional part of the program ONCE
and print all the data to be handled in a long running list called the DATA
statement. This is especially good for crowding large lists of numbers into a
program.
Arrays and matrices are similar to DATA statements in that long amounts of data
can be handled as a list, with the data handling portion of the program drawing
from that list, in sequence. Arrays differ in that the list can be multi-dimensional.
ELIMINATING SPACES
One of the easiest ways to reduce the size of your program is to eliminate all
the spaces. Although we often include spaces in sample programs to provide
clarity, you actually don't need any spaces in your program and will save space
if you eliminate them.
If you use a particular line or instruction over and over, it might be wise to
GOSUB to the line from several places in your program, rather than write the
whole line or instruction every time you use it.
This chapter also explains the BASIC functions built into the BASIC Language
Interpreter. Built-in functions can be used in direct mode statements or in any
program, without having to define the function further. This is NOT the case with
user-defined functions. The results of built-in BASIC functions can be used as
immediate output or they can be assigned to a variable name of an appropriate
type. There are two types of BASIC functions:
1. NUMERIC
2. STRING
AND A SHIFT N A
CLOSE CL SHIFT O CL
CLR C SHIFT L C
CMD C SHIFT M C
CONT C SHIFT O C
DATA D SHIFT A D
DEF D SHIFT E D
DIM D SHIFT I D
END E SHIFT N E
FN NONE FN
FOR F SHIFT O F
GET G SHIFT E G
GOSUB GO SHIFT S GO
GOTO G SHIFT O G
IF NONE IF
INPUT# I SHIFT N I
LET L SHIFT E L
LIST L SHIFT I L
LOAD L SHIFT O L
NEXT N SHIFT E N
NOT N SHIFT O N
ON NONE ON
OPEN O SHIFT P O
OR NONE OR
POKE P SHIFT O P
PRINT ? ?
PRINT# P SHIFT R P
READ R SHIFT E R
RESTORE RE SHIFT S RE
RETURN RE SHIFT T RE
RUN R SHIFT U R
STATUS ST ST NUMERIC
STEP ST SHIFT E ST
STOP S SHIFT T S
SYS S SHIFT Y S
THEN T SHIFT H T
TIME TI TI NUMERIC
TO NONE TO
VERIFY V SHIFT E V
WAIT W SHIFT A W
ABS
TYPE: Function–Numeric
FORMAT: ABS (<expression>)
Action: Returns the absolute value of the number, which is its value without any
signs. The absolute value of a negative number is that number multiplied by –1.
10 X = ABS (Y)
10 PRINT ABS (X * J)
10 IF X = ABS (X) THEN PRINT "POSITIVE"
AND
TYPE: Operator
FORMAT: <expression> AND <expression>
Action: AND is used in Boolean operations to test bits. It is also used in operations
to check the truth of both operands.
0 1 0 1
AND 0 AND 0 AND 1 AND 1
0 0 0 1
The Commodore 64 performs the AND operation on numbers in the range from
–32768 to +32767. Any fractional values are not used, and numbers beyond
the range will cause an ?ILLEGAL QUANTITY error message. When converted
17
AND 194
0000000000010001
AND 0000000011000010
(BINARY) 0000000000000000
(DECIMAL) 0
32007
AND 28761
0111110100000111
AND 0111000001011001
(BINARY) 0111000000000001
(DECIMAL) 28673
–241
AND 15359
1111111100001111
AND 0011101111111111
(BINARY) 0011101100001111
(DECIMAL) 15119
50 IF X=7 AND W=3 THEN GOTO 10: REM ONLY TRUE IF BOTH
X=7 AND W=3 ARE TRUE
60 IF A AND Q=7 THEN GOTO 10: REM TRUE IF A IS NON-
ZERO AND Q=7 IS TRUE
ASC
TYPE: Function–Numeric
FORMAT: ASC (<string>)
Action: ASC will return a number from 0 to 255 which corresponds to the
Commodore ASCII value of the first character in the string. The table of
Commodore ASCII values is shown in Appendix C.
10 PRINT ASC("Z")
20 X = ASC("ZEBRA")
30 J = ASC(J$)
30 J = ASC(J$ +CHR$(0))
TYPE: Function–Numeric
FORMAT: ATN ( <number> )
Action: This mathematical function returns the arctangent of the number. The
result is the angle (in radians) whose tangent is the number given. The result is
always in the range –π π/2 to +π π/2.
CHR$
TYPE: Function–String
FORMAT: CHR$ ( <number> )
Action: This statement shuts off any data file or channel to a device. The file
number is the same as when the file or device was OPENed (see OPEN statement
and the section on INPUT/OUTPUT programming).
When working with storage devices like cassette tape and disks, the CLOSE
operation stores any incomplete buffers to the device. When this is not
performed, the file will be incomplete on the tape and unreadable on the disk.
The CLOSE operation isn't as necessary with other devices, but it does free up
memory for other files. See your external device manual for more details.
10 CLOSE 1
20 CLOSE X
30 CLOSE 9 * (1 + J)
CLR
TYPE: Statement
FORMAT: CLR
Action: This statement makes available RAM memory that had been used but is
no longer needed. Any BASIC program in memory is untouched, but all variables,
arrays, GOSUB addresses, FOR… NEXT loops, user-defined functions, and files
are erased from memory, and their space is made available to new variables,
etc.
10 X = 25
20 CLR
30 PRINT X
RUN
0
READY
CMD
Action: This statement switches the primary output device from the TV screen to
the file specified. This file could be on disk, tape, printer, or an I/O device like
the modem. The file number must be specified in a prior OPEN statement. The
string, when specified, is sent to the file. This is handy for titling printouts, etc.
When this command is in effect, any PRINT statements and LIST commands will
not display on the screen, but will send the text in the same format to the file.
To re-direct the output back to the screen, the PRINT# command should send a
blank line to the CMD device before CLOSEing, so it will stop expecting data
(called "un-listening" the device).
CONT
TYPE: Command
FORMAT: CONT
Action: This command re-starts the execution of a program which was halted by
a STOP or END statement or the RUN/STOP key being pressed. The program
will re-start at the exact place from which it left off.
While the program is stopped, the user can inspect or change any variables or
look at the program. When de-bugging or examining a program, STOP
statements can be placed at strategic locations to allow examination of variables
and to check the flow of the program.
The error message ?CAN'T CONTINUE will result from editing the program
(even just hitting RETURN with the cursor on an unchanged line), or if the program
halted due to an error, or if you caused an error before typing CONT to re-start
the program.
10 PI=0: C=1
20 PI=PI+4/C-4/(C+2)
30 PRINT PI
40 C=C+4: GOTO 20
Type the command PRINT C to see how far the Commodore 64 has gotten. Then
use CONT to resume from where the Commodore 64 left off.
COS
TYPE: Function
FORMAT: COS ( <number> )
Action: This mathematical function calculates the cosine of the number, where the
number is an angle in radians.
DATA
TYPE: Statement
FORMAT: DATA <list of constants>
Action: DATA statements store information within a program. The program uses
the information by means of the READ statement, which pulls successive constants
from the DATA statements.
The DATA statements don't have to be executed by the program, they only have
to be present. Therefore, they are usually placed at the end of the program.
All data statements in a program are treated as a continuous list. Data is READ
from left to right, from the lowest numbered line to the highest. If the READ
statement encounters data that doesn't fit the type requested (if it needs a
number and finds a string) an error message occurs.
10 DATA 1, 10, 5, 8
20 DATA JOHN, PAUL, GEORGE, RINGO
30 DATA "DEAR MARY, HOW ARE YOU, LOVE, BILL"
40 DATA -1.7E-9, 3.33
DEF FN
TYPE: Statement
FORMAT: DEF FN <name> ( <variable> ) = <expression>
Action: This sets up a user-defined function that can be used later in the program.
The function can consist of any mathematical formula.
10 DEF FN A(X) = X + 7
20 DEF FN AA (X) = Y*Z
30 DEF FN A9(Q) = INT(RND(1)*Q+1)
The function is called later in the program by using the function name with a
variable in parentheses. This function name is used like any other variable, and
its value is automatically calculated.
40 PRINT FN A (9)
50 R = FNAA (9)
60 G = G + FN A9 (10)
In line 50 above, the number 9 inside the parentheses does not affect the
outcome of the function, because the function definition in line 20 doesn't use the
variable in the parentheses. The result is Y times Z, regardless of the value of X.
In the other two functions, the value in parentheses does affect the result.
DIM
TYPE: Statement
FORMAT: DIM <variable> ( <subscripts> ) [ ,
<variable> ( <subscripts> )… ]
Action: This statement defines an array or matrix of variables. This allows you
to use the variable name with a subscript. The subscript points to the element
being used. The lowest element number in an array is zero, and the highest is the
number given in the DIM statement, which has a maximum of 32767.
The DIM statement must be executed once and only once for each array. A
?REDIM'D ARRAY error occurs if this line is re-executed. Therefore, most
programs perform all DIM operations at the very beginning.
There may be any number of dimensions and 255 subscripts in an array, limited
only by the amount of RAM memory which is available to hold the variables. The
array may be made up of normal numeric variables, as shown above, or of
strings or integer numbers. If the variables are other than normal numeric, use
the $ or % signs after the variable name to indicate string or integer variables.
10 DIM A (100)
20 DIM Z (5, 7), Y(3,4,5)
30 DIM Y7% (Q)
40 DIM PH$ (1000)
50 F(4)=9: REM AUTOMATICALLY PERFORMS DIM F (10)
TYPE: Statement
FORMAT: END
Action: This finishes a program's execution and displays the READY message,
returning control to the person operating the computer. There may be any
number of END statements within a program. While it is not necessary to include
any END statements at all, it is recommended that a program does conclude with
one, rather than just running out of lines.
The END statement is similar to the STOP statement. The only difference is that
STOP causes the computer to display the message BREAK IN XX and END just
displays READY. Both statements allow the computer to resume execution by
typing the CONT command.
EXP
TYPE: Function–Numeric
FORMAT: EXP ( <number> )
TYPE: Function–Numeric
FORMAT: FN <name> ( <number> )
This function can be used in direct mode, as long as the statement DEFining it has
been executed.
PRINT FN A (Q)
1100 J = FN J (7) + FN J (9)
9990 IF FN B7 (I+1) = 6 THEN END
TYPE: Statement
FORMAT: FOR <variable> = <start> TO <limit> [ STEP <increment>]
Action: This is a special BASIC statement that lets you easily use a variable as a
counter. You must specify certain parameters: the floating-point variable name,
its starting value, the limit of the count, and how much to add during each cycle.
Here is a simple BASIC program that counts from 1 to 10, PRINTing each number
and ENDing when complete, and using no FOR statements:
100 L = 1
110 PRINT L
120 L = L + 1
130 IF L <= 10 THEN 110
140 END
100 FOR L = 1 TO 10
110 PRINT L
120 NEXT L
130 END
As you can see, the program is shorter and easier to understand using the FOR
statement.
When the FOR statement is executed, several operations take place. The <start>
value is placed in the <variable> being used in the counter. In the example
above, a 1 is placed in L.
When the NEXT statement is reached, the <increment> value is added to the
<variable>. If a STEP was not included, the <increment> is set to + 1. The first
time the program above hits line 120, 1 is added to L, so the new value of L is
2.
Now the value in the <variable> is compared to the <limit>. If the <limit> has
not been reached yet, the program GOes TO the line after the original FOR
statement. In this case, the value of 2 in L is less than the limit of 10, so it GOes
TO line 110.
When the value of <increment> is positive, the <variable> must exceed the
<limit>, and when it is negative it must become less than the <limit>.
Action: This function tells you how much RAM is available for your program and
its variables. If a program tries to use more space than is available, the ?OUT
OF MEMORY error results.
The number in parentheses can have any value, and it is not used in the
calculation.
NOTE: If the result of FRE is negative, add 65536 to the FRE number to get the number of bytes
available in memory.
NOTE: The following always tells you the current available RAM:
GET
TYPE: Statement
FORMAT: GET <variable list>
Action: This statement reads each key typed by the user. As the user is typing,
the characters are stored in the Commodore 64's keyboard buffer. Up to 10
characters are stored here, and any keys struck after the 10th are lost. Reading
one of the characters with the GET statement makes room for another character.
If the GET statement specifies numeric data, and the user types a key other than
a number, the message ?SYNTAX ERROR appears. To be safe, read the keys
as strings and convert them to numbers later.
GET#
Action: This statement reads characters one-at-a-time from the device or file
specified. It works the same as the GET statement, except that the data comes
from a different place than the keyboard. If no character is received, the
variable is set to an empty string (equal to "") or to 0 for numeric variables.
Characters used to separate data in files, like the comma (,) or RETURN key
code (ASC code of 13), are received like any other character.
When used with device #3 (TV screen), this statement will read characters one
by one from the screen. Each use of GET# moves the cursor 1 position to the
right. The character at the end of the logical line is changed to a CHR$(13),
the RETURN key code.
5 GET#1, A$
10 OPEN 1, 3: GET# 1, Z7$
20 GET# 1, A, B, C$, D$
TYPE: Statement
FORMAT: GOSUB <line number>
Action: This is a specialized form of the GOTO statement, with one important
difference: GOSUB remembers where it came from. When the RETURN statement
(different from the RETURN key on the keyboard) is reached in the program,
the program jumps back to the statement immediately following the original
GOSUB statement.
GOTO
TYPE: Statement
FORMAT: GOTO <line number> or GO TO <line number>
Action: This statement allows the BASIC program to execute lines out of
numerical order. The word GOTO followed by a number will make the program
jump to the line with that number. GOTO NOT followed by a number equals
GOTO 0. It must have the line number after the word GOTO.
It is possible to create loops with GOTO that will never end. The simplest
example of this is a line that GOes TO itself, like 10 GOTO 10.
These loops can be stopped using the RUN/STOP key on the keyboard.
GOTO 100
10 GO TO 50
20 GOTO 999
IF… THEN…
TYPE: Statement
FORMAT: IF <expression> THEN <line number>
IF <expression> GOTO <line number>
IF <expression> THEN <statements>
Action: This is the statement that gives BASIC most of its "intelligence," the ability
to evaluate conditions and take different actions depending on the outcome.
This program prints out the square root of any positive number. The IF statement
here is used to validate the result of the INPUT. When the result of N <= 0 is
true, the program skips to line 200, and when the result is false the next line to
be executed is 120. Note that THEN GOTO is not needed with IF. . .THEN, as in
line 110 where GOTO 200 actually means THEN GOTO 200.
The IF in line 110 tests a random number to see if it is less than .5.
When the result is true, the whole series of statements following the word THEN
are executed: first X is incremented by 1, then the program skips to line 130.
When the result is false, the program drops to the next statement, line 120.
TYPE: Statement
FORMAT: INPUT [ "<prompt>"; ] <variable list>
Action: This is a statement that lets the person RUNning the program "feed"
information into the computer. When executed, this statement PRINTs a question
mark (?) on the screen, and positions the cursor 1 space to the right of the question
mark. Now the computer waits, cursor blinking, for the operator to type in the
answer and press the RETURN key.
The word INPUT may be followed by any text contained in quote marks (" ").
This text is PRINTed on the screen, followed by the question mark.
After the text comes a semicolon (;) and the name of one or more variables
separated by commas. This variable is where the computer stores the information
that the operator types. The variable can be any legal variable name, and you
can have several different variable names, each for a different input.
100 INPUT A
110 INPUT B, C, D
120 INPUT "PROMPT"; E
When this program RUNs, the question mark appears to prompt the operator
that the Commodore64 is expecting an input for line 100. Any number typed in
goes into A, for later use in the program. If the answer typed was not a number,
the ?REDO FROM START message appears, which means that a string was
received when a number was expected. If the operator just hits RETURN without
typing anything, the variable's value doesn't change.
Now the next question mark, for line 110, appears. If we type only one number
and hit RETURN , the Commodore 64 will now display 2 question marks (??),
which means that more input is required. You can just type as many inputs as you
Line 120 displays the word PROMPT before the question mark appears. The
semicolon is required between the prompt and any list of variables.
The INPUT statement can never be used outside a program. The Commodore 64
needs space for a buffer for the INPUT variables, the same space that is used
for commands.
INPUT#
Action: This is usually the fastest and easiest way to retrieve data stored in a
file on disk or tape. The data is in the form of whole variables of up to 80
characters in length, as opposed to the one-at-a-time method of GET#. First, the
file must have been OPENed, then INPUT# can fill the variables.
If the variable type used is numeric, and non-numeric characters are received, a
BAD DATA error results. INPUT# can read strings up to 80 characters long,
beyond which a ?STRING TOO LONG error results.
When used with device #3 (the screen), this statement will read an entire logical
line and move the cursor down to the next line.
10 INPUT# 1, A
20 INPUT# 2, A$, B$
Action: Returns the integer value of the expression. If the expression is positive,
the fractional part is left off. If the expression is negative, any fraction causes
the next lower integer to be returned.
99 -13
LEFT$
10 A$ = "COMMODORE COMPUTERS"
20 B$ = LEFT$(A$, 9): PRINTB$
RUN
COMMODORE
18
LET
TYPE: Statement
FORMAT: [LET] <variable> = <expression>
Action: The LET statement can be used to assign a value to a variable. But the
word LET is optional and therefore most advanced programmers leave LET out
because it's always understood and wastes valuable memory. The equal sign (=)
alone is sufficient when assigning the value of an expression to a variable name.
TYPE: Command
FORMAT: LIST [[<first-line>] – [<last-line>]]
Action: The LIST command allows you to look at lines of the BASIC program
currently in the memory of your Commodore 64.This lets you use your computer's
powerful screen editor to edit programs which you've LISTed both quickly and
easily.
The LIST system command displays all or part of the program that is currently in
memory on the default output device. The LIST will normally be directed to the
screen and the CMD statement can be used to switch output to an external device
such as a printer or a disk. The LIST command can appear in a program, but
BASIC always returns to the system READY message after a LIST is executed.
When you bring the program LIST onto the screen, the "scrolling" of the display
from the bottom of the screen to the top can be slowed by holding down the
ConTRol CTRL key. LIST is aborted by hitting the RUN/STOP key.
If no line numbers are given the entire program is listed. If only the first line
number is specified, and followed by a hyphen (–), that line and all higher-
numbered lines are listed. If only the last line number is specified, and it is
preceded by a hyphen, then all lines from the beginning of the program through
that line are listed. If both numbers are specified, the entire range, including the
line numbers LISTed, are displayed.
TYPE: Command
FORMAT: LOAD ["<file name>"] [,<device>] [,<address>]
Action: The LOAD statement reads the contents of a program file from tape or
disk into memory. That way you can use the information LOADed or change the
information in some way. The device number is optional, but when it is left out
the computer will automatically default to 1, the cassette unit. The disk unit is
normally device number 8. The LOAD closes all open files and, if it is used in
direct mode, it performs a CLR (clear) before reading the program. If LOAD is
executed from within a program, the program is RUN. This means that you can
use LOAD to "chain" several programs together. None of the variables are
cleared during a chain operation.
If you are using file name pattern matching, the first file which matches the
pattern is loaded. The asterisk in quotes by itself ("*") causes the first file name
in the disk directory to be loaded. If the file name used does not exist or if it is
not a program file, the BASIC error message ?FILE NOT FOUND occurs.
When LOADing programs from tape, the <file name> can be left out, and the
next program file on the tape will be read. The Commodore 64 will blank the
screen to the border color after the PLAY key is pressed. When the program is
found, the screen clears to the background color and the "FOUND" message is
displayed. When the key, CTRL key, ← key, or SPACE BAR is pressed, the
file will be loaded. Programs will LOAD starting at memory location 2048 unless
a secondary <address> of 1 is used. If you use the secondary address of 1 this
will cause the program to LOAD to the memory location from which it was saved.
25 PRINT LOG(45/7)
RUN
1.86075234
MID$
TYPE: String Function
FORMAT: MID$ (<string>, <numeric-1> [,<numeric-2>])
Action: The MID$ function returns a sub-string which is taken from within a larger
<string> argument. The starting position of the sub-string is defined by the
<numeric-1> argument and the length of the sub-string by the <numeric-2>
argument. Both of the numeric arguments can have values ranging from 0 to 255.
If the <numeric-1> value is greater than the length of the <string>, or if the
<numeric-2> value is zero, then MID$ gives a null string value. If the <numeric-
2> argument is left out, then the computer will assume that a length of the rest
of the string is to be used. And if the source string has fewer characters than
<numeric-2>, from the starting position to the end of the string argument, then
the whole rest of the string is used.
10 A$="GOOD"
20 B$="MORNING EVENING AFTERNOON"
30 PRINTA$ + MID$(B$, 8, 8)
RUN
GOOD EVENING
TYPE: Command
FORMAT: NEW
Action: The NEW command is used to delete the program currently in memory
and clear all variables. Before typing in a new program, NEW should be used
in direct mode to clear memory. NEW can also be used in a program, but you
should be aware of the fact that it will erase everything that has gone before
and is still in the computer's memory. This can be particularly troublesome when
you're trying to debug your program.
BE CAREFUL: Not clearing out an old program before typing a new one can result in a confusing
mix of the two programs.
NEXT
TYPE: Statement
FORMAT: NEXT [<counter>] [,<counter>]…
Action: The NEXT statement is used with FOR to establish the end of a FOR…
NEXT loop. The NEXT need not be physically the last statement in the loop, but
it is always the last statement executed in a loop. The <counter> is the loop
index's variable name used with FOR to start the loop. A single NEXT can stop
several nested loops when it is followed by each FOR's <counter> variable
name(s). To do this each name must appear in the order of inner-most nested
loop first, to outer-most nested loop last. When using a single NEXT to increment
and stop several variable names, each variable name must be separated by
commas. Loops can be nested to 9 levels. If the counter variable(s) are omitted,
the counter associated with the FOR of the current level (of the nested loops) is
incremented.
10 FOR L = 1 TO 100
20 FOR M = 1 TO 10
30 NEXT M
400 NEXT L (Note how the loops do NOT cross each other)
10 FOR A = 1 TO 10
20 FOR B = 1 TO 20
30 NEXT
40 NEXT (Notice that no variable names are needed)
NOT
Action: The NOT logical operator "complements" the value of each bit in its
single operand, producing an integer "two's complement" result. In other words,
the NOT is really saying, "if it isn't. . . ". When working with a floating-point
number, the operands are converted to integers and any fractions are lost. The
NOT operator can also be used in a comparison to reverse the true/false value
which was the result of a relationship test and therefore it will reverse the
meaning of the comparison. In the first example below, if the "two's complement"
of "AA" is equal to "BB" and if "BB" is NOT equal to "CC" then the expression is
true.
NOTE: To find the value of NOT use the expression X=(–(X+1)). (The two's complement of any
integer is the bit complement plus one.)
ON
TYPE: Statement
FORMAT: ON <variable> GOTO / GOSUB <Iine number> [,<line
number>]. . .
Action: The ON statement is used to GOTO one of several given line numbers,
depending upon the value of a variable. The value of the variables can range
from zero through the number of lines given. If the value is a non-integer, the
fractional portion is left off. For example, if the variable value is 3, ON will
GOTO the third line number in the list.
If the value of the variable is negative, the BASIC error message ?ILLEGAL
QUANTITY occurs. If the number is zero, or greater than the number of items in
the list, the program just "ignores" the statement and continues with the statement
following the ON statement.
EXAMPLES of ON Statement:
ON X GOTO 100,130,180,220
Action: This statement OPENs a channel for input and/or output to a peripheral
device. However, you may NOT need all those ports for every OPEN statement.
Some OPEN statements require only 2 codes:
The <file number> is the logical file number, which relates the OPEN, CLOSE,
CMD, GET#, INPUT#, and PRINT# statements to each other and associates them
with the file name and the piece of equipment being used. The logical file number
can range from 1 to 255 and you can assign it any number you want in that
range.
NOTE: File numbers over 128 were really designed for other uses so it's good practice to use
only numbers below 127 for file numbers.
Each peripheral device (printer, disk drive, cassette) in the system has its own
number which it answers to. The <device> number is used with OPEN to specify
on which device the data file exists. Peripherals like cassette decks, disk drives
or printers also answer to several secondary addresses. Think of these as codes
which tell each device what operation to perform. The device logical file number
is used with every GET#, INPUT#, and PRINT#.
If the <device> number is left out the computer will automatically assume that
you want your information to be sent to and received from the
Datassette™, which is device number 1. The file name can also be left out, but
later on in your program, you can NOT call the file by name if you have not
already given it one. When you are storing files on cassette tape, the computer
will assume that the secondary <address> is zero (0) if you omit the secondary
address (a READ operation).
For disk files, the secondary addresses 2 through 14 are available for data-
files, but other numbers have special meanings in DOS commands. You must use
a secondary address when using your disk drive(s). (See your disk drive manual
for DOS command details.)
If you try to access a file before it is OPENed the BASIC error message ?FILE
NOT OPEN will occur. If you try to OPEN a file for reading which does not exist
the BASIC error message ?FILE NOT FOUND will occur. If a file is OPENed to
disk for writing and the file name already exists, the DOS error message FILE
EXISTS occurs. There is no check of this type available for tape files, so be sure
that the tape is properly positioned or you might accidentally write over some
data that had previously been SAVEd. If a file is OPENed that is already OPEN,
the BASIC error message FILE OPEN occurs. (See Printer Manual for further
details.)
10 OPEN 1, 1, 2, "TAPE-
WRITE" (Write End-of-File on Close)
Action: Just as the relational operators can be used to make decisions regarding
program flow, logical operators can connect two or more relations and return a
true or false value which can then be used in a decision. When used in
calculations, the logical OR gives you a bit result of 1 if the corresponding bit of
either, or both, operands is 1. This will produce an integer as a result depending
on the values of the operands.
When used in comparisons the logical OR operator is also used to link two
expressions into a single compound expression. If either of the expressions are
true, the combined expression value is true (–1). In the first example below if AA
is equal to BB OR if XX is 20, the expression is true.
EXAMPLES of OR Operator:
230 KK%=64 OR 32: PRINT KK% (You typed this with a bit value of
1000000 for 64 and 100000 for
32)
96 (The computer responded with bit
value 1100000.
1100000=96.)
Action: Returns an integer in the range of 0 to 255, which is read from a memory
location. The <numeric> expression is a memory location which must be in the
range of 0 to 65535. If it isn't then the BASIC error message ?ILLEGAL
QUANTITY occurs.
POKE
TYPE: Statement
FORMAT: POKE <location>, <value>
Action: The POKE statement is used to write a one-byte (8-bits) binary value into
a given memory location or input/output register. The <location> is an arithmetic
expression which must equal a value in the range of 0 to 65535. The <value>
is an expression which can be reduced to an integer value of 0 to 255. If either
value is out of its respective range, the BASIC error message ?ILLEGAL
QUANTITY occurs.
The POKE statement and PEEK statement (which is a built-in function that looks at
a memory location) are useful for data storage, controlling graphics displays or
sound generation, loading assembly language subroutines, and passing
arguments and results to and from assembly language subroutines. In addition,
Operating System parameters can be examined using PEEK statements or
changed and manipulated using POKE statements. A complete memory map of
useful locations is given in Appendix G.
POS
Action: Tells you the current cursor position which, of course, is in the range of 0
(leftmost character) though position 79 on an 80-character logical screen line.
Since the Commodore 64 has a 40-column screen, any position from 40 through
79 will refer to the second screen line. The dummy argument is ignored.
TYPE: Statement
FORMAT: PRINT [<variable>] [ <,/;><variable>]…
Action: The PRINT statement is normally used to write data items to the screen.
However, the CMD statement may be used to redirect that output to any other
device in the system. The <variable(s)> in the output-list are expressions of any
type. If no output-list is present, a blank line is printed. The position of each
printed item is determined by the punctuation used to separate items in the
output-list.
The punctuation characters that you can use are blanks, commas, or semicolons.
The 80 character logical screen line is divided into 8 print zones of 10 spaces
each. In the list of expressions, a comma causes the next value to be printed at
the beginning of the next zone. A semicolon causes the next value to be printed
immediately following the previous value. However, there are two exceptions to
this rule:
If a comma or a semicolon is at the end of the output-list, the next PRINT statement
begins printing on the same line, and spaced accordingly. If no punctuation
finishes the list, a carriage-return and a line-feed are printed at the end of the
data. The next PRINT statement will begin on the next line. If your output is
directed to the screen and the data printed is longer than 40 columns, the output
is continued on the next screen line.
There is no statement in BASIC with more variety than the PRINT statement. There
are so many symbols, functions, and parameters associated with this statement
that it might almost be considered as a language of its own within BASIC; a
language specially designed for writing on the screen.
1.
5 X = 5
10 PRINT -5*X, X-5, X+5, X↑5
-25 0 10 3125
2.
5 X = 9
10 PRINT X; "SQUARED IS";X*X;"AND";
20 PRINT X "CUBED IS" X↑3
3.
90 AA$="ALPHA":BB$="BAKER":CC$="CHARLIE":DD$="DOG":
EE$="ECHO"
100 PRINT AA$BB$;CC$ DD$,EE$
ALPHABAKERCHARLIEDOG ECHO
Once the quote mark ( SHIFT 2 ) is typed, the cursor controls stop operating
and start displaying reversed characters which actually stand for the cursor
control you are hitting. This allows you to program these cursor controls, because
once the text inside the quotes is PRINTed they perform their functions.
The INST/DEL key is the only cursor control not affected by “quote mode.”
1. Cursor Movement
KEY APPEARS AS
CLR/HOME
SHIFT CLR/HOME
↑CRSR↓
SHIFT ↑CRSR↓ ◘
←CRSR→
SHIFT ←CRSR→
If you wanted the word HELLO to PRINT diagonally from the upper left corner
of the screen, you would type:
2. Reverse Characters
Holding down the CTRL key and hitting 9 will cause R to appear inside the
quotes. This will make all characters start printing in reverse video (like a negative
of a picture). To end the reverse printing hit CTRL 0 , which prints a or else
PRINT a RETURN (CHR$(13)). (Just ending the print statement without a semicolon
or comma will take care of this.)
3. Color Controls
Holding down the CTRL key or key with any of the 8 color keys will make a
special reversed character appear in the quotes. When the character is PRINTed,
then the color change will occur.
If you wanted to print the word HELLO in cyan and the word THERE in white,
type:
4. Insert Mode
The spaces created by using the INST/DEL key have some of the same
characteristics as quote mode. The cursor controls and color controls show up as
reversed characters. The only difference is in the INST and DEL , which performs
When the above line is RUN, the word displayed will be HELP, because the last
two letters are deleted and the P is put in their place.
WARNING: The DELetes will work when LISTing as well as PRINTing, so editing a line with these
characters will be difficult.
The “insert mode” condition is ended when the RETURN (or SHIFT RETURN ) key
is hit, or when as many characters have been typed as spaces were inserted.
There are some other characters that can be PRINTed for special functions,
although they are not easily available from the keyboard. In order to get these
into quotes, you must leave empty spaces for them in the line,
hit RETURN or SHIFT RETURN , and go back to the spaces with the cursor
controls. Now you must hit CTRL RVS/ON , to start typing reversed characters,
and type the keys shown below:
Appears As
Function Type
SHIFT RETURN SHIFT M
switch to lower case N
switch to upper case SHIFT N
disable case-switching keys H
enable case-switching keys I
PRINT#
Actions: The PRINT# statement is used to write data items to a logical file. It
must use the same number used to OPEN the file. Output goes to the device
number used in the OPEN statement. The <variable> expressions in the output-
list can be of any type. The punctuation characters between items are the same
as with the PRINT statement and they can be used in the same ways. The effects
of punctuation are different in two significant respects.
When PRINT# is used with tape files, the comma, instead of spacing by print
zones, has the same effect as a semicolon. Therefore, whether blanks, commas,
semicolons or no punctuation characters are used between data items, the effect
on spacing is the same. The data items are written as a continuous stream of
characters. Numeric items are followed by a space and, if positive, are
preceded by a space.
The easiest way to write more than one variable to a file on tape or disk is to
set a string variable to CHR$(13), and use that string in between all the other
variables when writing the file.
1.
2.
10 CO$=CHR$(44):CR$=CHR$(13)
20 PRINT#1, "AAA" CO$ "BBB", AAA, BBB CCCDDDEEE
"CCC";"DDD";"EEE"CR$" (carriage return)
"FFF",CR$; FFF(carriage return)
30 INPUT#1, A$,BCDE$,F$
3.
5 CR$=CHR$(13)
10 PRINT#2, "AAA";CR$;"BBB" (10 blanks) AAA
20 PRINT#2, "CCC"; BBB
(10 blanks) CCC
30 INPUT#2, A$,B$,DUMMY$,C$
READ
TYPE: Statement
FORMAT: READ <variable> [,<variable>]…
Action: The READ statement is used to fill variable names from constants in DATA
statements. The data actually read must agree with the variable types specified
or the BASIC error message ?SYNTAX ERROR will result. Variables in the DATA
input-list must be separated by commas.
A single READ statement can access one or more DATA statements, which will be
accessed in order (see DATA), or several READ statements can access the same
DATA statement. If more READ statements are executed than the number of
NOTE: The ?SYNTAX ERROR will appear with the line number from the DATA statement, NOT
the READ statement.
110 READ A, B, C$
120 DATA 1, 2, HELLO
REM
TYPE: Statement
FORMAT: REM [<remark>]
Action: The REM statement makes your programs more easily understood when
LISTed. It's a reminder to yourself to tell you what you had in mind when you
were writing each section of the program. For instance, you might want to
remember what a variable is used for, or some other useful information. The
REMark can be any text, word, or character including the colon (:) or BASIC
keywords. The REM statement and anything following it on the same line number
are ignored by BASIC, but REMarks are printed exactly as entered when the
program is listed. A REM statement can be referred to by a GOTO or GOSUB
statement, and the execution of the program will continue with the next higher
program line having executable statements.
RESTORE
TYPE: Statement
FORMAT: RESTORE
10 DATA 1,2,3,4
20 DATA 5,6,7,8
30 FOR L=1 TO 8
40 READA: PRINT A
50 NEXT
60 RESTORE
70 FOR L=1TO 8
80 READA: PRINT A
90 NEXT
TYPE: Statement
FORMAT: RETURN
Action: The RETURN statement is used to exit from a subroutine called for by a
GOSUB statement. RETURN restarts the rest of your program at the next
executable statement following the GOSUB. If you are nesting subroutines, each
GOSUB must be paired with at least one RETURN statement. A subroutine can
contain any number of RETURN statements, but the first one encountered will exit
the subroutine.
RIGHT$
Action: The RIGHT$ function returns a sub-string taken from the right-most end
of the <string> argument. The length of the sub-string is defined by the
<numeric> argument which can be any integer in the range of 0 to 255. If the
value of the numeric expression is zero, then a null string ("") is returned. If the
value you give in the <numeric> argument is greater than the length of the
<string> then the entire string is returned.
Action: RND creates a floating-point random from 0.0 to 1.0. The computer
generates a sequence of random numbers by performing calculations on a
starting number, which in computer jargon is called a seed. The RND function is
seeded on system power-up. The <numeric> argument is a dummy, except for
its sign (positive, zero, or negative).
TYPE: Command
FORMAT: RUN [<line number>]
Action: The system command RUN is used to start the program currently in
memory. The RUN command causes an implied CLR operation to be performed
before starting the program. You can avoid the CleaRing operation by using
CONT or GOTO to restart a program instead of RUN. If a <line number> is
specified, your program will start on that line. Otherwise, the RUN command
starts at first line of the program.
The RUN command can also be used within a program. If the <line number> you
specify doesn't exist, the BASIC error message ?UNDEF'D STATEMENT occurs.
A RUNning program stops and BASIC returns to direct mode when an END or
STOP statement is reached, when the last line of the program is finished, or when
a BASIC error occurs during execution.
SAVE
TYPE: Command
FORMAT: SAVE ["<file name>"] [,<device number>] [,<address> ]
Action: The SAVE command is used to store the program that is currently in
memory onto a tape or diskette file. The program being SAVEd is only affected
by the command while the SAVE is happening. The program remains in the
current computer memory even after the SAVE operation is completed until you
put something else there by using another command. The file type will be "prg"
(program). If the <device number> is left out, then the C64 will automatically
assume that you want the program saved on cassette, device number 1. If the
<device number> is an <8>, then the program is written onto disk. The SAVE
A secondary address of 1 will tell the KERNAL to LOAD the tape at a later time,
with the program currently in memory instead of the normal 2048 location. A
secondary address of 2 will cause an end-of-tape marker to follow the program.
A secondary address of 3 combines both functions.
When saving programs onto a disk, the <file name> must be pre-sent.
Action: SGN gives you an integer value depending upon the sign of the
<numeric> argument. If the argument is positive the result is 1, if zero the result
is also 0, if negative the result is –1.
SIN
TYPE: Floating-Point Function
FORMAT: SIN (<numeric>)
Action: SIN gives you the sine of the <numeric> argument, in radians. The value
of COS(x) is equal to SIN(x+3.14159265/2).
.997494987
SPC
Action: The SPC function is used to control the formatting of data, as either an
output to the screen or into a logical file. The number of SPaCes given by the
<numeric> argument are printed, starting at the first available position. For
screen or tape files the value of the argument is in the range of 0 to 255 and
for disk files up to 254. For printer files, an automatic carriage-return and line-
feed will be performed by the printer if a SPaCe is printed in the last character
position of a line. No SPaCes are printed on the following line.
SQR
Action: SQR gives you the value of the SQuare Root of the <numeric> argument.
The value of the argument must not be negative, or the BASIC error message
?ILLEGAL QUANTITY will happen.
10 3.16227766
15 3.87298335
20 4.47213595
25 5
READY.
STATUS
Action: Returns a completion STATUS for the last input/output operation which
was performed on an open file. The STATUS can be read from any peripheral
device. The STATUS (or simply ST) keyword is a system defined variable-name
NOTE: The STEP value can NOT be changed once it's in the loop.
STOP
TYPE: Statement
FORMAT: STOP
Action: The STOP statement is used to halt execution of the current program and
return to direct mode. Typing the RUN/STOP key on the keyboard has the same
effect as a STOP statement. The BASIC error message BREAK IN XX is displayed
on the screen, followed by READY. The "XX" is the line number where the STOP
occurs. Any open files remain open and all variables are preserved and can be
examined. The program can be restarted by using CONT or GOTO statements.
Action: STR$ gives you the STRing representation of the numeric value of the
argument. When the STR$ value is converted to each variable represented in
the <numeric> argument, any number shown is followed by a space and, if it's
positive, it is also preceded by a space.
15000 15000
SYS
TYPE: Statement
FORMAT: SYS <memory-location>
Action: This is the most common way to mix a BASIC program with a machine
language program. The machine language program begins at the location given
in the SYS statement. The system command SYS is used in either direct or program
mode to transfer control of the microprocessor to an existing machine language
program in memory. The memory-location given is by numeric expression and
can be anywhere in memory, RAM or ROM.
When you're using the SYS statement you must end that section of machine
language code with an RTS (ReTurn from Subroutine) instruction so that when the
machine language program is finished, the BASIC execution will resume with the
statement following the SYS command.
Action: The TAB function moves the cursor to a relative SPC move position on the
screen given by the <numeric> argument, starting with the left-most position of
the current line. The value of the argument can range from 0 to 255. The TAB
function should only be used with the PRINT statement, since it has no effect if
used with PRINT# to a logical file.
NAME AMOUNT
G.T. JONES 25.
TAN
Action: Returns the tangent of the value of the <numeric> expression in radians.
If the TAN function overflows, the BASIC error message ?DIVISION BY ZERO is
displayed.
Action: The TI function reads the interval TImer. This type of "clock" is called a
"jiffy clock." The "jiffy clock" value is set at zero (initialized) when you power-up
the system. This 1/60 second interval timer is turned off during tape I/O.
EXAMPLE of TI Function:
TlME$
Action: The TI$ timer looks and works like a real clock as long as your system is
powered-on. The hardware interval timer (or jiffy clock) is read and used to
update the value of TI$, which will give you a TIme $tring of six characters in
hours, minutes and seconds. The TI$ timer can also be assigned an arbitrary
starting point similar to the way you set your wristwatch. The value of TI$ is not
accurate after tape I/O.
000011
Action: The USR function jumps to a User callable machine language SubRoutine
which has its starting address pointed to by the contents of memory locations
785 – 786. The starting address is established before calling the USR function
by using POKE statements to set up locations 785 – 786. Unless POKE statements
are used, locations 785 – 786 will give you an ?ILLEGAL QUANTITY error
message.
10 B=T * SIN(Y)
20 C=USR (B/2)
30 D=USR (B/3)
VAL
Action: Returns a numeric VALue representing the data in the <string> argument.
If the first non-blank character of the string is not a plus sign (+), minus sign (–),
or a digit the VALue returned is zero. String conversion is finished when the end
of the string or any non-digit character is found (except decimal point or
exponential e).
TYPE: Command
FORMAT: VERIFY ["<file name>"] [,<device>]
A program name can be given either in quotes (" ") or as a string variable.
VERIFY is also used to position a tape just past the last program, so that a new
program can be added to the tape without accidentally writing over another
program.
9000 SAVE"ME",8:
9010 VERIFY"ME",8 (Looks at device 8 for the program)
TYPE: Statement
FORMAT: WAIT <location>, <mask-1> [,<mask-2>]
For most programmers, this statement should never be used. It causes the
program to halt until a specific memory location's bits change in a specific way.
This is used for certain I/O operations and almost nothing else.
The WAIT statement takes the value in the memory location and performs a
logical AND operation with the value in mask-1. If there is a mask-2 in the
statement, the result of the first operation is exclusive-ORed with mask-2. In other
words mask-1 "filters out" any bits that you don't want to test. Where the bit is
0 in mask-1, the corresponding bit in the result will always be 0. The mask-2
value flips any bits, so that you can test for an off condition as well as an on
condition. Any bits being tested for a 0 should have a 1 in the corresponding
position in mask-2.
WAIT 1, 32, 32
WAIT 53273, 6, 6
WAIT 36868, 144, 16 (144 & 16 are masks.144 = 10010000 in
binary and 16=10000 in binary. The WAIT
statement will halt the program until the 128
bit is on or until the 16 bit is off)
In other words, the keyboard buffer allows you to "type-ahead" of the system,
which means it can anticipate responses to INPUT prompts or GET statements. As
you type on the keys their character values are lined up, single-file (queued) into
the buffer to wait for processing in the order the keys were struck. This type-
ahead feature can give you an occasional problem where an accidental
keystroke causes a program to fetch an incorrect character from the buffer.
In addition to GET and INPUT, the keyboard can also be read using PEEK to
fetch from memory location 197 ($00C5) the integer value of the key currently
being pressed. If no key is being held when the PEEK is executed, a value of 64
is returned. The numeric keyboard values, keyboard symbols and character
equivalents (CHR$) are shown in Appendix C. The following example loops until
a key is pressed then converts the integer to a character value:
10 AA = PEEK(197): IF AA = 64 THEN 10
20 BB$ = CHR$(AA)
Eight columns by eight rows yields 64 possible values. However, if you first strike
the RVS , CTRL or keys or hold down the SHIFT key and type a second
character, additional values are generated. This is because the KERNAL decodes
these keys separately and "remembers" when one of the control keys was
pressed. The result of the keyboard scan is then placed in location 197.
Characters can also be written directly to the keyboard buffer at locations 631–
640 using a POKE statement. These characters will be processed when the POKE
is used to set a character count into location 198. These facts can be used to
cause a series of direct-mode commands to be executed automatically by
printing the statements onto the screen, putting carriage-returns into the buffer,
and then setting the character count. In the example below, the program will LIST
itself to the printer and then resume execution:
SCREEN EDITOR
The SCREEN EDITOR provides you with powerful and convenient facilities for
editing program text. Once a section of a program is listed to the screen, the
cursor keys and other special keys are used to move around the screen so that
you can make any appropriate changes, After, making all the changes you want
to a specific line number of text, hitting the RETURN key anywhere on the line,
causes the SCREEN EDITOR to read the entire 80-character logical screen line.
Under certain conditions the SCREEN EDITOR treats the cursor control keys
differently from their normal mode of handling. If the CuRSoR is positioned to
the right of an odd number of double-quote marks (") the EDITOR operates in
what is known as the QUOTE MODE.
In quote mode data characters are entered normally but the cursor controls no
longer move the CuRSoR, instead reversed characters are displayed which
actually stand for the cursor control being entered. The same is true of the color
control keys. This allows you to include cursor and color controls inside string data
items in programs. You will find that this is a very important and powerful
feature. That's because when the text inside the quotes is printed to the screen it
performs the cursor positioning and color control functions automatically as part
of the string. An example of using cursor controls in strings is:
Computer prints AC BD
The DEL key is the only cursor control NOT affected by quote mode. Therefore,
if an error is made while keying in quote mode, the ←CRSR key can't be used
to back up and strike over the error – even the INST key produces a reverse
video character. Instead, finish entering the line, and then, after hitting
the RETURN key, you can edit the line normally. Another alternative, if no further
cursor-controls are needed in the string, is to press
the RUN/STOP and RESTORE keys which will cancel QUOTE MODE. The cursor
control keys that you can use in strings are shown in Table 2–2.
When you are NOT in quote mode, holding down the SHIFT key and then
pressing the INSerT INST key shifts data to the right of the cursor to open up
space between two characters for entering data between them. The Editor then
begins operating in INSERT MODE until all of the space opened up is filled.
The cursor controls and color controls again show as reversed characters in insert
mode. The only difference occurs on the DELete and INSerT INST/DEL key.
The DEL key instead of operating normally as in the quote mode, now creates
the reversed T . The INST key, which created a reverse character in quote mode,
inserts spaces normally.
This means that a PRINT statement can be created, containing DELetes, which
can't be done in quote mode. The insert mode is cancelled by pressing
the RETURN , SHIFT and RETURN or RUN/STOP and RESTORE keys. Or you can
cancel the insert mode by filling all the inserted spaces. An example of using DEL
characters in strings is:
When the example is RUN, the word displayed will be HELP, because the letters
LO are deleted before the P is printed. The DELete character in strings will work
with LIST as well as PRINT. You can use this to "hide" part or all of a line of text
using this technique. However, trying to edit a line with these characters will be
difficult if not impossible.
Holding down the SHIFT key and hitting RETURN causes a carriage-return and
line-feed on the screen but does not end the string. This works with LIST as well
as PRINT, so editing will be almost impossible if this character is used. When
output is switched to the printer via the CMD statement, the reverse "N" character
shifts the printer into its upper-lower case character set and the SHIFT "N" shifts
the printer into the upper-case/graphics character set.
All of the graphics abilities of the Commodore 64 come from the 6567 Video
Interface Chip (also known as the VIC-II chip). This chip gives a variety of
graphics modes, including a 40 column by 25 line text display, a 320 by 200
dot high resolution display, and SPRITES, small movable objects which make
writing games simple. And if this weren't enough, many of the graphics modes
can be mixed on the same screen. It is possible, for example, to define the top
half of the screen to be in high resolution mode, while the bottom half is in text
mode. And SPRITES will combine with anything! More on sprites later. First the
other graphics modes.
B. BITMAP MODES
C. SPRITES
1. Standard Sprites
2. Multicolor Sprites
Some general information first. There are 1000 possible locations on the
Commodore 64 screen. Normally, the screen starts at location 1024 ($0400 in
HEXadecimal notation) and goes to location 2023. Each of these locations is 8
bits wide. This means that it can hold any integer number from 0 to 255.
Connected with screen memory is a group of 1000 locations called COLOR
MEMORY or COLOR RAM. These start at location 55296 ($D800 in HEX) and
go up to 56295. Each of the color RAM locations is 4 bits wide, which means that
it can hold any integer number from 0 to 15. Since there are 16 possible colors
that the Commodore 64 can use, this works out well.
In addition, there are 256 different characters that can be displayed at any
time. For normal screen display, each of the 1000 locations in screen memory
contains a code number which tells the VIC-II chip which character to display at
that screen location.
The various graphics modes are selected by the 47 CONTROL registers in the
VIC-II chip. Many of the graphics functions can be controlled by POKEing the
correct value into one of the registers. The VIC-II chip is located starting at 53248
($D000 in HEX) through 53294 ($D02E in HEX).
The VIC-II chip can access ("see") 16K of memory at a time. Since there is 64K
of memory in the Commodore 64, you want to be able to have the VIC-II chip
see all of it. There is a way. There are 4 possible BANKS (or sections) of 16K of
memory. All that is needed is some means of controlling which 16K bank the VIC-
II chip looks at. In that way, the chip can "see" the entire 64K of memory. The
BANK SELECT bits that allow you access to all the different sections of memory
are located in the 6526 COMPLEX INTERFACE ADAPTER CHIP #2 (CIA#2).The
POKE and PEEK BASIC statements (or their machine language versions) are used
to select a bank by controlling bits 0 and 1 of PORT A of CIA#2 (location 56576
(or $DD00 HEX). These 2 bits must be set to outputs by setting bits 0 and 1 of
location 56578 ($DD02 HEX) to change banks. The following example shows
this:
This 16K bank concept is part of everything that the VIC-II chip does. You should
always be aware of which bank the VIC-II chip is pointing at, since this will affect
where character data patterns come from, where the screen is, where sprites
come from, etc. When you turn on the power of your Commodore 64, bits 0 and
1 of location 56576 are automatically set to BANK 0 ($0000 to $3FFF) for all
display information.
*NOTE: The Commodore 64 character set is not available to the VIC-II chip in BANKS 1 and 3.
(See character memory section.)
SCREEN MEMORY
LOCATION*
A BITS
DECIMAL HEX
0 0000XXXX 0 $0000
16 0001XXXX 1024 $0400 (DEFAULT)
32 0010XXXX 2048 $0800
48 0011XXXX 3072 $0C00
64 0100XXXX 4096 $1000
80 0101XXXX 5120 $1400
96 0110XXXX 6144 $1800
112 0111XXXX 7168 $1C00
128 1000XXXX 8192 $2000
144 1001XXXX 9216 $2400
160 1010XXXX 10240 $2800
176 1011XXXX 11264 $2C00
192 1100XXXX 12288 $3000
208 1101XXXX 13312 $3400
224 1110XXXX 14336 $3800
240 1111XXXX 15360 $3C00
*Remember that the BANK ADDRESS of the VIC-II chip must be added in. You must also tell the
KERNAL'S screen editor where the screen is as follows: POKE 648, page (where page =
address/256, e.g., 1024/256= 4, so POKE 648, 4).
COLOR MEMORY
Color memory can NOT move. It is always located at locations 55296 ($D800)
through 56295 ($DBE7). Screen memory (the 1000 locations starting at 1024)
and color memory are used differently in the different graphics modes. A picture
created in one mode will often look completely different when displayed in
another graphics mode.
CHARACTER MEMORY
Since the VIC-II chip looks at 16K of memory at a time, there are 8 possible
locations for a complete character set. Naturally, you are free to use less than a
full character set. However, it must still start at one of the 8 possible starting
locations.
LOCATION*
A BITS
DECIMAL HEX
0 XXXX000X 0 $0000–$07FF
2 XXXX001X 2048 $0800–$0FFF
4 XXXX010X 4096 $1000–$17FF ROM IMAGE in BANK
0 & 2 (default)
6 XXXX011X 6144 $1800–$1FFF ROM IMAGE in BANK
0&2
8 XXXX100X 8192 $2000–$27FF
10 XXXX101X 10240 $2800–$2FFF
12 XXXX110X 12288 $3000–£37FF
14 XXXX111X 14336 $3800–$3FFF
NOTE: If these ROM images get in the way of your own graphics, then set the BANK SELECT
BITS to one of the BANKS without the images (BANKS 1 or 3). The ROM patterns won't be there.
The location and contents of the character set in ROM are as follows:
ADDRESS VIC-II
BLOCK CONTENTS
DECIMAL HEX IMAGE
0 53248 D000–D1FF 1000–11FF Upper case characters
Sharp-eyed readers will have just noticed something. The locations occupied by
the character ROM are the same as the ones occupied by the VIC-II chip control
registers. This is possible because they don't occupy the same locations at the
same time. When the VIC-II chip needs to access character data the ROM is
switched in. It becomes an image in the16K bank of memory that the VIC-II chip
However, you may need to get to the character ROM if you are going to use
programmable characters and want to copy some of the character ROM for
some of your character definitions. In this case you must switch out the I/O
register, switch in the character ROM, and do your copying. When you're
finished, you must switch the I/O registers back in again. During the copying
process (when I/O is switched out) no interrupts can be allowed to take place.
This is because the I/O registers are needed to service the interrupts. If you
forget and perform an interrupt, really strange things happen. The keyboard
should not be read during the copying process. To turn off the keyboard and
other normal interrupts that occur with your Commodore 64, the following POKE
should be used:
After you are finished getting characters from the character ROM, and are
ready to continue with your program, you must turn the keyboard scan back on
by the following POKE:
The following POKE will switch out I/O and switch the CHARACTER ROM in:
The character ROM is now in the locations from 53248 to 57343 ($D000 to
$DFFF).
To switch I/O back into $D000 for normal operation use the following POKE:
POKE 1, PEEK(1) OR 4
Standard character mode is the mode the Commodore 64 is in when you first
turn it on. It is the mode you will generally program in.
Characters can be taken from ROM or from RAM, but normally they are taken
from ROM. When you want special graphics characters for a program, all you
have to do is define the new character shapes in RAM, and tell the VIC-II chip to
get its character information from there instead of the character ROM. This is
covered in more detail in the next section.
In order to display characters on the screen in color, the VIC-II chip accesses the
screen memory to determine the character code for that location on the screen.
At the same time, it accesses the color memory to determine what color you want
for the character displayed. The character code is translated by the VIC-II into
the starting address of the 8-byte block holding your character pattern. The 8-
byte block is located in character memory.
The translation isn't too complicated, but a number of items are combined to
generate the desired address. First the character code you use to POKE screen
memory is multiplied by 8. Next add the start of character memory (see
CHARACTER MEMORY section). Then the Bank Select Bits are taken into account
by adding in the base address (see VIDEO BANK SELECTION section). Below is
a simple formula to illustrate what happens:
CHARACTER DEFINITIONS
Each character is formed in an 8 by 8 grid of dots, where each dot maybe either
on or off. The Commodore 64 character images are stored in the Character
Generator ROM chip. The characters are stored as a set of 8 bytes for each
character, with each byte representing the dot pattern of a row in the character,
and each bit representing a dot. A zero bit means that dot is off, and a one bit
means the dot is on.
The character memory in ROM begins at location 53248 (when the I/O is
switched off). The first 8 bytes from location 53248 ($D000) to 53255 ($D007)
contain the pattern for the @ sign, which has a character code value of zero in
Each complete character set takes up 2K (2048 bits) of memory, 8 bytes per
character and 256 characters. Since there are two character sets, one for upper
case and graphics and the other with upper and lower case, the character
generator ROM takes up a total of 4K locations.
PROGRAMMABLE CHARACTERS
Since the characters are stored in ROM, it would seem that there is no way to
change them for customizing characters. However, the memory location that tells
the VIC-II chip where to find the characters is a programmable register which
can be changed to point to many sections of memory. By changing the character
memory pointer to point to RAM, the character set may be programmed for any
need.
If you want your character set to be located in RAM, there are a few VERY
IMPORTANT things to take into account when you decide to actually program
your own character sets. In addition, there are two other important points you
must know to create your own special characters:
1. It is an all or nothing process. Generally, if you use your own character set by
telling the VIC-II chip to get the character information from the area you have
prepared in RAM, the standard Commodore 64 characters are unavailable to
you. To solve this, you must copy any letters, numbers, or standard Commodore
64 graphics you intend to use into your own character memory in RAM. You can
pick and choose, take only the ones you want, and don't even have to keep them
in order!
WARNING: You must be careful to protect the character set from being overwritten by your
BASIC program, which also uses the RAM.
There are two locations in the Commodore 64 to start your character set that
should NOT be used with BASIC: location 0 and location 2048. The first should
not be used because the system stores important data on page 0. The second
can't be used because that is where your BASIC program starts! However, there
are 6 other starting positions for your custom character set.
The best place to put your character set for use with BASIC while experimenting
is beginning at 12288 ($3000 in HEX). This is done by POKEing the low 4 bits
of location 53272 with 12. Try the POKE now, like this:
POKE 53272,(PEEK(53272)AND240)+12
Immediately, all the letters on the screen turn to garbage. This is because there
are no characters set up at location 12288 right now… only random bytes. Set
the Commodore 64 back to normal by hitting the RUN/STOP key and then
the RESTORE key.
Now let's begin creating graphics characters. To protect your character set from
BASIC, you should reduce the amount of memory BASIC thinks it has. The amount
of memory in your computer stays the same… it's just that you've told BASIC not
to use some of it. Type:
PRINT FRE(0)-(SGN(FRE(0))<0)*65535
The number displayed is the amount of memory space left unused. Now type the
following:
Now type:
PRINT FRE(0)-(SGN(FRE(0))<0)*65535
The next step is to put your characters into RAM. When you begin, there is
random data beginning at 12288 ($3000 HEX). You must put character patterns
in RAM (in the same style as the ones in ROM) for the VIC-II chip to use.
The following program moves 64 characters from ROM to your character set
RAM:
Now POKE location 53272 with (PEEK(53272) AND 240) + 12. Nothing
happens, right? Well, almost nothing. The Commodore 64 is now getting its
character information from your RAM, instead of from ROM. But since we copied
the characters from ROM exactly, no difference can be seen… yet.
You can easily change the characters now. Clear the screen and type an @ sign.
Move the cursor down a couple of lines, then type:
TIP: Reversed characters are just characters with their bit patterns in character memory reversed.
Now move the cursor up to the program again and hit RETURN again to re-
reverse the character (bring it back to normal). By looking at the table of screen
display codes, you can figure out where in RAM each character is. Just remember
that each character takes eight memory locations to store. Here's a few examples
just to get you started:
Remember that we only took the first 64 characters. Something else will have to
be done if you want one of the other characters.
What if you wanted character number 154, a reversed Z? Well, you could make
it yourself, by reversing a Z, or you could copy the set of reversed characters
from the ROM, or just take the one character you want from ROM and replace
one of the characters you have in RAM that you don't need.
Suppose you decide that you won't need the > sign. Let's replace the > sign with
the reversed Z. Type this:
Now type a > sign. It comes up as a reversed Z. No matter how many times you
type the >, it comes out as a reversed Z. (This change is really an illusion. Though
the > sign looks like a reversed Z, it still acts like a > in a program. Try something
that needs a > sign. It will still work fine, only it will look strange.)
A quick review: You can now copy characters from ROM into RAM. You can
even pick and choose only the ones you want. There's only one step left in
programmable characters (the best step!)… making your own characters.
When creating your own characters, you set up the same kind of table in
memory. Type NEW and then type this program:
7 6 5 4 3 2 1 0 BINARY DECIMAL
ROW 0 * * * * 00111100 60
1 * * 01000010 66
2 * * * * 10100101 165
3 * * 10000001 129
4 * * * * 10100101 165
5 * * * * 10011001 153
6 * * 01000010 66
ROW 7 * * * * 00111100 60
7 6 5 4 3 2 1 0
Place an X on the matrix at every location where you want a dot to be in your
character. When your character is ready you can create the DATA statement for
your character.
Begin with the first row. Wherever you placed an X, take the number at the top
of the column (the power-of-2 number, as explained above) and write it down.
When you have the numbers for every column of the first row, add them together.
Write this number down, next to the row. This is the number that you will put into
the DATA statement to draw this row.
Do the same thing with all of the other rows (1 to 7). When you are finished you
should have 8 numbers between 0 and 255. If any of your numbers are not
within range, recheck your addition. The numbers must be in this range to be
correct! If you have less than 8 numbers, you missed a row. It's OK if some are
0. The 0 rows are just as important as the other numbers.
Replace the numbers in the DATA statement in line 20 with the numbers you just
calculated, and RUN the program. Then type a T. Every time you type it, you'll
see your own character!
If you don't like the way the character turned out, just change the numbers in the
DATA statement and re-RUN the program until you are happy with your
character.
HINT: For best results, always make any vertical lines in your characters at least 2 dots (bits)
wide. This helps prevent CHROMA noise (color distortion) on your characters when they are
displayed on a TV screen.
10 REM * EXAMPLE 1 *
20 REM CREATING PROGRAMMABLE CHARACTERS
31 POKE56334,PEEK(56334)AND254:POKE1,PEEK(1)AND251
35 FORI=0TO63
36 FORJ=0TO7
37 POKE12288+I*8+J,PEEK(53248+I*8+J)
38 NEXTJ, NEXTI
39 POKE1, PEEK(1)OR4:POKE56334,PEEK(56334)OR1
40 POKE53272, (PEEK(53272)AND240)+12
60 FORCHAR=60TO63
80 FORBYTE=0TO7
100 READNUMBER
120 POKE12288+(8*CHAR)+BYTE,NUMBER
140 NEXTBYTE:NEXTCHAR
150 PRINTCHR$(147)TAB(255)CHR$(60);
155 PRINTCHR$(61)TAB(55)CHR$(62)CHR$(63)
170 GETA$
180 IFA$="" THEN 170
190 POKE53272,21
200 DATA 4,6,7,5,7,7,3,3
210 DATA 32,96,224,160,224,224,192,192
220 DATA 7,7,7,31,31,95,143,127
230 DATA 224,224,224,248,248,248,240,224
240 END
Standard high-resolution graphics give you control of very small dots on the
screen. Each dot in character memory can have 2 possible values, 1 for on and
0 for off. When a dot is off, the color of the screen is used in the space reserved
for that dot. If the dot is on, the dot is colored with the character color you have
chosen for that screen position. When you're using standard high-resolution
graphics, all the dots within each 8x8 character can either have background
color or foreground color. In some ways this limits the color resolution within that
space. For example, problems may occur when two different colored lines cross.
Multicolor mode gives you a solution to this problem. Each dot in multicolor mode
can be one of 4 colors: screen color (background color register #0), the color in
background register #1, the color in background color register#2, or character
color. The only sacrifice is in the horizontal resolution, because each multicolor
mode dot is twice as wide as a high-resolution dot. This minimal loss of resolution
is more than compensated for by the extra abilities of multicolor mode.
To turn on multicolor character mode, set bit 4 of the VIC-II control register at
53270 ($D016) to a 1 by using the following POKE:
To turn off multicolor character mode, set bit 4 of location 53270 to a 0 by the
following POKE:
Multicolor mode is set on or off for each space on the screen, so that multicolor
graphics can be mixed with high-resolution (hi-res) graphics. This is controlled by
bit 3 in color memory. Color memory begins at location 55296 ($D800 in HEX).
If the number in color memory is less than 8 (0 to 7) the corresponding space on
the video screen will be standard hi-res, in the color (0 to 7) you've chosen. If the
number located in color memory is greater or equal to 8 (from 8 to 15), then
that space will be displayed in multicolor mode.
Once multicolor mode is set in a space, the bits in the character determine which
colors are displayed for the dots. For example, here is a picture of the letter A,
and its bit pattern:
In the image area above, the spaces marked AA are drawn in the background
#1color, the spaces marked BB use the background #2 color, and the spaces
marked CC use the character color. The bit pairs determine this, according to the
following chart:
NOTE: The sprite foreground color is a 10. The character foreground color is an 11.
100 POKE53281,1
110 POKE53282,3
120 POKE53283,8
130 POKE53270,PEEK(53270)OR16
140 C=13*4096+8*256
150 PRINTCHR$(147)"AAAAAAAAAA"
160 FORL=0TO9
170 POKEC+L,8
180 NEXT
The screen color is white, the character color is black, one color register is cyan
(greenish blue), the other is orange.
You're not really putting color codes in the space for character color, you're
actually using references to the registers associated with those colors. This
conserves memory, since 2 bits can be used to pick 16 colors (background) or 8
colors (character). This also makes some neat tricks possible. Simply changing one
100 POKE53270,PEEK(53270)OR16
110 PRINTCHR$(147)CHR$(18);
1
120 PRINT""; REM C= & 1
130 FORL=1TO22:PRINTCHR$(65);:NEXT
135 FORT=1TO500:NEXT
CTRL 7
140 PRINT""; REM CTRL & 7
145 FORT=1TO500:NEXT
CTRL 1
150 PRINT"HIT A KEY" REM CTRL & 1
160 GETA$:IFA$=""THEN160
170 X=INT(RND(1)*16)
180 POKE53282,X
190 GOTO160
By using the key and the COLOR keys the characters can be changed to any
color, including multicolor characters. For example, type this command:
The word READY and anything else you type will be displayed in multicolor
mode. Another color control can set you back to regular text.
10 REM * EXAMPLE 2 *
20 REM CREATING MULTI COLOR PROGRAMMABLE CHARACTERS
31 POKE56334,PEEK(56334)AND254:POKE1,PEEK(1)AND251
35 FORI=0TO63
36 FORJ=0TO7
37 POKE12288+I*8+J,PEEK(53248+I*8+J)
38 NEXTJ,I
39 POKE1,PEEK(1)OR4:POKE56334,PEEK(56334)OR1
40 POKE53272,(PEEK(53272)AND240)+12
50 POKE53270,PEEK(53270)OR16
51 POKE53281,0
52 POKE53282,2
53 POKE53283,7
60 FORCHAR=60TO63
80 FORBYTE=0TO7
100 READNUMBER
120 POKE12288+(8*CHAR)+BYTE,NUMBER
140 NEXTBYTE,CHAR
SHIFT CLR/HOME
150 PRINT""TAB(255)CHR$(60)CHR$(61)TAB(55)CHR$(62)
CHR$(63)
170 GETA$
180 IFA$="" THEN 170
190 POKE53272,21:POKE53270,PEEK(53270)AND239
200 DATA 129,37,21,29,93,85,85,85
210 DATA 66,72,84,116,117,85,85,85
220 DATA 87,87,85,21,8,8,40,0
230 DATA 213,213,85,84,32,32,40,0
240 END
Extended background color mode gives you control over the background color
of each individual character, as well as over the foreground color. For example,
in this mode you could display a blue character with a yellow background on a
white screen.
There are 4 registers available for extended background color mode. Each of
the registers can be set to any of the16 colors.
The character code (the number you would POKE to the screen) of the letter "A"
is a 1. When extended color mode is on, if you POKEd a 1 to the screen, an "A"
would appear. If you POKEd a 65 to the screen normally, you would expect the
character with character code (CHR$) 129 to appear, which is a reversed "A."
This does NOT happen in extended color mode. Instead you get the same
unreversed "A" as before, but on a different background color. The following
chart gives the codes:
BITMAPPED GRAPHICS
When writing games, plotting charts for business applications, or other types of
programs, sooner or later you get to the point where you want high-resolution
displays.
The Commodore 64 has been designed to do just that: high resolution is available
through bitmapping of the screen. Bitmapping is the method in which each
possible dot (pixel) of resolution on the screen is assigned its own bit (location)
in memory. If that memory bit is a one, the dot it is assigned to is on. If the bit is
set to zero, the dot is off.
All of the examples given in this section will be in BASIC to make them clear.
Now to the technical details.
There are two types of bitmapping available on the Commodore 64. They are:
Each is very similar to the character type it is named for: standard has greater
resolution, but fewer color selections. On the other hand, multicolor bitmapping
trades horizontal resolution for a greater number of colors in an 8-dot by 8-dot
square.
Standard bitmap mode gives you a 320 horizontal dot by 200 vertical dot
resolution, with a choice of 2 colors in each 8-dot by 8-dot section. Bitmap mode
is selected (turned ON) by setting bit 5 of the VIC-II control register to a 1 at
location 53265 ($D011 in HEX). The following POKE will do this:
Bitmap mode is turned OFF by setting bit 5 of the VIC-II control register to 0 at
location 53265 ($D011), like this:
Before we get into the details of the bitmap mode, there is one more issue to
tackle, and that is where to locate the bitmap area.
HOW IT WORKS
If you remember the PROGRAMMABLE CHARACTERS section you will recall that
you were able to set the bit pattern of a character stored in RAM to almost
anything you wanted. If at the same time you change the character that is
displayed on the screen, you would be able to change a single dot, and watch
it happen. This is the basis of bit-mapping. The entire screen is filled with
Each of the locations in screen memory that were used to control what character
was displayed, are now used for color information. For example, instead of
POKEing a 1 in location 1024 to make an "A" appear in the top left hand corner
of the screen, location 1024 now controls the colors of the bits in that top left
space.
Colors of squares in bitmap mode do not come from color memory, as they do
in the character modes. Instead, colors are taken from screen memory. The upper
4 bits of screen memory become the color of any bit that is set to 1 in the 8 by
8 area controlled by that screen memory location. The lower 4 bits become the
color of any bit that is set to a 0.
Garbage appears on the screen, right? Just like the normal screen mode, you
have to clear the HIGH-RESOLUTION (HI-RES) screen before you use it.
Unfortunately, printing a CLR won't work in this case. Instead you have to clear
out the section of memory that you're using for your programmable characters.
Hit the RUN/STOP and RESTORE keys, then add the following lines to your
program to clear the HI-RES screen:
Now RUN the program again. You should see the screen clearing, then the
greenish blue color, cyan, should cover the whole screen. What we want to do
now is to turn the dots on and off on the HI-RES screen.
We will use X and Y to stand for the horizontal and vertical positions of a dot.
The dot where X=0 and Y=0 is at the upper left of the display. Dots to the right
have higher X values, and the dots toward the bottom have higher Y values. The
best way to use bitmapping is to arrange the bitmap display something like this:
0------------------------------------------X-----------------------------------------319
. .
. .
. .
Y .
. .
. .
. .
199--------------------------------------------------------------------------------------
Each dot will have an X and a Y coordinate. With this format it is easy to control
any dot on the screen.
------ BYTE 320 BYTE 328 BYTE 336 BYTE 344 …… BYTE 632
BYTE 321 BYTE 329 . . BYTE 633
SECOND LINE
The following formula will make it easier to control a dot on the bitmap screen:
The start of the display memory area is known as the BASE. The row number
(from 0 to 24) of your dot is:
LINE = Y AND 7
BIT=7–(X AND 7)
Now we put these formulas together. The byte in which character memory dot
(X,Y) is located is calculated by:
To turn on any bit on the grid with coordinates (X,Y), use this line:
Let's add these calculations to the program. In the following example, the
COMMODORE 64 will plot a sine curve:
5 BASE=2*4096:POKE53272,PEEK(53272)OR8
10 POKE 53265,PEEK(53265)OR32
20 FORI=BASETOBASE+7999:POKEI,0:NEXT
30 FORI=1024TO2023:POKEI,3:NEXT
50 FORX=0TO319STEP.5
60 Y=INT(90+80*SIN(X/10))
70 CH=INT(X/8)
80 RO=INT(Y/8)
85 LN=YAND7
90 BY=BASE+RO*320+8*CH+LN
100 BI=7-(XAND7)
110 POKEBY,PEEK(BY)OR(2↑BI)
120 NEXTX
125 POKE1024,16
130 GOTO130
The calculation in line 60 will change the values for the sine function from a range
of +1 to –1 to a range of 10 to 170. Lines 70 to 100 calculate the character,
row, byte, and bit being affected, using the formulae as shown above. Line 125
signals the program is finished by changing the color of the top left corner of the
screen. Line 130 freezes the program by putting it into an infinite loop. When
you have finished looking at the display, just hold down RUN/STOP and
hit RESTORE .
50 FORX=0TO160
55 Y1=100+SQR(160*X-X*X)
56 Y2=100-SQR(160*X-X*X)
60 FORY=Y1TOY2STEPY1-Y2
70 CH=INT(X/8)
80 RO=INT(Y/8)
85 LN=YAND7
90 BY=BASE+RO*320+8*CH+LN
100 BI=7-(XAND7)
110 POKEBY,PEEK(BY)OR(2↑BI)
114 NEXT
WARNING: BASIC variables can overlay your high-resolution screen. If you need more memory
space you must move the bottom of BASIC above the high-resolution screen area. Or, you must
move your high-resolution screen area. This problem will NOT occur in machine language. It ONLY
happens when you're writing programs in BASIC.
Like multicolor mode characters, multicolor bitmap mode allows you to display
up to four different colors in each 8 by 8 section of bitmap. And as in multi-
character mode, there is a sacrifice of horizontal resolution (from 320 dots to
160 dots).
Multicolor bitmap mode uses an 8K section of memory for the bitmap. You select
your colors for multicolor bitmap mode from (1) the background color register 0,
(the screen background color), (2) the video matrix (the upper 4 bits give one
possible color, the lower 4 bits another), and (3) color memory.
POKE53265,PEEK(53265)OR 32:POKE53270,PEEK(53270)OR16
POKE53265,PEEK(53265)AND223:POKE53270,PEEK(53270)AND239
SMOOTH SCROLLING
The VIC-II chip supports smooth scrolling in both the horizontal and vertical
directions. Smooth scrolling is a one pixel movement of the entire screen in one
direction. It can move either up, or down, or left, or right. It is used to move new
information smoothly onto the screen, while smoothly removing characters from
the other side.
While the VIC-II chip does much of the task for you, the actual scrolling must be
done by a machine language program. The VIC-II chip features the ability to
place the video screen in any of 8 horizontal positions, and 8 vertical positions.
Positioning is controlled by the VIC-II scrolling registers. The VIC-II chip also has
a 38 column mode, and a 24 row mode. The smaller screen sizes are used to
give you a place for your new data to scroll on from.
When scrolling in the X direction, it is necessary to place the VIC-II chip into 38
column mode. This gives new data a place to scroll from. When scrolling LEFT,
the new data should be placed on the right. When scrolling RIGHT the new data
should be placed on the left. Please note that there are still 40 columns to screen
memory, but only 38 are visible.
When scrolling in the Y direction, it is necessary to place the VIC-II chip into 24
row mode. When scrolling UP, place the new data in the LAST row. When
scrolling DOWN, place the new data on the FIRST row. Unlike X scrolling, where
there are covered areas on each side of the screen, there is only one covered
area in Y scrolling. When the Y scrolling register is set to 0, the first line is
covered, ready for new data.
For scrolling in the X direction, the scroll register is located in bits 2 to 0 of the
VIC-II control register at location 53270 ($D016 in HEX). As always, it is
important to affect only those bits. The following POKE does this:
For scrolling in the Y direction, the scroll register is located in bits 2 to 0 of the
VIC-II control register at location 53265 ($D011 in HEX). As always, it is
important to affect only those bits. The following POKE does this:
To scroll text onto the screen from the bottom, you would step the low-order 3
bits of location 53265 from 0 to 7, put more data on the covered line at the
bottom of the screen, and then repeat the process.
To scroll characters onto the screen from left to right, you would step the low-
order 3 bits of location 53270 from 0 to 7, print or POKE another column of new
data into column 0 of the screen, then repeat the process.
If you step the scroll bits by –1, your text will move in the opposite direction.
10 POKE53265,PEEK(53265)AND247
20 PRINTCHR$(147)
30 FORX=1TO24:PRINTCHR$(17);:NEXT
40 POKE53265,(PEEK(53265)AND248)+7:PRINT
50 PRINT" HELLO";
60 FORY=6TO0STEP-1
70 POKE53265,(PEEK(53265)AND248)+Y
80 FORX=1TO50:NEXT
90 GOTO40
Sprites can be used with ANY of the other graphics modes: bitmapped,
character, multicolor, etc., and they'll keep their shape in all of them. The sprite
carries its own color definition, its own mode (HI-RES or multicolored), and its own
shape.
These special sprite abilities make it simple to program many arcade style
games. Because the sprites are maintained by hardware, it is even possible to
write a good quality game in BASIC!
There are 8 sprites supported directly by the VIC-II chip. They are numbered
from 0 to 7. Each of the sprites has its own definition location, position registers
and color register, and has its own bits for enable and collision detection.
DEFINING A SPRITE
Sprites are defined like programmable characters are defined. However, since
the size of the sprite is larger, more bytes are needed. A sprite is 24 by 21 dots,
or 504 dots. This works out to 63 bytes (504/8 bits) needed to define a sprite.
Another way to view how a sprite is created is to take a look at the sprite
definition block on the bit level. It would look something like Figure 3-2.
SPRITE POINTERS
Even though each sprite takes only 63 bytes to define, one more byte is needed
as a place holder at the end of each sprite. Each sprite, then, takes up 64 bytes.
This makes it easy to calculate where in memory your sprite definition is, since
64 bytes is an even number and in binary it's an even power.
Each of the 8 sprites has a byte associated with it called the SPRITE POINTER.
The sprite pointers control where each sprite definition is located in memory.
These 8 bytes are always located as the last 8 bytes of the1K chunk of screen
memory. Normally, on the Commodore 64, this means they begin at location
2040 ($07F8 in HEX). However, if you move the screen, the location of your
sprite pointers will also move.
Each sprite pointer can hold a number from 0 to 255. This number points to the
definition for that sprite. Since each sprite definition takes 64 bytes, that means
that the pointer can "see" anywhere in the 16K block of memory that the VIC-II
chip can access (since 256*64=16K).
Where BANK is the 16K segment of memory that the VIC-II chip is looking at
and is from 0 to 3.
The above formula gives the start of the 64 bytes of the sprite definition block.
When the VIC-II chip is looking at BANK 0 or BANK 2, there is a ROM IMAGE of
the character set present in certain locations, as mentioned before. Sprite
definitions can NOT be placed there. If for some reason you need more than
128 different sprite definitions, you should use one of the banks without the ROM
IMAGE, 1 or 3.
TURNING SPRITES ON
The VIC-II control register at location 53269 ($D015 in HEX) is known as the
SPRITE ENABLE register. Each of the sprites has a bit in this register which
controls whether that sprite is ON or OFF. The register looks like this:
$D015 7 6 5 4 3 2 1 0
A sprite is turned off by setting its bit in the VIC-lI control register at 53269
($D015 in HEX) to a 0. The following POKE will do this:
COLORS
A sprite can be any of the 16 colors generated by the VIC-II chip. Each of the
sprites has its own sprite color register. These are the memory locations of the
color registers:
ADDRESS DESCRIPTION
53287 ($D027) SPRITE 0 COLOR REGISTER
53288 ($D028) SPRITE 1 COLOR REGISTER
53289 ($D029) SPRITE 2 COLOR REGISTER
53290 ($D02A) SPRITE 3 COLOR REGISTER
53291 ($D02B) SPRITE 4 COLOR REGISTER
53292 ($D02C) SPRITE 5 COLOR REGISTER
53293 ($D02D) SPRITE 6 COLOR REGISTER
53294 ($D02E) SPRITE 7 COLOR REGISTER
All dots in the sprite will be displayed in the color contained in the sprite color
register. The rest of the sprite will be transparent, and will show whatever is
behind the sprite.
MULTICOLOR MODE
NOTE: The sprite foreground color is a 10. The character foreground is an 11.
To switch a sprite into multicolor mode you must turn ON the VIC-II control register
at location 53276 ($D01C). The following POKE does this:
To switch a sprite out of multicolor mode you must turn OFF the VIC-II control
register at location 53276 ($D01C). The following POKE does this:
EXPANDED SPRITES
The VIC-II chip has the ability to expand a sprite in the vertical direction, the
horizontal direction, or both at once. When expanded, each dot in the sprite is
twice as wide or twice as tall. Resolution doesn't actually increase… the sprite
just gets bigger.
To expand a sprite in the horizontal direction, the corresponding bit in the VIC-
II control register at location 53277 ($D01D in HEX) must be turned ON (set to
a 1). The following POKE expands a sprite in the X direction:
To expand a sprite in the vertical direction, the corresponding bit in the VIC-II
control register at location 53271 ($D017 in HEX) must be turned ON (set to a
1). The following POKE expands a sprite in the Y direction:
To unexpand a sprite in the vertical direction, the corresponding bit in the VIC-II
control register at location 53271($D017 in HEX) must be turned OFF (set to a
0). The following POKE "unexpands" a sprite in the Y direction:
SPRITE POSITIONING
Once you've made a sprite you want to be able to move it around the screen.
To do this, your Commodore 64 uses three positioning registers:
Each sprite has an X position register, a Y position register, and a bit in the X
most significant bit register. This lets you position your sprites very accurately.
You can place your sprite in 512 possible X positions and 256 possible Y
positions.
The X and Y position registers work together, in pairs, as a team. The locations
of the X and Y registers appear in the memory map as follows: first is the X
register for sprite 0, then the Y register for sprite 0. Next comes the X register
The chart below lists the locations of each sprite position register. You use the
locations at their appropriate time through POKE statements:
LOCATION
DESCRIPTION
DECIMAL HEX
53248 ($D000) SPRITE 0 X POSITION REGISTER
53249 ($D001) SPRITE 0 Y POSITION REGISTER
53250 ($D002) SPRITE 1 X POSITION REGISTER
53251 ($D003) SPRITE 1 Y POSITION REGISTER
53252 ($D004) SPRITE 2 X POSITION REGISTER
53253 ($D005) SPRITE 2 Y POSITION REGISTER
53254 ($D006) SPRITE 3 X POSITION REGISTER
53255 ($D007) SPRITE 3 Y POSITION REGISTER
53256 ($D008) SPRITE 4 X POSITION REGISTER
53257 ($D009) SPRITE 4 Y POSITION REGISTER
53258 ($D00A) SPRITE 5 X POSITION REGISTER
53259 ($D00B) SPRITE 5 Y POSITION REGISTER
53260 ($D00C) SPRITE 6 X POSITION REGISTER
53261 ($D00D) SPRITE 6 Y POSITION REGISTER
53262 ($D00E) SPRITE 7 X POSITION REGISTER
53263 ($D00F) SPRITE 7 Y POSITION REGISTER
53264 ($D010) SPRITE X MSB REGISTER
The position of a sprite is calculated from the TOP LEFT corner of the 24 dot by
21 dot area that your sprite can be designed in. It does NOT matter how many
or how few dots you use to make up a sprite. Even if only one dot is used as a
sprite, and you happen to want it in the middle of the screen, you must still
calculate the exact positioning by starting at the top left corner location.
VERTICAL POSITIONING
Setting up positions in the horizontal direction is a little more difficult than vertical
positioning, so we'll discuss vertical (Y) positioning first.
There are 200 different dot positions that can be individually programmed onto
your TV screen in the Y direction. The sprite Y position registers can handle
numbers up to 255. This means that you have more than enough register locations
The first on-screen value from the top of the screen, and in the Y direction for an
unexpanded sprite is 30. For a sprite expanded in the Y direction it would be 9.
(Since each dot is twice as tall, this makes a certain amount of sense, as the initial
position is STILL calculated from the top left corner of the sprite.)
The first Y value in which a sprite (expanded or not) is fully on the screen (all 21
possible lines displayed) is 50.
The last Y value in which an unexpanded sprite is fully on the screen is 229. The
last Y value in which an expanded sprite is fully on the screen is 208.
The first Y value in which a sprite is fully off the screen is 250.
EXAMPLE:
SHIFT CLR/HOME
10 PRINT"": REM SHIFT CLR/HOME
20 POKE 2040,13
30 FOR I = 0 TO 62: POKE832+I,129: NEXT
40 V = 53248
50 POKE V + 21,1
60 POKE V + 39,1
70 POKE V + 1, 100
80 POKE V + 16,0: POKE V,100
HORIZONTAL POSITIONING
EXAMPLE:
SHIFT CLR/HOME
10 PRINT""
20 POKE 2040,13
30 FOR I = 0 TO 62: POKE832+I,129: NEXT
40 V = 53248
50 POKE V + 21,1
60 POKE V + 39,1
70 POKE V + 1, 100
80 FOR J = 0 TO 347
90 HX = INT(J/256): LX = J – 256 * HX
100 POKE V,LX: POKE V + 16,HX: NEXT
When moving expanded sprites onto the left side of the screen in the X direction,
you have to start the sprite OFF SCREEN on the RIGHT SIDE. This is because an
expanded sprite is larger than the amount of space available on the left side of
the screen.
EXAMPLE:
SHIFT CLR/HOME
10 PRINT"": REM SHIFT CLR/HOME
20 POKE 2040,13
30 FOR I = 0 TO 62: POKE832+I,129: NEXT
40 V = 53248
50 POKE V + 21,1
60 POKE V + 39,1: POKE V + 23,1: POKE V + 29,1
70 POKE V + 1, 100
80 J = 488
90 HX = INT(J/256): LX = J – 256 * HX
100 POKE V, LX: POKE V + 16,HX
110 J = J + 1: IF J > 511 THEN J = 0
120 IF J > 488 OR J < 348 GOTO 90
By using these values, you can position each sprite anywhere. By moving the
sprite a single dot position at a time, very smooth movement is easy to achieve.
Expanded sprites are at least partially visible in the 40 column, by 25 row mode
within the following parameters:
Sprites have the ability to cross each other's paths, as well as cross in front of, or
behind other objects on the screen. This can give you a truly three dimensional
effect for games.
Sprite to sprite priority is fixed. That means that sprite 0 has the highest priority,
sprite 1 has the next priority, and so on, until we get to sprite 7, which has the
lowest priority. In other words, if sprite 1 and sprite 6 are positioned so that they
cross each other, sprite 1 will be in front of sprite 6.
So when you're planning which sprites will appear to be in the foreground of the
picture, they must be assigned lower sprite numbers than those sprites you want
to put towards the back of the scene. Those sprites will be given higher sprite
numbers.
NOTE: A "window" effect is possible. If a sprite with higher priority has "holes" in it (areas where
the dots are not set to 1 and thus turned ON), the sprite with the lower priority will show through.
This also happens with sprite and background data.
COLLISION DETECTS
One of the more interesting aspects of the VIC-II chip is its collision detection
abilities. Collisions can be detected between sprites, or between sprites and
background data. A collision occurs when a non-zero part of a sprite overlaps a
non-zero portion of another sprite or characters on the screen.
NOTE: Collisions can take place even when the sprites are off screen.
Sprite to data collisions are detected in the sprite to data collision register at
location 53279 ($D01F in HEX) of the VIC-II chip control register.
Each sprite has a bit in this register. If that bit is a 1, then that sprite is involved
in a collision. The bits in this register remain set until read (PEEKed). Once read,
the register is automatically cleared, so it is a good idea to save the value in a
variable until you are finished with it.
NOTE: MULTICOLOR data 01 is considered transparent for collisions, even though it shows up on
the screen. When setting up a background screen, it is a good idea to make everything that
should not cause a collision 01 in multicolor mode.
SCREEN BLANKING
Bit 4 of the VIC-II control register controls the screen blanking function. It is found
in the control register at location 53265 ($D011). When it is turned ON (in other
words, set to a 1) the screen is normal. When bit 4 is set to 0 (turned OFF), the
entire screen changes to border color.
The following POKE blanks the screen. No data is lost, it just isn't displayed:
NOTE: Turning off the screen will speed up the processor slightly. This means that program
RUNning is also sped up.
RASTER REGISTER
The raster register is found in the VIC-II chip at location 53266 ($D012). The
raster register is a dual purpose register. When you read this register it returns
the lower 8 bits of the current raster position. The raster position of the most
significant bit is in register location 53265 ($D011). You use the raster register
to set up timing changes in your display so that you can get rid of screen flicker.
The changes on your screen should be made when the raster is not in the visible
display area, which is when your dot positions fall between 51 and 251.
When the raster register is written to (including the MSB) the number written to
is saved for use with the raster compare function. When the actual raster value
becomes the same as the number written to the raster register, a bit in the VIC-
II chip interrupt register 53273 ($D019) is turned ON by setting it to 1.
NOTE: If the proper interrupt bit is enabled (turned on), an interrupt (IRQ) will occur.
The interrupt status register shows the current status of any interrupt source. The
current status of bit 2 of the interrupt register will be a 1 when two sprites hit
each other. The same is true, in a corresponding 1 to 1 relationship, for bits 0 to
3 listed in the chart below. Bit 7 is also set with a 1, whenever an interrupt occurs.
The interrupt status register is located at 53273 ($D019) and is as follows:
Once an interrupt bit has been set, it's "latched" in and must be cleared by
writing a 1 to that bit in the interrupt register when you're ready to handle it.
This allows selective interrupt handling, without having to store the other interrupt
bits.
To enable an interrupt request the corresponding interrupt enable bit (as shown
in the chart above) must be set to a 1.
This powerful interrupt structure lets you use split screen modes. For instance you
can have half of the screen bitmapped, half text, more than 8 sprites at a time,
etc. The secret is to use interrupts properly. For example, if you want the top half
of the screen to be bitmapped and the bottom to be text, just set the raster
compare register (as explained previously) for halfway down the screen. When
the interrupt occurs, tell the VIC-II chip to get characters from ROM, then set the
raster compare register to interrupt at the top of the screen. When the interrupt
occurs at the top of the screen, tell the VIC-II chip to get characters from RAM
(bitmap mode).
Color TV sets are limited in their ability to place certain colors next to each other
on the same line. Certain combinations of screen and character colors produce
blurred images. This chart shows which color combinations to avoid, and which
work especially well together:
For those of you having trouble with graphics, this section has been designed as
a more elementary tutorial approach to sprites.
There are at least three different BASIC programming techniques which let you
create graphic images and cartoon animations on the Commodore 64. You can
use the computer's built-in graphics character set (see Page 376). You can
program your own characters (see Page 108) or… best of all… you can use the
computer's built-in "sprite graphics." To illustrate how easy it is, here's one of the
shortest sprite making programs you can write in BASIC:
SHIFT CLR/HOME
10 PRINT"": REM SHIFT CLR/HOME
20 POKE2040, 13
30 FORS=832TO832+62:POKES,255:NEXT
40 V=53248
50 POKEV+21,1
60 POKEV+39,1
70 POKEV,24
80 POKEV+1,100
This program includes the key "ingredients" you need to create any sprite. The
POKE numbers come from the SPRITE MAKING CHART on Page 176. This
program defines the first sprite… sprite 0… as a solid white square on the
screen. Here's a line-by-line explanation of the program:
LINE 20 sets the "sprite pointer" to where the Commodore 64 will read its sprite
data from. Sprite 0 is set at 2040, sprite 1 at 2041, sprite 2 at 2042, and so
on up to sprite 7 at 2047. You can set all 8 sprite pointers to 13 by using this
line in place of line 20:
LINE 30 puts the first sprite (sprite 0) into 63 bytes of the Commodore 64's RAM
memory starting at location 832 (each sprite requires 63 bytes of memory). The
first sprite (sprite 0) is "addressed" at memory locations 832 to 894.
LINE 50 enables or "turns on" sprite 0. There are 8 sprites, numbered from 0 to
7. To turn on an individual sprite, or a combination of sprites, all you have to do
is POKEV+21 followed by a number from 0 (turn all sprites off) to 255 (turn all
8 sprites on). You can turn on one or more sprites by POKEing the following
numbers:
ALL ON SPRITE0 SPRITE1 SPRITE2 SPRITE3 SPRITE4 SPRITE5 SPRITE6 SPRITE7 ALL OFF
V+21,255 V+21,1 V+21,2 V+21,4 V+21,8 V+21,16 V+21,32 V+21,64 V+21,128 V+21,0
POKE V+21, 1 turns on sprite 0. POKE V+21, 128 turns on sprite 7. You can
also turn on combinations of sprites. For example, POKE V+21, 129 turns on both
sprite 0 and sprite 7 by adding the two "turn on" numbers (1+128) together.
(See SPRITE MAKING CHART, Page 176.)
LINE 60 sets the COLOR of sprite 0. There are 16 possible sprite colors,
numbered from 0 (black) to 15 (grey). Each sprite requires a different POKE to
set its color, from V+39 to V+46. POKE V+39, 1 colors sprite 0 white. POKE V
+46, 15 colors sprite 7 grey. (See the SPRITE MAKING CHART for more
information.)
When you create a sprite, as you just did, the sprite will STAY IN MEMORY until
you POKE it off, redefine it, or turn off your computer. This lets you change the
color, position and even shape of the sprite in DIRECT or IMMEDIATE mode, which
is useful for editing purposes. As an example, RUN the program above, then
type this line in DIRECT mode (without a line number) and hit the RETURN key:
POKE V+39, 8
The sprite on the screen is now ORANGE. Try POKEing some other numbers from
0 to 15 to see the other sprite colors. Because you did this in DIRECT mode, if
you RUN your program the sprite will return to its original color (white).
LINE 80 determines the VERTICAL or "Y" POSITION of the sprite. In this program,
we placed the sprite at X (horizontal) position 24, and Y (vertical) position 100.
To try another location, type this POKE in DIRECT mode and hit RETURN :
This places the sprite at the upper left corner of the screen. To move the sprite
to the lower left corner, type this:
Each number from 832 to 895 in our sprite 0 address represents one block of 8
pixels, with three 8-pixel blocks in each horizontal row of the sprite. The loop in
line 80 tells the computer to POKE 832, 255 which makes the first 8 pixels solid…
then POKE 833, 255 to make the second 8 pixels solid, and so on to location
894 which is the last group of 8 pixels in the bottom right corner of the sprite.
To better see how this works, try typing the following in DIRECT mode, and notice
that the second group of 8 pixels is erased:
POKE 833,0 (to put it back type POKE 833, 255 or RUN your program)
The following line, which you can add to your program, erases the blocks in the
MIDDLE of the sprite you created:
Remember, the pixels that make up the sprite are grouped in blocks of eight.
This line erases the 5th group of eight pixels (block 836) and every third block
up to block 890. Try POKEing any of the other numbers from 832 to 894 with
either a 255 to make them solid or 0 to make them blank.
Here's a helpful "crunching" tip: The program described above is already short, but it
can be made even shorter by "crunching" it smaller. In our example we list the key
sprite settings on separate program lines so you can see what's happening in the
program. In actual practice, a good programmer would probably write this program
as a TWO LINE PROGRAM… by "crunching" it as follows:
For more tips on how to crunch your programs so they fit in less memory and run more
efficiently, see the "crunching guide" on Page 24.
The entire display screen is divided into a grid of X and Y coordinates, like a
graph. The X COORDINATE is the HORIZONTAL position across the screen and
the Y COORDINATE is the VERTICAL position up and down (see Figure 3-4).
To position any sprite on the screen, you must POKE TWO SETTINGS… the X
position and the Y position… these tell the computer where to display the UPPER
LEFT-HAND CORNER of the sprite. Remember that a sprite consists of 504
individual pixels, 24 across by 21 down… so if you POKE a sprite onto the
upper left corner of your screen, the sprite will be displayed as a graphic image
24 pixels ACROSS and 21 pixels DOWN starting at the X-Y position you
defined. The sprite will be displayed based on the upper left corner of the entire
sprite, even if you define the sprite using only a small part of the 24x21 pixel
sprite area.
To understand how X-Y positioning works, study the following diagram (Figure
3-5), which shows the X and Y numbers in relation to your display screen. Note
that the GREY AREA in the diagram shows your television viewing area… the
white area represents positions which are OFF your viewing screen…
X VALUES BEYOND THE 255TH POSITION: To get beyond the 255th position
across the screen, you need to make a SECOND POKE using the numbers in the
"RIGHT X" row of the chart (Figure 3-5). Normally, the horizontal (X) numbering
would continue past the 255th position to 256, 257, etc., but because registers
only contain 8 bits we must use a "second register" to access the RIGHT SIDE of
the screen and start our X numbering over again at 0. So to get beyond X
position 255, you must POKE V+ 16 and a number (depending on the sprite).
This gives you 65 additional X positions (renumbered from 0 to 65) in the viewing
area on the RIGHT side of the viewing screen. (You can actually POKE the right
side X value as high as 255, which takes you off the right edge of the viewing
screen.)
SHIFT CLR/HOME
10 PRINT"":V=53248:POKEV+21,2:POKE2041,13:
FORS=832TO895:POKES,255:NEXT
20 POKEV+40,7
30 POKEV+2,24
40 POKEV+3,50
This simple program establishes sprite 1 as a solid box and positions it at the
upper left corner of the screen. Now change line 40 to read:
This moves the sprite to the bottom left corner of the screen. Now let's test the
RIGHT X LIMIT of the sprite. Change line 30 as shown:
This moves the sprite to the RIGHT but reaches the RIGHT X LIMIT, which is 255.
At this point, the "most significant bit" in register 16 must be SET. In other words,
you must type POKE V+16 and the number shown in the "RIGHT X" column in the
X-Y POKE CHART above to RESTART the X position counter at the 256th
pixel/position on the screen. Change line 30 as follows:
POKE V+16, 2 sets the most significant bit of the X position for sprite 1 and
restarts it at the 256th pixel/position on the screen. POKE V+2, 0 displays the
sprite at the NEW POSITION ZERO, which is now reset to the 256th pixel.
To get back to the left side of the screen, you must reset the most significant bit of
the X position counter to 0 by typing (for sprite 1):
TO SUMMARIZE how the X positioning works… POKE the X POSITION for any
sprite with a number from 0 to 255. To access a position beyond the 255th
position/pixel across the screen, you must use an additional POKE (V+16) which
sets the most significant bit of the X position and start counting from 0 again at
the 256th pixel across the screen.
SHIFT CLR/HOME
10 PRINT"":V=53248:FORS=832TO895:POKES,255:NEXT
20 FORM=2040TO2042:POKEM,13:NEXT
30 POKEV+21,7
40 POKEV+39,1:POKEV+40,7:POKEV+41,8
50 POKEV,24:POKEV+1,50
60 POKEV+2,12:POKEV+3,229
70 POKEV+4,255:POKEV+5,50
For convenience, all 3 sprites have been defined as solid squares, getting their
data from the same place. The important lesson here is how the 3 sprites are
positioned. The white sprite 0 is at the top left-hand corner. The yellow sprite 1
is at the bottom left-hand corner but HALF the sprite is OFF THE SCREEN
(remember, 24 is the leftmost X position in the viewing area… an X position less
than 24 puts all or part of the sprite off the screen and we used an X position
12 here which put the sprite halfway off the screen). Finally, the orange sprite 2
is at the RIGHT X LIMIT (position 255)… but what if you want to display a sprite
in the area to the RIGHT of X position 255?
Displaying a sprite beyond the 255th X position requires a special POKE which
SETS the most significant bit of the X position and starts over at the 256th pixel
position across the screen. Here's how it works…
First, you POKE V+16 with the number for the sprite you're using (check the
"RIGHT X" row in the X-Y chart… we'll use sprite 0). Now we assign an X position,
keeping in mind that the X counter starts over from 0 at the 256th position on
the screen. Change line 50 to read as follows:
Some experimentation with the settings in the sprite chart will give you the
settings you need to position and move sprites on the left and right sides of the
screen. The section on "moving sprites" will also increase your understanding of
how sprite positioning works.
SPRITE PRIORITIES
You can actually make different sprites seem to move IN FRONT OF or BEHIND
each other on the screen. This incredible three dimensional illusion is achieved by
the built-in SPRITE PRIORITIES which determine which sprites have priority over
the others when 2 or more sprites OVERLAP on the screen.
The rule is "first come, first served" which means lower-numbered sprites
AUTOMATICALLY have priority over higher-numbered sprites. For example, if
you display sprite 0 and sprite1 so they overlap on the screen, sprite 0 will
appear to be IN FRONT OF sprite 1. Actually, sprite 0 always supersedes all
the other sprites because it's the lowest numbered sprite. In comparison, sprite 1
has priority over sprites 2 to 7; sprite 2 has priority over sprites 3 to 7, etc.
Sprite 7 (the last sprite) has LESS PRIORITY than any of the other sprites, and
will always appear to be displayed "BEHIND" any other sprites which overlap
its position.
To illustrate how priorities work, change lines 50, 60, and 70 in the program
above to the following:
SHIFT CLR/HOME
10 PRINT"":V=53248:FORS=832TO895:POKES,255:NEXT
20 FORM=2040TO2042:POKEM,13:NEXT
30 POKEV+21,7
40 POKEV+39,1:POKEV+40,7:POKEV+41,8
50 POKEV,24:POKEV+1,50:POKEV+16,0
60 POKEV+2,34:POKEV+3,60
70 POKEV+4,44:POKEV+5,70
You should see a white sprite on top of a yellow sprite on top of an orange
sprite. Of course, now that you see how priorities work, you can also MOVE
SPRITES and take advantage of these priorities in your animation.
Look at the spritemaking grid in Figure 3-6. This is what a blank sprite looks like:
1 1 1
2 6 3 1 2 6 3 1 2 6 3 1
8 4 2 6 8 4 2 1 8 4 2 6 8 4 2 1 8 4 2 6 8 4 2 1
Each little "square" represents one pixel in the sprite. There are 24 pixels across
and 21 pixels up and down, or 504 pixels in the entire sprite. To make the sprite
look like something, you have to color in these pixels using a special
PROGRAM… but how can you control over 500 individual pixels? That's where
computer programming can help you. Instead of typing 504 separate numbers,
you only have to type 63 numbers for each sprite. Here's how it works…
STEP 1:
Write the sprite making program shown here ON A PIECE OF PAPER… note that
line 100 starts a special DATA section of your program which will contain the 63
numbers you need to create your sprite.
SHIFT CLR/HOME
10 PRINT"":POKE53280,5:POKE53281,6
20 V=53248:POKEV+34,3
30 POKE53269,4:POKE2042,13
40 FORN=0TO62:READQ:POKE832+N,Q:NEXT
128 64 32 16 8 4 2 1 128 64 32 16 8 4 2 1 128 64 32 16 8 4 2 1
STEP 2:
Color in the pixels on the spritemaking grid on Page 162 (or use a piece of
graph paper… remember, a sprite has 24 squares across and 21 squares
down). We suggest you use a pencil and draw lightly so you can reuse this grid.
You can create any image you like, but for our example we'll draw a simple
box.
STEP 3:
Look at the first EIGHT pixels. Each column of pixels has a number (128, 64, 32,
16, 8, 4, 2, 1). The special type of addition we are going to show you is a type
of BINARY ARITHMETIC which is used by most computers as a special way of
128 64 32 16 8 4 2 1
STEP 4:
Add up the numbers of the SOLID pixels. This first group of eight pixels is
completely solid, so the total number is 255.
STEP 5:
Enter that number as the FIRST DATA STATEMENT in line 100 of the Spritemaking
Program below. Enter 255 for the second and third groups of eight.
STEP 6:
Look at the FIRST EIGHT PIXELS IN THE SECOND ROW of the sprite. Add up the
values of the solid pixels. Since only one of these pixels is solid, the total value
is 128. Enter this as the first DATA number in line 101.
128 64 32 16 8 4 2 1
STEP 7:
Add up the values of the next group of eight pixels (which is 0 because they're
all BLANK) and enter in line 101. Now move to the next group of pixels and
repeat the process for each GROUP OF EIGHT PIXELS (there are 3 groups across
each row, and 21 rows). This will give you a total of 63 numbers. Each number
represents ONE group of 8 pixels, and 63 groups of eight equals 504 total
individual pixels. Perhaps a better way of looking at the program is like this…
each line in the program represents ONE ROW in the sprite. Each of the 3
numbers in each row represents ONE GROUP OF EIGHT PIXELS. And each
number tells the computer which pixels to make SOLID and which pixels to leave
blank.
SHIFT CLR/HOME
10 PRINT"":POKE53280,5:POKE53281,6
20 V=53248:POKEV+34,3
30 POKE53269,4:POKE2042,13
40 FORN=0TO62:READQ:POKE832+N,Q:NEXT
100 DATA 255,255,255,128,0,1,128,0,1,128,0,1,144,
0,1,144,0,1,144,0,1,144,01
101 DATA 144,0,1,144,0,1,144,0,1,144,0,1,144,0,1,
144,0,1,128,0,1,128,0,1
102 DATA 128,0,1,128,0,1,128,0,1,128,0,1,255,255,255
200 X=200:Y=100:POKE53252,X:POKE53253,Y
Now that you've created your sprite, let's do some interesting things with it. To
move your sprite smoothly across the screen, add these two lines to your
program:
50 POKEV+5,100:FORX=24TO255:POKEV+4,X:NEXT:POKE V+16,4
55 FORX=0TO65:POKEV+4,X:NEXTX:POKEV+16,0:GOTO50
LINE 50 POKEs the Y POSITION at 100 (try 50 or 229 instead for variety). Then
it sets up a FOR… NEXT loop which POKEs the sprite into X position 0, to X
position 255, in order. When it reaches the 255th position, it POKEs the RIGHT
X POSITION (POKE V+16, 4) which is required to cross to the right side of the
screen.
LINE 55 has a FOR… NEXT loop which continues to POKE the sprite in the last
65 positions on the screen. Note that the X value was reset to zero but because
you used the RIGHT X setting (POKE V + 16, 2) X starts over on the right side of
the screen.
This line keeps going back to itself (GOTO 50). If you just want the sprite to
move ONCE across the screen and disappear then take out GOTO 50.
50 POKEV+5,100: FORX=24TO255:POKEV+4,X:NEXT:POKEV+16,4:
FORX=0TO65:POKEV+4,X:NEXTX
55 FORX=65TO0STEP-1:POKEV+4,X:NEXT:POKEV+16,0:
FORX=255TO24STEP-1:POKEV+4,X:NEXT
60 GOTO50
Do you see how these programs work? This program is the same as the previous
one, except when it reaches the end of the right side of the screen, it REVERSES
ITSELF and goes back in the other direction. That is what the STEP –1
accomplishes… it tells the program to POKE the sprite into X values from 65 to
0 on the right side of the screen, then from 255 to 0 on the left side of the screen,
STEPping backwards minus –1 position at a time.
VERTICAL SCROLLING
This type of sprite movement is called "scrolling." To scroll your sprite up or down
in the Y position, you only have to use ONE LINE. ERASE LINES 50 and 55 by
typing the line numbers by themselves and hitting RETURN like this:
50 ( RETURN )
55 ( RETURN )
LINE 10:
LINE 15:
LINE 30:
LINE 35:
LINE 45:
LINE 50:
LINE 60:
LINE 70:
LINE 80:
LINE 85:
Turn on Sprite V+21,1 V+21,2 V+21,4 V+21,8 V+21,16 V+21,32 V+21,64 V+21,128
Put in Memory 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047,
(Set Pointers) 192 193 194 195 196 197 198 199
Locations for 12288 12352 12416 12480 12544 12608 12672 12736
Sprite Pixel to to to to to to to to
(12288–12798) 12350 12414 12478 12542 12606 12670 12734 12798
Sprite Color V+39,C V+40,C V+41,C V+42,C V+43,C V+44,C V+45,C V+46,C
Set LEFT X V+0,X V+2,X V+4,X V+6,X V+8,X V+10,X V+12,X V+14,X
Position (0–255)
Set RIGHT X V+16,1 V+16,2 V+16,4 V+16,8 V+16,16 V+16,32 V+16,64 V+16,128
Position (0–255) V+0,X V+2,X V+4,X V+6,X V+8,X V+10,X V+12,X V+14,X
Set Y Position V+1,Y V+3,Y V+5,Y V+7,Y V+9,Y V+11,Y V+13,Y V+15,Y
Expand Sprite V+29,1 V+29,2 V+29,4 V+29,8 V+29,16 V+29,32 V+29,64 V+29,128
Horizontally/X
Expand Sprite V+23,1 V+23,2 V+23,4 V+23,8 V+23,16 V+23,32 V+23,64 V+23,128
Vertically/Y
Turn On (Set) V+28,1 V+28,2 V+28,4 V+28,8 V+28,16 V+28,32 V+28,64 V+28,128
Multicolor Mode
Multicolor 1 V+37,C V+37,C V+37,C V+37,C V+37,C V+37,C V+37,C V+37,C
(First Color)
Multicolor 2 V+38,C V+38,C V+38,C V+38,C V+38,C V+38,C V+38,C V+38,C
(Second Color)
Set Priority The rule is that lower numbered sprites always have display priority over
of Sprites higher numbered sprites. For example, sprite 0 has priority over ALL other
sprites, sprite 7 has last priority. This means lower numbered sprites always
appear to move IN FRONT OF or ON TOP OF higher numbered sprites.
Collision (Sprite
V+30 IF PEEK(V+30) AND X = X THEN [action]
to Sprite)
Collision (Sprite
V+31 IF PEEK(V+31) AND X = X THEN [action]
to Background)
TURNING ON SPRITES:
You can turn on any individual sprite by using POKE V+21 and the number from
the chart… BUT… turning on just ONE sprite will turn OFF any others. To turn on
TWO OR MORE sprites, ADD TOGETHER the numbers of the sprites you want to
turn on (Example: POKE V+21, 6 turns on sprites 1 and 2). Here is a method you
can use to turn one sprite off and on without affecting any of the others (useful
for animation).
EXAMPLE:
To turn off just sprite 0 type: POKE V+21, PEEK V+21 AND (255–1). Change
the number 1 in (255–1) to 1, 2, 4, 8, 16, 32, 64, or 128 (for sprites 0 to 7). To
re-enable the sprite and not affect the other sprites currently turned on, POKE V
+ 21, PEEK (V+21) OR 1 and change the OR 1 to OR 2 (sprite 2), OR 4 (sprite
3), etc.
X positions run from 0 to 255… and then START OVER from 0 to 255. To put a
sprite beyond X position 255 on the far right side of the screen, you must first
POKE V+16 as shown, THEN POKE a new X value from 0 to 63, which will place
the sprite in one of the X positions at the right side of the screen. To get back to
positions 0–255, POKE V+16, 0 and POKE in an X value from 0 to 255.
Y POSITION VALUES:
Y positions run from 0 to 255, including 0 to 49 off the TOP of the viewing area,
50 to 229 IN the viewing area, and 230 to 255 off the BOTTOM of the viewing
area.
To make sprite 0 WHITE, type: POKE V+39, 1 (use COLOR POKE SETTING
shown in chart, and INDIVIDUAL COLOR CODES shown below):
MEMORY LOCATION:
Caution: you can set your sprite pointers anywhere in RAM memory but if you
set them too "low" in memory a long BASIC program may overwrite your sprite
data, or vice versa. To protect an especially LONG BASIC PROGRAM from
overwriting sprite data, you may want to set the sprites at a higher area of
memory (for example, 2040,192 for sprite 0 at locations 12288 to 12350…
2041, 193 at locations 12352 to 12414 for sprite 1 and so on… by adjusting
the memory locations from which sprites get their "data," you can define as many
as 64 different sprites plus a sizable BASIC program. To do this, define several
sprite "shapes" in your DATA statements and then redefine a particular sprite by
changing the "pointer" so the sprite you are using is "pointed" at different areas
of memory containing different sprite picture data. See the "Dancing Mouse" to
see how this works. If you want two or more sprites to have THE SAME SHAPE
(you can still change position and color of each sprite), use the same sprite pointer
and memory location for the sprites you want to match (for example, you can
point sprites 0 and 1 to the same location by using POKE 2040, 192 and POKE
2041, 192).
Priority means one sprite will appear to move "in front of" or "behind" another
sprite on the display screen. Sprites with more priority always appear to move
"in front of" or "on top of" sprites with less priority. The rule is that lower
numbered sprites have priority over higher numbered sprites. Sprite 0 has
priority over all other sprites. Sprite 7 has no priority in relation to the other
sprites. Sprite 1 has priority over sprites 2 to 7, etc. If you put two sprites in the
same position, the sprite with the higher priority will appear IN FRONT OF the
sprite with the lower priority. The sprite with lower priority will either be
obscured, or will "show through" (from "behind") the sprite with higher priority.
USING MULTICOLOR:
You can create multicolored sprites although using multicolor mode requires that
you use PAIRS of pixels instead of individual pixels in your sprite picture (in other
words each colored "dot" or "block" in the sprite will consist of two pixels side
by side). You have 4 colors to choose from: Sprite Color (chart above), Multicolor
1, Multicolor 2 and "Background Color" (background is achieved by using zero
settings which let the background color "show through"). Consider one horizontal
8-pixel block in a sprite picture. The color of each PAIR of pixels is determined
according to whether the left, right, or both pixels are solid, like this:
COLLISION:
You can detect whether a sprite has collided with another sprite by using this
line:
This line checks to see if a particular sprite has collided with ANY OTHER SPRITE,
where X equals 1 for sprite 0, 2 for sprite 1, 4 for sprite 2, 8 for sprite 3, 16
for sprite 4, 32 for sprite 5, 64 for sprite 6, and 128 for sprite 7. To check to
see if the sprite has collided with a "BACKGROUND CHARACTER" use this line:
The following program allows you to create a sprite using blanks and solid circles
( SHIFT Q ) in DATA statements. The sprite and the numbers POKEd into the sprite
data registers are displayed:
SHIFT CLR/HOME
10 PRINT"":FORI=0TO63:POKE832+I,0:NEXT
20 GOSUB60000
999 END
60000 DATA" ••••••• "
60001 DATA" ••••••••••• "
60002 DATA" ••••••••••••• "
60003 DATA" ••••• ••••• "
60004 DATA" ••••• ••• ••••• "
60005 DATA" ••••• ••• ••••• "
60006 DATA" ••••• ••• ••••• "
60007 DATA" ••••• ••••• "
60008 DATA" ••••••••••••• "
60009 DATA" ••••••••••••• "
60010 DATA" • ••••••••• • "
60011 DATA" • ••••••• • "
60012 DATA" • ••••• • "
60013 DATA" • ••• • "
60014 DATA" • ••• • "
60015 DATA" • • • "
60016 DATA" • • • "
60017 DATA" ••••• "
60018 DATA" ••••• "
60019 DATA" ••••• "
60020 DATA" ••• "
60100 V=53248:POKEV,200:POKEV+1,100:POKEV+21,1:
POKEV+39,14:POKE2040,13
60105 POKEV+23,1:POKEV+29,1
60110 FORI=0TO20:READA$:FORK=0TO2:T=0:FORJ=0TO7:B=0
60140 IFMID$(A$,J+K*8+1,1)="•"THENB=1
60150 T=T+B*2↑(7-J):NEXT:PRINT T;: POKE832 + I*3+K,T:
NEXT:PRINT:NEXT
60200 RETURN
This section of your Programmer’s Reference Guide has been created to help
you explore all the capabilities of the 6581 "SID" chip, the sound and music
synthesizer inside your Commodore computer. We’ll explain both the theory
behind musical ideas and the practical aspects of turning those ideas into real
finished songs on your Commodore computer.
You get to the sound generator by POKEing into specified memory locations. A
full list of the locations used is provided in Appendix O. We will go through each
concept, step by step. By the end you should be able to create an almost infinite
variety of sounds, and be ready to perform experiments with sound on your own.
Each section of this chapter begins by giving you an example and a full line-by-
line description of each program, which will show you how to use the
characteristic being discussed. The technical explanation is for you to read
whenever you are curious about what is actually going on.
The workhorse of your sound programs is the POKE statement. POKE sets the
indicated memory location (MEM) equal to a specified value (NUM).
POKE MEM,NUM
The memory locations (MEM) used for music synthesis start at 54272 ($D400) in
the Commodore 64. The memory locations 54272 to 54296 inclusive are the
POKE locations you need to remember when you're using the 6581 (SID) chip
register map. Another way to use the locations above is to remember only
location 54272 and then add a number from 0 through 24 to it. By doing this
you can POKE all the locations from 54272 to 54296 that you need from the
When you've had a little more practice with making music, then you can get a
little more involved by using the PEEK function. PEEK is a function that is equal to
the value currently in the indicated memory location.
X=PEEK(MEM)
The value of the variable X is set equal to the current contents of memory location
MEM.
Of course, your programs include other BASIC commands, but for a full
explanation of them, refer to the BASIC Statements section of this manual.
Let's jump right in and try a simple program using only one of the three voices.
Computer ready? Type NEW, then type in this program, and save it on your
Commodore Datassette ™ or disk. Then, RUN it.
EXAMPLE PROGRAM 1:
5 S=54272
10 FORL=STOS+24:POKEL,0:NEXT:REM CLEAR SOUND CHIP
20 POKES+5,9:POKES+6, 0
30 POKES+24,15 :REM SET VOLUME TO MAXIMUM
40 READHF,LF,DR
50 IFHF<0THENEND
60 POKES+1,HF:POKES,LF
70 POKES+4,33
80 FORT=1TODR:NEXT
90 POKES+4,32:FORT=1TO50:NEXT
100 GOTO40
110 DATA 25,177,250,28,214,250
120 DATA 25,177,250,25,177,250
130 DATA 25,177,125,28,214,125
140 DATA 32,94,750,25,177,250
150 DATA 28,214,250,19,63,250
160 DATA 19,63,250,19,63,250
170 DATA 21,154,63,24,63,63
180 DATA 25,177,250,24,63,125
190 DATA 19,63,250,-1,-1,-1
Here's a line-by-line description of the program you've just typed in. Refer to it
whenever you feel the need to investigate parts of the program that you don't
understand completely.
Lines(s) Description
5 Set S to start of sound chip
10 Clear all sound chip registers.
Set Attack/Decay for voice 1 (A=0,D=9).
20
Set Sustain/Release for voice 1 (S=0,R=0).
30 Set volume at maximum.
40 Read high frequency, low frequency, duration of note.
50 When high frequency less than zero, song is over.
60 Poke high and low frequency of voice 1.
70 Gate sawtooth waveform for voice 1.
80 Timing loop for duration of note.
90 Release sawtooth waveform for voice 1.
100 Return for next note.
110–180 Data for song: high frequency, low frequency, duration (number
of counts) for each note.
190 Last note of song and negative 1s signaling end of song.
VOLUME CONTROL
Chip register 24 contains the overall volume control. The volume can be set
anywhere between 0 and 15. The other four bits are used for purposes we'll get
into later. For now it is enough to know volume is 0 to 15. Look at line 30 to see
how it's set in Example Program 1.
Sound is created by the movement of air in waves. Think of throwing a stone into
a pool and seeing the waves radiate outward. When similar waves are created
in air, we hear it. If we measure the time between one peak of a wave and the
next, we find the number of seconds for one cycle of the wave (n=number of
seconds). The reciprocal of this number (1/n) gives you the cycles per second.
Cycles per second are more commonly known as the frequency. The highness or
lowness of a sound (pitch) is determined by the frequency of the sound waves
produced.
Fn=Fout/.06097
Once you've figured out what Fn is for your "new" note the next step is to create
the high and low frequency values for that note. To do this you must first round
off Fn so that any numbers to the right of the decimal point are left off. You are
now left with an integer value. Now you can set the high frequency location (Fhi)
by using the formula Fhi=INT(Fn/256) and the low frequency location (Flo) should
be Flo=Fn–(256*Fhi).
At this point you have already played with one voice of your computer. If you
wanted to stop here you could find a copy of your favorite tune and become
the maestro conducting your own computer orchestra in your "at home" concert
hall.
This example program shows you one way to translate sheet music for your
computer orchestra. Try typing it in and then SAVE it on your Datassette ™ or
disk. Don't forget to type NEW before typing in this program.
EXAMPLE PROGRAM 2:
10 S=54272:FORL=STOS+24: POKEL,0:NEXT
20 DIMH(2,200),L(2,200),C(2,200)
30 DIMFQ(11)
40 V(0)=17:V(1)=65:V(2)=33
50 POKES+10,8:POKES+22,128:POKES+23,244
60 FORI=0TO11:READFQ(I):NEXT
100 FORK=0TO2
110 I=0
120 READNM
130 IFNM=0THEN250
140 WA=V(K):WB=WA-1:IFNM<0THENNM=-NM:WA=0:WB=0
150 DR%=NM/128:OC%=(NM-128*DR%)/16
160 NT=NM-128*DR%-16*OC%
170 FR=FQ(NT)
Line(s) Description
10 Set S equal to start of sound chip and clear all sound chip
registers.
20 Dimension arrays to contain activity of song, 1/l6th of a
measure per location.
30 Dimension array to contain base frequency for each note.
40 Store waveform control byte for each voice.
50 Set high pulse width for voice 2.
Set high frequency for filter cutoff.
Set resonance for filter and filter voice 3.
60 Read in base frequency for each note.
100 Begin decoding loop for each voice.
110 Initialize pointer to activity array.
120 Read coded note.
130 If coded note is zero, then next voice.
140 Set waveform controls to proper voice.
If silence, set waveform controls to 0.
150 Decode duration and octave.
160 Decode note.
170 Get base frequency for this note.
180 If highest octave, skip division loop.
190 Divide base frequency by 2 appropriate number of times.
200 Get high and low frequency bytes.
210 If sixteenth note, set activity array: high frequency, low
frequency, and waveform control (voice on).
220 For all but last beat of note, set activity array: high
frequency, low frequency, waveform control (voice on).
230 For last beat of note, set activity array: high frequency, low
frequency, waveform control (voice off).
240 Increment pointer to activity array. Get next note.
250 If longer than before, reset number of activities.
260 Go back for next voice.
500 Set Attack/Decay for voice 1 (A=0, D=0).
Set Sustain/Release for voice 1 (S=15, R=0).
The values used in the data statements were found by using the note table in
Appendix E and the chart below:
In other words:
((((D*8)+O) *16)+N)
Once you have gotten used to using more than one voice, you will find that the
timing of the three voices needs to be coordinated. This is accomplished in this
program by:
The high and low frequency bytes are calculated by dividing the frequencies of
the highest octave by two (lines 180 and 190). The waveform control byte is a
start signal for beginning a note or continuing a note that is already playing. It
is a stop signal to end a note. The waveform choice is made once for each voice
in line 40.
Again, this is only one way to control multiple voices. You may come up with your
own methods. However, you should now be able to take any piece of sheet music
and figure out the notes for all three voices.
The tonal quality of a sound is called the timbre. The timbre of a sound is
determined primarily by its "waveform." If you remember the example of
throwing a pebble into the water you know that the waves ripple evenly across
the pond. These waves almost look like the first sound wave we're going to talk
about, the sinusoidal wave, or sine wave for short (shown below):
To make what we're talking about a bit more practical, let's go back to the first
example program to investigate different waveforms. The reason for this is that
you can hear the changes more easily using only one voice. LOAD the first music
program that you typed in earlier, from your Datassette ™ or disk, and RUN it
again. That program is using the sawtooth waveform (shown here):
from the 6581 SID chip's sound generating device. Try changing the note start
number in line 70 from 33 to 17 and the note stop number in line 90 from 32 to
16. Your program should now look like this:
5 S=54272
10 FORL=STOS+24:POKEL,0:NEXT
20 POKES+5,9:POKES+6,0
30 POKES+24,15
40 READHF,LF,DR
50 IFHF<0THENEND
60 POKES+1,HF:POKES,LF
70 POKES+4,17
80 FORT=1TODR:NEXT
90 POKES+4,16:FORT=1TO50:NEXT
100 GOTO40
110 DATA25,177,250,28,214,250
120 DATA25,177,250,25,177,250
130 DATA25,177,125,28,214,125
140 DATA32,94,750,25,177,250
150 DATA28,214,250,19,63,250
160 DATA19,63,250,19,63,250
170 DATA21,154,63,24,63,63
180 DATA25,177,250,24,63,125
190 DATA19,63,250,-1,-1,-1
Notice how the sound quality is different, less twangy, more hollow. That's
because we changed the sawtooth waveform into a triangular waveform (shown
below):
The third musical waveform is called a variable pulse wave (shown below):
Together these registers specify a 12-bit number for your pulse width, which you
can determine by using the following formula:
When PWn has a value of 2048, it will give you a square wave. That means
that register 2 (Lpw) = 0 and register 3 (Hpw) = 8.
15 POKES+3,8:POKES+2,0
Then change the start number in line 70 to 65 and the stop number in line 90 to
64, and RUN the program. Now change the high pulse width (register 3 in line
15) from an 8 to a 1. Notice how dramatic the difference in sound quality is?
It is used mostly for sound effects and such. To hear how it sounds, try changing
the start number in line 70 to 129 and the stop number in line 90 to 128.
UNDERSTANDING WAVEFORMS
In musical theory let's say that the fundamental frequency is harmonic number 1.
The second harmonic has a frequency twice the fundamental frequency, the third
harmonic is three times the fundamental frequency, and so on. The amounts of
each harmonic present in a note give it its timbre.
A triangular wave contains only odd harmonics. The amount of each harmonic
present is proportional to the reciprocal of the square of the harmonic number.
In other words harmonic number 3 is 1/9 quieter than harmonic number 1,
because the harmonic 3 squared is 9 (3 × 3) and the reciprocal of 9 is 1/9.
As you can see, there is a similarity in shape of a triangular wave to a sine wave
oscillating at the fundamental frequency.
Sawtooth waves contain all the harmonics. The amount of each harmonic present
is proportional to the reciprocal of the harmonic number. For example, harmonic
number 2 is 1/2 as loud as harmonic number 1.
The square wave contains odd harmonics in proportion to the reciprocal of the
harmonic number. Other rectangular waves have varying harmonic content. By
changing the pulse width, the timbre of the sound of a rectangular wave can be
varied tremendously.
The volume of a musical tone changes from the moment you first hear it, all the
way through until it dies out and you can't hear it anymore. When a note is first
struck, it rises from zero volume to its peak volume. The rate at which this happens
is called the ATTACK. Then, it falls from the peak to some middle-ranged
volume. The rate at which the fall of the note occurs is called the DECAY. The
mid-ranged volume itself is called the SUSTAIN level. And finally, when the note
stops playing, it falls from the SUSTAIN level to zero volume. The rate at which
it falls is called the RELEASE. Here is a sketch of the four phases of a note:
Each of the items mentioned above give certain qualities and restrictions to a
note. The bounds are called parameters.
5 S=54272
10 FORL=STOS+24:POKEL,0:NEXT
20 POKES+5,88:POKES+6,195
30 POKES+24,15
40 READHF,LF,DR
50 IFHF<0THENEND
60 POKES+1,HF:POKES,LF
70 POKES+4,33
80 FORT=1TODR:NEXT
90 POKES+4,32:FORT=1TO50:NEXT
100 GOTO40
110 DATA25,177,250,28,214,250
120 DATA25,177,250,25,177,250
130 DATA25,177,125,28,214,125
140 DATA32,94,750,25,177,250
150 DATA28,214,250,19,63,250
160 DATA19,63,250,19,63,250
170 DATA21,154,63,24,63,63
180 DATA25,177,250,24,63,125
190 DATA19,63,250,-1,-1,-1
Registers 5 and 6 define the ADSR for voice 1. The ATTACK is the high nybble
of register 5. Nybble is half a byte, in other words the lower 4 or higher 4 on/off
locations (bits) in each register. DECAY is the low nybble. You can pick any
number 0 through 15 for ATTACK, multiply it by 16 and add to any number 0
through 15 for DECAY. The values that correspond to these numbers are listed
below.
SUSTAIN level is the high nybble of register 6. It can be 0 through 15. It defines
the proportion of the peak volume that the SUSTAIN level will be. RELEASE rate
is the low nybble of register 6.
Here are a few sample settings to try in your example program. Try these and
a few of your own. The variety of sounds you can produce is astounding! For a
violin type sound, try changing line 20 to read:
20 POKES+5,88:POKES+6,89:REM A=5;D=8;S=5;R=9
Change the waveform to triangle and get a xylophone type sound by using
these lines:
20 POKES+5,9:POKES+6,9:REM A=0;D=9;S=O;R=9
70 POKES+4,17
90 POKES+4,16:FORT=1TO50:NEXT
15 POKES+3,8:POKES+2,0
20 POKES+5,9:POKES+6,0: REM A=0;D=9;S=0;R=0
70 POKES+4,65
90 POKES+4,64:FORT=1TO50:NEXT
The most exciting sounds are those unique to the music synthesizer itself, ones that
do not attempt to mimic acoustic instruments. For example try:
20 POKES+5,144:POKES+6,243:REM A=9;D=0;S=15;R=3
FILTERING
The harmonic content of a waveform can be changed by using a filter. The SID
chip is equipped with three types of filtering. They can be used separately or in
combination with one another. Let's go back to the sample program you've been
using to play with a simple example that uses a filter. There are several filter
controls to set.
You add line 15 in the program to set the cutoff frequency of the filter. The cutoff
frequency is the reference point for the filter. You SET the high and low frequency
cutoff points in registers 21 and 22. To turn ON the filter for voice 1, POKE
register 23.
Next change line 30 to show that a high-pass filter will be used (see the SID
register map).
5 S=54272
10 FORL=STOS+24:POKEL,0:NEXT
15 POKES+22,128:POKES+21,0:POKES+23,1
20 POKES+5,9:POKES+6,0
30 POKES+24,79
40 READHF,LF,DR
50 IFHF<0THENEND
60 POKES+1,HF:POKES,LF
70 POKES+4,33
80 FORT=1TODR:NEXT
90 POKES+4,32:FORT=1TO50:NEXT
100 GOTO40
110 DATA25,177,250,28,214,250
120 DATA25,177,250,25,177,250
130 DATA25,177,125,28,214,125
140 DATA32,94,750,25,177,250
150 DATA28,214,250,19,63,250
160 DATA19,63,250,19,63,250
170 DATA21,154,63,24,63,63
180 DATA25,177,250,24,63,125
190 DATA19,63,250,-1,-1,-1
Try RUNning the program now. Notice the lower tones have had their volume cut
down. It makes the overall quality of the note sound tinny. This is because you
are using a high-pass filter which attenuates (cuts down the level of) frequencies
below the specified cutoff frequency.
There are three types of filters in your Commodore computer's SID chip. We
have been using the high-pass filter. It will pass all the frequencies at or above
the cutoff, while attenuating the frequencies below the cutoff.
The SID chip also has a low-pass filter. As its name implies, this filter will pass the
frequencies below cutoff and attenuate those above.
The high- and low-pass filters can be combined to form a notch reject filter which
passes frequencies away from the cutoff while attenuating at the cutoff
frequency.
Through careful use of filtering, you can change the harmonic structure of any
waveform to get just the sound you want. In addition, changing the filtering of a
sound as it goes through the ADSR phases of its life can produce interesting
effects.
ADVANCED TECHNIQUES
The SID chip's parameters can be changed dynamically during a note or sound
to create many interesting and fun effects. In order to make this easy to do,
digitized outputs from oscillator three and envelope generator three are available
for you in registers 27 and 28, respectively.
EXAMPLE PROGRAM 6:
10 S=54272
20 FORL=0TO24:POKES+L,0:NEXT
30 POKES+3,8
40 POKES+5,41:POKES+6,89
50 POKES+14,117
60 POKES+18,16
70 POKES+24,143
80 READFR,DR
90 IFFR=0THENEND
100 POKES+4,65
110 FORT=1TODR*2
120 FQ=FR+PEEK(S+27)/2
130 HF=INT(FQ/256):LF=FQAND255
140 POKES+0,LF:POKES+1,HF
150 NEXT
160 POKES+4,64
170 GOTO80
500 DATA 4817,2,5103,2,5407,2
510 DATA 8583,4,5407,2,8583,4
520 DATA 5407,4,8583,12,9634,2
530 DATA 10207,2,10814,2,8583,2
540 DATA 9634,4,10814,2,8583,2
550 DATA 9634,4,8583,12
560 DATA 0,0
Line(s) Description
10 Set S to beginning of sound chip.
20 Clear all sound chip locations.
30 Set high pulse width for voice 1.
40 Set Attack/Decay for voice 1 (A=2, D=9).
Set Sustain/Release for voice 1 (S=5, R=9).
50 Set low frequency for voice 3.
60 Set triangle waveform for voice 3.
70 Set volume 15, turn off audio output of voice 3.
80 Read frequency and duration of note.
90 If frequency equals zero, stop.
100 POKE start pulse waveform control voice 1.
110 Start timing loop for duration.
120 Get new frequency using oscillator 3 output.
130 Get high and low frequency.
140 POKE high and low frequency for voice 1.
150 End of timing loop.
160 POKE stop pulse waveform control voice 1.
170 Go back for next note.
500–550 Frequencies and durations for song.
560 Zeros signal end of song.
A wide variety of sound effects can also be achieved using dynamic effects. For
example, the following siren program dynamically changes the frequency output
of oscillator 1 when it's based on the output of oscillator 3's triangular wave:
10 S=54272
20 FORL=0TO24:POKES+L,0:NEXT
30 POKES+14,5
40 POKES+18,16
50 POKES+3,1
60 POKES+24,143
70 POKES+6,240
80 POKES+4,65
90 FR=5389
100 FORT=1TO200
110 FQ=FR+PEEK(S+27)*3.5
120 HF=INT(FQ/256):LF=FQ-HF*256
130 POKES+0,LF:POKES+1,HF
140 NEXT
150 POKES+24,0
Line(s) Description
10 Set S to start of sound chip.
20 Clear sound chip registers.
30 Set low frequency of voice 3.
40 Set triangular waveform voice 3.
50 Set high pulse width for voice 1.
60 Set volume 15, turn off audio output of voice 3.
70 Set Sustain/Release for voice 1 (S=15, R=0).
80 POKE start pulse waveform control voice 1.
90 Set lowest frequency for siren.
100 Begin timing loop.
110 Get new frequency using output of oscillator 3.
120 Get high and low frequencies.
130 POKE high and low frequencies for voice 1.
140 End timing loop.
150 Turn off volume.
EXAMPLE PROGRAM 8:
10 S=54272
20 FORL=0TO24:POKES+L,0:NEXT
30 POKES+0,240:POKES+1,33
40 POKES+5,8
50 POKES+22,104
60 POKES+23,1
70 POKES+24,79
80 FORN=1TO15
90 POKES+4,129
100 FORT=1TO250:NEXT:POKES+4,128
110 FORT=1TO30:NEXT:NEXT
120 POKES+24,0
Line(s) Description
10 Set S to start of sound chip.
20 Clear all sound chip registers.
30 Set high and low frequencies for voice 1.
40 Set Attack/Decay for voice 1 (A=0, D=8).
50 Set high cutoff frequency for filter.
60 Turn on filter for voice 1.
70 Set volume 15, high-pass filter.
80 Count 15 claps.
90 Set start noise waveform control.
100 Wait, then set stop noise waveform control.
110 Wait, then start next clap.
120 Turn off volume.
EXAMPLE PROGRAM 9:
10 S=54272
20 FORL=0TO24:POKES+L,0:NEXT
30 POKES+1,100
40 POKES+5,219
50 POKES+15,28
60 POKES+24,15
70 POKES+4,19
80 FORT=1TO5000:NEXT
90 POKES+4,18
100 FORT=1TO1000:NEXT:POKES+24,0
Line(s) Description
10 Set S to start of sound chip.
20 Clear sound chip registers.
30 Set high frequency voice 1.
40 Set Attack/Decay for voice 1 (A=13, D=11).
50 Set high frequency voice 3.
60 Set volume 15.
70 Set start triangle, sync waveform control for voice 1.
80 Timing loop.
90 Set stop triangle, sync waveform control for voice 1.
100 Wait, then turn off volume.
The synchronization feature is enabled (turned on) in line 70, where bits 0, 1,
and 4 of register 4 are set. Bit 1 enables the syncing function between voice 1
and voice 3. Bits 0 and 4 have their usual functions of gating voice 1 and setting
the triangular waveform.
10 S=54272
20 FORL=0TO24:POKES+L,0:NEXT
30 POKES+1,130
40 POKES+5,9
50 POKES+15,30
60 POKES+24,15
70 FORL=1TO12:POKES+4,21
80 FORT=1TO1000:NEXT:POKES+4,20
90 FORT=1TO1000:NEXT:NEXT
Line(s) Description
10 Set S to start of sound chip.
20 Clear sound chip registers.
30 Set high frequency voice 1.
40 Set Attack/Decay for voice 1 (A=0, D=9).
50 Set high frequency voice 3.
60 Set volume 15.
70 Count number of dings, set start triangle, ring mod
waveform control voice 1.
80 Timing loop, set stop triangle, ring mod.
90 Timing loop, next ding.
The effects available through the use of the parameters of your Commodore
64's SID chip are numerous and varied. Only through experimentation on your
own will you fully appreciate the capabilities of your machine. The examples in
this section of the Programmer's Reference Guide merely scratch the surface.
To answer this question, you must first see what happens inside your Commodore
64. Apart from the microprocessor which is the brain of the Commodore 64, there
is a machine language program which is stored in a special type of memory so
that it can't be changed. And, more importantly, it does not disappear when the
Commodore 64 is turned off, unlike a program that you may have written. This
machine language program is called the OPERATING SYSTEM of the
Commodore 64. Your Commodore 64 knows what to do when it's turned on
because its OPERATING SYSTEM (program) is automatically "RUN."
READY.
█
The OPERATING SYSTEM of the Commodore 64 then allows you to type on the
keyboard, and use the built-in SCREEN EDITOR on the Commodore 64. The
SCREEN EDITOR allows you to move the cursor, DELete, INSert, etc., and is, in
fact, only one part of the operating system that is built in for your convenience.
All of the commands that are available in CBM BASIC are simply recognized by
another huge machine language program built into your Commodore 64. This
huge program "RUNs" the appropriate piece of machine language depending
on which CBM BASIC command is being executed. This program is called the
BASIC INTERPRETER, because it interprets each command, one by one, unless it
encounters a command it does not understand, and then the familiar message
appears:
?SYNTAX ERROR
READY.
█
You should be familiar with the PEEK and POKE commands in the CBM BASIC
language for changing memory locations. You've probably used them for
graphics on the screen, and for sound effects. Each memory location has its own
number which identifies it. This number is known as the "address" of a memory
location. If you imagine the memory in the Commodore 64 as a street of
buildings, then the number on each door is, of course, the address. Now let's look
at which parts of the street are used for what purposes.
ADDRESS DESCRIPTION
2
up to: — Start of memory.
1023 — Memory used by the operating system.
1024
up to: — Screen memory.
2039
2040
up to: — SPRITE pointers.
2047
2048
up to: — This is YOUR memory. This is where your BASIC or machine
40959 language programs, or both, are stored.
40960
up to: — 8K CBM BASIC interpreter.
49151
49152
up to: — Special programs RAM area.
53247
53248
up to: — VIC-II.
53294
54272
up to: — SID Registers.
55295
55296
up to: — Color RAM.
56296
56320
up to: — I/O Registers. (6526’s)
57343
57344
up to: — 8K CBM KERNAL Operating system.
65535
Machine language programs consist of instructions which may or may not have
operands (parameters) associated with them. Each instruction takes up one
memory location, and any operand is contained in one or two locations following
the instruction.
In your BASIC programs, words like PRINT and GOTO do, in fact, only take up
one memory location, rather than one for each character of the word. The
contents of the location that represents a particular BASIC keyword is called a
token. In machine language, there are different tokens for different instructions,
which also take up just one byte (memory location=byte).
THE ACCUMULATOR
This is a very important register. There are instructions for nearly all of the
transformations you can make to the accumulator. But there are other instructions
for things that only the X register can do. Various machine language instructions
allow you to copy the contents of a memory location into the X register, copy the
contents of the X register into a memory location, and modify the contents of the
X, or some other register directly.
This is a very important register. There are instructions for nearly all of the
transformations you can make to the accumulator, and the X register. But there
are other instructions for things that only the Y register can do. Various machine
language instructions allow you to copy the contents of a memory location into
the Y register, copy the contents of the Y register into a memory location, and
modify the contents of the Y, or some other register directly.
This register consists of eight "flags" (a flag = something that indicates whether
something has, or has not occurred).
This contains the address of the current machine language instruction being
executed. Since the operating system is always "RUN"ning in the Commodore 64
(or, for that matter, any computer), the program counter is always changing. It
could only be stopped by halting the microprocessor in some way.
This register contains the location of the first empty place on the stack. The stack
is used for temporary storage by machine language programs, and by the
computer.
This register appears at memory locations 0 (for the DATA DIRECTION REGISTER)
and 1 (for the actual PORT). It is an 8-bit input/output port. On the Commodore
64 this register is used for memory management, to allow the chip to control
more than 64K of RAM and ROM memory.
The details of these registers are not given here. They are explained as the
principles needed to explain them are explained.
The most common methods used to write machine language programs are
assembler programs. These packages allow you to write machine language
instructions in a standardized mnemonic format, which makes the machine
language program a lot more readable than a stream of numbers! Let's review:
A program that allows you to write machine language programs in mnemonic
format is called an assembler. Incidentally, a program that displays a machine
language program in mnemonic format is called a disassembler. Available for
your Commodore 64 is a machine language monitor cartridge (with
assembler/disassembler, etc.) made by Commodore:
64MON
The 64MON cartridge available from your local dealer, is a program that
allows you to escape from the world of CBM BASIC, into the land of machine
language. It can display the contents of the internal registers in the 6510
microprocessor, and it allows you to display portions of memory, and change
them on the screen, using the screen editor. It also has a built-in assembler and
disassembler, as well as many other features that allow you to write and edit
machine language programs easily. You don't HAVE to use an assembler to write
machine language, but the task is considerably easier with it. If you wish to write
machine language programs, it is strongly suggested that you purchase an
assembler of some sort. Without an assembler you will probably have to "POKE"
the machine language program into memory, which is totally unadvisable. This
manual will give its examples in the format that 64MON uses, from now on.
Nearly all assembler formats are the same, therefore the machine language
examples shown will almost certainly be compatible with any assembler. But
before explaining any of the other features of 64MON, the hexadecimal
numbering system must be explained.
HEXADECIMAL NOTATION
Hexadecimal notation is used by most machine language programmers when
they talk about a number or address in a machine language program.
Some assemblers let you refer to addresses and numbers in decimal (base 10),
binary (base 2), or even octal (base 8) as well as hexadecimal (base 16) (or just
"hex" as most people say). These assemblers do the conversions for you.
By looking at decimal (base 10) numbers, you can see that each digit falls
somewhere in the range between zero and a number equal to the base less one
(e.g., 9). THIS IS TRUE OF ALL NUMBER BASES. Binary (base 2) numbers have
digits ranging from zero to one (which is one less than the base). Similarly,
hexadecimal numbers should have digits ranging from zero to fifteen, but we do
not have any single digit figures for the numbers ten to fifteen, so the first six
letters of the alphabet are used instead:
Base raised by
increasing powers: .............. 103 102 101 100
Equals: ................................... 1000 100 10 1
Consider 4569 (base 10) 4 5 6 9
=(4x1000)+(5x100)+(6x10)+9
Base raised by
increasing powers: .............. 163 162 161 160
Equals: ................................... 4096 256 16 1
Consider 11D9 (base 16) 1 1 D 9
=(1x4096)+(1x256)+(13x16)+9
The range for addressable memory locations is 0 – 65535 (as was stated
earlier). This range is therefore 0 – FFFF in hexadecimal notation.
Usually hexadecimal numbers are prefixed with a dollar sign ($). This is to
distinguish them from decimal numbers. Let's look at some "hex" numbers, using
64MON, by displaying the contents of some memory by typing:
PC SR AC XR YR SP
.; 0401 32 04 5E 00 F6 (these may be different)
you will see rows of 9 hex numbers. The first 4-digit number is the address of the
first byte of memory being shown in that row, and the other eight numbers are
the actual contents of the memory locations beginning at that start address.
If you put a "#" symbol in front of the parameter associated with the instruction,
this means that you want the register specified in the instruction to be loaded
with the "value" after the "#". For example:
This instruction will put $05 (decimal 5) into the accumulator register. The
assembler will put into the specified address for this instruction, $A9 (which is the
token for this particular instruction, in this mode), and it will put $05 into the next
location after the location containing the instruction ($A9).
If the parameter to be used by an instruction has "#" before it; i.e., the
parameter is a "value," rather than the contents of a memory location, or another
register, the instruction is said to be in the "immediate" mode. To put this into
perspective, let's compare this with another mode:
If you want to put the contents of memory location $102E into the accumulator,
you're using the "absolute" mode of instruction:
LDA $102E
The assembler can distinguish between the two different modes because the
latter does not have a "#" before the parameter. The 6510 microprocessor can
distinguish between the immediate mode, and the absolute mode of the LDA
instruction, because they have slightly different tokens. LDA (immediate) has $A9
as its token, and LDA (absolute), has $AD as its token.
If you said "load the X register with…," go to the top of the class. If you didn't,
then don't worry, learning machine language does take patience, and cannot be
learned in a day.
READY.
█
If the limit of one byte is $FF (hex), how is the address parameter in the absolute
instruction "LDA $102E" expressed in memory? It's expressed in two bytes (it
won't fit into one, of course). The lower (rightmost) two digits of the hexadecimal
address form the "low byte" of the address, and the upper (leftmost) two digits
form the "high byte."
The 6510 requires any address to be specified with its low byte first, and then
the high byte. This means that the instruction "LDA $102E" is represented in
memory by the three consecutive values:
Now all you need to know is one more instruction and then you can write your
first program. That instruction is BRK. For a full explanation of this instruction,
refer to M.O.S. 6502 Programming Manual. But right now, you can think of it as
the END instruction in machine language.
If you've used the POKE statement in BASIC to put characters onto the screen,
you're aware that the character codes for POKEing are different from CBM
ASCII character values. For example, if you enter:
65
READY.
█
However, to put an "A" onto the screen by POKEing, the code is 1, enter:
Now let's try this in machine language. Type the following in 64MON: (Your
cursor should be flashing alongside a "." right now.)
Type:
(The STA instruction stores the contents of the accumulator in a specified memory
location.)
.A 1405 █
G 1400
You have now written your first machine language program. Its purpose is to
store one character ("A") at the first location in the screen memory. Having
achieved this, we must now explore some of the other instructions, and principles.
ADDRESSING MODES
ZERO PAGE
THE STACK
The 6510 microprocessor has what is known as a stack. This is used by both the
programmer and the microprocessor to temporarily remember things, and to
remember, for example, an order of events. The GOSUB statement in BASIC,
which allows the programmer to call a subroutine, must remember where it is
being called from, so that when the RETURN statement is executed in the
subroutine, the BASIC interpreter "knows" where to go back to continue
executing. When a GOSUB statement is encountered in a program by the BASIC
interpreter, the BASIC interpreter "pushes" its current position onto the stack
before going to do the subroutine, and when a RETURN is executed, the
interpreter "pulls" off the stack the information that tells it where it was before
the subroutine call was made. The interpreter uses instructions like PHA, which
pushes the contents of the accumulator onto the stack, and PLA (the reverse)
which pulls a value off the stack and into the accumulator. The status register can
also be pushed and pulled with the PHP and PLP, respectively.
The stack is 256 bytes long, and is located in page one of memory. It is therefore
from $0100 to $01FF. It is organized backwards in memory. In other words, the
first position in the stack is at $01FF, and the last is at $0100. Another register
in the 6510 microprocessor is called the stack pointer, and it always points to the
next available location in the stack. When something is pushed onto the stack, it
is placed where the stack pointer points to, and the stack pointer is moved down
to the next position (decremented). When something is pulled off the stack, the
stack pointer is incremented, and the byte pointed to by the stack pointer is
placed into the specified register.
NOTE: The X register will be referred to as X from now on, and similarly A (Accumulator), Y (Y
Index Register), S (Stack Pointer), and P (Processor Status).
INDEXING
Indexing plays an extremely important part in the running of the 6510
microprocessor. It can be defined as "creating an actual address from a base
address plus the contents of either the X or Y index registers."
EXAMPLE:
LDA $9000,X
There are absolute indexed, zero page indexed, indirect indexed, and indexed
indirect modes of addressing available on the 6510 microprocessor.
INDIRECT INDEXED
This only allows usage of the Y register as the index. The actual address can only
be in zero page, and the mode of instruction is called indirect because the zero
page address specified in the instruction contains the low byte of the actual
address, and the next byte to it contains the high order byte.
Let us suppose that location $02 contains $45, and location $03 contains $1E. If
the instruction to load the accumulator in the indirect indexed mode is executed
and the specified zero page address is $02, then the actual address will be:
The title of this mode does in fact imply an indirect principle, although this may
be difficult to grasp at first sight. Let's look at it another way:
"I am going to deliver this letter to the post office at address $02, MEMORY ST.,
and the address on the letter is $05 houses past $1600, MEMORY street." This
is equivalent to the code:
INDEXED INDIRECT
Indexed indirect only allows usage of the X register as the index. This is the same
as indirect indexed, except it is the zero page address of the pointer that is
indexed, rather than the actual base address. Therefore, the actual base
address IS the actual address because the index has already been used for the
indirect. Index indirect would also be used if a table of indirect pointers were
located in zero page memory, and the X register could then specify which
indirect pointer to use.
Let us suppose that location $02 contains $45, and location $03 contains $10. If
the instruction to load the accumulator in the indexed indirect mode is executed
and the specified zero page address is $02, then the actual address will be:
Therefore, the actual address is the indirect address contained in $02 which is
again $1045.
The title of this mode does in fact imply the principle, although it may be difficult
to grasp at first sight. Look at it this way:
"I am going to deliver this letter to the fourth post office at address $01,
MEMORY ST., and the address on the letter will then be delivered to $1600,
MEMORY Street." This is equivalent to the code:
NOTE: Of the two indirect methods of addressing, the first (indirect indexed) is far more widely
used.
Another very important principle in machine language is the ability to test, and
detect certain conditions, in a similar fashion to the "IF… THEN, IF… GOTO"
structure in CBM BASIC.
The various flags in the status register are affected by different instructions in
different ways. For example, there is a flag that is set when an instruction has
caused a zero result, and is reset when a result is not zero. The instruction:
LDA #$00
will cause the zero result flag to be set, because the instruction has resulted in the
accumulator containing a zero.
There are a set of instructions that will, given a particular condition, branch to
another part of the program. An example of a branch instruction is BEQ, which
means Branch if result EQual to zero. The branch instructions branch if the condition
is true, and if not, the program continues onto the next instruction, as if nothing
had occurred. The branch instructions branch not by the result of the previous
instruction(s), but by internally examining the status register. As was just
mentioned, there is a zero result flag in the status register. The BEQ instruction
branches if the zero result flag (known as Z) is set. Every branch instruction has
an opposite branch instruction. The BEQ instruction has an opposite instruction
BNE, which means Branch on result Not Equal to zero (i.e., Z not set).
The index registers have a number of associated instructions which modify their
contents. For example, the INX instruction INcrements the X index register. If the
X register contained $FF before it was incremented (the maximum number the X
register can contain), it will "wrap around" back to zero. If you wanted a
program to continue to do something until you had performed the increment of
the X index that pushed it around to zero, you could use the BNE instruction to
continue "looping" around, until X became zero.
The reverse of INX, is DEX, which is DEcrement the X index register. If the X index
register is zero, DEX wraps around to $FF. Similarly, there are INY and DEY for
the Y index register.
The compare, and branch instructions play a major part in any machine language
program.
The operand specified in a branch instruction when using 64MON is the address
of the part of the program that the branch goes to when the proper conditions
are met. However, the operand is only an offset, which gets you from where the
program currently is to the address specified. This offset is just one byte, and
therefore the range that a branch instruction can branch to is limited. It can
branch from 128 bytes backward, to 127 bytes forward.
NOTE: This is a total range of 255 bytes which is, of course, the maximum range of values one
byte can contain.
64MON will tell you if you "branch out of range" by refusing to "assemble" that
particular instruction. But don't worry about that now because it's unlikely that
you will have such branches for quite a while. The branch is a "quick" instruction
by machine language standards because of the "offset" principle as opposed to
an absolute address. 64MON allows you to type in an absolute address, and it
calculates the correct offset. This is just one of the "comforts" of using an
assembler.
NOTE: It is NOT possible to cover every single branch instruction. For further information, refer
to the Bibliography section in Appendix F.
Therefore, to print "HI" to the screen, the following program should be entered:
The "PRINT a character" routine we have just used is part of the KERNAL jump
table. The instruction similar to GOTO in BASIC is JMP, which means JuMP to the
specified absolute address. The KERNAL is a long list of "standardized" subroutines
that control ALL input and output of the Commodore 64. Each entry in the KERNAL
JMPs to a subroutine in the operating system. This "jump table" is found between
memory locations $FF84 to $FFF5 in the operating system. A full explanation of
the KERNAL is available in the "KERNAL Reference Section" of this manual.
However, certain routines are used here to show how easy and effective the
KERNAL is.
Let's now use the new principles you've just learned in another program. It will
help you to put the instructions into context:
To see the Commodore 64 print the alphabet, type the familiar command:
.G 1400
The comments that are beside the program, explain the program flow and logic.
If you are writing a program, write it on paper first, and then test it in small parts
if possible.
Having looked at other machine language programs, you MUST write your own.
These may be utilities for your BASIC programs, or they may be an all machine
language program.
READY.
█
This is the main outline. As each module is approached, you can break it down
further. If you look at a large indigestible problem as something that can be
broken down into small enough pieces to be eaten, then you'll be able to
approach something that seems impossible, and have it all fall into place.
NOP No Operation
A Accumulator
X, Y Index Registers
M Memory
P Processor Status Register
S Stack Pointer
Change
_ No Change
+ Add
Ʌ Logical AND
– Subtract
⊻ Logical Exclusive OR
↑ Transfer from Stack
↓ Transfer to Stack
→ Transfer to
← Transfer from
∨ Logical OR
PC Program Counter
PCH Program Counter High
PCL Program Counter Low
Oper Operand
# Immediate Addressing Mode
NOTE: At the top of each table is located in parenthesis a reference number (Ref: XX) which
directs the user to that Section in the MCS6500 Microcomputer Family Programming Manual in
which the instruction is defined and discussed.
(Ref: 10.2)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Accumulator ASL A 0A 1 2
Zero Page ASL Oper 06 2 5
Zero Page, X ASL Oper, X 16 2 6
Absolute ASL Oper 0E 3 6
Absolute, X ASL Oper, X 1E 3 7
(Ref: 4.1.2.3)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Relative BCC Oper 90 2 2*
* Add 1 if branch occurs to same page.
* Add 2 if branch occurs to different page.
(Ref: 4.1.2.4)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Relative BCS Oper B0 2 2*
* Add 1 if branch occurs to same page.
* Add 2 if branch occurs to different page.
(Ref: 4.1.2.5)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Relative BEQ Oper F0 2 2*
* Add 1 if branch occurs to same page.
* Add 2 if branch occurs to different page.
(Ref: 4.2.2.1)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Zero Page BIT Oper 24 2 3
Absolute BIT Oper 2C 3 4
(Ref: 4.1.2.1)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Relative BMI Oper 30 2 2*
* Add 1 if branch occurs to same page.
* Add 2 if branch occurs to different page.
(Ref: 4.1.2.6)
(Ref: 4.1.2.2)
N Ƶ C I D V
Operation: Forced Interrupt PC + 2 ↓ P ↓ _ _ _ 1 _ _
(Ref: 9.11)
Implied BRK 00 1 7
(Ref: 4.1.2.8)
(Ref: 4.1.2.7)
(Ref: 3.0.2)
(Ref: 3.3.2)
(Ref: 3.2.2)
(Ref: 3.6.1)
N Ƶ C I D V
Operation: M – 1 → M _ _ _ _
(Ref: 10.8)
N Ƶ C I D V
Operation: X – 1 → X _ _ _ _
(Ref: 7.6)
N Ƶ C I D V
Operation: Y – 1 → Y _ _ _ _
(Ref: 7.7)
N Ƶ C I D V
Operation: Y + 1 → Y _ _ _ _
(Ref: 7.5)
N Ƶ C I D V
Operation: (PC + 1) → PCL _ _ _ _ _ _
(PC + 2) → PCH
(Ref: 4.0.2)
(Ref: 9.8.1)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Absolute JMP Oper 4C 3 3
N Ƶ C I D V
Operation: PC + 2 ↓ , (PC + 1) → PCL _ _ _ _ _ _
(PC + 2) → PCH
(Ref: 8.1)
N Ƶ C I D V
Operation: M → A _ _ _ _
(Ref: 2.1.1)
(Ref: 7.0)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Immediate LDX # Oper A2 2 2
Zero Page LDX Oper A6 2 3
Zero Page, Y LDX Oper, Y B6 2 4
Absolute LDX Oper AE 3 4
Absolute, Y LDX Oper, Y BE 3 4*
* Add 1 when page boundary is crossed.
(Ref: 10.1)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Accumulator LSR A 4A 1 2
Zero Page LSR Oper 46 2 5
Zero Page, X LSR Oper, X 56 2 6
Absolute LSR Oper 4E 3 6
Absolute, X LSR Oper, X 5E 3 7
N Ƶ C I D V
Operation: A ↑ _ _ _ _
(Ref: 8.6)
N Ƶ C I D V
Operation: P ↑ From Stack
(Ref: 8.12)
N Ƶ C I D V
Operation: _ _ _
(Ref: 10.3)
N Ƶ C I D V
Operation: _ _ _
(Ref: 10.4)
(Ref: 9.6)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Implied RTI 40 1 6
(Ref: 8.2)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Implied RTS 60 1 6
(Ref: 2.2.2)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Immediate SBC # Oper E9 2 2
Zero Page SBC Oper E5 2 3
Zero Page, X SBC Oper, X F5 2 4
Absolute SBC Oper ED 3 4
Absolute, X SBC Oper, X FD 3 4*
Absolute, Y SBC Oper, Y F9 3 4*
(Indirect, X) SBC (Oper, X) E1 2 6
(Indirect), Y SBC (Oper), Y F1 2 5*
*Add 1 when page boundary is crossed.
(Ref: 3.0.1)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Implied SEC 38 1 2
(Ref: 3.3.1)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Implied SED F8 1 2
(Ref: 3.2.1)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Implied SEI 78 1 2
(Ref: 2.1.2)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Zero Page STA Oper 85 2 3
Zero Page, X STA Oper, X 95 2 4
Absolute STA Oper 8D 3 4
Absolute, X STA Oper, X 9D 3 5
Absolute, Y STA Oper, Y 99 3 5
(Indirect, X) STA (Oper, X) 81 2 6
(Indirect), Y STA (Oper), Y 91 2 6
N Ƶ C I D V
Operation: Y → M _ _ _ _ _ _
(Ref: 7.3)
N Ƶ C I D V
Operation: A → X _ _ _ _
(Ref: 7.11)
N Ƶ C I D V
Operation: A → Y _ _ _ _
(Ref: 7.13)
(Ref: 8.9)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Implied TSX BA 1 2
(Ref: 7.12)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Implied TXA 8A 1 2
(Ref: 8.8)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Implied TXS 9A 1 2
(Ref: 7.14)
Addressing OP No. No.
Assembly Language Form
Mode CODE Bytes Cycles
Implied TYA 98 1 2
Absolute Indirect
Zero Page, X
Zero Page, Y
Accumulator
(Indirect), Y
(Indirect, X)
Absolute, X
Absolute, Y
Zero Page
Immediate
Absolute
Relative
Implied
ADC 2 3 4 4 4* 4* 6 5*
AND 2 3 4 4 4* 4* 6 5*
ASL 2 5 6 6 7
BCC 2**
BCS 2**
BEQ 2**
BIT 3 4
BMI 2**
BNE 2**
BPL 2**
BRK
BVC 2**
BVS 2**
CLC 2
CLD 2
CLI 2
CLV 2
CMP 2 3 4 4 4* 4* 6 5*
CPX 2 3 4
CPY 2 3 4
DEC 5 6 6 7
DEX 2
DEY 2
EOR 2 3 4 4 4* 4* 6 5*
INC 5 6 6 7
INX 2
INY 2
JMP 3 5
* Add one cycle if indexing across page boundary.
**Add one cycle if branch is taken. Add one additional cycle if branching
Absolute Indirect
Zero Page, X
Zero Page, Y
Accumulator
(Indirect), Y
(Indirect, X)
Absolute, X
Absolute, Y
Zero Page
Immediate
Absolute
Relative
Implied
JSR 6
LDA 2 3 4 4 4* 4* 6 5*
LDX 2 3 4 4 4*
LDY 2 3 4 4 4*
LSR 2 5 6 6 7
NOP 2
ORA 2 3 4 4 4* 4* 6 5*
PHA 3
PHP 3
PLA 4
PLP 4
ROL 2 5 6 6 7
ROR 2 5 6 6 7
RTI 6
RTS 6
SBC 2 3 4 4 4* 4* 6 5*
SEC 2
SED 2
SEI 2
STA 3 4 4 5 5 6 6
STX 3 4 4
STY 3 4 4
TAX 2
TAY 2
TSX 2
TXA 2
TXS 2
TYA 2
00 – BRK 20 – JSR
01 – ORA – (Indirect, X) 21 – AND – (Indirect, X)
02 – Future Expansion 22 – Future Expansion
03 – Future Expansion 23 – Future Expansion
04 – Future Expansion 24 – BIT – Zero Page
05 – ORA – Zero Page 25 – AND – Zero Page
06 – ASL – Zero Page 26 – ROL – Zero Page
07 – Future Expansion 27 – Future Expansion
08 – PHP 28 – PLP
09 – ORA – Immediate 29 – AND – Immediate
0A – ASL – Accumulator 2A – ROL – Accumulator
0B – Future Expansion 2B – Future Expansion
0C – Future Expansion 2C – BIT – Absolute
0D – ORA – Absolute 2D – AND – Absolute
0E – ASL – Absolute 2E – ROL – Absolute
0F – Future Expansion 2F – Future Expansion
10 – BPL 30 – BMI
11 – ORA – (Indirect), Y 31 – AND – (Indirect), Y
12 – Future Expansion 32 – Future Expansion
13 – Future Expansion 33 – Future Expansion
14 – Future Expansion 34 – Future Expansion
15 – ORA – Zero Page, X 35 – AND – Zero Page, X
16 – ASL – Zero Page, X 36 – ROL – Zero Page, X
17 – Future Expansion 37 – Future Expansion
18 – CLC 38 – SEC
19 – ORA – Absolute, Y 39 – AND – Absolute, Y
1A – Future Expansion 3A – Future Expansion
1B – Future Expansion 3B – Future Expansion
1C – Future Expansion 3C – Future Expansion
1D – ORA – Absolute, X 3D – AND – Absolute, X
1E – ASL – Absolute, X 3E – ROL – Absolute, X
1F – Future Expansion 3F – Future Expansion
The secret is in the 6510 processor chip itself. On the chip is an input/output port.
This port is used to control whether RAM or ROM or I/O will appear in certain
portions of the system's memory. The port is also used to control the DatassetteTM,
so it is important to affect only the proper bits.
The 6510 input/output port appears at location 1. The data direction register
for this port appears at location 0. The port is controlled like any of the other
input/output ports in the system… the data direction controls whether a given
bit will be an input or an output, and the actual data transfer occurs through the
port itself.
BITS 5 4 3 2 1 0
1 0 1 1 1 1
The control lines, in general, perform the function given in their descriptions.
However, a combination of control lines are occasionally used to get a particular
memory configuration.
LORAM (bit 0) can generally be thought of as a control line which banks the 8K
byte BASIC ROM in and out of the microprocessor address space. Normally, this
line is HIGH for BASIC operation. If this line is programmed LOW, the BASIC
ROM will disappear from the memory map and be replaced by 8K bytes of
RAM from $A000 to $BFFF.
HIRAM (bit 1) can generally be thought of as a control line which banks the 8K
byte KERNAL ROM in and out of the microprocessor address space. Normally,
this line is HIGH for BASIC operation. If this line is programmed LOW, the
KERNAL ROM will disappear from the memory map and be replaced by 8K
bytes of RAM from $E000 to $FFFF.
CHAREN (bit 2) is used only to bank the 4K byte character generator ROM in
or out of the microprocessor address space. From the processor point of view,
the character ROM occupies the same address space as the I/O devices ($D000
to $DFFF). When the CHAREN line is set to 1 (as is normal), the I/O devices
appear in the microprocessor address space, and the character ROM is not
accessible. When the CHAREN bit is cleared to 0, the character ROM appears
in the processor address space, and the I/O devices are not accessible. (The
microprocessor only needs to access the character ROM when downloading the
character set from ROM to RAM. Special care is needed for this… see the section
on PROGRAMMABLE CHARACTERS in the GRAPHICS chapter). CHAREN can be
overridden by other control lines in certain memory configurations. CHAREN will
have no effect on any memory configuration without I/O devices. RAM will
appear from $D000 to $DFFF instead.
NOTE: In any memory map containing ROM, a WRITE (a POKE) to a ROM location will store data
in the RAM "under" the ROM. Writing to a ROM location stores data in the "hidden" RAM. For
example, this allows a hi-resolution screen to be kept underneath a ROM, and be changed without
having to bank the screen back into the processor address space. Of course a READ of a ROM
location will return the contents of the ROM, not the "hidden" RAM.
I/O BREAKDOWN
The following table lists the various memory configurations available on the
COMMODORE 64, the states of the control lines which select each memory map,
and the intended use of each map.
X = DON’T CARE
0 = LOW
1 = HIGH
LORAM =1
HIRAM =1
GAME =1
EXROM =1
LORAM =1
HIRAM =0
GAME =1
EXROM =X
OR
LORAM =1
HIRAM =0
GAME =0
(THE CHARACTER ROM IS NOT
ACCESSIBLE BY THE CPU IN THIS MAP)
EXROM =0
X = DON’T CARE
0 = LOW
1 = HIGH
LORAM =0
HIRAM =1
GAME =1
EXROM =X
LORAM =0
HIRAM =0
GAME =1
EXROM =X
OR
LORAM =0
HIRAM =0
GAME =X
EXROM =0
X = DON’T CARE
0 = LOW
1 = HIGH
LORAM =1
HIRAM =1
GAME =1
EXROM =0
LORAM =0
HIRAM =1
GAME =0
EXROM =0
X = DON’T CARE
0 = LOW
1 = HIGH
LORAM =1
HIRAM =1
GAME =0
EXROM =0
LORAM =X
HIRAM =X
GAME =0
EXROM =1
Essentially, the KERNAL is a standardized JUMP TABLE to the input, output, and
memory management routines in the operating system. The locations of each
routine in ROM may change as the system is upgraded. But the KERNAL jump
table will always be changed to match. If your machine language routines only
use the system ROM routines through the KERNAL, it will take much less work to
modify them, should that need ever arise.
The KERNAL is the operating system of the Commodore 64 computer. All input,
output, and memory management is controlled by the KERNAL.
To simplify the machine language programs you write, and to make sure that
future versions of the Commodore 64 operating system don't make your machine
language programs obsolete, the KERNAL contains a jump table for you to use.
By taking advantage of the 39 input/output routines and other utilities available
to you from the table, not only do you save time, you also make it easier to
translate your programs from one Commodore computer to another.
The jump table is located on the last page of memory, in read-only memory
(ROM).
To use the KERNAL jump table, first you set up the parameters that the KERNAL
routine needs to work. Then JSR (Jump to SubRoutine) to the proper place in the
KERNAL jump table. After performing its function, the KERNAL transfers control
back to your machine language program. Depending on which KERNAL routine
you are using, certain registers may pass parameters back to your program. The
particular registers for each KERNAL routine may be found in the individual
descriptions of the KERNAL subroutines.
1. On power-up, the KERNAL first resets the stack pointer, and clears
decimal mode.
2. The KERNAL then checks for the presence of an autostart ROM cartridge
at location $8000 HEX (32768 decimal). If this is present, normal
initialization is suspended, and control is transferred to the cartridge
code. If an autostart ROM is not present, normal system initialization
continues.
3. Next, the KERNAL initializes all INPUT/OUTPUT devices. The serial bus
is initialized. Both 6526 CIA chips are set to the proper values for
keyboard scanning, and the 60-Hz timer is activated. The SID chip is
cleared. The BASIC memory map is selected and the cassette motor is
switched off.
4. Next, the KERNAL performs a RAM test, setting the top and bottom of
memory pointers. Also, page zero is initialized, and the tape buffer is
set up.
5. Finally, the KERNAL performs these other activities. I/O vectors are set
to default values. The indirect jump table in low memory is established.
The screen is then cleared, and all screen editor variables reset. Then
the indirect at $A000 is used to start BASIC.
As mentioned before, the KERNAL is a jump table. This is just a collection of JMP
instructions to many operating system routines.
To use a KERNAL routine you must first make all of the preparations that the
routine demands. If one routine says that you must call another KERNAL routine
first, then that routine must be called. If the routine expects you to put a number
in the accumulator, then that number must be there. Otherwise your routines have
little chance of working the way you expect them to work.
After all preparations are made, you must call the routine by means of the JSR
instruction. All KERNAL routines you can access are structured as SUBROUTINES,
and must end with an RTS instruction. When the KERNAL routine has finished its
task, control is returned to your program at the instruction after the JSR.
Many of the KERNAL routines return error codes in the status word or the
accumulator if you have problems in the routine. Good programming practice
and the success of your machine language programs demand that you handle
this properly. If you ignore an error return, the rest of your program might
"bomb."
That's all there is to do when you're using the KERNAL. Just these three simple
steps:
1. Set up
2. Call the routine
3. Error handling
CALL ADDRESS: This is the call address of the KERNAL routine, given in
hexadecimal.
ERROR RETURNS: A return from a KERNAL routine with the CARRY set
indicates that an error was encountered in processing. The accumulator
will contain the number of the error.
ADDRESS
NAME FUNCTION
HEX DECIMAL
ACPTR $FFA5 65445 Input byte from serial port
CHKIN $FFC6 65478 Open channel for input
Description:
This is the routine to use when you want to get information from a device on
the serial bus, like a disk. This routine gets a byte of data off the serial bus
using full handshaking. The data is returned in the accumulator. To prepare
for this routine the TALK routine must be called first to command the device on
the serial bus to send data through the bus. If the input device needs a
secondary command, it must be sent by using the TKSA KERNAL routine before
calling this routine. Errors are returned in the status word. The READST routine
is used to read the status word.
How to Use:
EXAMPLE:
Description:
Any logical file that has already been opened by the KERNAL OPEN routine
can be defined as an input channel by this routine. Naturally, the device on
the channel must be an input device. Otherwise an error will occur, and the
routine will abort.
If you are getting data from anywhere other than the keyboard, this routine
must be called before using either the CHRIN or the GETIN KERNAL routines
for data input. If you want to use the input from the keyboard, and no other
input channels are opened, then the calls to this routine, and to the OPEN
routine are not needed.
When this routine is used with a device on the serial bus, it automatically sends
the talk address (and the secondary address if one was specified by the
OPEN routine) over the bus.
How to Use:
EXAMPLE:
Description:
Any logical file number that has been created by the KERNAL routine OPEN
can be defined as an output channel. Of course, the device you intend opening
a channel to must be an output device. Otherwise an error will occur, and the
routine will be aborted.
This routine must be called before any data is sent to any output device unless
you want to use the Commodore 64 screen as your output device. If screen
output is desired, and there are no other output channels already defined,
then calls to this routine, and to the OPEN routine are not needed.
When used to open a channel to a device on the serial bus, this routine will
automatically send the LISTEN address specified by the OPEN routine (and a
secondary address if there was one).
How to Use:
1. Use the KERNAL OPEN routine to specify a logical file number, a LISTEN
address, and a secondary address (if needed).
2. Load the .X register with the logical file number used in the open
statement.
3. Call this routine (by using the JSR instruction).
EXAMPLE:
Description:
This routine gets a byte of data from a channel already set up as the input
channel by the KERNAL routine CHKIN. If the CHKIN has NOT been used to
define another input channel, then all your data is expected from the
keyboard. The data byte is returned in the accumulator. The channel remains
open after the call.
Input from the keyboard is handled in a special way. First, the cursor is turned
on, and blinks until a carriage return is typed on the keyboard. All characters
on the line (up to 88 characters) are stored in the BASIC input buffer. These
characters can be retrieved one at a time by calling this routine once for each
character. When the carriage return is retrieved, the entire line has been
processed. The next time this routine is called, the whole process begins again,
i.e., by flashing the cursor.
How to Use:
EXAMPLE:
JSR CHRIN
STA DATA
EXAMPLE:
JSR CHRIN
STA DATA
Description:
NOTE: Care must be taken when using this routine to send data to a specific serial device
since data will be sent to all open output channels on the bus. Unless this is desired, all open
output channels on the serial bus other than the intended destination channel must be closed
by a call to the KERNAL CLRCHN routine.
EXAMPLE:
Description:
This routine is used to send information to devices on the serial bus. A call to
this routine will put a data byte onto the serial bus using full serial
handshaking. Before this routine is called, the LISTEN KERNAL routine must be
used to command a device on the serial bus to get ready to receive data. (If
a device needs a secondary address, it must also be sent by using the
SECOND KERNAL routine.) The accumulator is loaded with a byte to
handshake as data on the serial bus. A device must be listening or the status
word will return a timeout. This routine always buffers one character. (The
routine holds the previous character to be sent back.) So when a call to the
KERNAL UNLSN routine is made to end the data transmission, the buffered
character is sent with an End Or Identify (EOI) set. Then the UNLSN command
is sent to the device.
1. Use the LISTEN KERNAL routine (and the SECOND routine if needed).
2. Load the accumulator with a byte of data.
3. Call this routine to send the data byte.
EXAMPLE:
Description:
This routine sets up the 6567 video controller chip in the Commodore 64 for
normal operation. The KERNAL screen editor is also initialized. This routine
should be called by a Commodore 64 program cartridge.
How to Use:
EXAMPLE:
JSR CINT
JMP RUN ;BEGIN EXECUTION
Description:
This routine closes all open files. When this routine is called, the pointers into
the open file table are reset, closing all files. Also, the CLRCHN routine is
automatically called to reset the I/O channels.
How to Use:
EXAMPLE:
Description:
This routine is used to close a logical file after all I/O operations have been
completed on that file. This routine is called after the accumulator is loaded
with the logical file number to be closed (the same number used when the file
was opened using the OPEN routine).
1. Load the accumulator with the number of the logical file to be closed.
2. Call this routine.
EXAMPLE:
;CLOSE 15
LDA #15
JSR CLOSE
Description:
This routine is called to clear all open channels and restore the I/O channels
to their original default values. It is usually called after opening other I/O
channels (like a tape or disk drive) and using them for input/output operations.
The default input device is 0 (keyboard). The default output device is 3 (the
Commodore 64 screen).
How to Use:
EXAMPLE:
JSR CLRCHN
Description:
If the channel is the keyboard, this subroutine removes one character from the
keyboard queue and returns it as an ASCII value in the accumulator. If the
queue is empty, the value returned in the accumulator will be zero. Characters
are put into the queue automatically by an interrupt driven keyboard scan
routine which calls the SCNKEY routine. The keyboard buffer can hold up to
ten characters. After the buffer is filled, additional characters are ignored
until at least one character has been removed from the queue. If the channel
is RS-232, then only the .A register is used and a single character is returned.
See READST to check validity. If the channel is serial, cassette, or screen, call
BASIN routine.
How to Use:
EXAMPLE:
Description:
This routine sets the X and Y registers to the address of the memory section
where the memory mapped I/O devices are located. This address can then
be used with an offset to access the memory mapped I/O devices in the
Commodore 64. The offset is the number of locations from the beginning of
the page on which the I/O register you want is located. The .X register
contains the low order address byte, while the .Y register contains the high
order address byte.
This routine exists to provide compatibility between the Commodore 64, VIC-
20, and future models of the Commodore 64. If the I/O locations for a
machine language program are set by a call to this routine, they should still
remain compatible with future versions of the Commodore 64, the KERNAL
and BASIC.
How to Use:
EXAMPLE:
Description:
EXAMPLE:
JSR IOINIT
Description:
This routine will command a device on the serial bus to receive data. The
accumulator must be loaded with a device number between 0 and 31 before
calling the routine. LISTEN will OR the number bit by bit to convert to a listen
address, then transmits this data as a command on the serial bus. The specified
device will then go into listen mode, and be ready to accept information.
How to Use:
1. Load the accumulator with the number of the device to command to LISTEN.
2. Call this routine using the JSR instruction.
EXAMPLE:
Description:
This routine LOADs data bytes from any input device directly into the memory
of the Commodore 64. It can also be used for a verify operation, comparing
data from a device with the data already in memory, while leaving the data
stored in RAM unchanged.
The accumulator (.A) must be set to 0 for a LOAD operation, or 1 for a verify.
If the input device is OPENed with a secondary address (SA) of 0 the header
information from the device is ignored. In this case, the .X and .Y registers must
contain the starting address for the load. If the device is addressed with a
secondary address of 1, then the data is loaded into memory starting at the
location specified by the header. This routine returns the address of the highest
RAM location loaded.
Before this routine can be called, the KERNAL SETLFS, and SETNAM routines
must be called.
NOTE: You can NOT LOAD from the keyboard (0), RS-232 (2), or the screen (3).
How to Use:
1. Call the SETLFS, and SETNAM routines. If a relocated load is desired, use
the SETLFS routine to send a secondary address of 0.
2. Set the .A register to 0 for load, 1 for verify.
3. If a relocated load is desired, the .X and .Y registers must be set to the
start address for the load.
4. Call the routine using the JSR instruction.
Description:
This routine is used to set the bottom of the memory. If the accumulator carry
bit is set when this routine is called, a pointer to the lowest byte of RAM is
returned in the .X and .Y registers. On the unexpanded Commodore 64 the
initial value of this pointer is $0800 (2048 in decimal). If the accumulator
carry bit is clear (=0) when this routine is called, the values of the .X and .Y
registers are transferred to the low and high bytes, respectively, of the
pointer to the beginning of RAM.
EXAMPLE:
Description:
This routine is used to set the top of RAM. When this routine is called with the
carry bit of the accumulator set, the pointer to the top of RAM will be loaded
into the .X and .Y registers. When this routine is called with the accumulator
carry bit clear, the contents of the .X and .Y registers are loaded in the top
of memory pointer, changing the top of memory.
EXAMPLE:
Description:
This routine is used to OPEN a logical file. Once the logical file is set up, it can
be used for input/output operations. Most of the I/O KERNAL routines call on
this routine to create the logical files to operate on. No arguments need to be
set up to use this routine, but both the SETLFS and SETNAM KERNAL routines
must be called before using this routine.
How to Use:
EXAMPLE:
Description:
A call to this routine with the accumulator carry flag set loads the current
position of the cursor on the screen (in X, Y coordinates) into the .Y and .X
registers. Y is the column number of the cursor location (0 to 39), and X is the
row number of the location of the cursor (0 to 24). A call with the carry bit
clear moves the cursor to X, Y as determined by the .Y and .X registers.
How to Use:
EXAMPLE:
Description:
This routine is used to test RAM and set the top and bottom of memory pointers
accordingly. It also clears locations $0000 to $0101 and $0200 to $03FF. It
also allocates the cassette buffer, and sets the screen base to $0400.
Normally, this routine is called as part of the initialization process of a
Commodore 64 program cartridge.
EXAMPLE:
JSR RAMTAS
Description:
This routine is used to read the system clock. The clock's resolution is a 60th of
a second. Three bytes are returned by the routine. The accumulator contains
the most significant byte, the X index register contains the next most significant
byte, and the Y index register contains the least significant byte.
EXAMPLE:
JSR RDTIM
STY TIME
STX TIME+1
STA TIME+2
...
TIME *=*+3
Description:
This routine returns the current status of the I/O devices in the accumulator.
The routine is usually called after new communication to an I/O device. The
routine gives you information about device status, or errors that have occurred
during the I/O operation.
The bits returned in the accumulator contain the following information: (see
table below)
ST TAPE
ST BIT CASSETTE
NUMERIC SERIAL R/W VERIFY +
POSITION READ
VALUE LOAD
0 1 Time out
write
1 2 Time out
read
2 4 Short block Short block
3 8 Long block Long block
4 16 Unrecoverable Any
read error mismatch
5 32 Checksum Checksum
error error
6 64 End of file EOI line
7 –128 End of tape Device not End of tape
present
EXAMPLE:
Description:
This routine restores the default values of all system vectors used in KERNAL
and BASIC routines and interrupts. (See the Memory Map for the default
vector contents). The KERNAL VECTOR routine is used to read and alter
individual system vectors
How to Use:
EXAMPLE:
JSR RESTOR
NOTE: Device 0 (the keyboard), device 2 (RS-232), and device 3 (the screen) cannot be
SAVEd to. If the attempt is made, an error occurs, and the SAVE is stopped.
How to Use:
1. Use the SETLFS routine and the SETNAM routine (unless a SAVE with no
file name is desired on "a save to the tape recorder").
2. Load two consecutive locations on page 0 with a pointer to the start of
your save (in standard 6502 low byte first, high byte next format).
3. Load the accumulator with the single byte page zero offset to the pointer.
4. Load the .X and .Y registers with the low byte and high byte respectively
of the location of the end of the save.
5. Call this routine.
EXAMPLE:
Description:
This routine scans the Commodore 64 keyboard and checks for pressed keys.
It is the same routine called by the interrupt handler. If a key is down, its ASCII
value is placed in the keyboard queue. This routine is called only if the normal
IRQ interrupt is bypassed.
How to Use:
EXAMPLE:
Description:
This routine returns the format of the screen, e.g., 40 columns in .X and 25 lines
in .Y. The routine can be used to determine what machine a program is running
on. This function has been implemented on the Commodore 64 to help upward
compatibility of your programs.
EXAMPLE:
JSR SCREEN
STX MAXCOL
STY MAXROW
Description:
This routine is used to send a secondary address to an I/O device after a call
to the LISTEN routine is made, and the device is commanded to LISTEN. The
routine can NOT be used to send a secondary address after a call to the TALK
routine.
How to Use:
EXAMPLE:
Description:
This routine sets the logical file number, device address, and secondary
address (command number) for other KERNAL routines.
The logical file number is used by the system as a key to the file table created
by the OPEN file routine. Device addresses can range from 0 to 31. The
following codes are used by the Commodore 64 to stand for the CBM devices
listed below:
ADDRESS DEVICE
0 Keyboard
1 Datasette™ #1
2 RS-232C device
3 CRT display
4 Serial bus printer
8 CBM serial bus disk drive
How to Use:
Description:
This routine controls the printing of error and control messages by the KERNAL.
Either print error messages or print control messages can be selected by
setting the accumulator when the routine is called. FILE NOT FOUND is an
example of an error message. PRESS PLAY ON CASSETTE is an example of
a control message.
Bits 6 and 7 of this value determine where the message will come from. If bit
7 is 1, one of the error messages from the KERNAL is printed. If bit 6 is set,
control messages are printed.
How to Use:
EXAMPLE:
LDA #$40
JSR SETMSG ;TURN ON CONTROL MESSAGES
LDA #$80
JSR SETMSG ;TURN ON ERROR MESSAGES
LDA #0
JSR SETMSG ;TURN OFF ALL KERNAL MESSAGES
Description:
This routine is used to set up the file name for the OPEN, SAVE, or LOAD
routines. The accumulator must be loaded with the length of the file name. The
.X and .Y registers must be loaded with the address of the file name, in
standard 6502 low-byte/high-byte format. The address can be any valid
memory address in the system where a string of characters for the file name
is stored. If no file name is desired, the accumulator must be set to 0,
representing a zero file length. The .X and .Y registers can be set to any
memory address in that case.
How to Use:
EXAMPLE:
How to Use:
1. Load the accumulator with the MSB of the 3-byte number to set the clock.
2. Load the .X register with the next byte.
3. Load the .Y register with the LSB.
4. Call this routine.
EXAMPLE:
Description:
This routine sets the timeout flag for the IEEE bus. When the timeout flag is set,
the Commodore 64 will wait for a device on the IEEE port for 64 milliseconds.
If the device does not respond to the Commodore 64's Data Address Valid
(DAV) signal within that time the Commodore 64 will recognize an error
condition and leave the handshake sequence. When this routine is called when
the accumulator contains a 0 in bit 7, timeouts are enabled. A 1 in bit 7 will
disable the timeouts.
How to Use:
EXAMPLE:
;DISABLE TIMEOUT
LDA #0
JSR SETTMO
Description:
If the STOP key on the keyboard was pressed during a UDTIM call, this call
returns the Z flag set. In addition, the channels will be reset to default values.
All other flags remain unchanged. If the STOP key is not pressed then the
accumulator will contain a byte representing the lost row of the keyboard
scan. The user can also check for certain other keys this way.
How to Use:
Description:
To use this routine the accumulator must first be loaded with a device number
between 0 and 31. When called, this routine then ORs bit by bit to convert
this device number to a talk address. Then this data is transmitted as a
command on the serial bus.
How to Use:
EXAMPLE:
This routine transmits a secondary address on the serial bus for a TALK device.
This routine must be called with a number between 0 and 31 in the
accumulator. The routine sends this number as a secondary address command
over the serial bus. This routine can only be called after a call to the TALK
routine. It will not work after a LISTEN.
How to Use:
EXAMPLE:
Description:
This routine updates the system clock. Normally this routine is called by the
normal KERNAL interrupt routine every 1/60th of a second. If the user
program processes its own interrupts this routine must be called to update the
time. In addition, the STOP key routine must be called, if the STOP key is to
remain functional.
How to Use:
EXAMPLE:
JSR UDTIM
Description:
This routine commands all devices on the serial bus to stop receiving data from
the Commodore 64 (i.e., UNLISTEN). Calling this routine results in an UNLISTEN
command being transmitted on the serial bus. Only devices previously
commanded to listen are affected. This routine is normally used after the
Commodore 64 is finished sending data to external devices. Sending the
UNLISTEN commands the listening devices to get off the serial bus so it can be
used for other purposes.
How to Use:
1. Call this routine.
EXAMPLE:
JSR UNLSN
Description:
This routine transmits an UNTALK command on the serial bus. All devices
previously set to TALK will stop sending data when this command is received.
How to Use:
1. Call this routine.
EXAMPLE:
JSR UNTLK
Description:
This routine manages all system vector jump addresses stored in RAM. Calling
this routine with the accumulator carry bit set stores the current contents of the
RAM vectors in a list pointed to by the X and Y registers. When this routine is
called with the carry clear, the user list pointed to by the X and Y registers is
transferred to the system RAM vectors. The RAM vectors are listed in the
memory map.
NOTE: This routine requires caution in its use. The best way to use it is to first read the entire
vector contents into the user area, alter the desired vectors, and then copy the contents back
to the system vectors.
How to Use:
ERROR CODES
The following is a list of error messages which can occur when using the KERNAL
routines. If an error occurs during a KERNAL routine, the carry bit of the
accumulator is set, and the number of the error message is returned in the
accumulator.
NOTE: Some KERNAL I/O routines do not use these codes for error messages. Instead, errors are
identified using the KERNAL READST routine.
NUMBER MEANING
0 Routine terminated by the STOP key
1 Too many open files
2 File already open
3 File not open
4 File not found
5 Device not present
6 File is not an input file
7 File is not an output file
8 File name is missing
9 Illegal device number
240 Top-of-memory change RS-232 buffer allocation/deallocation
The SYS command is the most useful method of combining BASIC with
machine language. PEEKs and POKEs make multiple parameter passing
easy. There can be many SYS statements in a program, each to a
different (or even the same) machine language routine.
This statement is different from the SYS, because you have to set up an
indirect vector. Also different is the format through which the variable
is passed (floating point format). The indirect vector must be changed
if more than one machine language routine is used.
The KERNAL VECTOR routine is the most reliable way to change any
of the vectors, but a single vector can be changed by POKEs. A new
vector will point to a user prepared routine which is meant to replace
or augment the standard system routine. When the appropriate BASIC
command is executed, the user routine will be executed. If after
executing the user routine, it is necessary to execute the normal system
routine, the user program must JMP (JuMP) to the address formerly
contained in the vector. If not, the routine must end with a RTS to transfer
control back to BASIC.
This method is useful for tasks which must happen concurrently with a
BASIC program, but has the drawback of being more difficult.
The best place for machine language routines on the Commodore 64 is from
$C000 – $CFFF, assuming the routines are smaller than 4K bytes long. This
section of memory is not disturbed by BASIC.
If for some reason it's not possible or desirable to put the machine language
routine at $C000, for instance if the routine is larger than 4K bytes, it then
becomes necessary to reserve an area at the top of memory from BASIC for the
routine. The top of memory is normally $9FFF. The top of memory can be
changed through the KERNAL routine MEMTOP, or by the following BASIC
statements:
10 POKE51,L:POKE52,H:POKE55,L:POKE56,H:CLR
Where H and L are the high and low portions, respectively, of the new top of
memory. For example, to reserve the area from $9000 to $9FFF for machine
language, use the following:
10 POKE51,0:POKE52,144:POKE55,0:POKE56,144:CLR
There are 3 common methods to add the machine language programs to a BASIC
program. They are:
1. DATA STATEMENTS:
By READing DATA statements, and POKEing the values into memory at the start
of the program, machine language routines can be added. This is the easiest
method. No special methods are needed to save the two parts of the program,
and it is fairly easy to debug. The drawbacks include taking up more memory
space, and the wait while the program is POKEd in. Therefore, this method is
better for smaller routines.
EXAMPLE:
10 RESTORE:FORX=1T09:READA:POKE12*4096+X,A:NEXT
.
.
.
BASIC PROGRAM
.
.
.
1000 DATA 161,1,204,204,204,204,204,204,96
This program allows you to enter a program in either HEX or SYMBOLIC codes,
and save the portion of memory the program is in. Advantages of this method
include easier entry of the machine language routines, debugging aids, and a
much faster means of saving and loading. The drawback to this method is that it
generally requires the BASIC program to load the machine language routine
from tape or disk when it is started. (For more details on 64MON see the machine
language section.)
EXAMPLE:
10 IF FLAG=1 THEN 20
15 FLAG=1:LOAD"MACHINE LANGUAGE ROUTINE NAME",1,1
20
.
.
.
REST OF BASIC PROGRAM
3. EDITOR/ASSEMBLER PACKAGE:
Advantages are similar to using a machine language monitor, but programs are
even easier to enter. Disadvantages are also similar to the use of a machine
language monitor.
HEX DECIMAL
LABEL DESCRIPTION
ADDRESS LOCATION
D6510 0000 0 6510 On-Chip Data-Direction
Register
R6510 0001 1 6510 On-Chip 8-Bit
Input/Output Register
0002 2 Unused
ADRAY1 0003–0004 3–4 Jump Vector: Convert
Floating-Integer
0 Timer A Interrupt
7 Set Alarm/TOD-Clock: 1 =
Alarm, 0 = Clock
5 User
1 Timer B Interrupt
0 Timer A Interrupt
7 Set Alarm/TOD-Clock: 1 =
Alarm, 0 = Clock
Communication is the most complex, because it involves the least exacting set of
rules. This is not an oversight in the design of computers. The rules allow enough
flexibility to communicate virtually anything, and in many possible ways. The only
real rule is this: whatever sends information must present the information so that
it can be understood by the receiver.
OUTPUT TO THE TV
The simplest form of output in BASIC is the PRINT statement. PRINT uses the TV
screen as the output device, and your eyes are the input device because they
use the information on the screen.
When PRINTing on the screen, your main objective is to format the information
on the screen so it's easy to read. You should try to think like a graphic artist,
using colors, placement of letters, capital and lower case letters, as well as
graphics to best communicate the information. Remember, no matter how smart
your program, you want to be able to understand what the results mean to you.
The PRINT statement uses certain character codes as "commands" to the cursor.
The CRSR key doesn't actually display anything, it just makes the cursor change
position. Other commands change colors, clear the screen, and insert or delete
spaces. The RETURN key has a character code number (CHR$) of 13. A complete
table of these codes is contained in Appendix C.
There are two functions in the BASIC language that work with the PRINT
statement. TAB positions the cursor on the given position from the left edge of
the screen, SPC moves the cursor right a given number of spaces from the current
position.
The quote marks (" ") separate literal text from variables. The first quote mark
on the line starts the literal area, and the next quote mark ends it. By the way,
you don't have to have a final quote mark at the end of the line.
The RETURN code (CHR$ code of 13) makes the cursor go to the next logical line
on the screen. This is not always the very next line. When you type past the end
of a line, that line is linked to the next line. The computer knows that both lines
are really one long line. The links are held in the line link table (see the memory
map for how this is set up).
A logical line can be 1 or 2 screen lines long, depending on what was typed or
PRINTed. The logical line the cursor is on determines where the RETURN key
sends it. The logical line at the top of the screen determines if the screen scrolls
1 or 2 lines at a time.
There are other ways to use the TV as an output device. The chapter on graphics
describes the commands to create objects that move across the screen. The VIC
chip section tells how the screen and border colors and sizes are changed. And
the sound chapter tells how the TV speaker creates music and special effects.
OUTPUT TO PRINTER
The printer is an output device similar to the screen. Your main concern when
sending output to the printer is to create a format that is easy on the eyes. Your
tools here include reversed, double-width, capital and lower case letters, as well
as dot-programmable graphics.
The SPC function works for the printer in the same way it works for the screen.
However, the TAB function does not work correctly on the printer, because it
calculates the current position on the line based on the cursor's position on the
screen, not on the paper.
The OPEN statement for the printer creates the channel for communication. It also
specifies which character set will be used, either upper case with graphics or
upper and lower case.
Other special functions in the printer are controlled through character codes. All
these codes are simply PRINTed just like any other character.
See your Commodore printer's manual for details on using the command codes.
OUTPUT TO MODEM
The modem is a simple device that can translate character codes into audio
pulses and vice-versa, so that computers can communicate over telephone lines.
The OPEN statement for the modem sets up the parameters to match the speed
and format of the other computer you are communicating with. Two characters
can be sent in the string at the end of the OPEN statement.
The bit positions of the first character code determine the baud rate, number of
data bits, and number of stop bits. The second code is optional, and its bits
specify the parity and duplex of the transmission. See the RS-232 section or your
VICMODEM manual for specific details on this device.
Most computers use the American Standard Code for Information Interchange,
known as ASCII (pronounced ASK-KEY). This standard set of character codes is
somewhat different from the codes used in the Commodore 64. When
communicating with other computers, the Commodore character codes must be
translated into their ASCII counterparts. A table of standard ASCII codes is
included in this book in Appendix C.
Output to the modem is a fairly uncomplicated task, aside from the need for
character translation. However, you must know the receiving device fairly well,
especially when writing programs where your computer "talks" to another
computer without human intervention. An example of this would be a terminal
program that automatically types in your account number and secret password.
To do this successfully, you must carefully count the number of characters and
RETURN characters. Otherwise, the computer receiving the characters won't know
what to do with them.
Cassette tapes have an almost unlimited capacity for data. The longer the tape,
the more information it can store. However, tapes are limited in time. The more
data on the tape, the longer the time it takes to find the information.
The programmer must try to minimize the time factor when working with tape
storage. One common practice is to read the entire cassette data file into RAM,
then process it, and then re-write all the data on the tape. This allows you to sort,
edit, and examine your data. However, this limits the size of your files to the
amount of available RAM.
If your data file is larger than the available RAM, it is probably time to switch
to using the floppy disk. The disk can read data at any position on the disk,
without needing to read through all the other data. You can write data over old
data without disturbing the rest of the file. That's why the disk is used for all
business applications like ledgers and mailing lists.
The PRINT# statement formats data just like the PRINT statement does. All
punctuation works the same. But remember, you're not working with the screen
now. The formatting must be done with the INPUT# statement constantly in mind.
Even worse is what happens when the INPUT# statement tries to read these
strings. The statement INPUT# 1, A$, B$, C$ will discover no data for B$ and
C$. A$ will contain all three variables, plus the spaces between them. What
happens? Here's a look at the tape file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
D O G C A T T R E E RETURN
The INPUT# statement works like the regular INPUT statement. When typing
data into the INPUT statement, the data items are separated, either by hitting
the RETURN key or using commas to separate them. The PRINT# statement puts
a RETURN at the end of a line just like the PRINT statement. A$ fills up with all
three values because there's no separator on the tape between them, only after
all three.
A proper separator would be a comma (,) or a RETURN on the tape. The RETURN
code is automatically put at the end of a PRINT or PRINT# statement. One way
to put the RETURN code between each item is to use only one item per PRINT#
statement. A better way is to set a variable to the RETURN CHR$ code, which is
CHR$(13), or use a comma. The statement for this is R$=",":PRINT# 1, A$ R$ B$
R$ C$. Don't use commas or any other punctuation between the variable names,
since the Commodore 64 can tell them apart and they'll only use up space in
your program.
1 2 3 4 5 6 7 8 9 10 11 12 13
D O G , C A T , T R E E RETURN
The GET# statement will pick data from the tape one character at a time. It will
receive each character, including the RETURN code and other punctuation. The
CHR$(0) code is received as an empty string, not as a one character string with
a code of 0. If you try to use the ASC function on an empty string, you get the
error message ?ILLEGAL QUANTITY ERROR.
Diskettes allow 3 different forms of data storage. Sequential files are similar to
those on tape, but several can be used at the same time. Relative files let you
organize the data into records, and then read and replace individual records
within the file. Random files let you work with data anywhere on the disk. They
are organized into 256 byte sections called blocks.
The PRINT# statement's limitations are discussed in the section on cassette tape.
The same limitations to format apply on the disk. RETURNs or commas are needed
to separate your data. The CHR$(0) is still read by the GET# statement as an
empty string.
Relative and random files both make use of separate data and command
"channels." Data written to the disk goes through the data channel, where it is
stored in a temporary buffer in the disk's RAM. When the record or block is
complete, a command is sent through the command channel that tells the drive
where to put the data, and the entire buffer is written.
Applications that require large amounts of data to be processed are best stored
in relative disk files. These will use the least amount of time and provide the best
flexibility for the programmer. Your disk drive manual gives a complete
programming guide to use of disk files.
A digital joystick has five distinct switches, four of the switches are used for
direction and one of the switches is used for the fire button. The joystick switches
are arranged as shown:
These switches correspond to the lower 5 bits of the data in location 56320 or
56321. Normally the bit is set to a one if a direction is NOT chosen or the fire
button is NOT pressed. When the fire button is pressed, the bit (bit 4 in this case)
changes to a 0. To read the joystick from BASIC, the following subroutine should
be used:
JV EQUAL TO DIRECTION
0 NONE
1 UP
2 DOWN
3 –
4 LEFT
5 UP & LEFT
6 DOWN & LEFT
7 –
8 RIGHT
9 UP & RIGHT
10 DOWN & RIGHT
A paddle is connected to both CIA #1 and the SID chip (MOS 6581 Sound
Interface Device) through a game port. The paddle value is read via the SID
registers 54297 ($D419) and 54298 ($D41A). PADDLES ARE NOT RELIABLE
WHEN READ FROM BASIC ALONE!!!! The best way to use paddles, from BASIC
or machine code, is to use the following machine language routine... (SYS to it
from BASIC then PEEK the memory locations used by the subroutine).
1000 ;*****************************************************
1010 ;* FOUR PADDLE READ ROUTINE (CAN ALSO BE USED FOR TWO)
1020 ;*****************************************************
1030 ;AUTHOR - BILL HINDORFF
1040 PORTA=$DC00
1050 CIDDRA=$DC02
1060 SID=$D400
1070 *=$C100
1080 BUFFER *=*+1
1090 PDLX *=*+2
1100 PDLY *=*+2
1110 BTNA *=*+1
1120 BTNB *=*+1
1130 * = $C000
1140 PDLRD
1150 LDX #1 ; FOR FOUR PADDLES OR TWO ANALOG
JOYSTICKS
1160 PDLRD0 ; ENTRY POINT FOR ONE PAIR (CONDITION X
1ST)
1170 SEI
1180 LDA CIDDRA ; GET CURRENT VALUE OF DDR
1190 STA BUFFER ; SAVE IT AWAY
1200 LDA #$C0
1210 STA CIDDRA ; SET PORT A FOR INPUT
1220 LDA #$80
1230 PDLRD1
1240 STA PORTA ; ADDRESS A PAIR OF PADDLES
1250 LDY #$80 ; WAIT A WHILE
1260 PDLRD2
1270 NOP
1280 DEY
1290 BPL PDLRD2
1300 LDA SID+25 ; GET X VALUE
1310 STA PDLX,X
1320 LDA SID+26
1330 STA PDLY,X ; GET Y VALUE
SHIFT CLR/HOME
The light pen input latches the current screen position into a pair of registers (LPX,
LPY) on a low-going edge. The X position register 19 ($13) will contain the 8
MSB of the X position at the time of transition. Since the X position is defined by
a 512-state counter (9 bits), resolution to 2 horizontal dots is provided. Similarly,
the Y position is latched in its register 20 ($14), but here 8 bits provide single
raster resolution within the visible display. The light pen latch may be triggered
only once per frame, and subsequent triggers within the same frame will have
no effect. Therefore, you must take several samples before turning the pen to
the screen (3 or more samples average), depending upon the characteristics of
your light pen.
GENERAL OUTLINE
The Commodore 64 has a built-in RS-232 interface for connection to any RS-
232 modem, printer, or other device. To connect a device to the Commodore 64,
all you need is a cable and a little bit of programming.
RS-232 on the Commodore 64 is set-up in the standard RS-232 format, but the
voltages are TTL levels (0 to 5V) rather than the normal RS-232 –12 to 12 volt
range. The cable between the Commodore 64 and the RS-232 device should
take care of the necessary voltage conversions. The Commodore RS-232
interface cartridge handles this properly.
The RS-232 interface software can be accessed from BASIC or from the KERNAL
for machine language programming.
RS-232 on the BASIC level uses the normal BASIC commands: OPEN, CLOSE,
CMD, INPUT#, GET#, PRINT#, and the reserved variable ST. INPUT# and GET#
fetch data from the receiving buffer, while PRINT# and CMD place data into the
transmitting buffer. The use of these commands (and examples) will be described
in more detail later in this chapter.
The RS-232 KERNAL byte and bit level handlers run under the control of the
6526 CIA #2 device timers and interrupts. The 6526 chip generates NMI (Non-
Maskable Interrupt) requests for RS-232 processing. This allows background RS-
There are two buffers in the Commodore 64 RS-232 interface to help prevent
the loss of data when transmitting or receiving RS-232 information.
Only one RS-232 channel should be open at any time; a second OPEN statement
will cause the buffer pointers to be reset. Any characters in either the transmit
buffer or the receive buffer will be lost.
Up to 4 characters can be sent in the filename field. The first two are the control
and command register characters; the other two are reserved for future system
options. Baud rate, parity, and other options can be selected through this feature.
BASIC SYNTAX:
lfn – The logical file number (lfn) then can be any number from 1 through 255.
But be aware of the fact that if you choose a logical file number that is greater
than 127, then a line feed will follow all carriage returns.
<control register> – Is a single byte character (see Figure 6-1, Control Register
Map) required to specify the baud rates. If the lower 4 bits of the baud rate is
equal to zero (0), the <opt baud low><opt baud high> characters give you a
rate based on the following:
IMPORTANT NOTE: In a BASIC program, the RS-232 OPEN command should be performed
before creating any variables or arrays because an automatic CLR is performed when an RS-
232 channel is OPENed (This is due to the allocation of 512 bytes at the top of memory.) Also
remember that your program will be destroyed if 512 bytes of space are not available at the
time of the OPEN statement.
When getting data from an RS-232 channel, the Commodore 64 receiver buffer
will hold up to 255 characters before the buffer overflows. This is indicated in
the RS-232 status word (ST in BASIC, or RSSTAT in machine language). If an
overflow occurs, then all characters received during a full buffer condition, from
that point on, are lost. Obviously, it pays to keep the buffer as clear as possible.
If you wish to receive RS-232 data at high speeds (BASIC can only go so fast,
especially considering garbage collects. This can cause the receiver buffer to
overflow), you will have to use machine language routines to handle this type of
data burst.
BASIC SYNTAX:
KERNAL ENTRIES:
CHKIN ($FFC6) – See Memory Map for more information on entry and exit
conditions.
GETIN ($FFE4) – See Memory Map for more information on entry and exit
conditions.
CHRIN ($FFCF) – See Memory Map for more information on entry and exit
conditions.
If the word length is less than 8 bits, all unused bit(s) will be assigned a value of zero.
If a GET# does not find any data in the buffer, the character “” (a null) is returned.
If INPUT# is used, then the system will hang in a waiting condition until a non-null character and
a following carriage return is received. Therefore, if the Clear To Send (CTS) or DataSette Ready
(DSR) line(s) disappear during character INPUT#, the system will hang in a RESTORE-only state.
This is why the INPUT# and CHRIN routines are NOT recommended.
The routine CHKIN handles the x-line handshake which follows the EIA standard (August 1979)
for RS-232-C interfaces. (The Request To Send (RTS), CTS, and Received line signal (DCD) lines
are implemented with the Commodore 64 computer defined as the Data Terminal device.)
When sending data, the output buffer can hold 255 characters before a full
buffer hold-off occurs. The system will wait in the CHROUT routine until
transmission is allowed or the RUN/STOP and RESTORE keys are used to recover
the system through a WARM START.
BASIC SYNTAX:
KERNAL ENTRIES:
The routine CHKOUT handles the x-line handshake, which follows the EIA standard (August 1979)
for RS-232-C interfaces. The RTS, CTS, and DCD lines are implemented with the Commodore 64
defined as the Data Terminal Device.
Closing an RS-232 file discards all data in the buffers at the time of execution
(whether or not it had been transmitted or printed out), stops all RS-232
transmitting and receiving, sets the RTS and transmitted data (Sout) lines high,
and removes both RS-232 buffers.
BASIC SYNTAX:
CLOSE lfn
KERNAL ENTRY:
CLOSE ($FFC3) – See Memory Map for more information on entry and exit
conditions.
NOTE: Care should be taken to ensure all data is transmitted before closing the channel. A way
to check this from BASIC is:
[7] [6] [5] [4] [3] [2] [1] [0] (Machine Language – RSSTAT)
: : : : : : : : PARITY ERROR BIT
: : : : : : : FRAMING ERROR BIT
: : : : : : RECEIVER BUFFER OVERRUN BIT
: : : : : RECEIVER BUFFER – EMPTY
(USE TO TEST AFTER A GET#)
: : : : CTS SIGNAL MISSING BIT
: : : UNUSED BIT
: : DSR SIGNAL MISSING BIT
: BREAK DETECTED BIT
The RS-232 status register can be read from BASIC using the variable ST.
If ST is read by BASIC or by using the KERNAL READST routine the RS-232 status word is cleared
when you exit. If multiple uses of the STATUS word are necessary the ST should be assigned to
another variable. For example:
The RS-232 status is read (and cleared) only when the RS-232 channel was the last external I/O
used.
The two locations above are set up by the OPEN KERNAL routine, each pointing
to a different 256-byte buffer. They are de-allocated by writing a zero into the
high order bytes ($00F8 and $00FA), which is done by the CLOSE KERNAL entry.
They may also be allocated/de-allocated by the machine language
programmer for his/her own purposes, removing/creating only the buffer(s)
required. When using a machine language program that allocates these buffers,
care must be taken to make sure that the top of memory pointers stay correct,
especially if BASIC programs are expected to run at the same time.
All the above zero-page locations are used locally and are only given as a
guide to understand the associated routines. These cannot be used directly by
the BASIC or KERNAL level programmer to do RS-232 type things. The system
RS-232 routines must be used.
$0295–M51AJB – Two bytes following the control and command registers in the
file name field. These locations contain the baud rate for the
start of the bit test during the interface activity, which, in turn,
is used to calculate baud rate.
$0299–BAUDOF – Two bytes that are equal to the time of one bit cell. (Based
on system clock/baud rate.)
$029C–RIDBS – The byte index to the start of the receiver FIFO buffer.
$029D–RODBS – The byte index to the start of the transmitter FIFO buffer.
$029E–RODBE – The byte index to the end of the transmitter FIFO buffer.
$02A1–ENABL – Holds current active interrupts in the CIA #2 ICR. When bit 4
is turned on means that the system is waiting for the Receiver
Edge. When bit 1 is turned on then the system is receiving
data. When bit 0 is turned on then the system is transmitting
data.
The port on the Commodore 64 is directly connected to one of the 6526 CIA
chips. By programming, the CIA will connect to many other devices.
BOTTOM SIDE
BIT #: 7 6 5 4 3 2 1 0
VALUE: 0 0 1 1 1 0 0 0
You can see that lines 5, 4 and 3 will be outputs since those bits are ones. The
rest of the lines will be inputs, since those lines are zeros.
To PEEK or POKE the USER port, it is necessary to use both the DDR and the PORT
itself.
Remember that the PEEK and POKE statements want a number from 0–255. The
numbers given in the example must be translated into decimal before they can
be used. The value would be:
25 + 24 + 23 = 32 + 16 + 8 = 56
Notice that the bit # for the DDR is the same number that = 2 raised to a power
to turn the bit value on.
The two other lines, FLAG1 and PA2 are different from the rest of the USER
PORT. These two lines are mainly for HANDSHAKING, and are programmed
differently from port B.
Handshaking is needed when two devices communicate. Since one device may
run at a different speed than another device it is necessary to give the devices
some way of knowing what the other device is doing. Even when the devices are
operating at the same speed, handshaking is necessary to let the other know
when data is to be sent, and if it has been received. The FLAG1 line has special
characteristics which make it well suited for handshaking.
PA2 is bit 2 of PORT A of the CIA. It is controlled like any other bit in the port.
The port is located at 56576 ($DD00). The data direction register is located at
56578 ($DD02.)
There are three types of operation over a serial bus: CONTROL, TALK, and
LISTEN. A CONTROLLER device is one which controls operation of the serial bus.
A TALKER transmits data onto the bus. A LISTENER receives data from the bus.
The Commodore 64 is the controller of the bus. It also acts as a TALKER (when
sending data to the printer, for example) and as a LISTENER (when loading a
program from the disk drive, for example). Other devices may be either
LISTENERS (the printer), TALKERS, or both (the disk drive). Only the Commodore
64 can act as the controller.
All devices connected on the serial bus will receive all the data transmitted over
the bus. To allow the Commodore 64 to route data to its intended destination,
each device has a bus ADDRESS. By using this device address, the Commodore
64 can control access to the bus. Addresses on the serial bus range from 4 to 31.
Other device addresses are possible. Each device has its own address. Certain
devices (like the Commodore 64 printer) provide a choice between two
addresses for the convenience of the user.
OPEN 1,4,7
where:
1 is the logical file number (the number you PRINT# to),
4 is the ADDRESS of the printer, and
7 is the SECONDARY ADDRESS that tells the printer to go into UPPER/LOWER
case mode.
There are 6 lines used in serial bus operation – 3 input and 3 output. The 3 input
lines bring data, control, and timing signals into the Commodore 64. The 3 output
lines send data, control, and timing signals from the Commodore 64 to external
devices on the serial bus.
PIN DESCRIPTION
1 SERIAL SRQ IN
2 GND
3 SERIAL ATN IN/OUT
4 SERIAL CLK IN/OUT
5 SERIAL DATA IN/OUT
6 NO CONNECTION
Any device on the serial bus can bring this signal LOW when it requires attention
from the Commodore 64. The Commodore 64 will then take care of the device.
(See Figure 6-4).
The Commodore 64 uses this signal to start a command sequence for a device
on the serial bus. When the Commodore 64 brings this signal LOW, all other
devices on the bus start listening for the Commodore 64 to transmit an address.
The device addressed must respond in a preset period of time; otherwise, the
Commodore 64 will assume that the device addressed is not on the bus, and will
return an error in the STATUS WORD. (See Figure 6-4).
BUS TIMING.
This signal is used for timing the data sent on the serial bus (See Figure 6-4).
Data on the serial bus is transmitted one bit at a time on this line (See Figure 6-
4).
This port is used for expansions of the Commodore 64 system which require
access to the address bus or the data bus of the computer. Caution is necessary
when using the expansion bus, because it's possible to damage the Commodore
64 by a malfunction of your equipment.
R/ W 5 Read/Write
DOT
6 8.18 MHz video dot clock
CLOCK
I/O1 7 I/O block 1 @ $DE00–$DEFF (active low) unbuffered I/O
Pin 6 is the DOT CLOCK. This is the 8.18-MHz video dot clock. All system timing
is derived from this clock.
Pin 12 is the BA (BUS AVAILABLE) signal from the VIC-II chip. This line will go low
3 cycles before the VIC-II takes over the system busses, and remains low until the
VIC-II is finished fetching display information.
Pin 13 is the DMA (DIRECT MEMORY ACCESS) line. When this line is pulled low,
the address bus, the data bus, and the Read/Write line of the 6510 processor
chip enter high-impedance state mode. This allows an external processor to take
control of the system busses. This line should only be pulled low when the φ2 clock
is low. Also, since the VIC-II chip will continue to perform display DMA, the
external device must conform to the VIC-II timing. (See VIC-II timing diagram.)
This line is pulled up on the Commodore 64.
Another advantage of your Commodore 64 is the fact most programs you write
on your Commodore 64 today will be upwardly compatible with any new
Commodore computer you buy in the future. This is partially because of the
qualities of the computer's Operating System (OS).
However, there is one thing that the Commodore OS can't do: make your
programs compatible with a computer made by another company.
By the way, most computers that have a Z-80 microprocessor require that you
go inside the computer to actually install a Z-80 card. With this method you have
to be very careful not to disturb the delicate circuitry that runs the rest of the
computer. The Commodore CP/M® cartridge eliminates this hassle because our
Z-80 cartridge plugs into the back of your Commodore 64 quickly and easily,
without any messy wires that can cause problems later.
The Commodore Z-80 cartridge let's you run programs designed for a Z-80
microprocessor on your Commodore 64. The cartridge is provided with a diskette
containing the Commodore CP/M® operating system.
To run CP/M®:
Below is the memory address translation that is performed on the Z-80 cartridge.
You should notice that by adding 4096 bytes to the memory locations used in
CP/M® $1000 (hex) you equal the memory addresses of the normal Commodore
64 operating system. The correspondence between Z-80 and 6510 memory
addresses is as follows:
For more details about Commodore CP/M® and the Z-80 microprocessor look
for the cartridge and the Z-80 Reference Guide at your local Commodore
computer dealer.
374 APPENDIX A
Looks like Looks like
Command Abbreviation this Command Abbreviation this
on screen on screen
PRINT ? ? STATUS ST ST
PRINT# P SHIFT R P STEP ST SHIFT E ST
READ R SHIFT E R STOP S SHIFT T S
REM NONE REM STR$ ST SHIFT R ST
RESTORE RE SHIFT S RE SYS S SHIFT Y S
RETURN RE SHIFT T RE TAB T SHIFT A T
RIGHT$ R SHIFT I R TAN NONE TAN
RND R SHIFT N R THEN T SHIFT H T
RUN R SHIFT U R TIME TI TI
SAVE S SHIFT A S TIME$ TI$ TI$
SGN S SHIFT G S USR U SHIFT S U
SIN S SHIFT I S VAL V SHIFT A V
SPC S SHIFT P S VERIFY V SHIFT E V
SQR S SHIFT Q S WAIT W SHIFT A W
APPENDIX A 375
APPENDIX B
The following chart lists all of the characters built into the Commodore 64
character sets. It shows which numbers should be POKEd into screen memory
(locations 1024 – 2023) to get a desired character. Also shown is which
character corresponds to a number PEEKed from the screen.
Two character sets are available, but only one set at a time. This means that you
cannot have characters from one set on the screen at the same time you have
characters from the other set displayed. The sets are switched by holding down
the SHIFT and keys simultaneously.
From BASIC, POKE 53272,21 will switch to upper case mode and POKE
53272,23 switches to lower case.
Any number on the chart may also be displayed in REVERSE. The reverse
character code may be obtained by adding 128 to the values shown.
If you want to display a solid circle at location 1504, POKE the code for the
circle (81) into location 1504: POKE 1504,81.
Refer to Appendix D for the complete screen and color memory maps, along
with color codes.
NOTE: The following POKEs display the same symbol in set 1 and 2: 1, 27 to 64, 91 to 93, 96
to 104, 106 to 121, 123 to 127.
376 APPENDIX B
SCREEN CODES
APPENDIX B 377
SET1 SET2 POKE SET1 SET2 POKE SET1 SET2 POKE
99 109 119
100 110 120
101 111 121
102 112 122
103 113 123
104 114 124
105 115 125
106 116 126
107 117 127
108 118
378 APPENDIX B
APPENDIX C
This appendix shows you what characters will appear if you PRINT CHR$(X), for
all possible values of X. It will also show the values obtained by typing PRINT
ASC("x"), where x is any character you can type. This is useful in evaluating the
character received in a GET statement, converting upper/lower case, and
printing character based commands (like switch to upper/lower case) that could
not be enclosed in quotes.
APPENDIX C 379
PRINT CHR$ PRINT CHR$ PRINT CHR$ PRINT CHR$
D 68 97 126 Gray 3 155
E 69 98 127 PUR 156
F 70 99 128 ←CRSR 157
G 71 100 Orange 129 YEL 158
H 72 101 130 CYN 159
I 73 102 131 SPACE 160
J 74 103 132 161
K 75 104 f1 133 162
L 76 105 f3 134 163
M 77 106 f5 135 164
N 78 107 f7 136 165
O 79 108 f2 137 166
P 80 109 f4 138 167
Q 81 110 f6 139 168
R 82 111 f8 140 169
S 83 112 SHIFT RETURN 141 170
SWITCH TO
T 84 113 UPPER CASE 142 171
U 85 114 143 172
BLK
V 86 115 144 173
W 87 116 CRSR↑ 145 174
RVS
X 88 117 OFF 146 175
CLR
Y 89 118 HOME 147 176
INST
Z 90 119 DEL 148 177
[ 91 120 Brown 149 178
£ 92 121 Lt Red 150 179
] 93 122 Gray 1 151 180
↑ 94 123 Gray 2 152 181
← 95 124 Lt Green 153 182
96 125 Lt Blue 154 183
380 APPENDIX C
PRINT CHR$ PRINT CHR$ PRINT CHR$ PRINT CHR$
184 186 188 190
185 187 189 191
CODES 192 to 223 SAME AS 96 to 127
CODES 224 to 254 SAME AS 160 to 190
CODE 225 SAME AS 126
APPENDIX C 381
APPENDIX D
The following charts list which memory locations control placing characters on the
screen, and the locations used to change individual character colors, as well as
showing character color codes.
COLUMN
0 10 20 30 39
1063
↓
1024 → 0
1064
1104
1144
1184
1224
1264
1304
1344
1384
1424 10 ROW
1464
1504
1544
1584
1624
1664
1704
1744
1784
1824 20
1864
1904
1944
1984 24
↑
2023
382 APPENDIX D
The actual values to POKE into a color memory location to change a character's
color are:
0 BLACK 8 ORANGE
1 WHITE 9 BROWN
2 RED 10 Light RED
3 CYAN 11 GRAY 1
4 PURPLE 12 GRAY 2
5 GREEN 13 Light GREEN
6 BLUE 14 Light BLUE
7 YELLOW 15 GRAY 3
For example, to change the color of a character located at the upper left-hand
corner of the screen to red, type: POKE 55296,2.
COLUMN
0 10 20 30 39
55335
↓
55296 → 0
55336
55376
55416
55456
55496
55536
55576
55616
55656
ROW
55696 10
55736
55776
55816
55856
55896
55936
55976
56016
56056
56096 20
56136
56176
56216
56256 24
↑
56295
APPENDIX D 383
APPENDIX E
This appendix contains a complete list of Note#, actual note, and the values
to be POKED into the HI FREQ and LOW FREQ registers of the sound chip to
produce the indicated note. The table shows values based on both a φ2 clock of
1.02 MHz (shown as NTSC) and 0.985 MHz (shown as PAL).
384 APPENDIX E
MUSICAL NOTE OSCILLATOR FREQ (NTSC) OSCILLATOR FREQ (PAL)
NOTE OCTAVE DECIMAL HI LOW DECIMAL HI LOW
33 C#-2 1136 4 112 1179 4 155
34 D-2 1204 4 180 1250 4 226
35 D#-2 1275 4 251 1324 5 44
36 E-2 1351 5 71 1403 5 123
37 F-2 1432 5 152 1486 5 206
38 F#-2 1517 5 237 1575 6 39
39 G-2 1607 6 71 1668 6 132
40 G#-2 1703 6 167 1767 6 231
41 A-2 1804 7 12 1873 7 81
42 A#-2 1911 7 119 1984 7 192
43 B-2 2025 7 233 2102 8 54
48 C-3 2145 8 97 2227 8 179
49 C#-3 2273 8 225 2359 9 55
50 D-3 2408 9 104 2500 9 196
51 D#-3 2551 9 247 2649 10 89
52 E-3 2703 10 143 2806 10 246
53 F-3 2864 11 48 2973 11 157
54 F#-3 3034 11 218 3150 12 78
55 G-3 3215 12 143 3337 13 9
56 G#-3 3406 13 78 3535 13 207
57 A-3 3608 14 24 3746 14 162
58 A#-3 3823 14 239 3969 15 129
59 B-3 4050 15 210 4205 16 109
64 C-4 4291 16 195 4455 17 103
65 C#-4 4547 17 195 4719 18 111
66 D-4 4817 18 209 5000 19 136
67 D#-4 5103 19 239 5298 20 178
68 E-4 5407 21 31 5613 21 237
69 F-4 5728 22 96 5946 23 58
70 F#-4 6069 23 181 6300 24 156
71 G-4 6430 25 30 6675 26 19
72 G#-4 6812 26 156 7071 27 159
73 A-4 7217 28 49 7492 29 68
74 A#-4 7647 29 223 7938 31 2
75 B-4 8101 31 165 8410 32 218
80 C-5 8583 33 135 8910 34 206
81 C#-5 9094 35 134 9439 36 223
APPENDIX E 385
MUSICAL NOTE OSCILLATOR FREQ (NTSC) OSCILLATOR FREQ (PAL)
NOTE OCTAVE DECIMAL HI LOW DECIMAL HI LOW
82 D-5 9634 37 162 10001 39 17
83 D#-5 10207 39 223 10596 41 100
84 E-5 10814 42 62 11226 43 218
85 F-5 11457 44 193 11893 46 117
86 F#-5 12139 47 107 12600 49 56
87 G-5 12860 50 60 13350 52 38
88 G#-5 13625 53 57 14143 55 63
89 A-5 14435 56 99 14985 58 137
90 A#-5 15294 59 190 15876 62 4
91 B-5 16203 63 75 16820 65 180
96 C-6 17167 67 15 17820 69 156
97 C#-6 18188 71 12 18879 73 191
98 D-6 19269 75 69 20002 78 34
99 D#-6 20415 79 191 21192 82 200
100 E-6 21629 84 125 22452 87 180
101 F-6 22915 89 131 23787 92 235
102 F#-6 24278 94 214 25201 98 113
103 G-6 25721 100 121 26700 104 76
104 G#-6 27251 106 115 28287 110 127
105 A-6 28871 112 199 29970 117 18
106 A#-6 30588 119 124 31752 124 8
107 B-6 32407 126 151 33640 131 104
112 C-7 34334 134 30 35640 139 56
113 C#-7 36376 142 24 37759 147 127
114 D-7 38539 150 139 40005 156 69
115 D#-7 40830 159 126 42384 165 144
116 E-7 43258 168 250 44904 175 104
117 F-7 45830 179 6 47574 185 214
118 F#-7 48556 189 172 50403 196 227
119 G-7 51443 200 243 53400 208 152
120 G#-7 54502 212 230 56575 220 255
121 A-7 57743 225 143 59940 234 36
122 A#-7 61176 238 248 63504 248 16
123 B-7 64814 253 46 – – –
386 APPENDIX E
FILTER SETTINGS
Location Contents
54293 Low cutoff frequency (0 – 7)
54294 High cutoff frequency (0 – 255)
54295 Resonance (bits 4 – 7)
Filter Voice 3 (bit 2)
Filter Voice 2 (bit 1)
Filter Voice 1 (bit 0)
54296 High Pass (bit 6)
Bandpass (bit 5)
Low pass (bit 4)
Volume (bits 0 – 3)
APPENDIX E 387
APPENDIX F
BIBLIOGRAPHY
388 APPENDIX F
Publisher: Little, Brown
9780876261477 The Computer Tutor: Learning Orwig, Gary W.;
Activities For Homes and Hodges, W.
Schools
APPENDIX F 389
9780835955300 PET Games and Recreations Oglesby, Mac.;
Lindsay, Len.;
Kunkin, Dorothy B.
Publisher: Sams Publishing
9780672219856 The Howard W. Sams Crash Frenzel, Louis E.
Course In Microcomputers
9780810461864 I Speak BASIC To My PET Jones, A
9780672217906 Mostly BASIC: Applications Berenbon, Howard
for your PET
9780810410510 PET Graphics Hampshire, Nick
9780672217951 PET Interfacing Downey, James M
9780672219481 VIC 20 Programmer's Finkel, A;
Reference Guide Higginbottom, P;
Harris, N; Tomczyk,
M
Publisher: Tab Books
9780830615216 Basic, BASIC-English Noonan, Larry
Dictionary for the Apple, PET,
and TRS-80
Publisher: Total Information Services
Understanding Your PET/CBM
Understanding Your VIC Schultz, David
Publisher: Winthrop Publishers
9780876261668 Computer Games for Nahigian, J. Victor
Businesses, Schools, and
Homes
Commodore Magazines provide you with the most up-to-date information for
your Commodore 64. Two of the most popular publications that you should
seriously consider subscribing to are:
390 APPENDIX F
APPENDIX G
APPENDIX G 391
Register #
Dec Hex
DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
SPRITE
21 15 SE7 SE0ENABLE
ON/OFF
X SCROLL
22 16 N.C. N.C. RST MCM CSEL XSCL2 XSCL1 XSCL0
MODE
SPRITE
23 17 SEXY7 SEXY0
EXPAND Y
SCREEN
24 18 VS13 VS12 VS11 VS10 CB13 CB12 CB11 N.C. Character
Memory
Interrupt
25 19 IRQ N.C. N.C. N.C. LPIRQ ISSC ISBC RIRQ
Requests
Interrupt
26 1A N.C. N.C. N.C. N.C. MLPI MISSC MISBC MRIRQ Requests
MASKS
Background
27 1B BSP7 BSP0 Sprite
Priority
Multicolor
28 1C SCM7 SCM0
Sprite Select
SPRITE
29 1D SEXX7 SEXX0
EXPAND X
Sprite-Sprite
30 1E SSC7 SSC0
Collision
Sprite-
31 1F SBC7 SBC0 Background
COLLISION
392 APPENDIX G
REGISTER # REGISTER #
DEC HEX COLOR DEC HEX COLOR
32 20 BORDER COLOR 39 27 SPRITE 0 COLOR
33 21 BACKROUND COLOR 0 40 28 SPRITE 1 COLOR
34 22 BACKROUND COLOR 1 41 29 SPRITE 2 COLOR
35 23 BACKROUND COLOR 2 42 2A SPRITE 3 COLOR
36 24 BACKROUND COLOR 3 43 2B SPRITE 4 COLOR
37 25 SPRITE MULTICOLOR 0 44 2C SPRITE 5 COLOR
38 26 SPRITE MULTICOLOR 1 45 2D SPRITE 6 COLOR
46 2E SPRITE 7 COLOR
COLOR CODES
LEGEND:
ONLY COLORS 0 to 7 MAY BE USED IN MULTICOLOR CHARACTER MODE.
APPENDIX G 393
APPENDIX H
394 APPENDIX H
APPENDIX I
This appendix is designed to show you what connections may be made to the
Commodore 64.
Control Port 1
Pin Type Note
1 JOYA0
2 JOYA1
3 JOYA2
4 JOYA3
5 POT AY
6 BUTTON A/LP
7 +5V MAX. 50mA
8 GND
9 POT AX
Control Port 2
Pin Type Note
1 JOYB0
2 JOYB1
3 JOYB2
4 JOYB3
5 POT BY
6 BUTTON B
7 +5V MAX. 50mA
8 GND
9 POT BX
APPENDIX I 395
Cartridge Expansion Slot
Audio/Video
Pin Type
1 LUMINANCE
2 GND
3 AUDIO OUT
4 VIDEO OUT
5 AUDIO IN
Serial I/O
Pin Type
1 SERIAL SRQIN
2 GND
3 SERIAL ATN IN/OUT
4 SERIAL CLK IN/OUT
5 SERIAL DATA IN/OUT
6 RESET
396 APPENDIX I
Cassette
Pin Type
A-1 GND
B-2 +5V
C-3 Cassette Motor
D-4 Cassette Read
E-5 Cassette Write
F-6 Cassette Sense
User I/O
APPENDIX I 397
APPENDIX J
If you have programs written in a BASIC other than Commodore BASIC, some
minor adjustments may be necessary before running them on the Commodore
64. We've included some hints to make the conversion easier.
String Dimensions
Delete all statements that are used to declare the length of strings. A statement
such as DIM A$(I,J), which dimensions a string array for J elements of length
I, should be converted to the Commodore BASIC statement DIM A$(J).
In Commodore-64 BASIC, the MID$, RIGHT$, and LEFT$ functions are used
to take substrings of strings. Forms such as A$(I) to access the Ith character in
A$, or A$(I,J) to take a substring of A$ from position I to J, must be changed
as follows:
A$(I) = X$ A$ = LEFT$(A$,I–1)+X$+MID$(A$,I+1)
A$(I,J)=X$ A$=LEFT$(A$,I–1)+X$+MID$(A$,J+1)
Multiple Assignments
To set B and C equal to zero, some BASICs allow statements of the form:
10 LET B=C=0
10 C=0 : B=0
398 APPENDIX J
Multiple Statements
MAT Functions
Programs using the MAT functions available on some BASICs must be rewritten
using FOR… NEXT loops to execute properly.
APPENDIX J 399
APPENDIX K
ERROR MESSAGES
BAD DATA String data was received from an open file, but the
program was expecting numeric data.
BAD SUBSCRIPT The program was trying to reference an element of
an array whose number is outside of the range
specified in the DIM statement.
BREAK Program execution was stopped because you hit
the RUN/STOP key.
CAN'T CONTINUE The CONT command will not work, either because
the program was never RUN, there has been an
error, or a line has been edited.
DEVICE NOT The required I/O device was not available for an
PRESENT OPEN, CLOSE, CMD, PRINT#, INPUT#, or GET#.
DIVISION BY ZERO Division by zero is a mathematical oddity and not
allowed.
EXTRA IGNORED Too many items of data were typed in response to
an INPUT statement. Only the first few items were
accepted.
FILE NOT FOUND If you were looking for a file on tape, and END-OF-
TAPE marker was found. If you were looking on disk,
no file with that name exists.
FILE NOT OPEN The file specified in a CLOSE, CMD, PRINT#,
INPUT#, or GET#, must first be OPENed.
FILE OPEN An attempt was made to open a file using the
number of an already open file.
FORMULA TOO The string expression being evaluated should be
COMPLEX split into at least two parts for the system to work
with, or a formula has too many parentheses.
ILLEGAL DIRECT The INPUT statement can only be used within a
program, and not in direct mode.
ILLEGAL QUANTITY A number used as the argument of a function or
statement is out of the allowable range.
400 APPENDIX K
LOAD There is a problem with the program on tape.
NEXT WITHOUT FOR This is caused by either incorrectly nesting loops or
having a variable name in a NEXT statement that
doesn't correspond with one in a FOR statement.
NOT INPUT FILE An attempt was made to INPUT or GET data from a
file which was specified to be for output only.
NOT OUTPUT FILE An attempt was made to PRINT data to a file which
was specified as input only.
OUT OF DATA A READ statement was executed but there is no data
left unREAD in a DATA statement.
OUT OF MEMORY There is no more RAM available for program or
variables. This may also occur when too many FOR
loops have been nested, or when there are too many
GOSUBs in effect.
OVERFLOW The result of a computation is larger than the largest
number allowed, which is 1.70141183E+38.
REDIM'D ARRAY An array may only be DIMensioned once. If an
array variable is used before that array is DIM'd,
an automatic DIM operation is performed on that
array setting the number of elements to ten, and
any subsequent DIMs will cause this error.
REDO FROM START Character data was typed in during an INPUT
statement when numeric data was expected. Just
re-type the entry so that it is correct, and the
program will continue by itself.
RETURN WITHOUT A RETURN statement was encountered, and no
GOSUB GOSUB command has been issued.
STRING TOO LONG A string can contain up to 255 characters.
?SYNTAX ERROR A statement is unrecognizable by the Commodore
64. A missing or extra parenthesis, misspelled
keywords, etc.
TYPE MISMATCH This error occurs when a number is used in place of
a string, or vice-versa.
UNDEF'D FUNCTION A user defined function was referenced, but it has
never been defined using the DEF FN statement.
UNDEF'D An attempt was made to GOTO or GOSUB or RUN
STATEMENT a line number that doesn't exist.
VERIFY The program on tape or disk does not match the
program currently in memory.
APPENDIX K 401
APPENDIX L
DESCRIPTION
An 8-bit Bi-Directional I/O Port is located on-chip with the Output Register at
Address $0000 and the Data-Direction Register at Address $0001. The I/O Port
is bit-by-bit programmable.
The Three-State sixteen-bit Address Bus allows Direct Memory Accessing (DMA)
and multiprocessor systems sharing a common memory.
402 APPENDIX L
APPENDIX L 403
6510 BLOCK DIAGRAM
404 APPENDIX L
6510 CHARACTERISTICS
MAXIMUM RATINGS
NOTE: This device contains input protection against damage due to high static voltages or electric
fields; however, precautions should be taken to avoid application of voltages higher than the
maximum rating.
ELECTRICAL CHARACTERISTICS
SYM-
CHARACTERISTIC MIN. TYP. MAX. UNIT
BOL
Input High Voltage VIH VCC – 0.2 — VCC + 1.0V VDC
φ1, φ2(in)
Input High Voltage
RES , P0–P7, IRQ , Data VSS + 2.0 — — VDC
APPENDIX L 405
SYM-
CHARACTERISTIC MIN. TYP. MAX. UNIT
BOL
Out Low Voltage
(IOL = 1.6mADC, VCC = 4.75V)
Data, A0–A15, R/W, P0–P7 VOL — — VSS + 0.4 VDC
Power Supply Current ICC — 125 mA
Capacitance C pF
(Vin = 0, TA = 25°C, f = 1 MHz)
Logic, P0–P7
Cin — — 10
Data — — 15
A0–A15, R/W Cout — 12
φ1 Cφ1 — 30 50
φ2 Cφ2 — 50 80
406 APPENDIX L
APPENDIX L 407
408 APPENDIX L
APPENDIX L 409
SIGNAL DESCRIPTION
The 6510 requires a two-phase non-overlapping clock that runs at the Vcc
voltage level.
These outputs are TTL compatible, capable of driving one standard TTL load and
130 pf.
Eight pins are used for the data bus. This is a Bi-Directional bus, transferring data
to and from the device and peripherals. The outputs are tri-state buffers capable
of driving one standard TTL load and 130 pf.
Reset
This input is used to reset or start the microprocessor from a power down
condition. During the time that this line is held low, writing to or from the
microprocessor is inhibited. When a positive edge is detected on the input, the
microprocessor will immediately begin the reset sequence.
After a system initialization time of six clock cycles, the mask interrupt flag will
be set and the microprocessor will load the program counter from the memory
vector locations $FFFC and $FFFD. This is the start location for program control.
After VCC reaches 4.75 volts in a power-up routine, reset must be held low for
at least two clock cycles. At this time the R/W signal will become valid.
When the reset signal goes high following these two clock cycles, the
microprocessor will proceed with the normal reset procedure detailed above.
This TTL level input requests that an interrupt sequence begin within the
microprocessor. The microprocessor will complete the current instruction being
executed before recognizing the request. At that time, the interrupt mask bit in
the Status Code Register will be examined. If the interrupt mask flag is not set,
the microprocessor will begin an interrupt sequence. The Program Counter and
Processor Status Register are stored in the stack. The microprocessor will then set
the interrupt mask flag high so that no further interrupts may occur. At the end
410 APPENDIX L
of this cycle, the program counter low will be loaded from address $FFFE, and
program counter high from location $FFFF, therefore transferring program
control to the memory vector located at these addresses.
The Address Bus is valid only when the Address Enable Control line is high. When
low, the Address Bus is in a high-impedance state. This feature allows easy DMA
and multiprocessor systems.
Six pins are used for the peripheral port, which can transfer data to or from
peripheral devices. The Output Register is located in RAM at Address $0001,
and the Data Direction Register is at Address $0000. The outputs are capable
at driving one standard TTL load and 130 pf.
Read/Write (R/W)
ADDRESSING MODES
ZERO PAGE ADDRESSING — The zero page instructions allow for shorter code
and execution times by only fetching the second byte of the instruction and
assuming a zero high address byte. Careful use of the zero page can result in
significant increase in code efficiency.
APPENDIX L 411
INDEXED ZERO PAGE ADDRESSING — (X, Y indexing) – This form of addressing
is used in conjunction with the index register and is referred to as "Zero Page,
X" or "Zero Page, Y". The effective address is calculated by adding the second
byte to the contents of the index register. Since this is a form of "Zero Page"
addressing, the content of the second byte references a location in page zero.
Additionally, due to the "Zero Page" addressing nature of this mode, no carry is
added to the high order 8 bits of memory and crossing of page boundaries does
not occur.
The second byte of the instruction becomes the operand which is an "Offset"
added to the contents of the lower eight bits of the program counter when the
counter is set at the next instruction. The range of the offset is –128 to +127
bytes from the next instruction.
412 APPENDIX L
The carry from this addition is added to the contents of the next page zero
memory location, the result being the high order eight bits of the effective
address.
ABSOLUTE INDIRECT — The second byte of the instruction contains the low order
eight bits of a memory location. The high order eight bits of that memory location
is contained in the third byte of the instruction. The contents of the fully specified
memory location is the low order byte of the effective address. The next memory
location contains the high order byte of the effective address which is loaded
into the sixteen bits of the program counter.
APPENDIX L 413
DEC Decrement Memory by One
DEX Decrement Index X by One
DEY Decrement Index Y by One
NOP No Operation
414 APPENDIX L
TAX Transfer Accumulator to Index X
TAY Transfer Accumulator to Index Y
TSX Transfer Stack Pointer to Index X
TXA Transfer Index X to Accumulator
TXS Transfer Index X to Stack Register
TYA Transfer Index Y to Accumulator
PROGRAMMING MODEL
APPENDIX L 415
INSTRUCTION SET — OP CODES, EXECUTION
416 APPENDIX L
TIME, MEMORY REQUIREMENTS
APPENDIX L 417
6510 MEMORY MAP
APPLICATIONS NOTES
Locating the Output Register at the internal I/O Port in Page Zero enhances the
powerful Zero Page Addressing instructions of the 6510.
By assigning the I/O Pins as inputs (using the Data Direction Register) the user
has the ability to change the contents of address $0001 (the Output Register)
using peripheral devices. The ability to change these contents using peripheral
inputs, together with Zero Page Indirect Addressing instructions, allows novel and
versatile programming techniques not possible earlier.
COMMODORE SEMICONDUCTOR GROUP reserves the right to make changes to any products
herein to improve reliability, function or design. COMMODORE SEMICONDUCTOR
GROUP does not assume any liability arising out of the application or use of any product or
circuit described herein; neither does it convey any license under its patent rights nor the rights
of others.
418 APPENDIX L
APPENDIX M
DESCRIPTION
The 6526 Complex Interface Adapter (CIA) is a 65XX bus compatible peripheral
interface device with extremely flexible timing and I/O capabilities.
FEATURES
APPENDIX M 419
420 APPENDIX M
6526
BLOCK DIAGRAM
APPENDIX M 421
MAXIMUM RATINGS
All inputs contain protection circuitry to prevent damage due to high static
discharges. Care should be exercised to prevent unnecessary application of
voltages in excess of the allowable limits.
COMMENT
Stresses above those listed under "Absolute Maximum Ratings" may cause
permanent damage to the device. These are stress ratings only. Functional
operation of this device at these or any other conditions above those indicated
in the operational sections of this specification is not implied and exposure to
absolute maximum rating conditions for extended periods may affect device
reliability.
422 APPENDIX M
CHARACTERISTIC SYMBOL MIN. TYP. MAX. UNIT
Port Input Pull-up Resistance RPI 3.1 5.0 — KΩ
Output Leakage Current for ITSI — ±1.0 ±10.0 µA
High Impedance State (Three
State); VIN = 4V to 2.4V;
(DB0—DB7, SP, CNT, IRQ )
Output High Voltage VOH +2.4 — VCC V
VCC = MIN, ILOAD <
–200 µA (PA0—PA7, PC
PB0—PB7, DB0—DB7)
Output Low Voltage VOL — — +0.40 V
VCC = MIN, ILOAD, < 3.2 mA
Output High Current (Sourcing); IOH –200 –1000 — µA
VOH > 2.4V (PA0–PA7,
PB0—PB7, PC , DB0—DB7)
Output Low Current (Sinking); IOL 3.2 — — mA
VOL < .4V (PA0—PA7, PC ,
PB0—PB7, DB0—DB7)
Input Capacitance CIN — 7 10 pf
Output Capacitance COUT — 7 10 pf
Power Supply Current ICC — 70 100 mA
APPENDIX M 423
424 APPENDIX M
APPENDIX M 425
6526 INTERFACE SIGNALS
φ2 — Clock Input
The φ2 clock is a TTL compatible input used for internal device operation and as
a timing reference for communicating with the system data bus.
The CS input controls the activity of the 6526. A low level on CS while φ2 is high
causes the device to respond to signals on the R/W and address (RS) lines. A
high on CS prevents these lines from controlling the 6526. The CS line is normally
activated (low) at φ2 by the appropriate address combination.
The R/W signal is normally supplied by the microprocessor and controls the
direction of data transfers of the 6526. A high on R/W indicates a read (data
transfer out of the 6526), while a low indicates a write (data transfer into the
6526).
The address inputs select the internal registers as described by the Register Map.
The eight data bus pins transfer information between the 6526 and the system
data bus. These pins are high impedance inputs unless CS is low and R/W and
φ2 are high to read the device. During this read, the data bus output buffers are
enabled, driving the data from the selected register onto the system data bus.
IRQ is an open drain output normally connected to the processor interrupt input.
An external pull up resistor holds the signal high, allowing multiple IRQ outputs
to be connected together. The IRQ output is normally off (high impedance) and
is activated low as indicated in the functional description.
426 APPENDIX M
RES — Reset Input
A low on the RES pin resets all internal registers. The port pins are set as inputs
and port registers to zero (although a read of the ports will return all highs
because of passive pullups). The timer control registers are set to zero and the
timer latches to all ones. All other registers are reset to zero.
APPENDIX M 427
1 MHz 2 MHz
Symbol Characteristic MIN MAX MIN MAX Unit
TACC Data Access from — 550 — 275 ns
RS3-RS0
TCO(3) Data Access from — 320 — 150 ns
CS
TDR Data Release Time 50 — 25 — ns
NOTES:
1 — All timings are referenced from VIL max and VIH min on inputs and VOL max and VOH min
on outputs.
2 — TWCS is measured from the later of φ2 high or CS low. CS must be low at least until the
end of φ2 high.
3 — TCO is measured from the later of φ2 high or CS low. Valid data is available only after
the later of TACC or TCO.
REGISTER MAP
428 APPENDIX M
6526 FUNCTIONAL DESCRIPTION
Ports A and B each consist of an 8-bit Peripheral Data Register (PR) and an 8-
bit Data Direction Register (DDR). If a bit in the DDR is set to a one, the
corresponding bit in the PR is an output; if a DDR bit is set to a zero, the
corresponding PR bit is defined as an input. On a READ, the PR reflects the
information present on the actual port pins (PA0 – PA7, PB0 – PB7) for both input
and output bits. Port A and Port B have passive pull-up devices as well as active
pull-ups, providing both CMOS and TTL compatibility. Both ports have two TTL
load drive capability. In addition to normal I/O operation, PB6 and PB7 also
provide timer output functions.
Handshaking
Handshaking on data transfers can be accomplished using the PC output pin and
the FLAG input pin. PC will go low for one cycle following a read or write of
PORT B. This signal can be used to indicate "data ready" at PORT B or "data
accepted" from PORT B. Handshaking on 16-bit data transfers (using both PORT
A and PORT B) is possible by always reading or writing PORT A first. FLAG is a
negative edge sensitive input which can be used for receiving the PC output from
another 6526, or as a general purpose interrupt input. Any negative transition
of FLAG will set the FLAG interrupt bit.
REG NAME D7 D6 D5 D4 D3 D2 D1 D0
0 PRA PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0
1 PRB PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0
2 DDRA DPA7 DPA6 DPA5 DPA4 DPA3 DPA2 DPA1 DPA0
3 DDRB DPB7 DPB6 DPB5 DPB4 DPB3 DPB2 DPB1 DPB0
Each interval timer consists of a 16-bit read-only Timer Counter and a 16-bit
write-only Timer Latch. Data written to the timer are latched in the Timer Latch,
while data read from the timer are the present contents of the Time Counter. The
timers can be used independently or linked for extended operations. The various
timer modes allow generation of long time delays, variable width pulses, pulse
trains and variable frequency waveforms. Utilizing the CNT input, the timers can
APPENDIX M 429
count external pulses or measure frequency, pulse width and delay times of
external signals. Each timer has an associated control register, providing
independent control of the following functions:
Start/Stop
PB On/Off:
A control bit allows the timer output to appear on a PORT B output line (PB6 for
TIMER A and PB7 for TIMER B). This function overrides the DDRB control bit and
forces the appropriate PB line to an output.
Toggle/Pulse
A control bit selects the output applied to PORT B. On every timer underflow the
output can either toggle or generate a single positive pulse of one-cycle
duration. The Toggle output is set high whenever the timer is started – and is set
low by RES.
One-Shot/Continuous
A control bit selects either timer mode. In one-shot mode, the timer will count
down from the latched value to zero, generate an interrupt, reload the latched
value, then stop. In continuous mode, the timer will count from the latched value
to zero, generate an interrupt, reload the latched value and repeat the
procedure continuously.
Force Load
A strobe bit allows the timer latch to be loaded into the timer counter at any
time, whether the timer is running or not.
Input Mode:
Control bits allow selection of the clock used to decrement the timer. TIMER A can
count φ2 clock pulses or external pulses applied to the CNT pin. TIMER B can
count φ2 pulses, external CNT pulses, TIMER A under-flow pulses or TIMER A
underflow pulses while the CNT pin is held high.
The timer latch is loaded into the timer on any timer underflow, on a force load
or following a write to the high byte of the prescaler while the timer is stopped.
If the timer is running, a write to the high byte will load the timer latch, but not
reload the counter.
430 APPENDIX M
READ (TIMER)
REG NAME
4 TA LO TAL7 TAL6 TAL5 TAL4 TAL3 TAL2 TAL1 TAL0
5 TA HI TAH7 TAH6 TAH5 TAH4 TAH3 TAH2 TAH1 TAH0
6 TB LO TBL7 TBL6 TBL5 TBL4 TBL3 TBL2 TBL1 TBL0
7 TB HI TBH7 TBH6 TBH5 TBH4 TBH3 TBH2 TBH1 TBH0
WRITE (PRESCALER)
REG NAME
4 TA LO PAL7 PAL6 PAL5 PAL4 PAL3 PAL2 PAL1 PAL0
5 TA HI PAH7 PAH6 PAH5 PAH4 PAH3 PAH2 PAH1 PAH0
6 TB LO PBL7 PBL6 PBL5 PBL4 PBL3 PBL2 PBL1 PBL0
7 TB HI PBH7 PBH6 PBH5 PBH4 PBH3 PBH2 PBH1 PBH0
The TOD clock is a special purpose timer for real-time applications. TOD consists
of a 24-hour (AM/PM) clock with 1/10th second resolution. It is organized into
4 registers: 10ths of seconds, Seconds, Minutes and Hours. The AM/PM flag is in
the MSB of the Hours register for easy bit testing. Each register reads out in BCD
format to simplify conversion for driving displays, etc. The clock requires an
external 60 Hz or 50 Hz (programmable) TTL level input on the TOD pin for
accurate time-keeping. In addition to time-keeping, a programmable ALARM is
provided for generating an interrupt at a desired time. The ALARM registers are
located at the same addresses as the corresponding TOD registers. Access to the
ALARM is governed by a Control Register bit. The ALARM is write-only; any read
of a TOD address will read time regardless of the state of the ALARM access
bit.
A specific sequence of events must be followed for proper setting and reading
of TOD. TOD is automatically stopped whenever a write to the Hours register
occurs. The clock will not start again until after a write to the 10ths of seconds
register. This assures TOD will always start at the desired time. Since a carry
from one stage to the next can occur at any time with respect to a read
operation, a latching function is included to keep all Time Of Day information
constant during a read sequence. All four TOD registers latch on a read of Hours
and remain latched until after a read of 10ths of seconds. The TOD clock
continues to count when the output registers are latched. If only one register is to
APPENDIX M 431
be read, there is no carry problem and the register can be read "on the fly,"
provided that any read: of Hours is followed by a read of 10ths of seconds to
disable the latching.
READ
REG NAME
8 TOD 10THS 0 0 0 0 T8 T4 T2 T1
9 TOD SEC 0 SH4 SH2 SH1 SL8 SL4 SL2 SL1
A TOD MIN 0 MH4 MH2 MH1 ML8 ML4 ML2 ML1
B TOD HR PM 0 0 HH HL8 HL4 HL2 HL1
WRITE
CRB7 = 0 TOD
CRB7 = 1 ALARM
(SAME FORMAT AS READ)
The serial port is a buffered, 8-bit synchronous shift register system. A control bit
selects input or output mode. In input mode, data on the SP pin is shifted into the
shift register on the rising edge of the signal applied to the CNT pin. After 8
CNT pulses, the data in the shift register is dumped into the Serial Data Register
and an interrupt is generated. In the output mode, TIMER A is used for the baud
rate generator. Data is shifted out on the SP pin at ½ the underflow rate of
TIMER A. The maximum baud rate possible is φ2 divided by 4, but the maximum
useable baud rate will be determined by line loading and the speed at which
the receiver responds to input data. Transmission will start following a write to
the Serial Data Register (provided TIMER A is running and in continuous mode).
The clock signal derived from TIMER A appears as an output on the CNT pin. The
data in the Serial Data Register will be loaded into the shift register then shift
out to the SP pin when a CNT pulse occurs. Data shifted out becomes valid on
the falling edge of CNT and remains valid until the next falling edge. After 8
CNT pulses, an interrupt is generated to indicate more data can be sent. If the
Serial Data Register was loaded with new information prior to this interrupt, the
new data will automatically be loaded into the shift register and transmission
will continue. If the microprocessor stays one byte ahead of the shift register,
transmission will be continuous. If no further data is to be transmitted, after the
432 APPENDIX M
8th CNT pulse, CNT will return high and SP will remain at the level of the last
data bit transmitted. SDR data is shifted out MSB first and serial input data
should also appear in this format.
The bidirectional capability of the Serial Port and CNT clock allows many 6526
devices to be connected to a common serial communication bus on which one
6526 acts as a master, sourcing data and shift clock, while all other 6526 chips
act as slaves. Both CNT and SP outputs are open drain to allow such a common
bus. Protocol for master/slave selection can be transmitted over the serial bus,
or via dedicated hand-shaking lines.
REG NAME
C SDR S7 S6 S5 S4 S3 S2 S1 S0
There are five sources of interrupts on the 6526: underflow from TIMER A,
underflow from TIMER B, TOD ALARM, Serial Port full/empty and FLAG. A single
register provides masking and interrupt information. The interrupt Control
Register consists of a write-only MASK register and a read-only DATA register.
Any interrupt will set the corresponding bit in the DATA register. Any interrupt
which is enabled by the MASK register will set the IR bit (MSB) of the DATA
register and bring the IRQ pin low.
In a multi-chip system, the IR bit can be polled to detect which chip has generated
an interrupt request. The interrupt DATA register is cleared and the IRQ line
returns high following a read of the DATA register. Since each interrupt sets an
interrupt bit regardless of the MASK, and each interrupt bit can be selectively
masked to prevent the generation of a process or interrupt, it is possible to
intermix polled interrupts with true interrupts. However, polling the IR bit will
cause the DATA register to clear, therefore, it is up to the user to preserve the
information contained in the DATA register if any polled interrupts were present.
The MASK register provides convenient control of individual mask bits. When
writing to the MASK register, if bit 7 (SET/CLEAR) of the data written is a ZERO,
any mask bit written with a one will be cleared, while those mask bits written
with a zero will be unaffected. If bit 7 of the data written is a ONE, any mask
bit written with a one will be set, while those mask bits written with a zero will
be unaffected. In order for an interrupt flag to set IR and generate an Interrupt
Request, the corresponding MASK bit must be set.
APPENDIX M 433
READ (INT DATA)
REG NAME
D ICR IR 0 0 FLG SP ALRM TB TA
REG NAME
D ICR S/C X X FLG SP ALRM TB TA
CONTROL REGISTERS
There are two control registers in the 6526, CRA and CRB. CRA is associated
with TIMER A and CRB is associated with TIMER B. The register format is as
follows:
CRA:
434 APPENDIX M
CRB:
SP IN RUN OUT
REG NAME TOD IN LOAD PB ON START
MODE MODE MODE MODE
E CRA 0=60Hz 0=INPUT 0=φ2 1=FORCE 0=CONT. 0=PULSE 0=PB6 OFF 0=STOP
LOAD
1=50Hz 1=OUTPUT 1=CNT (STROBE) 1=O.S. 1=TOGGLE 1=PB6 ON 1=START
TA
RUN OUT
REG NAME ALARM IN MODE LOAD PB ON START
MODE MODE
F CRB 0=TOD 0 0=φ2 1=FORCE 0=CONT. 0=PULSE 0=PB7 OFF 0=STOP
1 1=CNT LOAD
1 0=TA
1=ALARM 1 1=CNT–TA (STROBE) 1=O.S. 1=TOGGLE 1=PB7 ON 1=START
TB
All unused registers bits are unaffected by a write and are forced to zero on a
read.
COMMODORE SEMICONDUCTOR GROUP reserves the right to make changes to any products
herein to improve reliability, function or design. COMMODORE SEMICONDUCTOR
GROUP does not assume any liability arising out of the application or use of any product or
circuit described herein; neither does it convey any license under its patent rights nor the rights
of others.
APPENDIX M 435
APPENDIX N
The 6566/6567 are multi-purpose color video controller devices for use in both
computer video terminals and video game applications. Both devices contain 47
control registers which are accessed via a standard 8-bit microprocessor bus
(65XX) and will access up to 16K of memory for display information. The various
operating modes and options within each mode are described.
A13 A12 A11 A10 A09 A08 A07 A06 A05 A04 A03 A02 A01 A00
VM13 VM12 VM11 VM10 VC9 VC8 VC7 VC6 VC5 VC4 VC3 VC2 VC1 VC0
436 APPENDIX N
The eight-bit character pointer permits up to 256 different character definitions
to be available simultaneously. Each character is an 8 × 8 dot matrix stored in
the character base as eight consecutive bytes. The location of the character base
is defined by CB13 – CB11 also in register 24 ($18) which are used for the 3
most significant bits (MSB) of the character base address. The 11 lower order
addresses are formed by the 8-bit character pointer from the video matrix (D7
– D0) which selects a particular character, and a 3-bit raster counter (RC2 –
RC0) which selects one of the eight character bytes. The resulting characters are
formatted as 25 rows of 40 characters each. In addition to the 8-bit character
pointer, a 4-bit COLOR NYBBLE is associated with each video matrix location
(the video matrix memory must be 12 bits wide) which defines one of sixteen
colors for each character.
A13 A12 A11 A10 A09 A08 A07 A06 A05 A04 A03 A02 A01 A00
CB13 CB12 CB11 D7 D6 D5 D4 D3 D2 D1 D0 RC2 RC1 RC0
In the standard character mode, the 8 sequential bytes from the character base
are displayed directly on the 8 lines in each character region. A "0" bit causes
the background #0 color (from register 33 ($21) to be displayed while the color
selected by the color nybble (foreground) is displayed for a "1" bit (see Color
Code Table).
CHARACTER
FUNCTION COLOR DISPLAYED
BIT
Background 0 Background #0 color
(register 33 ($21))
Foreground 1 Color selected by 4-bit color nybble
Therefore, each character has a unique color determined by the 4-bit color
nybble (1 of 16) and all characters share the common background color.
APPENDIX N 437
MULTICOLOR CHARACTER MODE (MCM = 1, BMM = ECM = 0)
CHARACTER
FUNCTION COLOR DISPLAYED
BIT
Background 00 Background #0 color
(register 33 ($21))
Background 01 Background #1 color
(register 34 ($22))
Foreground 10 Background #2 color
(register 35 ($23))
Foreground 11 Color specified by 3 LSB
of color nybble
Since two bits are required to specify one dot color, the character is now
displayed as a 4 × 8 matrix with each dot twice the horizontal size as in
standard mode. Note, however, that each character region can now contain 4
different colors, two as foreground and two as background (see MOB priority).
The extended color mode allows the selection of individual back-ground colors
for each character region with the normal 8 × 8 character resolution. This mode
is selected by setting the ECM bit of register 17 ($11) to "1." The character dot
data is displayed as in the standard mode (foreground color determined by the
color nybble is displayed for a "1" data bit), but the 2 MSB of the character
438 APPENDIX N
pointer are used to select the background color for each character region as
follows:
CHAR. POINTER
BACKGROUND COLOR DISPLAYED FOR 0 BIT
MS BIT PAIR
00 Background #0 color (register 33 ($21))
01 Background #1 color (register 34 ($22))
10 Background #2 color (register 35 ($23))
11 Background #3 color (register 36 ($24))
Since the two MSB of the character pointers are used for color information, only
64 different character definitions are available. The 6566/6567 will force
CB10 and CB9 to "0" regardless of the original pointer values, so that only the
first 64 character definitions will be accessed. With extended color mode each
character has one of sixteen individually defined foreground colors and one of
the four available background colors.
NOTE: Extended color mode and multicolor mode should not be enabled simultaneously
BITMAP MODE
In bitmap mode, the 6566/6567 fetches data from memory in a different
fashion, so that a one-to-one correspondence exists between each displayed dot
and a memory bit. The bitmap mode provides a screen resolution of 320H ×
200V individually controlled display dots. Bitmap mode is selected by setting
the BMM bit in register 17 ($11) to a "1." The VIDEO MATRIX is still accessed as
in character mode, but the video matrix data is no longer interpreted as
character pointers, but rather as color data. The VIDEO MATRIX COUNTER is
then also used as an address to fetch the dot data for display from the 8000-
byte DISPLAY BASE. The display base address is formed as follows:
A13 A12 A11 A10 A09 A08 A07 A06 A05 A04 A03 A02 A01 A00
CB13 VC9 VC8 VC7 VC6 VC5 VC4 VC3 VC2 VC1 VC0 RC2 RC1 RC0
APPENDIX N 439
VCx denotes the video matrix counter outputs, RCx denotes the 3-bit raster line
counter and CB13 is from register 24 ($18). The video matrix counter steps
through the same 40 locations for eight raster lines, continuing to the next 40
locations every eighth line, while the raster counter increments once for each
horizontal video line (raster line). This addressing results in, each eight sequential
memory locations being formatted as an 8 × 8 dot block on the video display.
When standard bitmap mode is in use, the color information is derived only from
the data stored in the video matrix (the color nybble is disregarded). The 8 bits
are divided into two 4-bit nybbles which allow two colors to be independently
selected in each 8 × 8 dot block. When a bit in the display memory is a "0" the
color of the output dot is set by the least significant (lower) nybble (LSN).
Similarly, a display memory bit of "1" selects the output color determined by the
MSN (upper nybble).
Multicolored bitmap mode is selected by setting the MCM bit in register 22 ($16)
to a "1" in conjunction with the BMM bit. Multicolor mode uses the same memory
access sequences as standard bitmap mode, but interprets the dot data as
follows:
Note that the color nybble (DB11 – DB8) is used for the multicolor bitmap mode.
Again, as two bits are used to select one dot color, the horizontal dot size is
doubled, resulting in a screen resolution of 160H × 200V. Utilizing multicolor
440 APPENDIX N
bitmap mode, three independently selected colors can be displayed in each 8
× 8 block in addition to the background color.
ENABLE
Each MOB can be selectively enabled for display by setting its corresponding
enable bit (MnE) to "1" in register 21 ($15). If the MnE bit is "0," no MOB
operations will occur involving the disabled MOB.
POSITION
Each MOB is positioned via its X and Y position register (see register map) with
a resolution of 512 horizontal and 256 vertical positions. The position of a MOB
is determined by the upper-left corner of the array. X locations 23 to 347 ($17
APPENDIX N 441
– $157) and Y locations 50 to 249 ($32 – $F9) are visible. Since not all
available MOB positions are entirely visible on the screen, MOBs may be moved
smoothly on and off the display screen.
COLOR
Each MOB has a separate 4-bit register to determine the MOB color. The two
MOB color modes are:
In the standard mode, a "0" bit of MOB data allows any background data to
show through (transparent) and a "1" bit is displayed as the MOB color
determined by the corresponding MOB Color register.
Each MOB can be individually selected as a multicolor MOB via MnMC bits in
the MOB multicolor register 28 ($1C). When the MnMC bit is "1," the
corresponding MOB is displayed in the multicolor mode. In the multicolor mode,
the MOB data is interpreted in pairs (similar to the other multicolor modes) as
follows:
Since two bits of data are required for each color, the resolution of the MOB is
reduced to 12 × 21, with each horizontal dot expanded to twice standard size
so that the overall MOB size does not change. Note that up to 3 colors can be
displayed in each MOB (in addition to transparent) but that two of the colors
are shared among all the MOBs in the multicolor mode.
442 APPENDIX N
MAGNIFICATION
Each MOB can be selectively expanded (2X) in both the horizontal and vertical
directions. Two registers contain the control bits (MnXE, MnYE) for the
magnification control:
REGISTER FUNCTION
23 ($17) Horizontal expand MnXE — “1” = expand; “0” = normal
29 ($1D) Vertical expand MnYE — “1” = expand; “0” = normal
PRIORITY
The priority of each MOB may be individually controlled with respect to the other
displayed information from character or bitmap modes. The priority of each
MOB is set by the corresponding bit (MnDP) of register 27 ($1B) as follows:
APPENDIX N 443
MOB data bits of "0" ("00" in multicolor mode) are transparent, always
permitting any other information to be displayed.
The MOBs have a fixed priority with respect to each other, with MOB 0 having
the highest priority and MOB 7 the lowest. When MOB data (except transparent
data) of two MOBs are coincident, the data from the lower number MOB will be
displayed. MOB vs. MOB data is prioritized before priority resolution with
character or bitmap data.
COLLISION DETECTION
Two types of MOB collision (coincidence) are detected, MOB to MOB collision
and MOB to display data collision:
444 APPENDIX N
The collision interrupt latches are set whenever the first bit of either register is
set to "1." Once any collision bit within a register is set high, subsequent collisions
will, not set the interrupt latch until that collision register has been cleared to all
"0s" by a read.
The data for each MOB is stored in 63 consecutive bytes of memory. Each block
of MOB data is defined by a MOB pointer, located at the end of the VIDEO
MATRIX. Only 1000 bytes of the video matrix are used in the normal display
modes, allowing the video matrix locations 1016 – 1023 (VM base + $3F8 to
VM base + $3FF) to be used for MOB pointers 0 to 7, respectively. The eight-
bit MOB pointer from the video matrix together with the six bits from the MOB
byte counter (to address 63 bytes) define the entire 14-bit address field:
A13 A12 A11 A10 A09 A08 A07 A06 A05 A04 A03 A02 A01 A00
MP7 MP6 MP5 MP4 MP3 MP2 MP1 MP0 MC5 MC4 MC3 MC2 MC1 MC0
Where MPx are the MOB pointer bits from the video matrix and MCx are the
internally generated MOB counter bits. The MOB pointers are read from the
video matrix at the end of every raster line. When the Y position register of a
MOB matches the current raster line count, the actual fetches of MOB data begin.
Internal counters automatically step through the 63 bytes of MOB data,
displaying three bytes on each raster line.
OTHER FEATURES
SCREEN BLANKING
The display screen may be blanked by setting the DEN bit in register 17 ($11)
to a "0." When the screen is blanked, the entire screen will be filled with the
exterior color as set in register 32 ($20). When blanking is active, only
transparent (Phase 1) memory accesses are required, permitting full processor
utilization of the system bus. MOB data, however, will be accessed if the MOBs
are not also disabled. The DEN bit must be set to "1" for normal video display.
APPENDIX N 445
ROW/COLUMN SELECT
The RSEL bit is in register 17 ($11) and the CSEL bit is in register 22 ($16). For
standard display the larger display window is normally used, while the smaller
display window is normally used in conjunction with scrolling.
SCROLLING
The display data may be scrolled up to one entire character space in both the
horizontal and vertical direction. When used in conjunction with the smaller
display window (above), scrolling can be used to create a smooth panning motion
of display data while updating the system memory only when a new character
row (or column) is required. Scrolling is also used to center a fixed display within
the display window.
LIGHT PEN
The light pen input latches the current screen position into a pair of registers (LPX,
LPY) on a low-going edge. The X position register 19 ($13) will contain the 8
MSB of the X position at the time of transition. Since the X position is defined by
a 512-state counter (9 bits) resolution to 2 horizontal dots is provided. Similarly,
the Y position is latched to its register 20 ($14) but here 8 bits provide single
raster resolution within the visible display. The light pen latch maybe triggered
446 APPENDIX N
only once per frame, and subsequent triggers within the same frame will have
no effect. Therefore, you must take several samples before turning the light pen
to the screen (3 or more samples, average), depending upon the characteristics
of your light pen.
RASTER REGISTER
INTERRUPT REGISTER
The interrupt register shows the status of the four sources of interrupt. An interrupt
latch in register 25 ($19) is set to "1" when an interrupt source has generated
an interrupt request. The four sources of interrupt are:
LATCH ENABLE
WHEN SET
BIT BIT
IRST ERST Set when (raster count) = (stored raster count)
IMDC EMDC Set by MOB — DATA collision register (first collision only)
IMMC EMMC Set by MOB — DATA collision register (first collision only)
ILP ELP Set by negative transition of LP input (once per frame)
IRQ Set high by latch set and enabled (invert of IRQ/ output)
To enable an interrupt request to set the IRQ/ output to "0," the corresponding
interrupt enable bit in register 26 ($1A) must be set to "1." Once an interrupt
latch has been set, the latch may be cleared only by writing a "1" to the desired
latch in the interrupt register. This feature allows selective handling of video
interrupts without software required to "remember" active interrupts.
APPENDIX N 447
DYNAMIC RAM REFRESH
THEORY OF OPERATION
SYSTEM INTERFACE
The 6566/6567 video controller devices interact with the system data bus in a
special way. A 65XX system requires the system buses only during the Phase 2
(clock high) portion of the cycle. The 6566/6567 devices take advantage of this
feature by normally accessing system memory during the Phase 1 (clock low)
portion of the clock cycle. Therefore, operations such as character data fetches
and memory refresh are totally transparent to the processor and do not reduce
the processor throughput. The video chips provide the interface control signals
required to maintain this bus sharing.
The video devices provide the signal AEC (address enable control) which is used
to disable the processor address bus drivers allowing the video device to access
the address bus. AEC is active low which permits direct connection to the AEC
input of the 65XX family. The AEC signal is normally activated during Phase 1
so that processor operation is not affected. Because of this bus "sharing," all
memory accesses must be completed in ½ cycle. Since the video chips provide a
1MHz clock (which must be used as system Phase 2), a memory cycle is 500 ns
including address setup, data access and data setup to the reading device.
448 APPENDIX N
processor to complete any current memory accesses. On the fourth Phase 2 after
BA low, the AEC signal will remain low during Phase 2 as the video chip fetches
data. The BA line is normally connected to the RDY input of a 65XX processor.
The character pointer fetches occur every eighth raster line during the display
window and require 40 consecutive Phase 2 accesses to fetch the video matrix
pointers. The MOB data fetches require 4 memory accesses as follows:
The MOB pointers are fetched every other Phase 1 at the end of each raster
line. As required, the additional cycles are used for MOB data fetches. Again,
all necessary bus control is provided by the 6566/6567 devices.
MEMORY INTERFACE
The two versions of the video interface chip, 6566 and 6567, differ in address
output configurations. The 6566 has thirteen fully decoded addresses for direct
connection to the system address bus. The 6567 has multiplexed addresses for
direct connection to 64K dynamic RAMs. The least significant address bits, A06
– A00, are present on A06 – A00 while RAS/ is brought low, while the most
significant bits, A13 – A08, are present on A05 – A00 while CAS/ is brought
low. The pins A11 – A07 on the 6567 are static address outputs to allow direct
connection of these bits to a conventional 16K (2Kx8) ROM. (The lower order
addresses require external latching.)
PROCESSOR INTERFACE
Aside from the special memory accesses described above, the 6566/6567
registers can be accessed similar to any other peripheral device. The following
processor interface signals are provided:
APPENDIX N 449
DATA BUS (DB7 – DB0)
The eight data bus pins are the bi-directional data port, controlled by CS/, RW,
and Phase 0. The data bus can only be accessed while AEC and Phase 0 are
high and CS/ is low.
The chip select pin, CS/, is brought low to enable access to the device registers
in conjunction with the address and RW pins. CS/ low is recognized only while
AEC and Phase 0 are high.
READ/WRITE (R/W)
The read/write input, R/W, is used to determine the direction of data transfer
on the data bus, in conjunction with CS/. When R/W is high ("1") data is
transferred from the selected register to the data bus output. When R/W is low
("0") data presented on the data bus pins is loaded into the selected register.
The lower six address pins, A5 – A0, are bi-directional. During a processor read
or write of the video device, these address pins are inputs. The data on the
address inputs selects the register for read or write as defined in the register
map.
The clock output, Phase 0, is the 1MHz clock used as the 65XX processor Phase
0 in. All system bus activity is referenced to this clock. The clock frequency is
generated by dividing the 8MHz video input clock by eight.
INTERRUPTS (IRQ/)
The interrupt output, IRQ/, is brought low when an enabled source of interrupt
occurs within the device. The IRQ/ output is open drain, requiring an external
pull-up resistor.
VIDEO INTERFACE
The video output signal from the 6566/6567 consists of two signals which must
be externally mixed together. SYNC/LUM output contains all the video data,
including horizontal and vertical syncs, as well as the luminance information of
450 APPENDIX N
the video display. SYNC/LUM is open drain, requiring an external pull-up of
500 ohms. The COLOR output contains all the chrominance information, including
the color reference burst and the color of all display data. The COLOR output is
open source and should be terminated with 1000 ohms to ground. After
appropriate mixing of these two signals, the resulting signal can directly drive a
video monitor or be fed to a modulator for use with a standard television.
COLOR CODES
D4 D3 D1 D0 HEX DEC COLOR
0 0 0 0 0 0 BLACK
0 0 0 1 1 1 WHITE
0 0 1 0 2 2 RED
0 0 1 1 3 3 CYAN
0 1 0 0 4 4 PURPLE
0 1 0 1 5 5 GREEN
0 1 1 0 6 6 BLUE
0 1 1 1 7 7 YELLOW
1 0 0 0 8 8 ORANGE
1 0 0 1 9 9 BROWN
1 0 1 0 A 10 LT RED
1 0 1 1 B 11 DARK GREY
1 1 0 0 C 12 MED GREY
1 1 0 1 D 13 LT GREEN
1 1 1 0 E 14 LT BLUE
1 1 1 1 F 15 LT GREY
APPENDIX N 451
452 APPENDIX N
APPENDIX N 453
454 APPENDIX N
APPENDIX N 455
6567 TIMING LIMITS
SPEC SPEC
SPEC MIN TYP MAX
Clock out hi 465 484 500
Clock out lo 475 494 510
Clock to RAS lo 150 171 190
Clock to RAS hi 20 35 50
RAS lo to CAS lo 25 46 65
Clock to CAS hi 15 25 35
Clock to AEC hi/lo 15 33 50
Ph in + pulse 50 43
Ph in – pulse 65 58
456 APPENDIX N
APPENDIX O
CONCEPT
FEATURES
3 TONE OSCILLATORS
Range: 0 – 4 kHz
4 WAVEFORMS PER OSCILLATOR
Triangle, Sawtooth,
Variable Pulse, Noise
3 AMPLITUDE MODULATORS
Range: 48 dB
3 ENVELOPE GENERATORS
Exponential response
Attack Rate: 2ms – 8s
Decay Rate: 6ms – 24s
Sustain level: 0 – peak volume
Release Rate: 6ms – 24s
OSCILLATOR SYNCHRONIZATION
RING MODULATION
APPENDIX O 457
PROGRAMMABLE FILTER
Cutoff range: 30 Hz – 12 kHz
12dB/octave Rolloff
Lowpass, Bandpass,
Highpass, Notch outputs
Variable Resonance
MASTER VOLUME CONTROL
2 A/D POT INTERFACES
RANDOM NUMBER/MODULATION GENERATOR
EXTERNAL AUDIO INPUT
458 APPENDIX O
APPENDIX O 459
DESCRIPTION
The 6581 consists of three synthesizer "voices" which can be used independently
or in conjunction with each other (or external audio sources) to create complex
sounds. Each voice consists of a Tone Oscillator/Waveform Generator, an
Envelope Generator and an Amplitude Modulator. The Tone Oscillator controls
the pitch of the voice over a wide range. The Oscillator produces four waveforms
at the selected frequency, with the unique harmonic content of each waveform
providing simple control of tone color. The volume dynamics of the oscillator are
controlled by the Amplitude Modulator under the direction of the Envelope
Generator. When triggered, the Envelope Generator creates an amplitude
envelope with programmable rates of increasing and decreasing volume. In
addition to the three voices, a programmable Filter is provided for generating
complex, dynamic tone colors via subtractive synthesis.
SID allows the microprocessor to read the changing output of the third Oscillator
and third Envelope Generator. These outputs can be used as a source of
modulation information for creating vibrato, frequency/filter sweeps and similar
effects. The third oscillator can also act as a random number generator for
games. Two A/D converters are provided for interfacing SID with
potentiometers. These can be used for "paddles" in a game environment or as
front panel controls in a music synthesizer. SID can process external audio signals,
allowing multiple SID chips to be daisy-chained or mixed in complex polyphonic
systems.
There are 29 eight-bit registers in SID which control the generation of sound.
These registers are either WRITE-only or READ-only and are listed below in
Table 1.
460 APPENDIX O
APPENDIX O 461
SID REGISTER DESCRIPTION
VOICE 1
Together these registers form a l6-bit number which linearly controls the
frequency of Oscillator 1. The frequency is determined by the following
equation:
Where Fn is the 16-bit number in the Frequency registers and FCIK is the system
clock applied to the φ2 input (pin 6). For a standard 1.0 MHz clock, the frequency
is given by:
Together these registers form a 12-bit number (bits 4 – 7 of PW HI are not used)
which linearly controls the Pulse Width (duty cycle) of the Pulse waveform on
Oscillator 1. The pulse width is determined by the following equation:
PWout = (PWn/40.95) %
The pulse width resolution allows the width to be smoothly swept with no
discernable stepping. Note that the Pulse waveform on Oscillator 1 must be
selected in order for the Pulse Width registers to have any audible effect. A
value of 0 or 4095 ($FFF) in the Pulse Width registers will produce a constant
DC output, while a value of 2048 ($800) will produce a square wave.
462 APPENDIX O
CONTROL REGISTER (Register 04)
This register contains eight control bits which select various options on Oscillator
1.
GATE (Bit 0): The GATE bit controls the Envelope Generator for Voice 1. When
this bit is set to a one, the Envelope Generator is Gated (triggered) and the
ATTACK/DECAY/SUSTAIN cycle is initiated. When the bit is reset to a zero, the
RELEASE cycle begins. The Envelope Generator controls the amplitude of
Oscillator 1 appearing at the audio output, therefore, the GATE bit must be set
(along with suitable envelope parameters) for the selected output of Oscillator
1 to be audible. A detailed discussion of the Envelope Generator can be found
at the end of this Appendix.
SYNC (Bit 1): The SYNC bit, when set to a one, synchronizes the fundamental
frequency of Oscillator 1 with the fundamental frequency of Oscillator 3,
producing "Hard Sync" effects.
RING MOD (Bit 2): The RING MOD bit, when set to a one, replaces the Triangle
waveform output of Oscillator 1 with a "Ring Modulated" combination of
Oscillators 1 and 3. Varying the frequency of Oscillator 1 with respect to
Oscillator 3 produces a wide range of non-harmonic overtone structures for
creating bell or gong sounds and for special effects. In order for ring modulation
to be audible, the Triangle waveform of Oscillator 1 must be selected and
Oscillator 3 must be set to some frequency other than zero. No other parameters
of Voice 3 have any effect on ring modulation.
TEST (Bit 3): The TEST bit, when set to a one, resets and locks Oscillator 1 at zero
until the TEST bit is cleared. The Noise waveform output of Oscillator 1 is also
reset and the Pulse waveform output is held at a DC level. Normally this bit is
used for testing purposes, however, it can be used to synchronize Oscillator 1 to
external events, allowing the generation of highly complex waveforms under
real-time software control.
APPENDIX O 463
(Bit 4): When set to a one, the Triangle waveform output of Oscillator 1 is
selected. The Triangle waveform is low in harmonics and has a mellow, flute-like
quality.
(Bit 5): When set to a one, the Sawtooth waveform output of Oscillator 1 is
selected. The Sawtooth waveform is rich in even and odd harmonics and has a
bright, brassy quality.
(Bit 6): When set to a one, the Pulse waveform output of Oscillator 1 is selected.
The harmonic content of this waveform can be adjusted by the Pulse Width
registers, producing tone qualities ranging from a bright, hollow square wave to
a nasal, reedy pulse. Sweeping the pulse width in real-time produces a dynamic
"phasing" effect which adds a sense of motion to the sound. Rapidly jumping
between different pulse widths can produce interesting harmonic sequences.
NOISE (Bit 7): When set to a one, the Noise output waveform of Oscillator 1 is
selected. This output is a random signal which changes at the frequency of
Oscillator 1. The sound quality can be varied from a low rumbling to hissing
white noise via the Oscillator 1 Frequency registers. Noise is useful in creating
explosions, gunshots, jet engines, wind, surf and other unpitched sounds, as well
as snare drums and cymbals. Sweeping the oscillator frequency with Noise
selected produces a dramatic rushing effect.
NOTE: The oscillator output waveforms are NOT additive. If more than one output waveform is
selected simultaneously, the result will be a logical ANDing of the waveforms. Although this
technique can be used to generate additional waveforms beyond the four listed above, it must
be used with care. If any other waveform is selected while Noise is on, the Noise output can "lock
up." If this occurs, the Noise output will remain silent until reset by the TEST bit or by bringing RES
(pin 5) low.
464 APPENDIX O
ATTACK/DECAY (Register 05)
Bits 4 – 7 of this register (ATK0 – ATK3) select 1 of 16 ATTACK rates for the
Voice 1 Envelope Generator. The ATTACK rate determines how rapidly the
output of Voice 1 rises from zero to peak amplitude when the Envelope
Generator is Gated. The 16 ATTACK rates are listed in Table 2.
Bits 4 – 7 of this register (STN0 – STN3) select 1 of 16 SUSTAIN levels for the
Envelope Generator. The SUSTAIN cycle follows the DECAY cycle and the output
of Voice 1 will remain at the selected SUSTAIN amplitude as long as the Gate
bit remains set. The SUSTAIN levels range from zero to peak amplitude in 16
linear steps, with a SUSTAIN value of 0 selecting zero amplitude and a SUSTAIN
value of 15 ($F) selecting the peak amplitude. A SUSTAIN value of 8 would
cause Voice 1 to SUSTAIN at an amplitude one-half the peak amplitude reached
by the ATTACK cycle.
Bits 0 – 3 (RLS0 – RLS3) select 1 of 16 RELEASE rates for the Envelope Generator.
The RELEASE cycle follows the SUSTAIN cycle when the Gate bit is reset to zero.
At this time, the output of Voice 1 will fall from the SUSTAIN amplitude to zero
amplitude at the selected RELEASE rate. The 16 RELEASE rates are identical to
the DECAY rates.
NOTE: The cycling of the Envelope Generator can be altered at any point via the Gate bit. The
Envelope Generator can be Gated and Released without restriction. For example, if the Gate
bit is reset before the envelope has finished the ATTACK cycle, the RELEASE cycle will immediately
begin, starting from whatever amplitude had been reached. If the envelope is then Gated again
(before the RELEASE cycle has reached zero amplitude), another ATTACK cycle will begin, starting
from whatever amplitude had been reached. This technique can be used to generate complex
amplitude envelopes via real-time software control.
APPENDIX O 465
Table 2. Envelope Rates
NOTE: Envelope rates are based on a 1.00 MHz φ2 clock. For other φ2 frequencies, multiply the
given rate by 1 MHz/φ2. The rates refer to the amount of time per cycle. For example, given an
ATTACK value of 2, the ATTACK cycle would take16 ms to rise from zero to peak amplitude. The
DECAY/RELEASE rates refer to the amount of time these cycles would take to fall from peak
amplitude to zero.
VOICE 2
Registers $07 – $0D control Voice 2 and are functionally identical to registers
$00 – $06 with these exceptions:
466 APPENDIX O
VOICE 3
Registers $0E – $14 control Voice 3 and are functionally identical to registers
$00 – $06 with these exceptions:
FILTER
FC LO/FC HI (Registers $15, $16)
Bits 4 – 7 of this register (RES0 – RES3) control the resonance of the filter.
Resonance is a peaking effect which emphasizes frequency components at the
Cutoff Frequency of the Filter, causing a sharper sound. There are16 resonance
settings ranging linearly from no resonance (0) to maximum resonance (15 or
$F). Bits 0 – 3 determine which signals will be routed through the Filter:
FILT1 (Bit 0): When set to a zero, Voice 1 appears directly at the audio output
and the Filter has no effect on it. When set to a one, Voice 1 will be processed
through the Filter and the harmonic content of Voice 1 will be altered according
to the selected Filter parameters.
FILTEX (Bit 3): Same as bit 0 for External audio input (pin 26).
APPENDIX O 467
MODE/VOL (Register $18)
Bits 4 – 7 of this register select various Filter mode and output options:
LP (Bit 4): When set to a one, the Low-Pass output of the Filter is selected and
sent to the audio output. For a given Filter input signal, all frequency components
below the Filter Cutoff Frequency are passed unaltered, while all frequency
components above the Cutoff are attenuated at a rate of 12 dB/Octave. The
Low-Pass mode produces full-bodied sounds.
BP (Bit 5): Same as bit 4 for the Bandpass output. All frequency components
above and below the Cutoff are attenuated at a rate of 6 dB/Octave. The
Bandpass mode produces thin, open sounds.
HP (Bit 6): Same as bit 4 for the High-Pass output. All frequency components
above the Cutoff are passed unaltered, while all frequency components below
the Cutoff are attenuated at a rate of 12 dB/Octave. The High-Pass mode
produces tinny, buzzy sounds.
3 OFF (Bit 7): When set to a one, the output of Voice 3 is disconnected from the
direct audio path. Setting Voice 3 to bypass the Filter (FILT 3 = 0) and setting 3
OFF to a one prevents Voice 3 from reaching the audio output. This allows Voice
3 to be used for modulation purposes without any undesirable output.
NOTE: The Filter output modes ARE additive and multiple Filter modes may be selected
simultaneously. For example, both LP and HP modes can be selected to produce a Notch (or Band
Reject) Filter response. In order for the Filter to have any audible effect, at least one Filter output
must be selected and at least one Voice must be routed through the Filter. The Filter is, perhaps,
the most important element in SID as it allows the generation of complex tone colors via
subtractive synthesis (the Filter is used to eliminate specific frequency components from a
harmonically rich input signal). The best results are achieved by varying the Cutoff Frequency in
real-time.
Bits 0-3 (VOL0 – VOL3) select 1 of 16 overall Volume levels for the final
composite audio output. The output volume levels range from no output (0) to
maximum volume (15 or $F) in 16 linear steps. This control can be used as a static
volume control for balancing levels in multi-chip systems or for creating dynamic
volume effects, such as Tremolo. Some Volume level other than zero must be
selected in order for SID to produce any sound.
468 APPENDIX O
MISCELLANEOUS
This register allows the microprocessor to read the position of the potentiometer
tied to POTX (pin 24), with values ranging from 0 at minimum resistance, to 255
($FF) at maximum resistance. The value is always valid and is updated every
512 φ2 clock cycles. See the Pin Description section for information on pot and
capacitor values.
This register allows the microprocessor to read the upper 8 output bits of
Oscillator 3. The character of the numbers generated is directly related to the
waveform selected. If the Sawtooth waveform of Oscillator 3 is selected, this
register will present a series of numbers incrementing from 0 to 255 ($FF) at a
rate determined by the frequency of Oscillator 3. If the Triangle waveform is
selected, the output will increment from 0 up to 255, then decrement down to 0.
If the Pulse waveform is selected, the output will jump between 0 and 255.
Selecting the Noise waveform will produce a series of random numbers,
therefore, this register can be used as a random number generator for games.
There are numerous timing and sequencing applications for the OSC 3 register,
however, the chief function is probably that of a modulation generator. The
numbers generated by this register can be added, via software, to the Oscillator,
or Filter Frequency registers or the Pulse Width registers in real-time. Many
dynamic effects can be generated in this manner. Siren-like sounds can be
created by adding the OSC 3 Sawtooth output to the frequency control of
another oscillator. Synthesizer "Sample and Hold" effects can be produced by
adding the OSC 3 Noise output to the Filter Frequency control registers. Vibrato
can be produced by setting Oscillator 3 to a frequency around 7 Hz and adding
the OSC 3 Triangle output (with proper scaling) to the Frequency control of
another oscillator. An unlimited range of effects are available by altering the
frequency of Oscillator 3 and scaling the OSC 3 output. Normally, when
Oscillator3 is used for modulation, the audio output of Voice 3 should be
eliminated (3 OFF = 1).
APPENDIX O 469
ENV 3 (Register $1C)
Same as OSC 3, but this register allows the microprocessor to read the output of
the Voice 3 Envelope Generator. This output can be added to the Filter
Frequency to produce harmonic envelopes, WAH-WAH, and similar effects.
"Phaser" sounds can be created by adding this output to the frequency control
registers of an oscillator. The Voice 3 Envelope Generator must be Gated in
order to produce any output from this register. The OSC 3 register, however,
always reflects the changing output of the oscillator and is not affected in any
way by the Envelope Generator.
These pins are used to connect the two integrating capacitors required by the
programmable Filter. C1 connects between pins 1 and 2, C2 between pins 3
and 4. Both capacitors should be the same value. Normal operation of the Filter
over the audio range (approximately 30 Hz – 12 kHz) is accomplished with a
value of 2200 pF for C1 and C2. Polystyrene capacitors are preferred and in
complex polyphonic systems, where many SID chips must track each other,
matched capacitors are recommended.
The frequency range of the Filter can be tailored to specific applications by the
choice of capacitor values. For example, a low-cost game may not require full
high-frequency response. In this case, larger values for C1 and C2 could be
chosen to provide more control over the bass frequencies of the Filter. The
maximum Cutoff Frequency of the Filter is given by:
FCmax = 2.6E – 5 / C
Where C is the capacitor value. The range of the Filter extends 9 octaves below
the maximum Cutoff Frequency.
RES (Pin 5)
This TTL-level input is the reset control for SID. When brought low for at least ten
φ2 cycles, all internal registers are reset to zero and the audio output is silenced.
This pin is normally connected to the reset line of the microprocessor or a power-
on-clear circuit.
470 APPENDIX O
φ2 (Pin 6)
This TTL-Ievel input is the master clock for SID. All oscillator frequencies and
envelope rates are referenced to this clock. φ2 also controls data transfers
between SID and the microprocessor. Data can only be transferred when φ2 is
high. Essentially, φ2 acts as a high-active chip select as far as data transfers are
concerned. This pin is normally connected to the system clock, with a nominal
operating frequency of 1.0 MHz.
R/W (Pin 7)
This TTL-Ievel input controls the direction of data transfers between SID and the
microprocessor. If the chip select conditions have been met, a high on this line
allows the microprocessor to Read data from the selected SID register and a low
allows the microprocessor to Write data into the selected SID register. This pin is
normally connected to the system Read/Write line.
CS (Pin 8)
This TTL-Ievel input is a low active chip select which controls data transfers
between SID and the microprocessor. CS must be low for any transfer. A Read
from the selected SID register can only occur if CS is low, φ2 is high and R/W is
high. A Write to the selected SID register can only occur if CS is low, φ2 is high
and R/W is low. This pin is normally connected to address decoding circuitry,
allowing SID to reside in the memory map of a system.
A0 – A4 (Pins 9 – 13)
These TTL-Ievel inputs are used to select one of the 29 SID registers. Although
enough addresses are provided to select 1 of 32 registers, the remaining three
register locations are not used. A Write to any of these three locations is ignored
and a Read returns invalid data. These pins are normally connected to the
corresponding address lines of the microprocessor so that SID may be addressed
in the same manner as memory.
GND (Pin14)
For best results, the ground line between SID and the power supply should be
separate from ground lines to other digital circuitry. This will minimize digital
noise at the audio output.
APPENDIX O 471
D0 – D7 (Pins 15 – 22)
These bidirectional lines are used to transfer data between SID and the
microprocessor. They are TTL compatible in the input mode and capable of
driving 2 TTL loads in the output mode. The data buffers are usually in the high-
impedance off state. During a Write operation, the data buffers remain in the
off (input) state and the microprocessor supplies data to SID over these lines.
During a Read operation, the data buffers turn on and SID supplies data to the
microprocessor over these lines. The pins are normally connected to the
corresponding data lines of the microprocessor.
These pins are inputs to the A/D converters used to digitize the position of
potentiometers. The conversion process is based on the time constant of a
capacitor tied from the POT pin to ground, charged by a potentiometer tied
from the POT pin to +5 volts. The component values are determined by:
RC = 4.7E – 4
The larger the capacitor, the smaller the POT value jitter. The recommended
values for R and C are 470 kΩ and 1000 pF. Note that a separate pot and cap
are required for each POT pin.
As with the GND line, a separate +5V DC line should be run between SID VCC
and the power supply in order to minimize noise. A bypass capacitor should be
located close to the pin.
This analog input allows external audio signals to be mixed with the audio output
of SID or processed through the Filter. Typical sources include voice, guitar, and
organ. The input impedance of this pin is on the order of 100 kΩ. Any signal
applied directly to the pin should ride at a DC level of 6 volts and should not
exceed 3 volts p–p. In order to pre vent any interference caused by DC level
differences. External signals should be AC-coupled to EXT IN by an electrolytic
capacitor in the 1 – 10 μF range. As the direct audio path (FILTEX = 0) has unity
472 APPENDIX O
gain, EXT IN can be used to mix outputs of many SID chips by daisy-chaining.
The number of chips that can be chained in this manner is determined by the
amount of noise and distortion allowable at the final output. Note that the output
Volume control will affect not only the three SID voices, but also any external
inputs.
This open-source buffer is the final audio output of SID, comprised of the three
SID voices, the Filter and any external input. The output level is set by the output
Volume control and reaches a maximum of 2 volts p–p at a DC level of 6 volts.
A source resistor from AUDIO OUT to ground is required for proper operation.
The recommended resistance is 1Ω for a standard output impedance.
As with VCC, a separate + 12V DC line should be run to SID VDD and a bypass
capacitor should be used.
APPENDIX O 473
474 APPENDIX O
APPENDIX O 475
6581 SID TIMING
READ CYCLE
476 APPENDIX O
WRITE CYCLE
APPENDIX O 477
EQUAL-TEMPERED MUSICAL SCALE VALUES
The table in Appendix E lists the numerical values which must be stored in the SID
Oscillator frequency control registers to produce the notes of the equal-
tempered musical scale. The equal-tempered scale consists of an octave
containing 12 semitones (notes): C, D, E, F, G, A, B and C#, D#, F#, G#, A#. The
frequency of each semitone is exactly the 12th root of 2 ( √2) times the
frequency of the previous semitone. The table shows values based on both a φ2
clock of 1.02 MHz (shown as NTSC) and 0.985 MHz (shown as PAL). Refer to the
equation given in the Register Description for use of other master clock
frequencies. The scale selected is concert pitch, in which A-4 = 440 Hz.
Transpositions of this scale and scales other than the equal-tempered scale are
also possible.
Although the table in Appendix E provides a simple and quick method for
generating the equal-tempered scale, it is very memory inefficient as it requires
192 bytes for the table alone. Memory efficiency can be improved by
determining the note value algorithmically. Using the fact that each note in an
octave is exactly half the frequency of that note in the next octave, the note
look-up table can be reduced from 96 entries to 12 entries, as there are 12
notes per octave. If the 12 entries (24 bytes) consist of the 16-bit values for the
eighth octave (C-7 through B-7), then notes in lower octaves can be derived by
choosing the appropriate note in the eighth octave and dividing the 16-bit value
by two for each octave of difference. As division by two is nothing more than a
right-shift of the value, the calculation can easily be accomplished by a simple
software routine. Although note B-7 is beyond the range of the oscillators, this
value should still be included in the table for calculation purposes (the MSB of B-
7 would require a special software case, such as generating this bit in the CARRY
before shifting). Each note must be specified in a form which indicates which of
the 12 semitones is desired, and which of the eight octaves the semitone is in.
Since four bits are necessary to select 1 of 12 semitones and three bits are
necessary to select 1 of 8 octaves, the information can fit in one byte, with the
lower nybble selecting the semitone (by addressing the look-up table) and the
upper nybble being used by the division routine to determine how many times
the table value must be right-shifted.
478 APPENDIX O
SID ENVELOPE GENERATORS
The four-part ADSR (ATTACK, DECAY, SUSTAIN, RELEASE) envelope generator
has been proven in electronic music to provide the optimum trade-off between
flexibility and ease of amplitude control. Appropriate selection of envelope
parameters allows the simulation of a wide range of percussion and sustained
instruments. The violin is a good example of a sustained instrument. The violinist
controls the volume by bowing the instrument. Typically, the volume builds slowly,
reaches a peak, then drops to an intermediate level. The violinist can maintain
this level for as long as desired, then the volume is allowed to slowly die away.
A "snapshot" of this envelope is shown below:
This volume envelope can be easily reproduced by the ADSR as shown below,
with typical envelope rates:
Note that the tone can be held at the intermediate SUSTAIN level for as long as
desired. The tone will not begin to die away until GATE is cleared. With minor
alterations, this basic envelope can be used for brass and woodwinds as well as
strings.
APPENDIX O 479
struck, the sound reaches full volume and decays rapidly regardless of how it
was struck. A typical cymbal envelope is shown below:
ATTACK: 0 2 ms
DECAY: 9 750 ms
SUSTAIN: 0
RELEASE: 9 750 ms
Note that the tone immediately begins to decay to zero amplitude after the
peak is reached, regardless of when GATE is cleared. The amplitude envelope
of pianos and harpsichords is somewhat more complicated, but can be
generated quite easily with the ADSR. These instruments reach full volume when
a key is first struck. The amplitude immediately begins to die away slowly as
long as the key remains depressed. If the key is released before the sound has
fully died away, the amplitude will immediately drop to zero. This envelope is
shown below:
ATTACK: 0 2 ms
DECAY: 9 750 ms
SUSTAIN: 0
RELEASE: 0 6 ms
Note that the tone decays slowly until GATE is cleared, at which point the
amplitude drops rapidly to zero.
The most simple envelope is that of the organ. When a key is pressed, the tone
immediately reaches full volume and remains there. When the key is released,
the tone drops immediately to zero volume. This envelope is shown below:
ATTACK: 0 2 ms
DECAY: 0 6 ms
SUSTAIN: 15 ($F)
RELEASE: 0 6 ms
The real power of SID lies in the ability to create original sounds rather than
simulations of acoustic instruments. The ADSR is capable of creating envelopes
which do not correspond to any "real" instruments. A good example would be
the "backwards" envelope. This envelope is characterized by a slow attack and
480 APPENDIX O
rapid decay which sounds very much like an instrument that has been recorded
on tape then played backwards. This envelope is shown below:
Many unique sounds can be created by applying the amplitude envelope of one
instrument to the harmonic structure of another. This produces sounds similar to
familiar acoustic instruments, yet notably different. In general, sound is quite
subjective and experimentation with various envelope rates and harmonic
contents will be necessary in order to achieve the desired sound.
APPENDIX O 481
APPENDIX P
GLOSSARY
ADSR Attack/Decay/Sustain/Release envelope.
attack Rate at which musical note reaches peak volume.
binary Base-2 number system.
Boolean operators Logical operators.
byte Memory location.
CHROMA noise Color distortion.
CIA Complex Interface Adapter.
DDR Data Direction Register.
decay Rate at which musical note falls from peak volume to
sustain volume.
decimal Base-10 number system.
e Mathematical constant (approx. 2.71828183).
envelope Shape of the volume of a note over time.
FIFO First-In/First-Out.
hexadecimal Base-16 number system.
integer Whole number (without decimal point).
jiffy clock Hardware interval timer.
NMI Non-Maskable Interrupt.
octal Base-8 number system.
operand Parameter.
OS Operating System.
pixel Dot of resolution on the screen.
queue Single-file line.
register Special memory storage location.
release Rate at which a musical note fails from sustain volume to
no volume.
ROM Read-Only Memory.
SID Sound Interface Device
signed numbers Plus or minus numbers.
subscript Index variable.
sustain Volume level for sustain of musical note.
syntax Programming sentence structure.
truncated Cut off, eliminated (not rounded).
VIC-II Video Interface Chip.
video screen Television set
482 APPENDIX P
INDEX
Abbreviations, BASIC Commands, Statements, and Business aids xiii-xvi
Functions x, 29, 31, 374-375 BVC 232, 239, 254
ABS function 31, 35, 374 BVS 232, 239, 254
Accessories 335-371 Byte 3, 104, 108, 117-119, 124-127, 196,
Accumulator 213 213, 218-220, 222-227, 260-263, 274, 278-
ACPTR 272-274 279, 286, 292, 299, 307,357-359
ADC 232, 235, 254
Addition 3, 9-11, 16 Cassette port 337, 340-342
Addressing 211, 215-217, 411-413 Cassette, tape recorder xiii, 39-41, 65-67, 81-82,
A/D/S/R 183-185, 189, 196-199 91, 187, 192, 283, 294, 297, 320-320, 337-
AND 232, 235, 254 338, 340-342
AND operator 13-16, 31, 35-36, 374 Character PEEKs and POKES 104, 106, 109-
111, 115, 118, 120-122, 127-130, 134-137,
Animation xiii, 153, 166
150, 154-155, 159-161, 165-166
Applications xiii-xvi
CHAREN 260-261
Arithmetic expressions 10-12
CHKIN 272, 275
Arithmetic operators 10-12, 16
CHKOUT 272, 276
Arrays 10-12, 44-45
CHRGET 272, 307-308
ASC function 31, 37, 374 CHRIN 272, 277-278
ASCII character code 31, 38, 340, 374 CHROUT 272, 278-279
ASL 232, 236, 254 CHR$ function 24, 31, 37-38, 45, 50, 55, 75-76,
Assembler 215, 218, 227, 310 93-94, 97, 120, 156, 336-342, 374, 379-381
ArcTaNgent function 31, 38, 374 CINT 272, 280
Attack (see A/D/S/R) CIOUT 272, 279-280
CLALL 272, 281
Bank selection 101-102, 133 CLC 232, 239, 254
BASIC abbreviations 29, 31, 374-375 CLD 232, 240, 254
BASIC commands 31, 41, 58-60, 62, 81-82, 91 CLI 232, 240, 254
BASIC miscellaneous functions 31, 43-44, Clock 80, 89, 314, 320-320, 366, 406-408,
49, 56-57, 61, 69, 70, 80, 83-85, 89 421-427, 431, 451
BASIC numeric functions 31-35, 37-38, 42, 46-47, Clock timing diagram 406-408
49, 83-84, 88-89 CLOSE 272, 281-282
BASIC operators 3, 9-15, 31-36, 63-64, 68, 92 CLOSE statement 31, 39-41, 348, 354, 374
BASIC statements 18-26, 31, 39-55, 57, 62-67, CLR statement 31, 39-40, 81, 109, 374
69-79, 86-87, 92 CLRCHN 272, 282
BASIC string functions 31, 38, 56, 61, 79, 87, 89 CLR/HOME key 220
BASIC variables 7-26 CLV 232, 240, 254
BCC 232, 236, 254 CMD statement 31, 40-41, 374
BCS 232, 236, 254 CMP 232, 241, 254
BEQ 226-227, 232, 237, 254 Collision detect 144-145, 180
Bibliography 388-390 Color adjustment 113
Binary 69, 92, 108, 112, 216-217 Color combinations chart 152
Color memory 103
Bit 99-148, 290, 298, 300-301, 305, 343-
Color register 117, 120, 128, 135-136,
357, 359
179
BIT 232, 237, 254
Color screen, background, border 115-119,
Bitmap mode 121-130
128, 135-137, 176, 179-180
Bitmap mode, multicolor 127-130 Commands, BASIC 31-92
Bitmapping 121-130 Commodore magazine xvii-xviii, 390
BMI 232, 237, 254 Commodore 64 memory map 310
BNE 226-227, 232, 238, 254 Complement, twos 63-64
Boolean arithmetic 14 Constants, floating-point, integer, string 4-7, 46,
BPL 232, 238, 254 77-78
Branches and testing 226-227 CONTinue command 31, 41-42, 46, 81, 86, 374
BRK 232, 238, 254 ConTRoL key 58, 72, 93-97, 171
Buffer, keyboard 93 COSine function 31, 42, 374
INDEX 483
CP/M x, xiv, 368-371 Graphics mode xiv-xv, 99-183
CPX 227, 232, 241, 254 Graphics mode, bitmapped 121-130
CPY 227, 232, 241, 254 Graphics symbols (see graphics keys)
Crunching BASIC programs 24-27, 156 Greater than, equal to or 3, 12-13, 16
CuRSoR keys 93-97, 336
Hexadecimal notation 101, 209, 215-218
Datasette™ recorder (see cassette, tape Hierarchy of operations 16
recorder)
DATA statement 26, 31, 42-43, 76-77, IEEE-488-interface (see serial port)
111-114, 164, 169, 174, 374 IF...THEN statement 31, 46-47, 49, 52-53,
DEC 232, 242, 254 64, 70, 86, 172-173, 180, 374
Decay (see A/D/S/R) INC 232, 243, 254
DEFine FuNction statement 31, 43-44, Income/expense program 20-21
374 Indexed-indirect 224-225
DELete key 71-72, 95-96 Indexing 223-225
DEX 226, 232, 242, 254 Indirect-indexed 223-224
DEY 226, 232, 242, 254 INPUT statement 18-22, 31, 45, 53-55,
DiMension statement 3, 31, 44-45, 374 93, 374
Direct mode 3 INPUT# statement 31, 55, 75, 86, 88, 90,
Division 3, 10-11 374
INSerT key 72, 95-96
Edit mode 93-97 INTeger function 31, 56, 80, 374
Editor, screen 93-97 Integer, arrays, constants, variables 4-5, 7-9
END statement 31, 46, 79, 93, 374 INX 226-227, 232, 243, 254
Envelope generator (see A/D/S/R) INY 226-227, 232, 244, 254
EOR 232, 243, 254 IOBASE 272, 284
Equal, not-equal-to signs 3, 9-12 I/O Guide 335-375
Error messages 306, 400-401 IOINIT 272, 285
Expansion port(s) (also user port, serial I/O Pinouts 395-397
port, RS-232 port), 335-371 I/O Ports 214, 260, 335-375
EXPonent function 31, 46, 374 I/O Registers 104-106, 212-214
Exponentiation 5-6, 10, 12, 16 I/O Statements 39, 50, 54-55, 65-67,
75
Files (cassette) 40, 50, 55, 59-60, 65- IRQ 308
66, 75, 84-85, 91, 337-338, 340-342
Files (disk) 40, 50, 55, 59-60, 65-66, 75, 84- Joysticks 343-345
85, 91, 337-338, 342 JMP 228-230, 232, 244, 254, 270, 308
Filtering 183, 189, 199-202 JSR 228-230, 232, 244, 255, 268, 270
Fire button, joystick/paddle/lightpen
320-320, 343-348 KERNAL 2, 94, 209, 228-230, 308, 268-
FOR statement 20-21, 31, 39, 47-48, 306, 348-358
62-63, 77-78, 86, 110, 155-156, 165-166, Keyboard 93-98
169-171, 198-199, 309, 374 Keywords, BASIC 29-92
Football 45
FREE function 31, 49, 109, 374 LDA 218-220, 232, 245, 255
FuNction function 31, 47, 374 LDX 232, 245, 255
Functions 31, 35, 37-38, 42, 46-47, 49, 56- LDY 232, 246, 255
57, 61, 69-70, 79-80, 83-85, 87-90, 374-375 LEFT$ function 31, 56, 375
LENgth function 31, 57, 375
Game controls and ports 343-348 Less than, equal to or 3, 12-13, 16
GET statement 22-24, 31, 37, 49-50, LET statement 31, 57, 375
93, 374-375 LIST command 31, 58, 375
GETIN 272, 283 LISTEN 272, 285
GET# statement 31, 37, 50, 55, 65, LOAD 272, 286
341-342, 348, 374 LOAD command 31, 59-60, 370, 375
GOSUB statement 31, 39, 51-52, 77, 79, Loading programs from tape, disk 59-60, 337-
85, 374 338, 340-342
GOTO (GO TO) statement 31, 37, 48, LOGarithm function 31, 61, 375
52-53, 64, 77, 81, 86, 374 Lower case characters 72-74, 105
Graphics keys xiv-xv, 70-74, 95-96, LPX (LPY) 348
108-114 LSR 232, 246, 255
484 INDEX
Machine language 209-320, 411-413 POSition function 31, 70, 375
Mask 92 Power/Play xvi, 390
Mathematics formulas 394 PRINT statement 13-15, 18-22, 25, 31-
Mathematical symbols 3, 6-17, 394 54, 56-61, 63, 68-75, 79-80, 83-84, 87-89,
MEMBOT 272, 287 94-96, 109, 168, 171, 210, 213, 220, 375
Memory maps 212, 262-267, 272, PRINT# statement 31, 40-41, 75-76, 85,
310-320 94, 337, 340-341, 348, 353, 375
Memory map, abbreviated 212 Printer xv, 338-339
Memory reallocation 101-103 Program counter 214
MEMTOP 272, 288 Program mode 3
MID$ function 31, 61, 375 Prompt 45
Modem xiii-xviii, 339-340
Modulation 183, 207-208 Quotation marks xi, 3, 23, 72, 95, 337
Multiplication 3, 10-11 Quote mode 72-73, 95-96
Music 183-208
RAM 49, 100-101, 104-105, 107-108,
NEW command 18, 31, 62, 111, 117, 110-111, 117, 122, 260-262, 269, 340
185, 187, 375 RAMTAS 272, 291
NEXT command 20-21, 31, 39, 47-48, Random numbers 53, 80
62-63, 77-78, 86, 110, 155-156, 165-166, RaNDom function 31, 43, 53, 80, 375
169-171, 198-199, 309, 375 Raster-interrupt 131, 150-152
NOP 232, 246, 255 RDTIM 272, 291
NOT operator 13-16, 31, 63-64, 375 READST 272, 292
Note types 190 READ statement 31, 42, 76-77, 111,
Numeric variables 7-8, 26 170, 309, 375
Release (see A/D/S/R)
ON (ON… GOTO/GOSUB) statement Register map, CIA chip 428
31, 64, 375 Register map, SID chip 461
OPEN 272, 289 Register map, VIC chip 454-455
OPEN statement 31, 41, 65-67, 75-76, REMark statement 25-26, 31, 37-38, 41-
85, 94, 337-339, 349-352, 375 42, 45-46, 50, 77-78, 93-95, 101, 118, 198-
Operating system 210-211 199, 338, 340, 356, 375
Operators, arithmetic 3, 9-12, 16 Reserved words (see Keywords, BASIC)
Operators, logical 13-16, 31-31, 35-37, RESTOR 272, 293
63-64, 68, 374-375 RESTORE key 22, 92, 126, 353
Operators, relational 3, 10-12, 16 RESTORE statement 31, 78, 375
OR operator 13-26, 31, 68, 101- RETURN key 3, 18, 22, 41, 50-51,
102, 104, 106, 115, 118, 120, 122, 126-127, 74, 93-97, 154-155, 166, 217, 220, 336-337,
129, 134, 136-137, 375 370
ORA 232, 247, 255 RETURN statement 31, 51-52, 79, 85, 175,
375
Parentheses 3, 8, 30, 31, 83-84, 88, 375 ReVerSe ON, OFF keys 97
PEEK function 31, 69, 93, 101-102, RIGHT$ function 31, 79, 375
104, 106, 108-111, 115, 118, 120-122, 126- ROL 232, 248, 255
130, 134-137, 145, 150, 159-160, 176-177, ROM 261, 268-269
180, 185, 211, 361, 375 ROM, character generator 103-111,
Peripherals (see I/O Guide) 134
PHA 232, 247, 255 ROR 232, 249, 255
PHP 232, 247, 255 RS-232C 335, 348-359
Pinouts (also see I/O Pinouts), 363, 395- RTI 232, 249, 255, 308
397 RTS 232, 249, 255
PLA 232, 248, 255 RUN command 31, 40, 59, 81, 113,
PLOT 272, 290 154, 375
PLP 232, 248, 255 RUN/STOP key 22, 41-42, 52, 58, 86,
POKE statement 25, 31, 69-70, 94, 101- 92, 126, 220, 353
102, 104, 106, 109-111, 115-116, 118, 120-
123, 126-130, 134-137, 150, 153-161, 165- SAVE 272, 294
166, 168-170, 172-173, 177-178, 180, 184- SAVE command 31, 81-82, 375
186, 194, 198-199, 204-205, 211, 220, 309, SBC 232, 250, 255
361, 375-376 SCNKEY 272, 295
Ports, I/O 214, 335-375, 395-397 SCREEN 272, 295-296
INDEX 485
Screen editor 2, 94-97, 211 Subtraction 3, 10-11, 16
Screen memory 102-103 Sustain (see A/D/S/R)
Scrolling 128-130, 166 SYS statement 31, 87, 121, 307, 375
SEC 232, 250, 255
SECOND 272, 296 TAB function 27, 31, 45, 88, 336,
SED 232, 250, 255 375
SEI 232, 251, 255 TANgent function 31, 88, 375
Serial port (IEEE-488) 262, 320, 320, 362- TALK 272, 302
366, 432-433 TAX 232, 252, 255
SETLFS 272, 297 TAY 232, 252, 255
SETMSG 272, 298 THEN keyword (see IF...THEN), 31
SETNAM 272, 299 TIME function 31, 89, 375
SETTIM 272, 299-300 TIME$ function 31, 89, 375
SETTMO 272, 300-301 TKSA 272, 302-303
SGN function 31, 83, 109, 375 TO keyword (see FOR...TO), 31
SHIFT key 4, 30, 72, 74, 94, 96-97, 168, 220 TSX 232, 253, 255
SID chip programming xiv, 183-208 TXA 229, 232, 253, 255
SID chip specifications 457-481 TXS 232, 253, 255
SID chip memory map 223-320 TYA 229, 232, 253, 255
SiNe function 31, 83, 375
Sound waves 186-187, 192-196 UDTIM 272, 303
SPaCe function 27, 31, 83-84, 336, UNLSN 272, 304
375 UNTLK 272, 304
Sprites x, xiv, 99-100, 131-148, 153-182 User port 355, 359-362
Sprite display priorities 144, 161, 179 USR function 31, 90, 307, 375
Sprite positioning 137-143, 157-161, 177
SQuare Root function 31, 84, 375 VALue function 31, 90, 375
STA 221, 232, 251, 255 VECTOR 272, 305-306
Stack pointer 214, 222 VERIFY command 31, 91, 375
STATUS function 31, 84-85, 354, 375 Vibrato 203
Status register 214, 354 Voices 187-191
STEP keyword, (see FOR...TO) 31, 86 Volume control, SID 186
STOP 272, 301-302
STOP command 31, 41, 86, 375 WAIT statement 13-14, 31, 92, 375
STOP key (see RUN/STOP key)
String arrays, constants, variables 4, 6-9 XOR, (see WAIT statement) 13-14
String expressions 3, 17 X-index register 213, 223-224
String operators 3, 16-17
STR$ function 31, 87, 375 Y-index register 214, 223-224
STX 232, 251, 255
STY 232, 252, 255 Z-80 (see CP/M)
Subroutines 222, 228-229, 270, 307 Zero page 221-222, 358-359
486 INDEX