An Introduction to the Commodore 64_ Adventures in Programming ( PDFDrive )
An Introduction to the Commodore 64_ Adventures in Programming ( PDFDrive )
Commodore 64
Adventures in Programming
Serantz 5.29.83
An Introduction
to the
Commodore 64
Adventures in
Programming
Nevin B. Scrimshaw
and
James Vogel
Bibliography: p.
Includes index.
1. Commodore 64 (Computer) —Programming. I.Vogel,
James, 1952- . II. Title.
QA76.8.C64S371983 001.64 '2 83-15650
ABCDEFGHIJ
Acknowledgements
The able assistance of the following people is deeply appreciated:
David Epstein
Virginia Michie
Cort Shurtleff
Roy Piascik
N. Scrantz Lersch did all of the illustrations for this book. She is a freelance illustrator
living in Worcester, Massachusetts with her husband and two children. She also works
as a photographer in the Anatomy Department at the University of Massachustets
Medical School.
This book was produced on an IBM PC and telecommunicated and typeset by Arts
& Letters, Brookline, Massachusetts.
An Introduction to the
Commodore 64
Adventures in Programming
1 First Things First
THE KEYBOARD
Your primary means of communicating with the Commodore 64 is
the keyboard, which is similar in many ways to that of a standard
1
typewriter. But you'll notice that the Commodore keyboard has several
special keys; these keys make it much more versatile than a typewriter's.
Modes
Set up your 64 as directed in the User's Guide and flip up the rocker
switch on the keyboard's right side. When you first turn the computer
on, you're in Standard, or upper easelgraphic, Mode. That blinking
square under READY is the cursor; it marks the spot where what you
type next will appear on the screen.
Look for the two cursor control keys on the lower right of the
keyboard. In Standard Mode, pressing these keys moves the cursor down
or to the right. Pressing the [SHIFT] key and a [CRSR] key at the same
time moves the cursor up or to the left. In this book, pressing two keys
together will be indicated with a colon, e.g., [SHIFT]:[RCRSR]. Our
notation for the right cursor is [RCRSR]; the left cursor is [LCRSR],
otherwise we shall simply use [CRSR] to ambiguously refer to either
cursor. Go ahead and experiment to get a feel for using the cursor
controls.
Perhaps the most important key on the keyboard is the [RETURN]
key. Like its counterpart on a typewriter, [RETURN] brings you (the
cursor actually) back to the left margin, one line down; if the cursor
is at the bottom of your screen, pressing [RETURN] scrolls up the display
one line. Try it!
But [RETURN] on a computer has a· more important function: it
signals the computer that you have finished typing instructions and enters
those instructions into memory. Failing to press [RETURN] at the end
of any command is like not talking to the computer at all; pressing
[RETURN] means that you expect the computer to respond.
Now, starting with the letter A, type in all the characters in the third
row from the top of your keyboard (but don't push [RETURN)). You'll
see that in standard mode the Commodore prints on the screen either
the character on the top face of the key or the lower character when
there are two; all the letters are upper-case.
Now push [RETURN]. Your screen should look like this:
ASDFGHJKL:; =
?SYNTAX ERROR
READY.
By hitting [RETURN], you entered an instruction that makes no sense
in the BASIC language your computer understands; the way you phrased
2
your instruction - your syntax - was faulty, and your Commodore
responded with an ERROR message. (For a list of ERROR messages
and what they mean, see Appendix L, page 150, in your User's Guide).
Now, from left to right, press all the keys in the top row. What hap-
pened? When you hit the [CLR/HOME] key the cursor shot back up
to the left corner of your screen. That position is called home; the com-
puter followed the instruction printed on the lower half of the
[CLR/HOME] key, sending the cursor home. Use the left [LCRSR] key
to bring the cursor back one line below the line you )ust typed.
On a typewriter [SHIFT]ing gives you a completely different set of
characters. On the Commodore [SHIFT]ing does the same thing, but
what characters or functions you get depends on what mode you're in.
In Standard Mode holding down the [SHIFT] key while pressing any
other key will print the graphics symbol on the right front face of that
key. For keys with two characters on the top (the number keys, for in-
stance), [SHIFT]ing gives you the top character or function. Pushing
a [SHIFT]ed [CLR/HOME] key thus not only takes the cursor home,
but clears the screen as well.
Type in some letters and symbols and find the [COMMODORE] key
on the keyboard's lower left corner. Press this and the [SHIFT] key at
the same time.
Welcome to the lower case! In this second mode the Commodore
keyboard behaves essentially like a typewriter: the [SHIFT] key produces
upper-case letters and symbols, but no graphics. Experiment for a while.
To get back to Standard Mode, push both [COMMODORE] and
[SHIFT] again.
Quote Mode
A third mode is Quote Mode, and you get in and out of it from either
Standard or Typewriter Mode by typing quotation marks: one set gets
you in, a second set gets you out. Quote Mode can be disconcerting at
first because keys like [CLR/HOME], [INST/DEL], and the [CRSR]
keys don't do what they did in the other modes; instead they print graphic
symbols. [DEL] is the only function that works normally. For example,
if you hold down the [SHIFT] key and type "[CLR/HOME]" you should
see a deep blue heart on a light blue square. I guess your Commodore
thinks that home is where the heart is.
Quote Mode is used with the BASIC command PRINT to display
something in a precise format. Try this: first clear the screen by typing
[SHIFT]: [CLR/HOME].
3
Now type PRINT and quotation marks followed by [SHIFT]:
[CLR/HOME] and A LITTLE SONG. The line should look like this
so far:
PRINT" A LITTLE SONG
Now press the left [LCRSR] key three times and type AND DANCE"
so that the line looks (except on your screen each "Q" is in inverse video)
like this:
PRINT" A LITTLE SONGQQQAND DANCE"
To make the 64 respond to your command, press [RETURN]. With
any luck you should have:
A LITTLE SONG
AND DANCE
In Quote Mode, pressing the [CRSR] or [CLR/HOME] keys elicits
a kind of delayed response from the computer. You don't want the cur-
sor moved or the screen cleared now; rather, you want those actions
incorporated into your display. The graphic symbols are placeholders
representing what you want done. The computer won't print them when
it "reads" them - one at a time - as part of your instruction; it performs
the indicated action instead.
Your Commodore 64 has still another mode: Reverse Field Mode.
The heart that appears when you type [SHIFT]:[CLR/HOME] is in a
reverse field. To make everything appear on a reverse field, hold down
the [CTRL] key (second row left) while pressing [9]. Type in some let-
ters and graphic symbols and watch the effect. What happens when you
hold down the space bar? To get back to a normal field, type [CTRL]:[ffl.
SPECIAL KEYS
[RUN/STOP] and [RESTORE]
By now, you've probably filled the screen with symbols and are wonder-
ing how to get back to normal. Hold down [RUN/STOP] (third row
left) and press [RESTORE] (second row right). This combination returns
you to the original blue screen with light blue border and lettering; nothing
stored in memory is altered or lost. When you start experimenting with
complex programs, this combination will be a lifesaver.
[RUN/STOP] is also used with BASIC commands and to stop the
4
execution of most BASIC programs. For example, typing LIST followed
by [RETURN) displays any program stored in memory. If you decide
you don't want a LISTing after all, hitting [RUN/STOP) will break it
off. [RUN/STOP) also stops a tape loading sequence.
[CTRL] and [COMMODORE]
Whatever mode you're in, two keys, [CTRL) and [COMMODORE],
work something like the [SHIFT] key, giving extra characters or per-
forming special functions when pressed with other keys. Using [COM-
MODORE], [CTRL], or [SHIFT] with other keys while in Quote Mode
allows you to PRINT an amazing array of patterns in almost any color.
We'll see such combinations in action in later chapters.
On the Commodore 64, [CTRL] is used primarily with the number
keys [1]-[8] to set colors (see pages 11-12 in the User's Guide); when used
with numbers [9] and [0], it turns the reverse field on and off. It can
also produce some special effects when used in Quote Mode. Try typing:
PRINT"
Now press simultaneously the [CONTROL] and the [5] keys. (Our nota-
tion for pressing two keys together is to separate the brackets with a
colon e.g. [CONTROL]:[5).)
You should see a reverse field graphic symbol between your quota-
tion marks. Now hit [RETURN). The text color changes. To get back
5
to the light blue start-up screen push [RUN/STOP]: [RESTORE].
You can also press [CTRL] to slow a BASIC program LISTing to
scroll at a readable pace.
Used with letters in Standard Mode, the [COMMODORE] key pro-
duces the left front graphic symbol. Used with the color keys, it generates
eight new colors. And when combined with the [SHIFT] key, it takes
you from standard upper caselgraphic mode to upper Ilower case mode.
The [COMMODORE] key can also speed up loading time of tape
cassettes. Normally, several seconds elapse between the time you get a
FOUND statement and a LOADING statement (see pages 19-20 in the
User's Guide). You can load without waiting by pressing the [COM-
MODORE] key after the FOUND statement flashes.
[INST/DEL]
In Standard Mode this key allows you to correct typing mistakes:
pushing it moves the cursor back one space, deleting the previous
character. (Remember, [DEL] always gets rid of the character to the
left of the cursor.) A [SHIFT]ed [INSTIDEL] allows you to insert one
letter, symbol, or space. To insert more than one character, you must
type [SHIFT]:[INST/DEL] before typing in each new character.
In Quote Mode, [DEL] still deletes, but [INST] prints a reverse field
graphic symbol. Pressing [COMMODORE]:[INST/DEL] in Quote Mode
will print the graphic for [DEL].
Space Bar
Hitting the space bar on a typewriter puts empty space between words.
On the Commodore the space bar also puts a space between words, but
the space is not empty: it holds a perfectly distinct character - just like
A or Z-that simply looks like empty space.
This means that you can't use the space bar to advance quickly to
the end of a typed line, as you can on an electric typewriter. If you try
it, you'll replace each character with a space and wipe out the line. (This
feature can actually come in handy when you start typing long programs.)
If you want to leave your text intact, you must use the cursor keys to
move around.
One more note: in Quote Mode, where you put spaces affects how
your PRINTed display will look.
[SHIffILOCK]
Like its counterpart on a typewriter, this key locks on the [SHIFT]
6
functions. But a word of warning: the down and right cursor functions
won't work. To unlock the [SHIFT] just push the [SHIFTfLOCK] key
a second time. (This feature of pushing a key twice to get back to the
original state is called a toggle.)
[ <], [>] and [1]
[ <] means "less than," [> ] means "greater than," and [t] means ex-
ponentiate. The shifted [t] key, or [71"] allows you to use an approximate
value of PI (3. 14159264-there's more but no one's ever reached the last
digit). PI is a number that occupies a special place in nature.
Function Keys
Our look at the keyboard ends with the four FUNCTION keys located
on the extreme right. Each key has two functions: one un[SHIFT]ed
and one [SHIFT]ed. In future chapters, we will program these keys to
perform in a number of different ways.
7
2 BASIC Number Crunching
8
machine using English verbs. (For a glossary of Commodore 64 BASIC
vocabulary and syntax, refer to Appendix C, pages 112-119 of the User's
Guide.)
From the keyboard, you can command your Commodore in two ways:
by issuing a single-line instruction and getting an immediate response,
or by typing in a formal program consisting of a numbered list of in-
structions. In this chapter we'll get acquainted with the immediate form
of BASIC; Chapter 3 will introduce formal programming. But first ...
9
and PRINT "COMMODORE 64" is not the same as "COMMO-
DORE64". As you can see, the PRINT command prints whatever is in-
side the quotation marks exactly as is.
Here is a list of symbols that have special meanings in BASIC; we'll
explore their functions further as we use them:
$ identifies a string variable
0/0 identifies an integer variable
? is an abbreviation for the PRINT statement
separates different BASIC statements used on the same line
separates variables in DATA lists; puts space in a PRINTed display
indicates no space or carriage return after a PRINT statement
functions as a decimal point
MANIPULATING MEMORY
Certain post office boxes, or addresses, within the Commodore's
memory are set aside for special purposes. Two sets of addresses turn
the graphics and sound features on and off. Another lOO0-byte block
beginning at address number 55296 controls the colors you see on the
screen.
You can control the information at different memory addresses directly
from the keyboard with the BASIC command POKE. Type:
POKE 53281,0
10
Now press [RETURN]. The screen turns black! Bring the cursor up over
the" and type 5; the screen in now bright green. 53281 is the memory
address for screen color; the number " is the code for black, and 5 is
the code for green. You'll find a complete list of color codes on page
61 of the User's Guide. Experiment with other color codes.
To get back to normal, type color code 6 or press [RUN/STOP]:
[RESTORE].
Two other useful immediate BASIC commands are LIST, which
displays any program stored in memory, and RUN, which executes that
program. You'll use these commands frequently.
MANIPULATING NUMBERS
In its simplest form, your Commodore 64 is a calculator. Using the
PRINT command without quotation marks and the +, -, *, /, and
= keys tells the computer to add, subtract, multiply (*) or divide (I)
and puts the results on the screen. If you type:
PRINT "256/8 = "; 256/8
and hit [RETURN], you should see 256/8 = 32 printed below the line
you just entered. The semicolon indicates that you want the result of
256/8. (For more arithmetic, see pages 22-29 in the User's Guide.)
You can enter the above calculation in another way. Clear the com-
puter's memory by typing NEW on an empty line and pressing
[RETURN]. Clear the screen with [SHIFT]:[CLR/HOME]. Now type
(being sure to hit [RETURN] after each line):
A = 256
B = 8
PRINT AlB
If you enter these lines accurately, your Commodore responds with
READY after the first two and with 32 after the last one.
What you've just done is to define two variables named A and B,
assigning them the numerical values of 256 and 8, respectively. A variable
is a name for a quantity that varies. The temperature, your bank balance,
or your weight all are variables. Because the 64 never forgets (unless
you tell it to or the power fails), it responds to your PRINT statement
by performing the requested calculation using the variable values you
entered.
Variables are among the most useful creatures in programming because
11
a simple name like A or B can represent a great deal of information.
Once you defme your variables, you need only keep track of their names,
and manipulating short names is easier than manipulating long expres-
sions. For example, you could redefine A and B and add a new variable
like this:
A = 256/8
B = 2*4
C$ = "A DIVIDED BY B = "
PRINT C$;A/B
Did you type in each line followed by [RETURN]? Then you should
have gotten:
A DIVIDED BY B = 4
as your last line.
The $ in C$ means that what follows - the variable's value, or
definition - will contain a string of text; such variables are called string
variables (which we'll explore these further in Chapter 12). A 0,10 after
a variable name (e.g., X%) defines an integer variable. If you type:
x% = 1.67
PRINT X%
the Commodore will PRINT only the 1, truncating what comes after
the decimal point to the whole number (integer) alone.
12
You should keep in mind a few rules when naming variables. First,
a variable name can have one or two characters. The first must be a
letter of the alphabet, and the last indicates the type of variable. As we
just saw a $ indicates a string variable and a % indicates that the variable
contains a whole number. The computer will accept longer names, but
will read only the first two characters. Thus, COUNT and COUNTESS
both reduce to CO, and the computer reads them as the same variable.
Second, variable names cannot be or contain any BASIC keyword.
VALUE won't work, for example, because VAL is a BASIC keyword
(in this case a function.) For a list of BASIC keywords, see Appendix
D, pages 130-131 in the User's Guide.
Variables can be updated: if you change their values, as you did for
variables A and B in the example on page 0, the new values replace the
old ones. In ordinary algebra, the statement X = X + 3 cannot possibly
be true. But to the computer, that statement makes perfect sense: it is
an instruction to update the value of X. The computer simply adds 3
to the current value of X and gives the new sum the same name. It can
continue to add 3 until you tell it to stop.
13
3 A BASIC Sampler
14
grams will behave strangely. Remember: The Commodore 64 does
everything you tell it to, even when you've forgotten what you told it
and when.
A last word of warning: While experimenting you may, unwittingly,
issue a command that crashes the computer - the cursor freezes or dis-
appears, nothing you type appears on the screen, and pressing
[RUN/STOP]:[RESTORE] has no effect. If this happens, turn the
machine off, wait a few seconds, then turn it on again. The good news-
you haven't damaged anything; the bad news - you've lost anything
entered into memory but not yet SAVEd. So, before you experiment
too radically, SAVE your programs!
A QUICK FORAY
For a clear slate, type [RUN/STOP]:[RESTORE] and NEW followed
by [RETURN]. Now type in the following program (don't forget to press
[RETURN] after each line):
10 LET X = 10
20 Z = Xt2
30 PRINT "TEN SQUARED IS ";Z
On the next line type RUN and hit [RETURN]. The following two lines
should appear on your screen:
100
TEN SQUARED IS 100
This program follows the patterns used in Chapter 2, but because the
lines are numbered, the computer waits for the RUN command to per-
form the calculations.
Remember how, in Chapter 1, you created
A LITTLE SONG
AND DANCE
15
Line 10 by pressing [SHIff]: [CLR/HOME] -you are in Quote Mode.)
10 PRINT" ~" : REM *** CLEAR SCREEN ***
20 PRINT "NOW HERE" TAB (25) "NOW THERE"
30 PRINT: PRINT : PRINT
40 PRINT "A BIG" TAB (250) "JUMP"
The REM statement in Line 10 stands for REMark and can be followed
by any text. It's a note to yourself or to anyone reading your program
and can keep long programs organized and easy to understand. The 64
ignores your REMarks when it RUNs a program.
In Line 20 the TAB function PRINTs "NOW THERE" 25 spaces from
the left margin. As on a typewriter, TAB is a handy feature for pre-
paring charts and tables.
The three PRINT commands in Line 30 guarantee that A BIG will
print three lines below NOW HERE and against the left margin. Go
ahead and experiment with different TAB(numbers). Remember that no
change is official until you press [RETURN].
The next program illustrates some different ways of assigning values
to variables. Type:
10 LET A = 3
20 B = 5
30 INPUT "ENTER A NUMBER BETWEEN 1 AND 10";COP
40 LET EX = (A*B)/COP
50 PRINT" EX = ";EX
16
Did you remember to press [RETURN] after every line? Good; RUN
your program. The computer asks you to enter a number. Go ahead,
enter a number as directed and hit [RETURN].
INPUT is a convenient way of assigning variable values and illustrates
what people mean when they describe BASIC as an interactive language.
When the computer reaches an INPUT statement, it stops, prints out
the phrase inside the quotation marks and waits for you to type in a
value. It then takes that value and automatically assigns it to the variable
named after the semicolon - in this case, COP. INPUT statements are
particularly helpful when you want the computer to run the same long
procedure with many different variable values.
Line 10 declares that until further notice A has the value of 3.
Line 20 is similar but shows that LET is optional.
Line 30 stops the program to ask for your INPUT.
Line 40 demonstrates a powerful way to use variables: the variable
EX is defined in terms of the current value of other variables.
Line 50 PRINTs the value of EX.
What happens if you add:
60 GOTO 10
to your program? When you get tired of INPUTing numbers, hit
[RUN/STOP]:[RESTORE]. You have just broken an infinite loop.
The following program introduces more BASIC elements.
10 A = 3
20 A$ = "HOW DID I DO THAT?"
30 INPUT "TYPE IN A NUMBER AND HIT RETURN";
NUMBER
40 READ F,G
50 DATA 1,2,2,3
60 PRINT A : PRINT "F = ";F : PRINT A$
17
another READ statement or other appropriate instruction (more on this
in later chapters). A pointer inside the computer keeps track of which
DATA values have already been READ (see pages 93-94 in the User's
Guide).
Line 60 PRINTs the current values for A, F, G, and A$. The colon
separates the four different PRINT statements.
But whatever happened to that NUMBER you put in? Like the two
extra numbers in the DATA statement, it too, is still in memory. Type:
PRINT NUMBER
18
Amending the Fifth
4 Program Editing
19
will automatically carry it onto the next line.) The REMark statements
are optional. If you choose not to use them, make sure you also delete
the : that precedes them. And finally, spaces are irrelevant to the Com-
modore except inside quotation marks, but they do make your programs
easier to read.
5 REM *** THE FIFTH ***
10 PRINT" ~" : REM *** CLEAR SCREEN
15 FOR M = 54272 TO 54296 : POKE M,0 : NEXT
20 POKE 54296,15
30 POKE 54277 ,88 : POKE 54278,89 : REM ADSRI
40 POKE 54284,88 : POKE 54285,89 : REM ADSR2
50 POKE 54291,88 : POKE 54292,89 : REM ADSR3
60 READ A,B,C,D,E,F,G
70 IF A < 0 THEN GOTO 900
80 POKE 54273,A : POKE 54272,B : REM HFl, LFI
90 POKE 54280,C : POKE 54279,D : REM HF2, LF2
100 POKE 54287,E : POKE 54286,F : REM HF3, LF3
110 POKE 54276,33 : POKE 54283,33 : POKE 54290,33
120 FOR Z = 1 TO G : NEXT
130 POKE 54276,32 : POKE 54283,32 : POKE 54290,32
140 GOTO 60
200 DATA 15,210,2,233,3,244,150
210 DATA 15,210,2,233,3,244,150
230 DATA 15,210,2,233,3,244,150
240 DATA 12,143,6,71,3,35,1050
250 DATA -1,-1,-1,-1,-1,-1,-1
900 POKE 54296,0
910 END
Type RUN on a new line and hit [RETURN]. Any luck? Sorry about
the pun ...
If your program didn't run, let's figure out why. Even if it did, use
20
this section to familiarize yourself with editing - a vital skill for debug-
ging programs.
Perhaps you made a syntax error, say in Line 40, and you got this
message:
? SYNTAX ERROR IN 40
READY
To find the error, type LIST 40 on a new line. You should now see your
Line 40. Check it against ours. Are all your commas really commas,
or is one a period? How about your zeros? Are they really zeros or are
they the letter O? Are your POKE numbers the same?
Here is a sample Line 40 for you to change. If you have a similar
error in a different line, follow these directions.
40 POKE 54284,88 ; PAKE 52485.89 : REM ADSR2
Bring your cursor up to this Line 40 or to your LISTed line. Then
bring it over the semicolon after 88. When the cursor is flashing on the
semicolon, press a colon on your keyboard. Now move the cursor over
the A in P AKE and type in an O. Hit [RETURN] to enter your correc-
tions. If you don't, the screen may look right but the version inside the
computer won't have changed.
Go to a blank line, type RUN, and hit [RETURN].
Hmmm ... still a syntax error in Line 40. Once again, type LIST 40
on a new line and hit [RETURN]. Look closely: the period in POKE
54285.89 should really be a comma. Bring your cursor up and over, type
in a comma, and hit [RETURN]. RUN the program again. Now does
it work?
Yes? Good! No? Keep trying. Are all your syntax errors corrected?
If not, go back and list each line that has an error and try to find the
problem.
Does your program run but give you only one brief sound? That could
happen for many reasons. Try this: On a new line, type LIST -100
and [RETURN].
LINE LISTING
Now you should see displayed on your screen all the lines from 0
through 100. Typing LIST plus a minus sign before the line number LISTs
all the lines up to and including that line - here, the first section of your
program.
21
Before going on, let's go over other ways of LISTing. On a new line,
type:
LIST 100-
This gives you a display from Line 100 to the end of the program. You
can also:
LIST 69-200 [RETURN]
which will display the lines from 60 through 200. If the LIST moves
(scrolls) by too fast to read, hold down the CTRL key.
NON-SYNTAX ERRORS
Let's return to Lines 0-100. Is your READ Statement in Line 60 cor-
rect? Let's say you mistyped a letter, and your line looked like this:
69 READ A,B,C,D,E,F,V
Because the format, or syntax, of this command is correct, the com-
puter will not find a syntax error, and will run the program. The pro-
gram will work fine until it reaches V, then it will END, and the com-
puter won't give you any hint of what went wrong. If this happens, you'll
need to do more sophisticated debugging than you're using in this chapter.
(Hint: look at Line 120.)
For now, however, let's concentrate on the editing. Bring the cursor
up to the V and change it to a G. Hit [RETURN], and try to RUN
your program.
Once you get your program running properly , SAVE it by typing on
a new line:
SAVE "THE FIFTH" ,8
for the disk drive, or just
SAVE "THE FIFTH"
for DATASSEITE storage.
By the way, if you're curious about all those POKE numbers, you
might want to skip ahead to Chapter 10, "SID's Song." Meanwhile, let's
take the Fifth and amend it.
22
ADDING, ERASING AND RENUMBERING
You've seen how easy it is to use LIST to help make changes in ex-
isting program lines. Adding and erasing lines is even easier. To add
a line, just type in a numbered line after the READY prompt followed
by [RETURN]. To erase, type the line number on an empty line im-
mediately followed by [RETURN]. When the program LISTs again, ad-
ditions will have been incorporated, and unwanted lines will have
disappeared.
Often when you add lines to a program, you have to renumber some
of the original lines, either for clarity or to conform to the rules of BASIC.
Say we want to add four DATA lines to "The Fifth," numbered 250,
260, 270, and 280. But we already have a Line 250 that we need at the
end of the DATA statements for the program to run correctly. To preserve
its information, let's renumber it 300.
Here's how: type LIST 250 and hit [RETURN]. Now bring the cur-
sor up and change the 250 to 300. The line should read:
300 DATA -1,-1,-1,-1,-1,-1,-1
Press [RETURN], now LIST. As you see, all the new lines have been
added in numerical order even though they were not typed in that order.
23
The computer arranges the lines automatically as one of its editing
functions.
RUN your program to see it if works.
INSERTING CHANGES
Often you will want to add infonnation to existing lines but find there
isn't enough room. Time to use the INSerT function.
On a new line, type LIST - 40 to display Lines 5 through 40 on your
screen. Let's change the 88 in Line 30 to read 137. In this instance, we
have to put three numbers into a place currently occupied by two. To
do this, bring your cursor up to Line 30. Then bring it over so that the
cursor flashes on the first 8 of the 88. Press [SHIFT]: [lNST/DEL].
If you did this properly, the whole text starting with the first , moved
one step to the right, leaving the cursor where the 8 used to be.
Now type 137. Hit [RETURN] to enter the change.
Now change the 89 to a 128: Bring the cursor over the 8 of 89; press
[SHIFT]:[INST/DEL], and type 128. Press [RETURN].
Note that once you command the computer to make room for an
INSerT, you must fill the space even if you only hit the space bar. If
you attempt to use DELete to correct what you're inserting, you will
print the reversed field graphic symbol for DELete.
Now for a surprise. On a new line, type LIST - 40 again. You should
now have a blank line between Lines 30 and 40. By INSerTing your
new numbers, you carried Line 30 out a full 40 characters. (Remember,
spaces count as characters.) The cursor therefore moved automatically
down to the next line. Watch out! The 64 reads that blank as part of
Line 30 so don't try to put another numbered command there.
And another thing: the computer can only handle two full lines, or
80 characters in one instruction. Therefore, when entering any BASIC
statement or DATA lines, you must not exceed two lines. If you do,
anything running over the second line will not be entered into memory.
Remember, too, that if you use alternate symbols for BASIC words
(such as ? in place of PRINn, the entire word will appear when you
LIST. Therefore, information that might have fit on two lines with an
abbreviation will not necessarily fit on two lines after it is LISTed, and
your Commodore works with the LISTed version.
24
EDITING IN QUOTE MODE
In Chapter 1, you saw that typing a set of quotation marks always
puts the computer into Quote Mode. Everything to the right of the quota-
tion mark will be in Quote Mode. Typing the closing quotation marks
gets you back to Standard Mode.
Remember, the cursor controls stop functioning when in Quote Mode,
printing their reversed field graphic symbols. Therefore, if you make
a mistake and wish to edit, you must use the DELete key, which is the
only editing key that works normally in Quote Mode. Of course, you
can also finish the line and enter it with the mistake; then you can go
back and use the cursor normally - it's awkward, but it works.
Let's make a final change by retyping Line 5:
5 REM *** THE FIFTH AMENDED ***
Type RUN, say AMEN, and press [RETURN].
25
5 The Case of The Cursory
Cursor
Here is simple game that will make using the cursor controls second
nature to you. The program will place a letter and the cursor at two
random points on the screen. Use the cursor controls to bring the cursor
over the letter. The amount of time you took will then appear briefly
at the top of the screen, and the program will loop back to let you play
again. Try to get your average time below six seconds. To stop the pro-
gram press [RUN/STOP]: [RESTORE]; or, if all else fails, turn off your
computer. Make sure to SAVB your program. We will return to and
expand this program in Chapter 8.
26
CURSORY CURSOR
2 REM *** CURSORY CURSOR ***
4 REM *** n.b.scrimshaw
12 POKE 53280,11 : POKE 53281,0
16 GOTO 150
19 REM *** PICK POINT ***
20 LET CP = INT(RND(l)*I000)
35 RETURN
49 REM *** SET LETTER ***
50 GOSUB 20
60 LET A= INT(RND(l)*26) + 1
70 LET W = CP
80 POKE CP + 1024,A
90 POKE CP + 55296,3
95 RETURN
99 REM *** GET CURSOR ***
100 GOSUB 20
110 POKE CP + 1024,83
120 POKE CP + 55296,1
125 RETURN
149 REM ******** MAIN LOGIC UNIT**
150 PRINT " ~" : REM *** CLEAR SCREEN
160 GOSUB 50
170 GOSUB 100
180 LET SC = TI
190 GET A$ : IF A$ = "" THEN 190
200 LET CD = ASC(A$)
204 POKE CP + 55296,9
210 IF CD = 29 THEN CP = CP+ 1
27
220 IF CD = 157 THEN CP = CP-l
230 IF CD = 145 THEN CP = CP-40
240 IF CD = 17 THEN CP = CP+40
250 IF CP <0 OR CP> HJOO THEN CP = 1
260 IF CP = W THEN 300
270 GOSUB 110
280 GOTO 190
299 REM *** KEEP SCORE ***
300 PRINT "YOU TOOK ";(TI - SC)/60;" SECONDS"
310 AT = AT+(TI-SC) : TRIES = TRIES + 1
320 PRINT "YOUR A VERAGE IS ";(AT/60)/TRIES;" SECONDS"
330 FOR I = 1 TO 1500 : NEXT I
333 GOTO 150
28
"One night I was asleep and dreamed that
I was awake, then I woke and realized
that it was just a dream .... "
Loops, which we flrst saw in Chapter 3 and have been using ever since,
are powerful tools that deserve a closer look. Loops can be nested and,
when teamed with IF ITHEN statements can make your program fold
into itself like an Escher design.
First, let's use loops to predict the result of tossing ten coins. Say you
want to know the probability of getting exactly eight heads. To calculate
this directly, you need to know that there are 1024 (2 t 10) different possible
outcomes, and 45 of them have exactly eight heads. Dividing these two
numbers gives you the probability: 45/1024 = .0439.
Many problems of probability are far harder than this, and it is
sometimes difficult just to figure out how to approach them. One tool
for estimating probabilities is simulation, that is, using mathematics and
the computer to mimic the problematic situation. Simulation works
because of the law of averages: even though individual trials of some
chance phenomenon vary in outcome, the average of many trials varies
only marginally from a single number, the probability. The greater the
number of trials, the more accurate the probability estimate. But once
you reach a certain number of trials, the accuracy gained from still more
trials is minimal. (That's why polling companies are able to poll relatively
few people and still predict how national elections will turn out.)
LOOP TECH
Before approaching the coin problem we need to take a look at loops.
We have been using FOR/NEXT loops, but now we must use a new
creature: the nested loop. Enter this short program (to form the inverse
Q in Line 20, press the down cursor [LCRSR] while in Quote Mode):
29
10 FOR H = 1 TO 5
20 PRINT "PASS# ";H;" [QJ ";
30 NEXT H
Typing H after the NEXT in Line 30 is optional but helps keep your
bookkeeping straight.
When this program RUNs, the computer follows the instructions in
Line 20 five times. Notice that inside each pass of the loop, the current
value of H (called the counter variable) is printed onto the screen. This
will help you keep track of what is going on. If we are in loop number
five, the computer prints:
PASS# 5
When the computer reaches the down cursor symbol, the cursor obedi-
ently shifts down one line; the semicolon at the end of Line 20 holds
it in the same column. With Line 20 completed, the computer moves
to Line 30, and follows that instruction by going on to the next value
of H. The old value is incremented by one so that 6 is the value of H
after PASS# 5. To check this, type PRINT H.
The word STEP can be added to the basic FOR/NEXT loop to ad-
just what the computer counts by, or the increment size (see page 119
of the User's Guide). Using the screen editor, change Line 10 so that
it looks like this:
10 FOR H = 1 TO 21 STEP 2
30
RUN your program.
STEP has made the variable H count to 21 by twos. Since there are
10 increments of two, there are 10 passes through the loop.
STEPs can also be negative. Clear out the old program with NEW
and try this one:
10 FOR I = 20 TO 1 STEP - 1 : PRINT "DOWN";I : NEXT I
Here we have compressed the whole loop into a single line using the
colon to separate statements. One-line loops tend to make a program
more readable.
RUN this program and trace the value of the loop counter as each
line is printed.
10 FOR P= 1 TO 10
20 FOR H = 1 TO 20
30 PRINT"*";
40 NEXT H
50 PRINT
60 NEXT P
We are using the semicolon in Line 30 to control print format. When
the inner loop, begun on Line 20, has printed out a line of 20 asterisks,
it exits the loop and encounters the PRINT on Line 50. Since there is
nothing to print, the 64 prints nothing. But, this time there is no
semicolon. So the cursor gets bumped to the beginning of the next line.
The next pass through the inner loop thus has a fresh line to work with.
RUN the program and you will see a block of asterisks appear on the
screen. If you're not sure of how Line 50 works, simply erase it by typ-
ing 50 and [RETURN] on an empty line and reRUN the program.
Now, to see a classic application of loop-variable technology, LIST
your program and amend Line 20 to read:
20 FOR H = 1 TO P
31
Don't forget to hit [RETURN] after you make your change. Before
RUNning the amended program, try to predict on paper what this single
change will accomplish.
Now we are ready to use the computer to answer questions that have
obscure precise answers ...
32
the total number of heads. If RND has selected a one then H = 1 and
ET gets incremented by H. COP counts how many times ET is equal
to eight. After the inner loop is finished, the program reaches Line 70
and asks: is ET equal to eight? IF ET equals eight THEN the counter
COP gets bumped up by one.
Now we need to close off the outer loop we started back on Line 10
and calculate the estimated probability. Line 80 closes our loop:
80 NEXT TR
The probability of a given event may be expressed as a percent, as
in "50 percent chance of rain." It may also be written as a decimal func-
tion of 1: 0.3 means 30 percent probable; 0.5 means 50 percent pro-
bable and 1.0 means 100 percent probable. Since the probability of get-
ting eight heads from flipping 10 coins equals the number of trials in
100 that get exactly eight heads divided by the total number of trials,
we add:
90 P = COP/(TR-I)
100 PRINT "THE ESTIMATED PROBABILITY IS ";P
RUN the program (it takes several seconds). Oh dear! The value you
get looks suspicious; maybe there's a bug.
To find bugs in situations like this we can use tracers to trace the value
of key variables as the program runs. We ask the computer to print out
the current value of the variables at key points in the computation. This
slows the calculations but can often pinpoint problems. Insert the follow-
ing line:
75 PRINT "ET = ";ET; " COP = ";COP
When you RUN the program now you should see immediately
that COP stops changing and that ET keeps climbing. ET has not come
home after the first pass. We intended that ET would be the count of
how many times there were exactly eight heads in ten tosses. It worked
fine the first time through the loop, but on the second pass, ET still
had the count from the last pass. ET must be re-initialized, or reset to
0, to make our program work. Add the following line (which erases our
tracer):
75 ET = 0
This line sets the counter ET back to 0 so it is ready for duty again.
The program now works correctly, and we should be able to adapt
33
it to answer similar questions. For example: what is the probability of
getting at most eight heads? Change Line 70 to:
70 IF ET < 8 THEN COP = COP+ 1
RUNning your program should give you a reasonable estimate.
Remember to change it back to the original before we put the whole
thing inside yet another loop.
A TRIPLE-NESTED LOOP
The last program illustrates a nested loop. The inside loop flips 10
coins. The outside loop performs the inside loop 100 times. Now to get
an even more accurate estimate we shall take the average of five runs
of 100 flips. Hmmm ... how to devise a program that will flip 10 coins
100 times 5 times?
Add to our previous program the following line:
5 FOR Z = 1 TO 5
Line 5 starts our big loop. Now we insert a line that will add together
the five estimated probabilities:
110 PR = PR + P
and close off the Z loop:
120 NEXT Z
and print out the computed average:
130 PRINT" THE AVERAGE ESTIMATE IS "; PR/(Z-I)
Ooops! Another bug; haul out the tracers if need be. But, as you may
see from the LISTed program, we have made a similar error as before-
COP has to come home after each pass of the Z loop, so we add:
115 COP =0
Before you RUN this program it might be nice to add the following
line to clear the screen at the beginning. Remember that the reversed
field heart inside the quotes comes from pressing [SHIFf):[CLRlHOME]
in Quote Mode.
2 PRINT" ~ " : REM CLEAR SCREEN
34
A picture is worth a thousand bytes ...
7 Graphics
35
Proofread the line (spaces don't matter); now, without clearing the
screen, RUN the program. Press various keys on the keyboard and watch
the show. When you get tired of all that action press [RUN/STOP]:
[RESTORE]. This convenient key combination will get you back to nor-
mal without erasing the program. Be careful to get POKE numbers right!
You have just changed the organizational structure of memory so that
the computer lost track of which addresses contained which
information - it lost track of the keyboard characters. This ability to
move video memory is an advanced feature of your 64 (which will not
be used in this book).
The VIC II chip is so versatile that this book can't hope to cover all
of its features; we will concentrate on using sprites. Mastering the sprite
switchboard will get you a long way toward understanding how to use
the VIC II chip. Let's begin with a program that will move all eight sprites
around on the screen.
SPRITE CHECKLIST
To play with sprites, we must turn them on and off, set the shape,
assign colors, and define screen positions. This may seem like a lot of
work, but we can actually do it all with a program that's only eight lines
long!
So here's what we have to do:
1. Turn on sprites.
2. Set sprite color.
3. Define sprite shape.
4. Set sprite coordinates.
5. Set memory pointers.
And here's the program that does the job:
999 REM *** SQUAREFISH TANK ***
1000 FOR M = 2040 TO 2042 : POKE M, 13 : NEXT
1010 FOR W = 832 TO 832+62 : POKE W,255 : NEXT
1020 V = 53248 : POKE V + 21,255
1030 FOR J = 39 TO 46 : POKE V + J,J - 38 : NEXT
1040 FOR H = 0 TO 14 STEP 2 : GOSUB 1200
1050 POKE V+H,X: POKE V+H+l,Y: NEXT: GOTO 1000
36
1200 X = INT(RND(0)*250+3) : Y = INT(RND(0)*140+50) :
RETURN
To clear the screen and turn the background black (to better show
off the colors of our sprites), add:
10 REM *** INITIALIZATION ***
20 PRINT" ~ " : REM *** CLEAR SCREEN
30 POKE 53281,0
Go ahead and RUN this program.
WHAT HAPPENED
Those little dancing squares are sprites. Stop the program by hitting
[RUN/STOP] and then press [SHIFf]:[CLR/HOME] to clear the screen.
The sprites are still right there because they are controlled independently
by the VIC II chip. LIST your program and you will fmd both the sprites
and your program filling the screen. To get rid of the sprites, press
[RUN/STOP]: [RESTORE].
The only reason that this short program can control all eight sprites
is the use of FOR/NEXT loops. In addition, we have included a con-
venient subroutine (a sort of subprogram) to keep choosing new loca-
tions for the sprites as the program runs. Subroutines, by the way, are
handy because you can use them over and over in a variety of programs.
37
color code for Sprite 1 and so on. We don't want to POKE in the same
color code for each sprite so we tie the value that is POKEd to how
far we worked through the loop. If you think about it, you will realize
that color codes one through eight are POKEd into the color control
addresses for Sprites 0-7. We used a loop, and the value that gets POKEd
in changes in each pass of the loop.
Lines 1040 and 1050. It takes two lines to define this loop. In each
pass through the loop, a random position in X, Y coordinates is chosen
for the sprite active at that moment. This loop uses a subroutine: the
last statement on Line 1040, GOSUB 1070, temporarily sends the com-
putation careening through Line 1070 where it picks up new, randomly
chosen values for X and Y. Line 1050 POKEs the values just retrieved
by the subroutine into the appropriate address numbers. At this point
the active sprite takes a hop on the screen. The last command on this
line, GOTO 1000, is easy to understand. It tells the computer to go back
to the instruction on Line 1000 and start the cycle allover again.
Line 1200 is the subroutine. It uses the RND function to select ap-
propriate random values for X and Y. You could use a user-defined
function here if you prefer. For longer formulas this can be a real time
and space saver. Look at the description of the DEF FN command on
page 118 of the User's Guide for the details.
You also might want to inspect the sprite switchboard in the Appendix.
Almost all programs involving sprites start with declaring the variable
V to have the value 53248, the first address in the VIC II switchboard.
If we want to fiddle with the other 46 addresses, or control registers,
we can simply POKE in an increment of V such as POKE V + 21 rather
than POKE 53269. Besides making the address numbers shorter and easier
to remember, POKE V + a number reduces the chance of typos that could
lead to a panicky [RUN/STOP):[RESTORE).
PROGRAM PROJECT
Note that Sprites 0, 1, and 3 are solid blocks, while the rest are flicker-
ing odd patterns. If you look at Line 1000, you will notice we only
POKEd three of the eight shape registers. Add a couple of lines to this
program and try POKEing other values into the last five shape registers.
38
to count to 10. People have 10 fingers, so through the ages we've
developed a number system with 10 digits ("digit" even means finger):
°
0, 1,2, 3, 4, 5, 6, 7, 8, and 9. Computers, in contrast, have only two
fingers - off and on - so they count with only two digits: and 1. Our
counting system, called the decimal system, is thus based on the number
10; the computer's system, called the binary system, is based on the
number two. Everything you feed into your Commodore 64 is translated
electronically into strings of Os and Is.
Specific memory addresses in the Commodore contain a byte of binary
code: eight ones or zeroes (eight binary digits, or bits) in a row. That
series of bits has a numeric value that is interpreted by the computer
as a command. But because the computer's counting system is based
on the number two, 10110010 doesn't carry the same numeric value to
the computer as it does to us. We would read 10,110,010 as ''ten million
one hundred ten thousand ten"; the computer reads it as 178. How can
this be? This is where other ways of counting come in.
In our number system we can write:
2
3
4
5
6
7
8
9
10
11
etc.
°
Counting to 10 simply requires adding one to the rightmost place until
we exhaust the available digits; then we started with in the rightmost
place again and add 1 in the next place to the left, called the tens place.
Because it only has two digits, the computer can only write:
39
10
11
100
etc.
With only two digits, how can the computer write ''two'' in the binary
system? The same way we write 10 in the decimal system: by going to
o in the rightmost column or place and adding one in the next column
to the left, the twos place.
The third place to the left in the decimal system is for hundreds - it
takes us from 10 to 99 in the tens column to exhaust our digits. The
third place to the left in the binary system is the fours place-it only
takes to four to exhaust binary digits in the twos column.
Do you begin to see a pattern? If we label the 10 the base of the decimal
system and two the base of the binary system, we can label each col-
umn as follows:
Decimal Binary
11111111 1 1 1 1 1 111
11s 11s
base = 10 base (written 10 but = 2)
base x base = b2 = 100 base x base = b2 = 4
In both cases, adding the values in each place will give us the total decimal
value of each string of eight ones above: in base 10, 1 + 10 + 100 +
1000 + 10,000 + 100,000 + 1,000,000 + 11,000,000 = eleven million
one hundred eleven thousand one hundred eleven; in base 2, 1 + 2 +
4 + 8 + 16 + 32 + 64 + 128 = 255. Thus, 255 is the highest value
possible for one eight-bit string.
We can calculate the decimal equivalent for any binary number-
40
any string of eight bits - by adding the values in each place:
10110010
I bx 1 = 0
1x 2 2
Ox 4 0
Ox 8 0
1 x 16 16
1 x 32 = 32
Ox64 = 64
ox 128 = 128
Total decimal value = 178
Grasping the concept of counting to 255 with two fingers will help
us figure out how to control the sprite switchboard. We will learn more
about sprites in Chapter 12.
41
An in-depth charge at subroutines
8 Program Design
42
Line 190 pauses until the user hits a key.
Lines 200 stores the ASC code that corresponds to the key pressed
in the variable CD.
Line 204 changes the heart at the cursor position to red.
Line 210. IF right cursor key was pressed THEN move right.
Line 220. IF left cursor key THEN move left.
Line 230. IF down cursor key THEN move down.
Line 240. IF up cursor key THEN move up.
Line 250. IF cursor is now off the screen THEN send it to upper right
corne~.
Line 260. IF last move hits the target, OOTO the Keep Score section
at Line 300.
Line 270 places a white heart at the new cursor position.
Line 280 says OOTO Line 190 and wait for another key.
The subroutines are called up in Lines 160, 170, and 270. In BASIC:
149 REM *** MAIN LOGIC ***
150 PRINT" [!] " : REM *** CLEAR SCREEN
160 GOSUB 50
170 GOSUB 100
180 LET SC = TI
190 GET AS : IF AS = "" THEN 190
200 LET CD = ASC(AS)
294- POKE CP + 55296,9
210 IF CD = 29 THEN CP = CP + 1
220 IF CD = 157 THEN CP = CP-1
230 IF CD = 145 THEN CP = CP-40
240 IF CD = 17 THEN CP = CP+40
250 IF CP<0 OR CP> 1000 THEN CP = 1
260 IF CP = W THEN 300
270 GOSUB 110
280 GO TO 190
See? There really is some English behind all that code. Let's take a closer
look at the subroutines.
43
SUBROUTINES
Subroutines (defined in Chapter 7, pages 5-6) aren't really needed,
in this (relatively) short program, but because the program is designed
to grow, they will prove useful. Using subroutines is partly a matter of
style, and, like all programmers, you will develop your own style.
The GOSUB command we have used is essentially the GOTO com-
mand with a special feature attached. Like GOTO, GOSUB makes the
computer branch off to the indicated program line (e.g., GOSUB 19
means go to the subroutine beginning at Line 19). The special feature
involves the RETURN command at the end of the subroutine. The com-
puter automatically returns to the next line after the GOSUB statement
that sent it to the subroutine in the first place. Thus, you can use GOSUB
to call the same subroutine from different parts of a long program, and
the computer will always come back to the right line to continue the
program.
The first subroutine we need is:
19 REM *** PICK A POINT ***
20 CP = INT(RND(0)* 1000)
35 RETURN
This subroutine chooses a random number and assigns it to the variable
CP. CP takes on one of 1000 binary code values, each code value
representing one of the 1000 locations on the 64's screen. The RETURN
on Line 35 then sends the program to the next line after the one that
called the subroutine. In essence this subroutine chooses for us a loca-
tion on the screen when we need one.
Remember, though, all subroutines called by a GOSUB call must end
with a RETURN statement.
44
RUN this demonstration and 64K or no 64K, you run out of memory!
Now change Line 12 to:
12 RETURN
Now RUN it. Hmmm ... RETURN without GOSUB error?
The problem is that after the first successful subroutine call, the pro-
gram returns to Line 3, then Line 11 and - aha - hits that RETURN
without having been sent by a GOSUB call. The moral of the story is
that subroutines have to be blocked off from the rest of the program.
A NESTED SUBROUTINE
The next subroutine is a bit longer:
49 REM *** SET LETTER ***
59 GOSUB 29
69 A = INT(RND(9)*26) + 1
79 W = CP
89 POKE CP + 1924,83
99 POKE CP + 55296,1
95 RETURN
The Set Letter subroutine first calls the Pick Point subroutine to get
a location on the screen (these are the nested subroutines). It then puts
a randomly chosen letter at that location. Line 60 gives us a screen display
code that corresponds to a letter in the alphabet. (See Appendix E, page
132 of the User's Guide for more screen display codes.)
The next subroutine really serves as two, depending on which line the
computation enters it. If you enter at Line 100 the cursor will be placed
randomly. If you enter at Line 110 the computer will update the cursor
position according to which cursor key you have just pressed while the
game is on. Line 120 sets the color to white.
99 REM *** GET CURSOR ***
100 GOSUB 29
119 POKE CP + 1924,83
129 POKE CP + 55296,1
125 RETURN
45
The final section of the program is not reached by a GOSUB; here
GOTO works fine: we don't want to RETURN after the score is tallied;
we want to go back and improve our cursor control response time. The
delay loop in Line 310 allows you enough time to read your score.
299 REM"* KEEP SCORE ***
300 PRINT "YOU TOOK";(TI - SC)/60;"SECONDS"
310 FOR I = 1 TO 1500 : NEXT
333 GOTO 150
ALPHA-CURSORY CURSOR
That's that, but let's add a module to expand the game. Now after
you reach the letter on the screen, the clock doesn't stop until you press
the letter on the keyboard. We first change Line 260 to:
260 IF CP = W THEN 500
and add:
500 REM .. * ALPHA MODULE .. *
510 Q = PEEK (W + 1024)
520 Z$ = CHR$(64+Q)
530 GET A$ : IF A$ = "" THEN 530
540 IF A$ = Z$ GOTO 300
550 GOTO 530
560 REM
46
CENTIPEDE
If you fmd the time, here's a program that shows how you might trade
in the heart symbol for a centipede. Right now the program is an isolated
block, but you can access these new subroutines by adjusting the main
logic unit.
5 REM *** CENTIPEDE ***
10 INPUT A
20 PRINT " ~ " : REM *** CLEAR SCREEN
30 FOR P = 1 TO 20
40 FL = INT ««P /2) - INT (P /2»*2) + .5)
50 SN = 1 - 2 * FL
60 FOR J == 0 TO 39
70 CH = (40*P) + (39*FL) + (SN* J)
80 POKE 1024+ CH,81
90 POKE 55296+CH,1
100 IF J > == A THEN POKE 1024 + (40*P) + «J - A)*SN) +
(39*FL),32
110 IF J<A THEN POKE 1024+(40*(P-l»+«A-J)*SN)+
(39*FL)-SN,32
120 FOR T = 1 TO 10 : NEXT
130 NEXT: NEXT
47
Tired of playing catatonic to the computer's dogmatic?
Try ...
9 Number Theory I
In this chapter we put the computer to work doing the kind of tasks
it does best: repeated performance of simple procedures. Ever wonder
what the sum of the first 1000 odd numbers was? Probably not. But
the ideas behind the solution to such a problem are central to many in-
teresting programs. Let's go ahead and see what we can do with the first
1000 odd numbers.
One of the simplest programs for adding up those numbers is:
19 FOR Q = 1 TO 1999 STEP2
29 LET S = S+Q
39 NEXT Q
49 PRINT "THE SUM IS ";S
When you RUN this program you will get 1,000,000. This answer seems
suspicious. Did we really get the first 1000 odd numbers? How can we
be sure that there weren't 999 by mistake? To check this we can put
tracers into the program as we did in the coin flip program in Chapter
6. Add the following lines:
2S COP = COP+ 1
27 PRINT S,Q,COP
3S PRINT "THE COUNTER IS AT ";COP
The variable COP enters the FOR/NEXT loop with a value of"
(another example of initialization). In the first pass through the loop,
COP gets incremented to one: that's what we want because this is pass #1.
Line 27 gives us an interim status report on our variables. This will
48
slow our computation because the computer has to stop and print
numbers on the screen. But seeing our values helps make the program
more transparent. (Reminder: the two commas separating the three
variables tell the computer to separate what it is printing.)
When you RUN the program now, you will see three lines of numbers
scrolling up your screen. The righthand column is the number of loops
so far; the center contains the current odd number; and the left column
contains our running sum. After a while the program halts and the bot-
tom of our three colums look like this.
996004 1995 998
998001 1997 999
1000000 1999 1000
THE COUNTER IS AT 1000
THE SUM IS 1000000
Now we can have more confidence in our answer because the counter
shows that we have indeed added 1000 numbers. Let's check further to
see if there are any hidden logical errors in our program. A H~OO-pass
loop is somewhat unmanageable, so let's make the program smaller.
Change Line 10 to:
10 FOR Q = 1 TO 9 STEP 2
All the results now fit on the screen and should look like this:
111
432
9 5 3
16 7 4
25 9 5
THE COUNTER IS AT 5
THE SUM IS 25
The third column indicates that we have passed through the loop five
times. The second is the list of numbers that we want to add: it does
indeed contain the first five odd numbers. And there's no arguing that
the sum of these numbers is 25. The first column gives a running sub-
total, and ends where it should with 25. The case is now pretty strong
that our answer of 1,000,000 for the first 10000 odd numbers is correct.
49
Let's use this program one more time to add up the first 500 odd
numbers. (Note that this is not the same as the sum of odd numbers
from 1-500.) Change Line 10 again so it looks like:
10 FOR Q = 1 TO 999 STEP 2
When you RUN the program, time it with a watch or clock. We will
then delete Line 27 and see how much time that PRINT statement is
using. What's the answer?
THE COUNTER IS AT 500
THE SUM IS 250000
Hmmm ... adding up half as many numbers gives one-quarter the sum.
The computation took about 40 seconds. Erase Line 27 by typing 27
on any empty line and hitting [RETURN]. Now get out your timepiece
again: pretty impressive improvement!
EVEN STEVEN
Let's try something else. What is the sum of the first 1000 even
numbers? A very simple modification of our program can handle this.
For this run, we'll let the computer keep time with its internal clock.
But we must decide: is zero or two the first even number? For the
moment we'll say that two is the first. Since this program takes so long,
we'll work with the first 500 even numbers:
5 SC = TI
10 FOR Q = 2 TO 1000
20 S = S+Q
25 COP = COP+ 1
27 PRINT S,Q,COP
30 NEXTQ
35 LET SC = (TI - SC)/60
40 PRINT "THE COUNTER IS AT ";COP
50 PRINT "THE SUM IS ";S
60 PRINT "COMPUTATION TIME: ";SC;" SECONDS"
The variable TI is a reserved variable in BASIC that always contains
the current value of the clock. This variable increments at lI60-second
50
intervals. PRINTing the current value of TI tells you how long your
computer has been turned on. Find an empty line and type:
PRINT TI/3600
The number appearing on the next line is the number of minutes your
computer has been on.
RUN your program. My computer took 36.533333 seconds (or so)
to add the first 500 even numbers. What happens when we erase Line
271 This time my computer took 3.716666673 seconds: a tenfold
improvement.
Amend Line 10 to find the sum of 2 + 4 + 6 + 8 + 10 + 12 +
14 + ... + 1000.
51
A single note well played is a thing of beauty ...
SOUND SAMPLER
Let's begin with a program that allows you to create a musical note
by pressing any letter or number on the keyboard. Type in the program,
RUN it, then press any letter or number on your keyboard and see what
happens.
One important note before you begin: to exit this program, press the
[RUN/STOP] key. Otherwise, you will continue to get notes every time
you touch a key.
52
5 REM *** SID's Single Solo Sound Sampler ***
10 FOR M = 54272 TO 54296 : POKE M,O : NEXT
15 GET A$ : IF A$ = '''' THEN 15
20 POKE 54296,15
30 POKE 54277,9 : POKE 54278,64
40 POKE 54273,28 : POKE 54272,49
50 POKE 54276,17
60 FOR DR = 1 TO 350 : NEXT
70 POKE 54276,16
75 GOTO 15
53
Clear the Chip
Line 10. As we have seen, memory always holds a lot of leftover in-
formation so it's a good idea to start each sound program by clearing
the SID chip memory. SID is organized much like the VIC II in that
a section of RAM addresses (54272-54296 inclusive), serves as a SID
switchboard. The statement:
H' FOR M = 54272 to 54296 : POKE M,e : NEXT
POKEs a zero into each SID switchboard address register, thereby clearing
the switchboard.
The GET Statement
Line 15. We used this commmand in Cursory Cursor. The line:
15 GET A$ : IF A$ = "" THEN 15
instructs the computer to GET the last key pressed, if any; if none, keep
trying.
Setting Volume Controls
Line 2e sets the volume at 15. You have a choice of 0-15 volume set-
tings; 15 is the loudest and most frequently used. Numbers larger than
15 influence certain filters that can be used in more advanced program-
ming. For now, however, stick with 15. Also, note that one volume set-
ting governs all three voices.
Setting ADSR Controls
Line 30 sets the ADSR, or Attack, Decay, Sustain, Release. POKE
54277,9 controls the note's attack and decay; POKE 54278,64 controls
its sustain and release. These two settings affect the coloration of your
sound. They control the loudness of the sound at different points dur-
ing its production, forming what is called an envelope - hence the name
''Envelope Generator."
The Attack is the beginning of a sound; it controls how rapidly the
sound rises to peak volume. The Decay controls the time it takes for
the volume to come down to the middle level, which will be defined and
then sustained by your sustain setting. Finally, the sound will decay down
to nothing; the time this takes is the release time. Drums, for example,
have an explosive attack and a rapid decay with little sustain. Bowed
violins, on the other hand, can have a slow, steady attack, sustain over
a long period, and then fade away with a slow release.
54
You will notice that one number controls both the Attack and Decay,
while another number controls the Sustain and Release. That's because
they are additive.
Attack/Decay Control Numbers
Each voice has a POKE number for its Attack/Decay control setting:
Voice 1, POKE 54277; Voice 2, POKE 54284; Voice 3, POKE 54291.
Following the POKE number is a comma, and then a number between
o and 255 that encodes the combined Attack and Decay. The control
is built around the numbers 1,2,4,8, 16, 32,64, and 128, the decimal
equivalents of the bits in the voices' address register. The first four
numbers control the Decay; the last four numbers, the Attack.
You can add any, all, or none of your Attack numbers together for
your attack range, i.e., 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160,
176, 192, 208, 224, 240; 240 is the maximum Attack setting. You can
also add any, all or none of your Decay numbers; thus, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 are all possible Decay settings. To
encode your final setting, add the Attack number to the Decay and enter
the sum; the computer will do the rest.
Here are some examples: the command POKE 54277,73 means set
the Attack at 64 and the Decay at 9 for Voice 1. POKE 54284,63 means
set Attack at 48, Decay at 15 for Voice 2. In our sample program, we
used POKE 54277,9, which sets the Attack at 0 and the Decay at 9 for
Voice 1.
Sustain/Release Control Numbers
The Sustain/Release setting functions much the same as the Attack/
Decay. The higher numbers-128, 64, 32, 16-control the Sustain, and
the lower numbers-8, 4, 2, I-control the Release. The same rules hold
for entering your setting. Thus, POKE 54278,137 means set Sustain at
128 and release at 9 for Voice 1.
Creating An Envelope
Because the Attack/Decay settings interact with those for Sustain/
Release, finding the right combinations can be tricky. Why not try a
few in your program? Try to be systematic. For example, try the maxi-
mum Attack of 240; then try 128, then 16, then 0. Surprised? As you
see, the maximum Attack does not necessarily mean maximum sound.
Now try the Decay settings 15, 9, 4, 0. After that, try a few combina-
tions such as 240 and 15, or 128 and 9. As you can hear, they are all
different.
55
Now, set your AttacklDecay back to 64 and test your SustainlRelease
setting. Try 240, 128, 64, 16, 15, 9, 4, 0; then try combination settings
such as 255,68 or 20. As you can hear, the Sustain number has a great
deal of influence over how loud and long the middle part of your note
sounds. If you use 128, the note tends to stay loud much longer than
when you use 16, even though the overall duration of the note is the same.
Now for the big surprise: start combining your AttacklDecay and
SustainlRelease settings. Once again, try to be systematic. Try 240 AID
with 240 SIR, then keep the 240 AID and try 128 SIR, etc. For exam-
ple: set AID at 9, SIR at 0, 16, 128, and 240. Next, set your SIR at
o and try AID at 9, 89, and 137.
Setting Pitch Controls
Now that you have a handle on the ADSR, let's change the pitch,
or frequency of vibration. This is done in the next line of SID's Single
Solo Sound Sampler.
Line 40 has two POKE statements. The first, POKE 54273, sets the
high bit frequency number of Voice 1, while the second, POKE 54272,
sets the low bit frequency for Voice 1. Each pitch requires a high fre-
quency number and a low frequency number, which are listed in the
Table of Note Values in the Appendix. Right now, the frequency is set
for A-440, which is the A in the 4th octave. If you wanted to play the
A in the 6th octave, you would look up A-6 in your Table of Note Values
and see that the high setting is 112 and the low setting is 199. Tryenter-
ing these new values in Line 40.
The SID has an eight-octave range. Try a low note such as D-2. Go
to the Appexndix again: the high number is 4, the low is 180. Enter these
new values. It's that simple.
If you wanted to program the pitch for Voice 2 or 3, you would follow
the same procedure, using different POKE numbers. For Voice 2, the
high bit frequency number is preceded by POKE 54280, and the low
number is preceded by POKE 54279. For Voice 3, you would use POKE
54287 for the high and POKE 54286 for the low.
56
sounds-mellow and organ-like-because it's the one we've been using
up until now. You turn on the triangle waveform by POKEing 54276
with the number 17. You turn it off by POKEing 54276,16. Waveform
settings are the same for all voices. In other words, a triangle waveform
is always 17 -only the POKE number changes. So POKE 54283,17 turns
on the triangle waveform for Voice 2 and POKE 54290,17 sets the triangle
for Voice 3.
White Noise Waveform
Lefs dramatically change the sound by using the "white noise"
waveform. To do this, just go to SID's Sampler, and change the 17 in
Line 50 to 129. Also change Line 70 so that the 16 is now 128. Sur-
prised? You would use this waveform for many videogame sound ef-
fects. You can make explosions, crash noises, rattles, shots, and hisses.
Try different ADSR settings along with this white noise waveform. Now
try pressing a key many times in quick succession. Don't be afraid to
experiment; who knows what you may discover?
Sawtooth Waveform
Let's return to a more musical electronic sound with the "sawtooth"
waveform. Just go to your program and change the 129 on Line 50 to
33. Also change Line 70 so that the 128 reads 32. As you can hear, the
sawtooth waveform has a kind of buzzing quality. Try it with a few
different ADSR settings: AID 9, SIR 0; AID 25, SIR 9. They both
have a "harpsichord" sound. Now try AID 137, SIR 128.
Pulse Waveform
The final waveform available to you is the ''pulse.'' It is a bit more
difficult to use and requires two extra POKE statements: you must POKE
in a high pulse number and a low pulse number. Listen to what hap-
pens if you forget by changing Line 50 from POKE 54276,33 to POKE
54276,65. Also edit Line 70 so that the 32 now reads 64. When you RUN
this version, you should get a low, buzzing and thunking. Now add this
line to your program:
45 POKE 54275,8 : POKE 54274,255
See what a difference it makes?
Try experimenting with high pulse and low pulse numbers. The one
rule you must follow is that the high pulse number must be between
o and 15 inclusive; the low pulse can be between 0 and 255. The same
rule applies when using Voices 2 and 3. Once again, only the POKE
57
number will change; the settings are identical. For example, POKE
54283,65 to tum on the pulse waveform for Voice 2; then POKE 54282,8
for the high pulse number, and POKE 54281,255 for the low pulse
number. For Voice 3, POKE 54290,65 to tum on the pulse; POKE
54282,8 for the high pulse number and POKE 54281,255 for the low
pulse number.
Now go back to the original triangle waveform. (Don't forget to remove
Line 45.)
One final note: always set your ADSR be/ore turning on the waveform
control. That is essential because the ADSR cycle is triggered by the
waveform gate that opens when you tum on a note.
Controlling Duration
We have seen how a note is built electronically by setting its volume,
envelope, and waveform. Our final control in this program is the
duration-how long the note lasts.
Line 60 is a simple time loop. It tells the computer how long to hold
the note before going on to the next statement. If you want the note
to last for a shorter period, just decrease the time loop. Go to your pro-
gram and change Line 60, for example, from FOR DR = 1 TO 350 :
NEXT to FOR DR = 1 TO 50 : NEXT. If you want to make the note
last longer, try FOR DR = 1 TO 750 : NEXT.
Ending Notes By Closing The Gate
Line 70 turns off the note by closing the waveform gate. To do this,
we POKE in the waveform control for Voice 1, setting it at a number
one less than the starting waveform-e.g., 16 to tum off 17,32 to tum
off 33, 64 to tum off 65, and 128 to tum off 129. The closing of the
waveform gate triggers the release cycles of the ADSR.
Line 75 sends the program back to Line 15. You may notice a residual
noise after each note. This can be avoided by going back to Line 10
instead of Line 15. This will clear the chip. Unfortunately, it will also
cause a clicking noise. The choice is yours.
Multiple Voice Samplers
Now that you have control of the sound, try changing SID's Single
Solo Sound Sampler into SID's Double Duo Sound Sampler by adding:
22 POKE 54284,9 : POKE 54285,O
58
42 POKE 54283,33
72 POKE 54283,32
Or how about adding these lines for SID's Triple Trio Sound Sampler:
23 POKE 54291,125 : POKE 54292,64
33 POKE 54287,50 : POKE 54286,60
43 POKE 54290,17
73 POKE 54290,16
You can now experiment with chords and multiple-voice sound effects.
Try having all the notes play the same pitch, but with different waveforms
and envelopes.
59
Part II
60
100 OOTO 40
200 DATA 7,12,200,7,233,300,8,225,300,9,247,250,11,48,250,12,
143,250,14,24,200
210 DATA 15,210,200,17,195,200,19,239,150,22,96,150,25,30,150,
28,49,100
220 DATA 31,165,200,35,134,100,39,223,50,44,193,50,50,60,50,56,
99,1750
230 DATA -1,-1,-1
900 POKE 54276,0
Here is a line-by-line explanation of SID's Whole Tones.
Line 5 is a REM statement for the title.
Line 10 clears the SID Chip.
Line 20 sets the volume at maximum.
Line 30 sets the Attack/Decay at 9, the Sustain/Release at 0.
Line 40 is a READ statement. It tells the computer to read the first
three elements stored in the DATA bank and names them H, L, and
DR. Each time the computer passes the READ statement (see Line 100),
it READs in the next three DATA values. A pointer keeps track of which
value comes next.
Line 50 is an IF/THEN statement that tells the computer to go to
Line 900 if the value of H is less than 0. If you look at DATA Line
230, you will see - 1, - 1, - 1. This line is called a flag. Since - 1 is less
than 0, when the computer READs this line it will execute Line 900.
It's good idea to store as many elements in your FLAG as called for
in your READ statement - three, in this case.
Line 60 POKEs in the high frequency number for Voice 1 and assigns
it the value of H. It then POKEs in the low frequency number with the
value L, the next variable in DATA.
Line 70 turns on the triangle waveform for Voice 1 and starts the note.
Line 80 is a timing loop for each note. It means that the duration
of each note will equal 1 to DR. DR will be READ as the third element
in DATA.
Line 90 turns off the note or waveform in Voice 1.
Line 100 says go back to Line 40 and run through the program again.
This time, however, the READ statement will take the next three variables
in DATA.
Lines 200-230 encode the high frequency number, low frequency
61
number and duration for each note. When entering DATA, always
remember to type the word DATA after the line number. Place a com-
ma after each variable but do not place a comma after the last variable
in any given line; just hit [RETURN]. Always carry your numbers out
40 columns on your screen when entering long DATA statements; your
Commodore 64 will automatically advance the numbers down to the
next line on the screen. It's OK if a number starts on one line and finishes
on another. Finally, never exceed two display lines (80 columns) of
numbers for any single DATA grouping; your computer can handle only
80 columns at a time.
Line 900 turns off the sound.
If you want to play the tones over again, just add these two lines:
910 RESTORE
920 GOTO 40
Line 910 resets the memory pointer back to the first number in your
DATA statements, thus re-storing your DATA.
Line 920 sends the computer back to reREAD the DATA and play
it again.
To stop those whole tones, hit [RUN/STOP].
Now that you have the format of this program, you can use it to com-
pose other songs; all you have to do is change the DATA. For example,
here's a familiar song, "Oh, Susannah," played on our synthesized banjo.
OH, SUSANNAH!
5 REM *** OH SUSANNAH BY STEPHEN FOSTER ***
10 FOR M = 54272 TO 54296 : POKE M,0: NEXT
20 POKE 54296,15
30 POKE 54277,7 : POKE 54278,5
40 READ H,L,DR
50 IF H<0 THEN 900
60 POKE 54273,H : POKE 54272,L
70 POKE 54276,33
80 FOR T = 1 TO DR : NEXT
90 POKE 54276,32
62
95 FOR B = 1 TO 34 : NEXT
100 GO TO 40
200 DATA 18,209,75,21,31,75,23,181,150,28,49,150,28,49,225,31,
165,75
210 DATA 28,49,150,23,181,150,18,209,225,21,31,75,23,181,150,
23,181,150
220 DATA 21,31,150,18,209,150,21,31,450,18,209,75,21,31,75,23,
181,150
230 DATA 28,49,150,28,49,225,31,165,75,28,49,150,23,181,150,18,
209,225
240 DATA 21,31,75,23,181,150,23,181,150,21,31,150,18,209,900
250 DATA - 1, - 1, - 1
900 POKE 54276,O
Line 95 is a second time loop inserted between notes to make the banjo
articulation crisper.
Now that you've sampled what the SID can do, you're ready for "SID's
Song," which combines sound effects, multiple voices, and color graphics.
But first, here are a few suggestions to save typing time. You can ab-
breviate the word POKE by typing P then [SHIFT]:[O] (see Appendix
o in the User's Guide). The shifted 0 will produce a graphics symbol,
but when you LIST your program, the computer will print POKE. You
can shorten the POKE numbers by entering S = 54272 at the beginning
of your program; then all you have to do is enter POKE S + a number.
63
Thus, POKE S + 24 means POKE 54296, while POKE S + 5 means
POKE 54277. (You don't have to use the letter S - we just use it to stand
for SID.)
5 REM *** SID'S SONG BY J.e.VOGEL ***
10 S = 54272
20 FOR M = 0 TO 24: POKE S+M,0 : NEXT
30 POKE S + 0,240 : POKE S + 1,33
40 POKE S + 5,9 : POKE S + 6,0
50 POKE S+24,15
60 FOR B = 1 TO 2
70 POKE S+4,129
80 FOR X = 1 TO 500 : NEXT: POKE S+4,128
90 FOR X = 1 TO 30 : NEXT : NEXT
110 POKE S+5,9 : POKE S+6,0
120 POKE S+12,102: POKE S+13,0
140 READ Hl,Ll ,H2,L2,BR,BG,DR
150 IF HI < 0 THEN 910
160 POKE S+ I,HI : POKE S+0,Ll : POKE S+8,H2 : POKE
S+7,L2
165 POKE 53280,BR : POKE 53281,BG
170 POKE S+4,17 : POKE S+ 11,17
180 FOR T = 1 TO DR : NEXT
190 POKE S+4,16 : POKE S+ 11,16
210 GOTO 140
300 DATA 56,99,25,30,0,15,200,50,60,37,162,0,14,200,75,69,18,
209,1,14,200
310 DATA 63,75,29,223,1,13,200,59,190,50,60,2,13,200,59,190,22,
96,2,12,200
320 DATA 63,75,28,49,3,12,200,75,69,28,49,3,11,200,50,60,22,96,
4,11,200
64
330 DATA 56,99,50,60,4,10,200,56,99,29,223,5,10,200,50,60,18,
209,5,9,200
340 DATA 75,69,37,162,6,9,200,63,75,25,30,6,8,200,59,90,25,30,
7,8,200
350 DATA 59,190,37,162,7,7,200,63,75,18,209,15,0,200,75,69,29,
223,14,O,200
360 DATA 50,60,50,60,14,1,200,56,99,22,96,13,1,200,56,99,28,49,
13,2,200
370 DATA 50,60,28,49,12,2,200,75,69,22,96,12,3,200,63,75,50,60,
11,3,200
380 DATA 59,190,29,223,11,4,200,59,190,18,209,10,4,200,63,75,37,
162,10,5,200
390 DATA 75,69,25,30,9,5,200,50,60,25,30,9,6,200,56,99,37,162,
8,6,200
400 DATA 56,99,18,209,8,7,200,50,60,29,223,7,7,200,75,69,50,60,
7,6,200
410 DATA 63,75,29,96,5,6,200,59,190,28,49,5,5,200
900 DATA -1,-1,-1,-1,-1,-1,-1
910 RESTORE
920 FOR T = 1 TO 250 : NEXT
930 GOTO 30
Now let's examine the program.
Line 10 assigns 54272 to the letter S.
Line 20 clears the sound chip.
Line 30 to Line 100 creates the sound effect twice.
Line 30 sets the frequency.
Line 40 sets the ADSR.
Line 50 sets the volume.
Line 60 sets up the repetition.
Line 70 turns on the white noise waveform.
Line 80 controls the duration of the effect, then turns off the
waveform.
65
Line 90 tells the computer to wait and then do it a second time.
Lines 1H}-2I0 set up the same song format as "Oh, Susannah," only
this time we added a second voice and the POKE statements control-
ling border and background color.
Line 110 sets the ADSR for Voice 1.
Line 120 sets the ADSR for Voice 2.
Line 140 tells the computer to read the fIrst seven numbers in the DATA
bank and assign them variable names: HI (high frequency 1), LI (low
frequency 1), H2 (high frequency 2), L2 (low frequency 2), BR (border),
BO (background), DR (duration).
Line 150 instructs the computer to go to Line 910 if HI is less than 0.
Line 160 POKEs the high and low frequency numbers for Voices 1
and 2.
Line 165 POKEs values for screen border and background colors.
Line 170 sets the waveform for Voices 1 and 2.
Line 210 tells the computer to go back to Line 140 and READ in the
next note color and duration.
Lines 300-410 are DATA numbers for HI, LI, H2, L2, BR, BO, D
(each note's color).
Line 900 is part of the DATA bank, the flag to break out of the
READ/DATA loop.
Line 910 restores the DATA.
Line 920 tells the computer to wait.
Line 930 tells the computer to go back to Line 30 and play again.
To break out of this program, you must hit the [RUN/STOP] key.
If you want to have a little fun with this program, try hitting
[SHIFT):[CLRlHOME]. Now, press [CTRL]:[9] and the space bar, then
[CTRL] and a number between 1 and 8. Scatter a few color bars around
the screen. Now, re-RUN the program: different colors will appear and
disappear during the song.
Playing music on a computer is like playing music on an instrument:
it takes time and patience to learn. As your programming skills grow,
you will find more and more ways of shaping sounds. Experimenting
with new ideas is the secret of success.
NICK'S FAVORITE
Here's a program for all three of the SID voices - "Swing Low Sweet
Chariot" in three-part harmony. In it we've used the jiffy clock for keeping
time instead of a FOR/NEXT time loop. Each DATA line in this pro-
66
gram encodes the duration as well as the high and low frequency numbers
for each voice.
PRINT"~ "
5 PRINT "SWING LOW SWEET CHARIOT (TRAD)"
10 PRINT "MUSIC ARRANGED BY JIM VOGEL"
100 M = 54272
110 POKE M+24,15
120 POKE M+5,9: POKE M+6,0
130 POKE M + 12,26 : POKE M + 13,36
140 POKE M+ 19,24: POKE M+20,202
150 T = TI
160 POKE M+4,32 : POKE M+ 11,32: POKE M+ 18,16
170 READ X: IF X<0 THEN 690
180 READ H1,Ll,H2,L2,H3,L3
190 POKE M + 1,H1 : POKE M,Ll : POKE M + 4,33
200 POKE M+8,H2 : POKE M+7,L2 : POKE M+ 11,33
210 POKE M+ 15,H3 : POKE M+ 14,L3 : POKE M+ 18,17
220 T = T+X
230 IF T > TI GOTO 230
240 GOTO 160
300 DATA 30,28,49,33,135,5,152
310 DATA 60,22,96,14,24,0,0
320 DATA 30,28,49,33,135,5,152
330 DATA 45,22,96,29,223,9,104
340 DATA 15,22,96,0,0,0,0
350 DATA 15,18,209,29,223,0,0
360 DATA 45,16,195,10,143,6,71
370 DATA 15,22,96,16,195,7,12
380 DATA 15,22,96,11,48,0,0
390 DATA 15,22,96,14,24,9,104
67
400 DATA 15,22,96,11,48,O,O
410 DATA 15,28,49,21,31,8,97
42O DATA 15,33,135,O,O,O,O
43O DATA 3O,33,135,21,31,7,12
44O DATA 3O,33,135,22,96,8,97
45O DATA 3O,O,O,O,O,18,209
46O DATA 3O,O,O,21,31,16,195
49O DATA 3O,O,O,O,O,14,239
500 DATA 15,37,162,22,96,14,24
510 DATA 15,33,135,O,O,14,24
52O DATA 6O,28,49,O,O,16,195
53O DATA 3O,33,135,22,96,9,247
54O DATA 45,22,96,14,239,9,104
55O DATA 15,22,96,14,239,9,104
56O DATA 15,18,209,O,O,O,O
57O DATA 45,16,195,14,239,1O,143
58O DATA 15,22,96,16,195,11,48
59O DATA 15,22,96,O,O,O,O
600 DATA 15,22,96,18,209,9,104
610 DATA 15,22,96,O,O,O,O
62O DATA 15,28,49,18,209,7,119
63O DATA 15,28,49,O,O,O,O
64O DATA 3O,25,3O,14,239,8,97
65O DATA 3O,22,96,14,24,11,48
66O DATA 3O,O,O,O,O,8,97
67O DATA 3O,O,O,O,O,5,152
675 DATA -1
68O DATA -1
69O C = C + 1 : IF C = 2 THEN 1000
700 RESTORE
68
710 FOR J = 1 TO 200 : NEXT
720 GOTO 150
1000 FOR Z = M TO 54296 : POKE Z,0 : NEXT Z
Here's a line-by-line description.
Line 1 clears the screen.
Line 5 prints the title.
Line 10 prints the arranger's name.
Line 100 sets M at 54272.
Line 110 sets master volume at 15
Line 120 sets ADSR for Voice I.
Line 130 sets ADSR for Voice II.
Line 140 sets ADSR for Voice III.
Line 150 sets the variable T equal to the value of the jiffy clock.
Line 160 turns off the wavefomi for Voices I, II, and III.
Line 170 READs the first piece of information in the DATA, which
is given the variable name X and represents the duration number. If the
value of X is less than 0 then go to Line 690.
Line 180 READs the next 6 pieces of DATA and assigns them the
variable names-I, Ll, H2, L2, H3, L3, which represent the high and
low frequency numbers for Voices I, II and III.
Line 190 POKEs the high and low frequency number and turns on
the waveform for Voice I.
Line 200 performs the same function as Line 190 but for Voice II.
Line 210 performs the same function as Line 190 but for Voice III.
Line 220 sets up the duration by adding the duration value, read as
X from the DATA, to the variable T. T was equal to the jiffy clock
but is now greater by the value we have just added.
Line 230 holds the note on for the duration of time it takes the jiffy
clock to catch up to the new value of T.
Line 240 sends the computer back to Line 160 where it turns off the
note and begins the whole cycle over again.
Lines 300-670 contain the DATA encoded as the duration numbers
and the high and low frequency numbers for Voices I, II, and III.
Line 700 restores the DATA.
Line 710 is a time loop that puts a space between the first and second
times through the song.
Line 720 returns the computer to Line 150 where it resets the variable
T equal to the jiffy clock. Then the whole program begins its second pass.
Line 1000 turns off the sound chip.
69
There's a whole world of sound possibilities locked in the SID. If you'd
like to try more sound effects, skip ahead to Chapter 15, "Tricks of the
SID."
If you'd like to learn more about music programming and the electronic music
capabilities of your 64, try The Commodore Music Book by Jim Vogel and Nevin
Scrimshaw.
70
Pale jale shadows flashed red as the spacecraft lifted off ...
11 Real-Time Graphics
We are now ready to learn how to move sprites around the screen.
We will use two sprites in a program that can form the core of all kinds
of adventure programs. Since our task has many components, we'll have
to be organized.
The fIrst step is deciding what we want. How about a rocket that rises
off the ground and disappears with a deafening roar?
We'll begin with the task of moving sprites in block shapes. Later we
can adapt and experiment until we get our spaceship. Here goes:
5 REM *** SPACETREE ***
7 REM ********************
Hl POKE 53280,11 : POKE 53281,0
20 FOR M = 54272 TO 54296 : POKE M,0 : NEXT
30 PRINT" [!] " : REM *** CLEAR SCREEN
These first few lines present a typical problem: so many POKE com-
mands make it hard to keep track of what does what. You'll need some
careful bookkeeping to keep track of all those switchboard addresses-
keep a scratch pad handy and use REM statements liberally.
Line 5 displays the name of the our future adventure.
Line 10 sets the screen and border color.
Line 20 clears the SID chip's switchboard.
Line 30 clears the screen using [SHIFT]: [CLR/HOME].
The next group of program lines sets two constants for later use. M
is a sprite shape pointer and V is the starting address for the sprite switch-
board. Lines 40 and 50 set some of the sound addresses. For practice
71
you should check the use of these settings in the SID Chip Control chart
(see Appendix).
40 POKE 54272,64 : POKE 54273,33
50 POKE 54277,64 : POKE 54278,128
60 V = 53248 : M = 12288 : X = 125
We won't be using sound right away; these lines are inserted as a future
convenience. When we have the whole program running you can come
back and change the POKE values to get different sound effects.
TURNING ON SPRITES
We need two sprites for this job. That means doing some research
into the sprite portion of VIC II's video memory switchboard. First we
need to decide which of the eight sprites, numbered 9 to 7, to use. When
they move, Sprite 9 always passes in front of Sprite 2, Sprite 2 always
in front of Sprite 3, and so on; collisions never happen. Let's use Sprites
4 and 5; that way, if we later want to add a character that could pass
in front or in back of our spaceship, we have a sprite available for the job.
To turn these sprites on, we have to POKE the right value in address
register V + 21. This single byte, with its internal code of eight bits-
one for each sprite - controls which of the sprites is on and off at any
given moment. Remember learning to calculate the decimal values of
bytes in Chapter 7? Finding the right POKE value for turning sprites
on and off requires calculating the decimal value of the byte in address
register V + 21. Imagine the register looking like this:
Sprite # 7 6 5 4 3 2
o= off
1 = on o o 1 o o o o
box value 128 64 32 16 8 4 2 1
32 + 16 = 48
To find the POKE number that will turn on Sprites 4 and 5 and leave
the others off, add up the decimal values of the "one's" in the boxes
corresponding to Sprites 4 and 5. Then POKE that sum into address
V + 21. In this case we want 32 + 16 which equals 48, so the next line is:
70 POKE V +21,48
72
If you check the sprite switchboard chart in the Appendix, you will
note that the sprite color registers of 4 and 5 are V + 43 and V + 44. Let's
choose a color code from the color chart on the next page. Say you
choose 2. Then the following two POKE lines will make our sprites red.
80 POKE V+43,2: POKE V+44,2
The following line is temporary. It POKEs into memory the code for
the shape of our sprites. The variable M takes on the values of those
memory addresses where the shape of our two sprites is stored.
90 FOR Q = M TO M + 62 : POKE Q,255 : NEXT
We are almost ready for a test. All we have to do is to tell our sprites
where to go on the screen. These lines POKE in the X and Y coordinates
for both sprites.
99 REM *** MAIN LOGIC UNIT ***
100 POKE V+8,75 : POKE V+9,75
110 POKE V+10,125: POKE V+ll,125
That should do it for this pass. Type RUN and hit [RETURN]. Any
bugs? If you haven't made any syntax errors, your screen will show a
rather pale stationary sprite and also a flickering one. If you did mistype
something, go back and hunt it down.
A pale flicker is not what we really want in a sprite, so let's go down
the following checklist and see what we forgot.
1. Turn on sprites.
2. Set sprite color.
3. Define sprite shape.
4. Set sprite coordinates.
5. Set memory pointers.
If you go back through the program you'll see that we have inserted
program lines for the first four items on the list. But we did not set the
memory pointers, so there's more work to do.
MEMORY POINTERS
The memory pointer for any given sprite points the VIC II chip to
the right block in RAM to get the shape for that sprite. The pointer
value is multiplied by 64 to find the starting place of the block of ad-
dresses that the computer looks into to find the shape of your sprite.
73
We insert a solid square shape into block 192. This block inhabits ad-
dresses 12288-12350. (Note that 12288 = 64*192.) If you look carefully
at Line 90 you'll see that we fill the entire block of memory with the
value 255.
90 FOR Q = M TO M + 62 : POKE Q,255 : NEXT
Go back to the sprite chart and look up the registers that set the
memory pointers for Sprites 4 and 5; these are addresses 2044 and 2045.
The following line will set 192 into each pointer address.
75 POKE 2044,192 : POKE 2045,192
Let's test our correction. Find an empty line and type RUN, hold your
breath ... hit [RETURN]. If you have made no further mistakes you will
see two red squares on your screen.
LIST your program on the screen. Change the character color to white
by pressing [CONTROL]:[2] and LIST again. The sprites have priority
over characters so they cover any program lines that try to upstage them.
If this gets annoying just press [RUN/STOP:RESTORE], which will
clear the video switchboard and return you to the familiar blue screen.
Before we go back and tinker with our program, save it under the
name TEMPLATE 1. That way if you crash or wander too far with
additions and experiments you can always come back to a clean slate.
Get a clear LIST of the program if you haven't already, and we'll use
the screen editor to explore the sprite switchboard.
SWITCHBOARD TRICKS
Line 80 controls the color of our two sprites. (The color codes are
in the sprite switchboard chart in the Appendix.)
When you're ready, change the POKE values in Line 80 of the LISTed
program to read:
80 POKE V +43,3 : POKE V +44,7
Let's see what this does. Bring the cursor to a free line and reRUN
the program. Your sprites have changed color! Experiment with different
74
color codes. This might be a good time to adjust the color of your TV
set or monitor. Choose your favorite color; you'll want to use it later.
On and Off
Line 70 turned our sprites on; it can be edited to tum them off as
well. Use the screen editor to change the 48 on that line to 16, the box
number of Sprite 4. (Sprite 4 is the higher of the two sprites on your
screen.)
Now when you RUN the program the lower sprite will blink off. If
you change the number POKEd in Line 70 from 16 to 32, and RUN
the program again, the lower sprite will appear. But the other is now
turned off. To get them both back add 16 plus 32 to get 48, and replace
the 32 on Line 70 with 48. Hit [RETURN] (as usual) to make your change
official, and then test that both your sprites are switched on by RUNning
the program once again.
Controls For Sprite Size And Shape
Let's add a program line to see what vertical expansion is all about.
If you look in the switchboard chart, you'll see that there is a single ver-
tical expansion register for all eight sprites. We control this register the
same way we handled the register we just played with, V + 21 (called
the sprite enable register). Add the following line to the program:
120 POKE V+23,16
When you RUN the program now, Sprite 4 will suddenly grow. As
before, use the screen editor to change the 16 in Line 120 to 32. Now
RUN the program; Sprite 5 will be the tall one.
Finally, change that 32 to 32+ 16 which equals 48 (sound familiar?).
Now Line 120 POKEs 48 into V + 23, which will expand both sprites
at once. This line can be used later in a program as an on-and-off tog-
gle switch to expand and contract your sprites.
The following line will put in a toggle for horizontal expansion:
130 POKE V + 29,48
Experiment until you get a feel for the dimensions and color that the
sprites offer.
Moving our sprites involves changing the values in Lines 100 and 110.
This is somewhat simpler than what we just did because each sprite has
two whole addresses that control location. To make exploring these
registers a little easier, let's add a simple input loop. Change Line 100
to read:
75
100 POKE V+8,X: POKE V+9,Y
V + 8 is the register that holds the horizontal coordinate for Sprite
4; V + 9 holds the vertical. (Confirm this in the chart.) Note that V + 10
and V + 11 control Sprite 5; you'll need that fact later. Meanwhile, add
the following lines to the program:
199 PRINT" [!] " : REM *** CLEAR SCREEN
200 INPUT "X VALUE PLEASE:";X
210 INPUT "Y VALUE PLEASE:";Y
220 IF Y = 0 THEN END
230 GOTO 100
Now the program will prompt you to input different X and Y values
so as to move Sprite 4 around the screen. The sprite can move off the
screen to a point but if the numbers get too large you get a curt message
saying that you tried to slip in an illegal quantity. Play around with this
a bit. The sprite switchboard chart contains a description of the rules
of sprite positioning. When you are through, make sure the colors of
the sprites are different.
We will return to this program in the last chapter to finish this adven-
ture. Meanwhile, get used to the,sprite switchboard. See if you can go
through the checklist on page 73 and get Sprite 0 up and running.
Keep using 192 as the memory pointer until we have a chance to ex-
plain more about this extremely handy feature. Remember that 192 is
the value that points to the block occupying RAM addresses 12288
through 12350.
Meanwhile, here's a glimpse of how we can get our rocket to take
off after we have designed it. Type in the lines shown below. They will
replace the input loop, so if that version of the program appeals to you,
SAVB it now. Make sure that your sprites are different colors so that
one sprite can upstage the other.
98 FOR TT = 1 TO 54
199 REM *** BLAST OFF ***
200 U=U+l
210 Y = 235 - (INT(1.1 tU) + 42)
220 IF Y < 23 THEN POKE V +21,32 : END
230 NEXT TT
76
The surgeon leaned forward. He didn't like what
he saw in there. So with quiet determination
he excised it with a deft flip of the MID$ . . .
12 Microsurgery
77
another method to show you that blank spaces make perfectly good
strings. Add these lines to your program:
25 Z$ =" "
40 C$ = A$+Z$+B$
50 PRINT "SPOCK HERE; SPACES ADDED TO C$"
60 PRINT "C$ IS NOW" : C$
You can see from Line 60 that we use the same syntax for PRINTing
strings as we use for numbers. Go ahead, RUN the program.
If you really want a string of nothing, instead of spaces that look like
nothing, you must use ...
78
10 A$ = "4"
20 B$ = "5"
30 C$ = A$+B$
This program will not add the value four to the value five, but it will
concatenate the two symbols "4" and "5," making a new string "45."
MICROSURGERY: MID$(XX$,Y,Z)
We will now introduce a peculiar BASIC function that will help us
operate on a peculiar string variable to create an odd hexmas tree.
Do you remember using the TAB(X) function back in Chapter 3 to
scatter "NOW HERE NOW THERE" across your screen? The
MID$(XX$,Y,Z) function works much the same way: MID$ (like TAB)
tells the computer what to do; the values in parentheses specify how or
where to do it. MID$(XX$, Y,Z) cuts out a substring of XX$ starting
from position Y and containing the next Z characters. Remember, a space
counts as one position. To demonstrate:
130 MUD$ = "THE MIDDLE OF"
135 PRINT "MUD$ = ";MUD$
140 M$ = MID$(MUD$,5,6)
150 PRINT MUD$;" MUD$ IS ";M$
Line 150 is a little terse, but it should say: ''THE MIDDLE OF MUD$
IS MIDDLE."
ODD FORESTRY
Now for the surgery. The string going under the knife is "13579BDF."
No, this is not a license plate number; it is a bite-sized string of all the
odd single digits in the base 16 counting system (remember base 10 and
base 2 from Chapter 7?). Since people don't have any way of writing
more than 10 digits, we use letters for the digits 10-16. Thus, B is base
16 for 11, D is base 16 for 13, and so on. Base 16 numbers are called
hexadecimal numbers ("hexadecimal" means 16); they convert easily to
binary numbers (2 t 4 = 16) and are important in many programming
languages. Hence, our distinguished string consists of odd hex numbers-
just the thing for an odd hexmas tree!
79
B3B
*
DBDIF
33B7Dll
9F3B353FF
97551D3FF57
75D9353B7FBFD
FFDD75BBD71FBIB
17DFIFB9197913991
3D3FD3915BB7FD3DFF3
FD1797F3D91511BB3931D
Fl13F71BFBD715B5977D3D9
D5BIBBFBD3BF5DB993FID13B3
D53775DDBD799F9BD953DD555D9
7BIBFD79D5173DIB75B777B311BB9
9F7
793
755
FD3
7FB
D73
This program uses loops, the TAB function, and a little algebra to
print out a Christmas tree shape on the screen. The MID$ function will
splice out random digits from the string of odd hex numbers. Begin by
setting up the screen. For the two special symbols in Line 30 press
[SHIFT):[CLR/HOME) and [CONTROL): [6).
10 REM *** IT IS ODD ***
20 REM *****************
30 PRINT " [!J rn "
40 POKE 53280,6 : POKE 53281,1
50 A$ = "13579BDF"
60 FOR Q = 1 TO 39 STEP 2
79 COP = COP+I
89 FOR J = 1 TO Q
90 D$ = "*,,
100 PRINT T AB(20 - COP + J) D$;
129 NEXT J
130 PRINT
149 NEXTQ
80
If you RUN this program as it stands, it will print a handsome triangle
of asterisks.
The following lines define the tree's trunk. For the two special sym-
bols in Line 150 press the [SHIFT]:[LCRSR] and [COMMODORE]:[2]
combinations in Quote Mode. The fIrst key combination moves the cursor
up one line to counteract the very last PRINT in the loop. The second
turns the character color to brown.
150 PRINT" III U3"
160 FOR P ::: 1 TO 6
170 FOR Y ::: 1 TO 3
180 PRINT TAB (18 + Y)D$;
190 NEXT Y
200 PRINT
210 NEXTP
An ordinary tree. Now for some magic. Add the following subroutine:
220 STOP
499 REM *** GET A HEX ***
500 X::: INT(RND(0)*8) + 1
510 D$::: MID$(A$,X,I)
520 RETURN
RUN the program. What happened to the subroutine? We must call
it up; add:
90 GOSUB 500
175 GOSUB 500
There, an odd hexmas tree! Can you figure out how to put a star
at the top?
81
Days are numbered
13 Number Theory II
When we used the computer to add up the first 1000 odd numbers
(Chapter 9) and to build our odd hexmas tree (Chapter 12), we told the
computer what was even or odd. Now we pose the problem: how do
we teach our 64 to figure for itself whether a given integer is even or
odd? The key to this problem is to make the computer look for some
property of the integer in question. In other words, if an integer satisfies
one condition, it must be odd; if it satisfies another, it must be even.
We can apply the same process of checking for properties like odd
or even to detect whether a graphics character is on the edge of the screen.
Once the computer "knows" whether the character is on- or off-screen,
we can get a delightful display illustrating a classic example of probability
theory: the random walk.
EVEN OR ODD?
The computer can easily detect even or odd, but we need to .mpply
the clues. There are a number of ways to do this. We could ask the com-
puter to do an exhaustive search of all even numbers:
5 REM *** I DO IT ***
10 INPUT"NUMBER PLEEYUZ";N
20 W = W+2
30 IF N = W THEN GOTO 60
40 IF N = W - 1 THEN GOTO 80
50 GOTO 20
82
60 PRINT"IT IS EVEN"
70 STOP
80 PRINT"THAT'S ODD"
90 STOP
Line 20 keeps adding 2 to the variable W to get the next even number.
Line 30 checks to see if W equals our mystery number N. If it does,
the program skips to the PRINT statement on Line 30.
Line 40 checks to see if W is one greater than N. Since this can only
happen if W is odd, the program skips to the PRINT statement on Line
80. In both these cases the program proceeds to Line 90 and STOPs.
Line 50 is reached when the preceding two IF statements are false.
It simply says "go back and try the next even number."
The 64 will contentedly loop around all afternoon if need be. Try
inputting a value for N of say, 200. Hmmm ... how about something
faster than that!
What we need is some property that distinguishes between even and
odd numbers. Examine the following program:
100 REM·** I DO IT FASTER •••
110 INPUT" INPUT NUMBER";ZZ
120 IF ZZ/2 = INT(ZZ/2) THEN GOTO 140
130 PRINT"THE NUMBER ";ZZ;" IS ODD" : STOP
140 PRINT ZZ;"IS EVEN"
The key line is 120. When you divide an even number by two you
get a whole number. When you divide an odd number by two, 0.5 re-
mains in the result. Line 120 compares ZZ/2 to the INTeger portion
of ZZ/2. This is where the INT function goes to work. Recall that INT
function picks off the integer part of a number:
INT(33.12345) = 33
INT(0.999999) = 0
INT( - 22.00234) = + 22
Notice that the computer always takes the next lower whole number.
Line 120 uses the INT function to test whether a given number meets
our criterion for being even, i.e., ZZ/2 = INT(ZZ/2). If it does, the
program jumps to Line 140 and prints out the happy news. If not, the
83
program goes on to the next line, prints out the sad news, and STOPs.
Try our benchmark value of 200 to compare speed. Try a larger
number: this is more like it!
With this trick in hand, we are ready to take a drunken graphics bug
on a ...
RANDOM WALK
The rules for this exercise are simple. The bug starts at the center of
the screen. Every 10 seconds the bug has to decide whether to sway back
and forth for another 10 seconds or stagger in one of four directions.
We want to keep track of two things: how many times the bug gets back
to the starting point and, on average, how long it takes for the poor
thing to fall of the edge.
Note that if we start our bug in the center of the screen, the bug can .
disappear at left or right, in 12 straight steps.
A TEMPORARY RESPITE
Before we set the bug to walking, let's examine the POKE commands
for placing characters on the screen. The screen is divided into a 40 x
24 grid. Two blocks of memory addresses store the current screen display.
A 1000-byte block begins at address 1024. Each byte stores the binary
code for a particular location on the screen. Another 1000-byte block
starts at address 55296 and contains codes that determine the color of
the characters on the screen. (The Appendix of your User's Guide con-
tains Screen and Color Memory Maps.)
84
The following test will fill the screen with white A's.
10 D = 1024 : C = 55296
20 FOR X = 0 TO 999
30 POKE D+X,1 : POKE C+X,1 : NEXT X
40 STOP
It is a good idea to POKE the symbol code and the color code into
the same program line. If you wonder why, delete the second POKE
statement on Line 30. Now you are not specifying a code for color. Press
[RUN/STOP]: [RESTORE] and try RUNning the program.
PROGRAM DESIGN
For long programs, budgeting line numbers allows you to write pro-
grams in modules that you can test independently. Working out the
budget in advance helps keep your program organized. Here's the budget
for "A BUGS DILEMMA":
Line 10
Line 100 ] Initialize
Line 110
Line 200 ] Subroutines
Line 300
Line 400 ] Main Logic
Line 410
Line 500 ] Keep Score
85
tion sets up the screen and defines a constant that will start the bug off
in the middle of the screen. You can test the screen by putting in a tem-
porary Line 300 that contains a STOP:
300 PRINT"INIT IN IT" : STOP
Now the program will go through the initialization procedure when
you RUN it. When you're through testing, remember to erase Line 300.
86
Line 320 checks to see if the bug has tried to go off either the top
or the bottom of the screen. The criteria for that are a good deal simpler,
as you can see.
Now let's turn to the subroutine that determines where the bug will
step next:
109 REM *** TAKE A STEP ***
110 POKE CP+1024,108: POKE CP + 55296,7
120 LET L = INT(RND(0)*5)
130 IF L = 0 THEN CP = CP + 1
132 IF L = 1 THEN CP = CP - 1
134 IF L = 2 THEN CP = CP+40
136 IF L = 3 THEN CP = CP-40
150 RETURN
This is a straightforward use of conditional logic. The only subtlety
here is what happens if the variable L is given the value 4. Since none
of the conditions are met, the value of CP remains unchanged and the
bug sways back and forth for another 10 seconds unable to make up
its mind. The program will (barring your own bug) run now, so go ahead!
KEEPING SCORE
We will now insert a few more lines that create variables for keeping
score:
360 COP = COP + 1
365 IF CP = 500 THEN ET = ET +
Line 360 is a simple counter that increments every time the bug has
to make a decision. If we have assigned 10 seconds per step then the
total (simulated) time in seconds is COP* 10. The simulated time in
minutes is (COP*10)/60. Now we can add:
399 REM *** KEEP SCORE ***
410 PRINT"THE BUG TOOK ";(COP*I0)/60;"MINUTES"
420 PRINT"TO GO OVER THE EDGE " : PRINT
430 PRINT"THE NUMBER OF TIMES RETURNED HOME";
440 PRINT" IS ";ET
87
SHIP (TUG BOA T)
0, 0, 0
0, 0, 0
0, 0, 0
---
0, 0, 0
0, 0, 0
0, 0, 0
-0, -0, -0
0, 0. 0
0. 0. 0
0, 0, 0
12. 0. 0 • •
12 , 0, 0 • •
15.
15.
0.
0.
0
0
• • •
• • • ·•
255. 0, 14 • • • • • • • • • • »
127.255. 252
• • • • • • • • • • • • • • • "
• • • . »
63. 255.248
• • • '-;' • • • • • • • • • • • • • .. •
31.255.240 • • • • • • • • • • • • • • • • •
0. 0, 0
0, O. 0
0. 0,
88
The Chip That Launched A Thousand Shapes ...
14 Launching a Sprite
89
corresponded to a pixel, or video picture element. We divide the 24 blocks
°
into three groups of eight. The pattern in each group is coded by a number
between and 255. Sixty-three groups of eight will give us our sprite
shape. So, we need to produce 63 numbers. The first 27 are easy: they
are all O. Why? Look at the first row of the grid:
8. 8. 81 I I I I I I II I I I I I I II I I I I I I I I
°
Since there are no pixels filled in any of the first three groups of eight,
we assign each a and record that fact at the left of the row. These
are the first three numbers of our DATA code. The second row is iden-
tical to the first - no pixels, so the next three codes are also O. In fact,
since the first 10 rows are empty, the first 3*10 = 30 numbers in our
code are O.
Now for the first occupied row, Row 11:
tl. 8, 8\ I I I . . I I I I I I I I I I I I I I I I I I
The first group of eight has two filled blocks. The decimal values of
these blocks are four and eight so we add the values to get a decimal
translation number that tells the computer that we want those two pixels
filled. You've seen this block system before, when we used the VIC II
switchboard to turn on a sprite in the first place. Here we are using the
same code to turn on or off the individual pixels that make up the sprite.
Since the other two groups in Row 11 are empty, the full code for
the row is 12,O,O. Row 12 is identical to Row 11 so its code is also 12,O,O.
Let's skip to the more challenging Row 15.
1%7.255.252
The first column has seven out of eight blocks filled: the only one
empty is the one whose value is 128. Add up the values of the other
blocks: 64 + 32 + 16 + 8 + 4 + 2 + 1 = 127. All eight blocks of the second
column are filled, so the code for that column is: 128 + 64 + 32 + 16 +
8 + 4 + 2 + 1 = 255 (which, you'll remember, the computer interprets as
11111111). The third column has the 128, 64, 32, 16, 8, and four blocks
filled. Adding up these numbers gives the final value and code number
for Row 15, namely, 252.
The Character Design Chart in the Appendix shows the filled blocks
for numbers 0-127. You may find the chart easier to use than adding
the series of eight boxes each time you design a new sprite shape.
90
THE BOUNDING MAIN
You may wish to go back to Chapter 11 to reacquaint yourself with
the sprite switchboard. To start the program:
10 REM *** HOME WATERS ***
20 REM *******************
30 PRINT " ~" : REM *** CLEAR SCREEN
40 POKE 53280,0 : POKE 53281,6
50 V == 53248 : POKE V +21,4 : POKE V +29,4
52 X == 125
60 POKE V +41,1 : POKE 2042,199
69 REM *** PUT IN WATER ***
70 FOR W == 0 to 399 : POKE 56295 - W,5
80 POKE 2023 - W,102 : NEXT
We are using Sprite 2 as you perhaps noticed when you typed Line
50. RUN the program at this stage to check for typing errors and to
see what it looks like. You may wish to choose your own color.
THINGS TO REMEMBER
Review the sprite checklist one last time-always a good habit that
will make sure you didn't forget something important.
1. Turn on sprites.
2. Set sprite color.
3. I>efine sprite shape.
4. Set sprite coordinates.
5. Set memory pointers.
A TEST
One more item on the sprite checklist remains: determining the posi-
tion of the ship on the screen. Insert this temporary line to check what
we have done so far (and to look at the shape of your new ship!).
230 POKE V+4,125: POKE V+5,166
92
Without further ado, let's get our ship into the water.
93
If you look at Line 380, you'll see that address V + 16 is poked with
the value RX. V + 16 is a single-byte switch that controls all eight sprites.
When the switch is on for any particular sprite, the computer will assume
that the X coordinate for that sprite is to be added to 255. This allows
us to send the sprite to all 512 positions on the X axis.
Let's consider the case for Sprite 2. The toggle control number of Sprite
2 is 4. If we POKE V + 16 with 4, the computer will interpret the X
value in V + 4 to indicate that the sprite is to appear at position 255 +
X. If we turn off the left X for Sprite 2 by poking a 0 into the V + 16
register, the sprite will suddenly hop 255 spaces to the left. Go ahead
and experiment.
If you want, insert tracers into the program by adding the following
line:
355 PRINT X,RX : REM *** JUST A TEST ***
This slows the program and scrolls away the sea, but it will allow you
to inspect the values of X and RX as your sprite moves around the screen.
When you're satisfied erase the line from the program. This trick helps
BIG WHALE
0, 0, 0
0, 0, 0
0, 0, 0
0, 0, 0
.
0, 0, 0
. •
0, 38, 0
.. · · ..
~
..
. . • · • . . '* ..• ..• ,. .
32,127,224 . •
. .
lr
• . . .. . .. " .. .. . .. . ... • • . . .. •
49,2S5 , 184
"'
• . " • . .. . . • · • .. '. . • ..
63, 2SS, 2S2 t '
. • . . ..
63, 2S5, 192
0, 0, 0
0, 0, 0
0, 0, 0
0, 0, 0
94
you to debug when the computer complains of being given an illegal
quantity.
By the way, if you like this sort of thing, there is a very nice program
called "The Dancing Mouse" on page 166 in Commodore's Program-
mer's Reference Guide.
If you have trouble with the RIGHT ILEFT X concept, then simply
put a block graphic mountain on the right side of the screen. Now your
boats and whales can happily swim on the left and you can ignore the
V + 16 register.
ADDING SOUND
The next section gives our boat a foghorn.
119 REM *** SET FOGHORN ***
120 FOR M = 54276 TO 54296 : POKE M,0 : NEXT
121 POKE 54296,15
122 POKE 54277,0 : POKE 54278,240
123 POKE 54284,0 : POKE 54285,240
125 POKE 54273,6 : POKE 54272,71
126 POKE 54280,12 : POKE 54279,143
Then we program the "on" switch:
1199 REM *** FOGHORN ON ***
1200 POKE 54276,33
1210 POKE 54283,17
1230 FLAG = TI
1240 RETURN
And the "off' switch:
1259 REM *** FOGHORN OFF ***
1260 POKE 54276,0 : POKE 54283,0
1280 RETURN
And finally, we program the [Fl] function key to be the pull cord.
The special symbol in Line 310 on the next page is the result of pressing
the [Fl] key in Quote Mode.
95
ICEBERG
0. 0. 9
0. 0. 0
0. 9. 9
0. 0. 0
, ..
0. 0. 0
0, 120. 0
• .,.
0. 124. 0
• . • ..
0. 126. 0 . .
"• .. .. •..
• .
0. 127.224
9. 127.224 •
· . " . .. • . . · ·
. . . .. •
0.127.224 • .. . .. . • .. · · ·
; • . • .. •
0. 255.224
0.255.224
.. •
. • ·• •
• • . .. • • • • ..
3.255.252 . . ., .. . • . . .. .. • .. .. .. . •
.. .. . .. . • •. .. ... .. .. ... .• . . .• ..• .
. • .. .. . ..
7.255.252
31. 255. 255 • • .. .. • • ..
• • .. . .. .. .. • .. .. .. . • • • · · • .. . •
.. .. . . .. ..
31. 2S5. 255
31.255.255
-0. -0. -0 • . , •·• . . • . • . . • •
0. 0. 0
0. 0. 0
128 64 32 16 8 4 2 I 123 64 32 16 8 4 2 1 128 64 32 16 8 4 2 I
96
PROGRAM PROJECTS
How about a tugboat to add to your fleet? Edit Line 513 to turn on
Sprite 3:
50 V = 53248: POKE V+21,12: POKE V+29,4
CLOUDS
0, 0, 0
r-r-r-r-+-+-+-+-+-~_r_r_r_r_r-+_+_+_+_+_+_+_+_+~
0, 0, 0
r-r-+-+-1-4--r-+-+~~--r-r-+-+-1--r4--r-+-+~~--~
0, 0, 0
14, 6, 0
. .. .. .. , . . .
------r-r-r-+-+-+-+-+-4-~_r~_r_r_r_r_+_+_+_+_+_+_+_+~
r-r-+-+-1-4--r-+-+~~--r-r-+-+-~-r~-+-+-+~~--~
.. . . . . . . .
0, 7,128 f • • •
0, IS, 192 f-t--+-+-+--r-r-+-+,""'o............,j-~--r......;..-+-+-+-=Jf-t--+-+-+-~-+--1
------ r-r-r-+-+-+-+-+-~~4_~~_r_r_+_+_+_+_+_t_+_+_+~
0, 31. 240
...
O. ll. 240 f-t--+-+-+-_r-+-+_+-+-+--f-....-r.-+-.+-.+-.-I-.-+.-r.-+.-+-+-+--1------1
0, IS,240
------r-r-t--+-+-+-+-+-+--r-r-+--+-+-+-+-+-+-+-+-+_+_+_+~
• • •
0,
0,
1. 192
0, 0 r-r-+-+-1--r-r-+-+~~--f--+--+-+-1--r-+--+--+-+---+---1'--~
• • •
0, 0, 0
97
15 Tricks Of The SID
Z-RAY
This program creates a Z-ray. Use it with animation to zap objects.
5 REM *** Z-RAY ***
10 POKE 54296,15
20 POKE 54277,0 : POKE 54278,240
30 POKE 54276,17
35 FOR Z = 1 TO 7
40 FOR X = 1 TO 255 STEP 5
50 POKE 54273,X : NEXT X: NEXT Z
60 POKE 54276,16
98
Line 60 turns off the sound.
For fun, alter some of the variables. First try altering sound length
by changing Line 35.
You can also alter the values of X by changing the command in Line
40. Try:
FOR X = 1 TO 255 STEP 25
SIREN
Here is a program for a warning siren.
5 REM *** SIREN ***
10 POKE 54296,15
20 POKE 54277,0 : POKE 54278,240
30 POKE 54276,33
40 FOR X =: 1 TO 255
50 POKE 54273,X : FOR J =: 1 TO 15 : NEXT J : NEXT X
60 FOR Z =: 255 TO 1 STEP - 1
70 POKE 54273,Z : NEXT
80 C =: C+ 1 : IF C =: 3 THEN POKE 54296,0 : END
90 GOTO 40
99
Line 10 sets the volume.
Line 20 sets the ADSR.
Line 30 sets the waveform.
Line 40 assigns X to all the values between 1 and 255.
Line 50 POKEs the low frequency register with the values of X, placing
a time loop of 15 between each value.
The next portion of the program handles the siren's descending sound:
Lines 60-70 assign the variable Z to all the values from 255 down to
1 and POKEs these values into the low frequency register.
Line 80 is a counter that causes the effect to play three times and then
end.
Line 90 creates the repeat loop.
As you can see, this effect uses the same READ/DATA format as
some of our earlier music programs.
You get another kind of effect from this program by changing the
waveform setting on Line 20 from 33 to 17, while leaving the 32 setting
100
in Line 90.
Change the speed of the treadmill by altering the time loop in Line 80.
ALTERED STATES
We have some "other-worldly" sound effects for you to try. They are
all built around one program which you can modify to create astound-
ing audio changes. The program is called "Scaler" and in its unaltered
state produces a chromatic scale over the entire eight-octave range of
your Commodore 64. (That's why there are so many numbers in the
DATA bank.) Be sure to save this program because you can use it for
many different sound effects.
5 REM *** "SCALER" ***
10 FOR L = 54272 TO 54296 : POKE L,0 :NEXT
20 POKE 54296,15
30 POKE 54277,0 : POKE 54278,128
40 POKE 54276,17
50 FOR T = 1 TO 200 : NEXT
60 READ A,B
70 IF A = - 1 THEN OOTO 900
80 POKE 54273,A : POKE 54272,B
90 OOTO 20
100 DATA 1,12,1,28,1,45,1,62,1,81,1,102,1 ,123,1,145,1,169,1, 195,
1,221,1,250
110 DATA 2,24,2,56,2,90,2,125,2,163,2,204,2,246,3,35,3,83,3,134,
3,187,3,244
120 DATA 4,48,4,112,4,180,4,251,5,71,5,152,5,237
130 DATA 6,71,6,167,7,12,7,119,7,233,8,978,225,9,104,9,247,10,
143,11 ,48,11,218
140 DATA 12,143,13,78,14,24,14,239,15,210,16,195,17,195,18,209,
19,239
150 DATA 21,31,22,96,23,181,25,30,26,156,28,49,29,223,31,165,
33,135,35,134
101
160 DATA 37,162,39,223,42,62,44,193,47,107,50,60,53,57,56,99,
59,190,63,75,67,15
170 DATA 71,12,75,69,79,191,84,125,89,131,94,214,100,121,106,
115,112,199,119,124
180 DATA 126,151,134,30,142,24,150,139,159,126,168,250,179,6,
189,172,200,243
190 DATA 212,230,225,143,238,248,253,46
200 DATA - 1, - 1
900 POKE 54296,O
910 RESTORE
920 OOTO 20
To quit, hit [RUN/STOP]:[RESTORE]. If you wish to save your
screen display, hit [RUN/STOP] and type POKE 54296,0. This will turn
off the volume.
Out of Step Sound Effect
Now let's create our first change. On a new line type the command:
LIST 100-200
Now go to Line 100 and delete the first number in the scaler DATA
bank along with the comma that follows. Your old line started:
100 DATA 1,12,1,28 etc.
Your new line will be:
100 DATA 12,1,28 etc.
Press [RETURN] to enter the change. You have just thrown a monkey
wrench into the orderly group of frequency numbers. So the monkey
wrench doesn't "damage" the program too much, take the 1 you removed
from Line 100 and add it to the end of Line 190. The new Line 190
will look like this:
190 DATA 212,230,225,143,238,248,253,46,1
Now RUN this new program for a strange piece of computer music.
102
Robot Speech Sound Effect
Let's change Line 50, which is our time loop. If we increase the speed
we can dramatically change the entire effect. Try it. Change:
50 FOR T = 1 to 200 : NEXT
to:
50 FOR T = 1 to 2 : NEXT
With that simple change, you have a program that sounds a little like
R2-D2's speech in "Star Wars."
Speaking of "Star Wars," with two more short changes you can use
this program to create a rocket blast-off sound effect. Return to the pro-
gram version before you changed the DATA and timing loop.
BLAST-OFF
LIST Lines 40 and 50. Now change:
40 POKE 54276,17
to:
40 POKE 54276,129
and change Line 50 from:
50 FOR T = 1 TO 200 : NEXT
to:
50 FOR T = 1 TO 20 : NEXT
By changing the waveform from triangle to white noise and by speeding
up the time loop, we can produce the rocket effect. RUN and see.
103
50 FOR T = 1 TO 50 : NEXT
Finally change Line 80, which currently reads:
80 POKE 54273,A : POKE 54272,B
to:
80 POKE 54273,A : POKE 54287,B
These changes open the sync bit, which synchronizes the fundamental
frequencies of Voices 1 and 3. For variations try:
80 POKE 54287,A : POKE 54273,B
You can create hundreds of effects from this single program. Have fun!
104
The end of the beginning
105
120 POKE V + 23,16
200 U=U+l
220 Y = 235 - (INT(1.21 U) + 42)
230 NEXT TT
Note that line 80 has been slightly changed; this line controls the color
of our sprites - white for the rocket and red for the flame. Test the pro-
gram to see if all is well. (It worked before.)
Now we design the shape of our spacecraft with techniques we
developed in Chapter 14:
ROCKET
0, 0, 0
0, 0, 0
0, 0, 0
0, 32,
0, 32,
0
0
•
•
·
·
0, 32,
-0, -32,-0
0
·• ·•
0, 32, 0 • •
0, 32 0 • •
0, 60, 0 • • • •
..
.• • •
0, 60, 0
·• •• ·.. ··•
0, 60, 0
• •
0, 60, 0
0, 60, 0
0,189, ° . • • • • .
1,189, 128 • • • • • .. . .
1,189,128 • • • • • .. .. •
1,255,128 • .. • • • • • • " •
1,255, 128 • • • • • • • .. • ..
0, 153,
0, 153 ,
0
0
· • • .
128 64 32 16 8 4 2 I 231 64 32 16 8 4 2 I 281 64 32 16 8 4 2 I
106
1060 DATA 1,189,128,1,189,128,1,255,128
1070 DATA 1,255,128,O,153,O,O,153,O
0, 60, °
0, 60. °~~-+-+~~+-+-~~-+-+~~4-+-~~-+-+~~
r-~+-+-+-+-+-4-4-4-~~~~-+-+-+-+-+-+~~~~~
- -°H-+-+-+~-+-+-+-HH-+-+-+++-+-~~--+-+~~
-0,126. ~
. .. .. . .. ..
0: •
0,255. °
2. 126. 64 ~~-+-+~~+-+-~~--+-+~++-+-~~-+-+~~
,. •
4. 255. 32 ., .. ..
~~-+-+~~+-+-H~-+-+-+++-~~~--+-+~~
---r-~+-+-+-+-+-4-4-~~~~~~-+-+-+-+-+~~~~~
.. •
0.1 26. 0 • • • •
0.255. 0I-+-+++--+-t-I---+-.+.+.+.-+-.+,+.•+.-+-t-I---+-+-++-+--1
2. 126. 64 •• • • • • •
---~H--+-+~~~+-~~--+-+-+~4-~+-~-4-+-+-
4.255. 32 ". .. -. .. " ...
•
r-+-+-+-+-~1-4-~~~~~-+-+-+-+-+~~~-~~~
..
°I-+--+----+--+--t--if---t-+-+.+.-+-.+-.-!-.-+.4---t--iI-t-+-+--+--+--+---!
0,126. 6
"" . . .. .
0, 126.
----~H-+-++~~+-+-~~_+-+~~+-+-H~_+-+~
.
....
0,126. 0
0, 126. 0 I-+--+----+--+--t--i-t-+-+-.+.-+--+--I-.-+.-+--+----li-t-+-+--+--+--+---!
0. 60. 0
-----~H-+-++~-+-+-+-~H-+~~~+-+-H~-+-+~
I , 60,128 .,. • • • ~~
2, 24. 641-+-++-+-+--i~.+-+-+~I---+-.+-.++-+-4~r---~+-~~+-+~
o. 24. 0
---- H--+-+-+-~-+-+-+-~~--+-+~~4-+-~H-+-+~~
0, 24. 0 • •
0. 24 , 01-+-+-++-+-+--iI-+-+-++.-+..---+--i-+-+-+-++-+---1-I---H
0. 24. 0 • •
128 64 32 16 8 4 2 1 231 64 32 16 8 4 2 1 281 64 32 16 8 4 2 I
107
and:
LAME 2
0, 0. 0
0, 0. 0
10. 36. 80
• • of • . '¥l
10. 36. 80
.~.. •
.
• • • •
10. 36. 80 i~ • • .. •
10, 36. 80 • • • •
..
~
..
.,
,~tc
10. 36. 80
.!: • • •
10. 36. 80 '# • • • It
10. 36. 80 . • • • .
..
~
0. 36. 9
•
0. 36. 0 • •
9. 36. 9 . •
0. 36. 9
'" .
..
. ...
3.165.192
~n i~ • ril'; ..
.. ~'.,
[.~;
•
',' ;1; ...
3.165.192 *.< •
k~J '"
t t~; 1
3,165,192 • .. ~;~
• •
., ..,;,t
3.165.192 It· it
3,165.192
•• ;~, il'.: .. l~
it' ..
3.165,192 ~,;. ii.
r:! . .: ",r ;+i
0. 9. 0
0. 9. 9
108
90 FOR Q = 192*64 TO (192*64)+62 : READ Z
92 POKE Q,Z: NEXT
Now create Line 94 by changing the 0 in 90 to 4, and then change each
192 to a 193 and press [RETURN]. To create Line 96, change the 92
to 96 and again press [RETURN]. LIST the program to check what you
just did. This gives you a pair of loops. We need one more. Use the
same procedure to insert these next two lines:
86 FOR Q = 194*64 TO (194*64)+62 : READ Z
88 POKE Q,Z : NEXT
For bookkeeping purposes you should note:
Memory block 192 contains Flame 1.
Memory block 193 contains Flame 2.
Memory block 194 contains ROCKET.
We need to set the memory pointers, so edit Line 75 to match:
75 POKE 2044,194 : POKE 2045,193
We're ready for a test: the rocket should take off but the flame will
just float in the middle of the screen. Any errors? Find out now, before
we venture too far into the unknown.
All's well? OK, time to get the flame behaving properly. The following
section ties the two sprites together; the flame should now follow the
rocket as it rises:
110 POKE V + 10,X : POKE V + 11,Y +40
220 Y = 235 - INT(1.ltU) + 42)
The Y + 40 value in Line 110 gets us the correct spacing between the
flame and rocket. If you want a smaller rocket,change Line 120 to POKE
in a 0 instead of a 16 (this is the vertical expansion switch); you'll have
to experiment to get the right spacing (but do try 21 in Line 120).
Run the program and correct any syntax errors. If you want to tinker
at this point be sure to SAVE what you have lest you crash.
The following lines produce the flicker effect. First we insert the lines
that alternate between the blocks in memory where the sprite shapes are
stored:
224 IF J = 2 THEN POKE 2045,193 : J = 0
226 IF J = 1 THEN POKE 2045,192
109
To make this work we need a counter, so edit Line 200 to match:
200 U=U+l:J=J+l
This fits inside the big FOR/NEXT loop we set up in Chapter 11. Look
at Lines 98 through 230 to see what happens in a given pass through
the loop.
Before the big test, we need to install the sound effects: For volume
control and to set the waveform, add these lines:
55 POKE 54296,15
105 POKE 54276,129
Test RUN the program. We still need to insert the hyperspace jump.
(You may begin to understand why some programmers use line numbers
that increment by 100.)
HYPERSPACE
This section can be customized in all sorts of ways. The first step is
to switch off the sprites and turn off the sound:
300 POKE V +21,0: POKE 54276,0
Then an explanation is in order (the square box in the following is
[CONTROL]:[0] in Quote Mode):
310 PRINT TAB(210)" D H Y PER SPA C E "
and hyperspace itself:
320 FOR I = 0 TO 14 : POKE 53281,1
330 FOR M = 1 TO 10 : NEXT M
340 POKE 53281,1+ 1 : NEXT I
350 GOTO 320
Well, you've done it! A successful blast-off into hyperspace. We hope
you've enjoyed this guided tour of your Commodore 64 and that you
feel inspired to experiment further on your own. We'll continue our ex-
periments and hope to take you BEYOND HYPERSPACE in a future
book.
110
Appendix
111
QUOTE MODE SPECIAL SYMBOL CHART
Reading or typing in program listings with special Quote Mode symbols can
be trying. The following chart will help.
•
Orange [COMMODORE] : [1] ~
Brown [COMMODORE] : [2]
•
Light red [COMMODORE] : [3] ~
Grey 1 [COMMODORE] : [4]
Grey 2 [COMMODORE] : [5] C
Light green [COMMODORE] : [6] II
Light blue [COMMODORE] : [7] C
Grey 3 [COMMODORE} : [8] ••
••
113
SPRITE SWITCHBOARD CHART
(V = 53248)
ON/OFF V+21
TOGGLE (53269)
SPRITE# ((J 2 3 4 5 6 7
MEMORY
2((J4((J 2941 2942 2943 2944 2945 2946 2947
POINTERS
SPRITE# ((J 2 3 4 5 6 7
SPRITE# ((J 2 3 4 5 6 7
V+ 16 MULTICOLOR v + 28
LEFT X (53264) (53276)
SPRITE# ((J 2 3 4 5 6 7
For the switches controlled by a single memory address use the sprite switchboard code to individual-
ly control all eight sprites.
114
Sprite Position Chart
X POSITIONS RUN FROM 0 TO 255,
o 24 THEN YOU MUST POKE V+16, 1 255
; AND START OVER AT 0 TO 91~'~""-----'~1
0-
x = 24. Y = 50 x = 255. Y = 50
X =231. Y =50
~
o I
a: I
~
VIEWING SCREEN AREA
Zit) I
:::lit)
a:N I
(/)0
Z~
,
I
I
~I
I
I
x = 24. Y = 229 X = 229. Y = 231 I
-~+-~------------------~--~~--~
POKE V + 16. , AND
X = 65. Y = 229
The X and Y values that you POKE into memory indicate the position of upper left hand comer
of the sprite in question. Chapter 11 develops a program that will let you explore positioning sprites.
OFF BIT
ON BIT
ON 128 64 32 16 8 4 2
Note: 8 bits = 1 byte. Add a group of ON bits to determine the sprite control values which
are used to activate the switches of single byte addresses. For example,
128 + 16 + 4 = 148 64 + 32 + 4 + 1 = 85 32 + 16 + 8 + 2 = 58
115
COLOR COMBINATION CHART
CHARACTER COLOR
o 2 3 4 5 6 7 8 9 10 11 12 13 14 15
o x • ••• •• ••••••
X X X
• • ••• ••••• ••
X X X X
2 X
• • X
•• •
X X X • X X X X X
3
•• X • •
X X X• • X X X X X X X
4
• X X X X X • X X X X X X X X
5
•• • X X• • •
X X X X X X X X
~
.... 6 • • • X X X • ••
X X X X X X X
o(,) 7
• Ir. •
X • • • •• •
X X X X X X X
ffiUJ
8 • • • •
X X X X • X X X X X X
a: 9 X
• X X
•• •X X
• X X X X X
r.
(,)
X
CI) 10
• • • X • •
X X X • X X X X X X
11
•• • X
• X X ..
>
X • •
X X X X ~,
12
••• • X • • X
X X
• X X X "
X X
• •• •
'.
13 X X X X X X X X X X X X
14
•• • X X X X X X • .j,
X X X X •
15
••• ••• X X X • • • '2' X
• X
= EXCELLENT
•X = FAIR
= POOR
0 BLACK 8 ORANGE
WHITE 9 BROWN
2 RED 10 Light RED
3 CYAN 11 GRAY I
4 PURPLE 12 GRAY 2
5 GREEN 13 Light GREEN
6 BLUE 14 Light BLUE
7 YELLOW 15 GRAY 3
Certain color choices for character and screen choices yield blurred and distorted images.
You can use such choices for creative graphics effects. However for legible text on
the screen you need better resolution. The above chart will guide you to appropriate
choices for colorful programs.
116
COLOR MEMORY MAP
,
COL....
o 10 20 30 39
55335
55296- o
55336
55376
5~16
5~56
5~96
55536
55576 1
55616
55656
55696
55736
10 I
55776
55116
55856
55896
55936
55976
56016
56056
56096 20
56136
56176
56216
56256 24
t
56295
o 10
...
SCREEN MEMORY MAP
20 30 39
10&3
,
10U-~++::p:++=mm++++l+~+l::p:++~m::p++~
1064
0
1104
1144
1114
1224
1264
1304
1344
1314
1424
1464
10 I
1504
1544
1584
1624
1664
1704
17«
1714
1824 20
1864
1904
1944
1914 24
t
2023
117
SID CHIP CONTROL CHART
BIT no. 7 6 S 4 3 2 I 0
DEC no. 128 64 32 16 8 4 2 1
"12 54283 WAVE FORM NOISE IUl 11M 6 TEST RMOD SYNC GATE
54284 ATK-DEC ATK3 ATK2 ATK 1 ATKO DEC 3 DEC 2 DEC I DECO
Il 54285 SUS-REL SUS 3 SUS 2 SUS I SUSO REL3 REl2 REL I RELO
VOICE 3
.. 54286 LOFQ f7 f6 f5 f4 f3 f2 f I fO
.."
54287 HI FQ f 15 f 14 f13 f 12 f II flO f9 f8
54288 LO PW pw 7 pw 6 pw 5 pw4 pw 3 pw 2 pw I pwO
"
20
54291
54292
ATK-DEC
SUS-REL
ATK 3 ATK 2
SUS 3 SUS 2
ATK I
SUS I
ATKO
SUS 0
DEC 3
REL3
DEC 2
REL 2
DEC I
REL 1
DECO
RELO
VOLUME FILTERS MISC.
11 54293 LOFC '/1/1 IIIII IIIII fc 2 fc 1 feO
I 54294 HI FC fc 10 fc 9 fc 8 fc 1 fc 6 fc 5 fc 4 fc 3
I 5429S RES-FILT RES 3 RES 2 RES 1 RES 0 FILTEX FILT 3 FILT 2 FILT I
• 54296 VOL-MODE 3 OFF HP BP LP VOL 3 VOL 2 VOL I VOL 0
, 54297 POT I 7 6 5 4 3 2 I 0
6 54298 POT 2 7 6 5 4 3 2 I 0
, 54299 OSC 3 07 06 05 U4 03 02 01 00
~I 54300 ENV 3 E7 E6 E5 E4 E3 E2 EI EO
118
TABLE OF NOTE VALUES
OCTAVE 0 OCTAVE 4
c-o 268 I 12 C-4 4291 16 195
0-0 284 I 28 ('#-4 4547 17 195
0-0 301 I 45 0-4 4817 18 209
0#-0 318 I 62 0#-4 5103 19 239
E-O 337 I 81 E-4 5407 21 31
F-O 358 I 102 F-4 5728 22 96
F#-O 379 I 123 F#-4 6069 23 181
G-O 401 I 145 G-4 6430 25 30
G#-O 425 I 169 G#-4 6812 26 156
A-O 451 I 195 A-4 7217 28 49
A#-O 477 I 221 A#-4 7647 29 223
8-0 506 I 250 8-4 8101 31 165
OCTAVE I OCTAVE 5
C-I 536 2 24 ('-5 8583 3) 135
C#-I 568 2 56 C#-5 9094 35 134
0-1 602 2 90 0-5 9634 37 162
0#-1 637 2 125 0#-5 10207 39 223
E-I 675 2 163 E-5 10814 42 62
F-I 716 2 204 f5 11457 44 193
F#-I 758 2 246 F#-5 12139 47 107
G-I 803 3 35 G-5 12860 50 60
G#-I 851 3 83 (;#-5 13625 53 57
A-I 902 3 134 A-5 14435 56 99
A#-I 955 3 187 A#-5 15294 59 190
8-1 1012 3 244 8-5 16203 63 75
OCTAVE 2 OCTAVE 6
C-2 1072 4 48 C-6 17167 67 15
0-2 \136 4 \12 0-6 18188 71 12
0-2 1204 4 180 0-6 19269 75 69
0#-2 1275 4 251 0#-6 20415 79 191
E-2 1351 5 71 E-6 21629 84 125
F-2 1432 5 152 F-6 22915 89 131
F#-2 1517 5 237 F#-6 24278 94 214
G-2 1607 6 71 (;-6 25721 100 121
G#-2 1703 6 167 G#-6 27251 106 115
A-2 1804 7 12 A-6 28871 112 199
A#-2 1911 7 119 A#-6 30588 \19 124
8-2 2025 7 233 8-6 32407 126 151
OCTAVE 3 OCTAVE 7
C-3 2145 8 97 ('-7 343)4 134 )0
C#-3 2273 8 225 C#-7 )6)76 142 24
0-3 2408 9 104 0-7 38539 150 1)9
0#-3 2551 9 247 D#-7 40830 159 126
E-3 2703 10 143 E-7 43258 168 250
F-3 2864 II 48 1'-7 45830 179 6
F#-3 3034 II 218 F#-7 48556 189 172
G-3 3215 12 143 G-7 51443 2m 243
G#-3 3406 13 78 G#-7 54502 212 2)0
A-) 3608 14 24 A-7 57743 225 14)
A#-3 )823 14 2)9 A#-7 61176 2)8 248
B-3 4050 15 210 B-7 64814 25) 46
119
CHARACTER DESIGN CHART
2' 2' 2' 2' 2' 2' 2' 2· 2' 2' 2' 2' 2' 2' 2' 2·
0 • 32
• 1 • • 33
• 2 • • 34
•
• • 3
4
·• •
• • 35
36
• • 5 • • • 37
• • 6 • • • 38
• • • 7 • • • • 39
• 8 • • 40
• • 9 • • • 41
• • 10 • • • 42
• • • 11 • • • • 43
• • 12 • • • 44
• • • 13 • • • • 45
• • • 14 • • • • 46
• • • • 15 • • • • • 47
• 16 • • 48
• • 17 • • • 49
• • 18 • • • 50
• • • 19 • • • • 51
• • 20 • • • 52
• • • 21 • • • • 53
• • • 22 • • • • 54
• • • • 23 • • • • • 55
• • 24 • • • 56
• • • 25 • • • • 57
• • • 26 • • • • 58
• • • • 27 • • • • • 59
•
•
• •
• • •
28
29
· • • •
• • • • •
60
61
• • • • 30 • • • • • 62
• • • • • 31 • • • • • · 63
120
2' 2' 2' 24 2' 2' 2' 2· 2' 2' 2' 24 2' 2' 2' 2·
· 64
·• ·• 96
· · 65
· 97
· • 66 • • ·• 98
·• · • 67
·· • 99
•
•
• •
68
69
·• ·• •
• •
100
101
· • • 70 • • • ·• 102
·• · ·
• 71
·• ·• · • 103
·• 72 • 104
·• • •
• 73
74
• •
• •
·• •
• 105
106
· · · • 75
·• ·• • • • 107
·• ·• ·• 76 • • 108
· 77 • • · • • 109
• • • • 78 • • • • · 110
• • • • · 79 • • • • · • 111
·• ·• •
80
81
·• ·• •• •
112
113
• • • 82
·• ·• • • 114
• • • • 83
• · •
· · • 115
• · · • 84 • 116
• · · 85
·• ·• · ·• · 117
·• ·• • • • 86
· • ·• 118
·· 87
··· · 119
• • • 88
·• ·• ·• · • 120
·• • • • · 89
·• • 121
·• ·• • 90
·• • • • • •
• • 122
• · 91
• • • · •
123
·• • •• ·• • 92 124
·• • • 93
·• • •• •• •• • • 125
•
•
·
• • • • •
94
95
·
• • • • • • •
126
127
Note: for characters that have a dot in the 2' position, add 128 to the
FI 133
F2 137
F3 134
F4 138
F5 135
F6 139
F7 136
F8 140
-
abbreviations 63 GET 78
address 10,35 GOSUB/RETURN 37,42,44
ADSR 52,54-56 GOTO 37
arithmetic 11-13
ASCII 122 hexadecimal 78
123
POKE 10,21,35 space bar 6
PRINT 3-4 sprite
pun 20 shape 35,71-76,89-97,
105-110
quote mode 3-4,5,15-16,25 switchboard chart 112-113
checklist 36,73,92
RAM 8 STEP 30-31
random 32,84 STOP 86
[RCRSR] 2 string 77-81
READ 61-62 string variable 12,77,81
register 35 subroutines 37,42,44
REM 20
[RESTORE] 4 TAB 15
[RETURN] 2,9 Tl 50,51
reverse field 4 toggle 7
RND 32 tracer 33-34
[RUN/STOP] 4,5,9,26
RUN 11,14 VAL 34
variables 11,32-34,
SAVE 22 48-51,77
screen editor 9 variable names 13
screen memory: VIC II chip 1,35
character map 84-85,115
color map 84-85,115 waveform 56-58
[SHIFT]: [CLR/HOME] 3,4,9
[SHIFT/LOCK] 6 < 7
SID chip 1,52,98 > 7
simulation 29,32 I 7,15
124