First Book of Commodore 64 (1983)
First Book of Commodore 64 (1983)
COMMODORE
COMPUTE!" Publicationsjnc.^5
One of the ABC Publishing Companies . ^0
Reproduction or translation of any part of this work beyond that permitted by Sections
107 and 108 of the United States Copyright Act without permission of the copyright
owner is unlawful.
ISBN 0-942386-20-5
10 98765432
COMPUTE! Publications, Inc. Post Office Box 5406, Greensboro, NC 27403, (919)
275-9809, is a subsidiary of American Broadcasting Companies, Inc. and is not associated
with any manufacturer of personal computers. Commodore 64 is a trademark of
Commodore Electronics, Ltd.
Dntents
Foreword V
ill
64DOSmaker
Charley Kozarski 135
Backup 1540/1541 Disks
Harvey B. Herman 137
Using the User Port
John Heilborn 143
Index 263
IV
Foreword
The Commodore 64 computer was introduced in the fall of 1982,
and immediately became the first choice of hundreds of thou
sands of new and experienced computer users. Its music, sound,
and graphics capabilities are remarkable, and its price tag brought
it within the reach of many first time buyers.
COMPUTE! Books is ready to help you make the most of it.
COMPUTEI's First Book of Commodore 64 offers something for
computer users at every level of expertise, from the beginner to
the expert. And as you gain experience and move from one level
to the next, you'll find that this book can provide the key to each
level of computer knowledge.
For beginners, the "Starting Out" section offers an introduc
tion to the Commodore 64 and the step-by-step creation of a
simple program.
If you're interested in graphics, Jim Butterfield's seven-part
"Commodore 64 Video" is the ideal introduction.
Do you use joysticks, printers, disks, cassettes? There are
articles and programs to help you.
To learn your computer from the inside out, the "Memory"
section shows you where everything is — and provides "A Win
dow on Memory" which lets you scroll through all 64K and see
what is happening to memory while the computer is running.
And if you program in machine language, this book includes
a complete monitor, "Micromon-64," and a complete assembler
program, written in BASIC.
Of the articles in this book which originally appeared in
COMPUTE! Magazine or COMPUTERS Gazette for Commodore,
many have been enhanced since their original publication. Many
other articles and programs, however, are appearing here for the
first time anywhere.
Chapter 1
Starting Out
Starting'
Out
More Than
Just Another
Computer
Sheldon Leemon
Don't let its outward resemblance to the VIC fool you. Inside, the
Commodore 64 is full of brand-new technology. While it retains
certain features of older Commodore computers, the 64 extends
many of those features and at the same time introduces new ones.
left over for "safe" memory, which can be used for machine lan
guage programs, an I/O buffer, etc.
This default memory allocation can be easily changed by the
user to one of seven other possible memory maps. Any of the
programs in ROM may be switched out and replaced by RAM.
That means a program like a word processor, which needs as
large a storage area as possible, could simply switch out the
BASIC ROM and gain access to 8K more RAM space. As a matter
of fact, all 64K of RAM could be used at once (although some por
tion would have to be devoted to I/O driver routines, like a screen
editor, and the I/O devices would have to be switched back in for
communication with peripherals).
Memory addressing space can be allocated not only between
internal RAM and ROM, but between external ROM cartridges as
well. These cartridges (which are not compatible with those de
signed for the VIC) can hold up to 16K of ROM and can be made
to operate either in place of the BASIC ROM or along with it to ex
tend its set of commands.
Better Graphics
What makes the 64's color graphics so extraordinary is a separate
starting
Out
Character Graphics
Character graphics includes the ordinary text characters that ap
pear on the screen when you turn the computer on. The text dis
play consists of 25 lines, each having 40 characters. These charac
ters are formed from data stored in the Character Generator
ROM, which holds the two standard Commodore character sets,
regular and inverse video. One set contains uppercase letters and
graphics characters, and the other has both upper- and lowercase.
However, the user is not limited to the standard character set
stored in ROM. User-defined characters, up to 256 at any one
time, may be displayed from RAM, allowing the programmer to
display foreign language alphabets, math symbols, or custom
graphics characters. Like the VIC, one area of memory on the 64
is set aside for the characters to be displayed, while a separate
area holds the color information for each character. This means
that the user can individually select one of 16 different foreground
colors for each of the 1000 characters that appears on the screen.
Besides the standard character display, there are two other
more specialized text modes. The first is a multicolor character
mode, similar to those found on the VIC and the Atari computers.
In this mode, each character is made up of eight rows, each four
dots across. The color of each dot may be selected from one of two
color registers or from the value stored in color memory for that
particular character, so that each character may display up to
three colors at once, in addition to the background color.
Although the standard character ROM is not set up to accom
modate such characters, by using custom graphics characters the
programmer can take advantage of this feature to create colorful
graphics displays that are easily animated.
To aid in this animation, the 64 has fine-scrolling registers,
which allow both the horizontal and vertical position of charac
ters to be changed one increment at a time, so that they may be
moved smoothly across the screen. In order to create a "buffer"
area for new information to enter the screen as the old informa
tion scrolls off it, the screen size may be shrunk to 24 rows of 38
characters each.
1 Starting
Out
Bitmap Graphics
Bitmap graphics enables the high-resolution plotting of 320 dots
horizontally by 200 dots vertically. As on the VIC, the display
data, or bitmap, is set up in the same format as character graphics.
Each byte of information has eight bits, each of which represents a
horizontal dot. Each group of eight bytes has its rows of dots
stacked one on top of the other, so that the groups of eight bytes
form an 8 x 8 grid. This makes plotting individual points a little
more difficult than a sequential arrangement would, but it also
makes it easier to intermix character data into a bitmap display.
As in the character modes, the foreground color of each 8x8
grid maybe individually selected. Bitmap mode requires 8K of
memory for screen data and another IK for a color memory. The
multicolor option is also available in bitmap mode. Although the
resolution is reduced to 160 dots horizontally, this mode offers the
widest variety of color selection, as it allows each dot within a 4 x 8
grid to be one of three individually selectable colors.
Sprite Graphics
Sprite graphics is a feature which aids in the animation of
graphics characters, or sprites. It really comprises a completely
separate system for displaying graphics, in addition to the more
normal character or bitmap graphics. A sprite is a special graphics
character whose shape is defined by 63 bytes of data, laid out in a
24 x 21 dot array. This means that each sprite is approximately
three text characters wide by two-and-a-half characters tall. Up to
Starting
Out
More Features!
Much more could be said about the VIC-II chip. For instance,
though it can address only 16K of memory at a time, any of four
banks of 16K can be selected. Within a 16K bank, the placement of
the screen display may be easily selected, allowing two or more
screen areas to be set up in memory at once and rapidly alter
nated, a procedure known as page flipping. Even if the 16K bank
chosen is one in which the 6510 addresses ROM memory, the
VIC-II can address the RAM which shares its memory space, thus
allowing the same memory location to do double duty. Likewise,
the VIC-II can address the character ROM as if it were in RAM,
even though the 6510 cannot tell that it is tljere. The VIC-II also
provides support for input from a light pen. Of great interest to
machine language programmers is the system of raster interrupts.
The VIC-II can generate an interrupt request in synchronization
1 Starting
Out
with the raster scan display. This means that the more advanced
programmer can change any of the VIC registers partway down
the screen, so that two or more character sets can be displayed on
different parts of the screen simultaneously, or that the same
sprite can appear at two different vertical locations at once, there
by increasing the total number of sprites that can be shown.
string instruments the note may be sustained for a long time. The
ADSR controls of the SID chip allow it not only to imitate the
sounds of a wide range of instruments, but to synthesize patterns
not found on any existing musical instrument.
There are a number of other controls as well. A Sync control
synchronizes the fundamental frequency of two oscillators, pro
ducing "hard sync" effects. A Ring Modulation control allows the
creation of bell or gong sounds. Individually selected Highpass,
Lowpass, and Bandpass filters are available for all three voices
and can be used singly or in combination.
Though not sound related, this chip also controls the reading
of paddle controllers.
If reading about SID's capabilities doesn't excite you, hearing
them certainly will. The only drawback to all of this power is that
there are no BASIC commands to allow easy access to 64 sound.
After setting up volume and ADSR levels, each note will require
that you POKE at a minimum two frequency bytes and one wave
form byte.
This stands to reason, for even with 64K of RAM and full
blown color graphics and sound capabilities, the Commodore 64
is one of the least expensive computers currently on the market.
With its introduction, the group of people who can afford to own
a powerful computer has suddenly grown much, much larger.
10
Starting
Out 1
Making the
Computer •it
what You want
Orson Scott Card
11
1 Starting
out
12
starting
Out 1
PI and P2. These are the "high frequency byte" and "low fre
quency byte." The addresses for voice 1 are 54273 (PI) and 54272
(P2). What they control is the pitch of voice 1 — how high or low
the note is on the musical scale. The higher the number, the high
er the note. PI is the broad control, like the channel selector on
your TV. P2 is fine tuning.
VL. This is the general volume setting for all three voices in
the 64. It can be set from 0 to 15: 0 is off; 15 is maximum. We are
going to set it once, at the beginning of the program, and leave it
alone — there are much better volume controls later in the pro
gram. The address is 54296.
AD. Attack and decay are the first two parts of the sound en
velope, often referred to as ADSR envelope — Attack/Decay/
Sustain/Release. Attack is how quickly the sound gets to full
volume. Decay is how quickly it drops off. Sustain is how loud it
is through the rest of the note. Release is how long it takes for the
sound to die away when the note is stopped. I won't even attempt
to describe the effects of different sound envelopes to you — the
program will do it much better.
Attack and decay are controlled from the same location in
memory: 54277. There are 15 possible levels for attack, and 15 pos
sible levels for decay. And there are eight bits in the number
stored at 54277. Attack is controlled by the four highest bits (the
"high nybble"), and decay by the four lowest. If you don't know
what bits are, don't worry. It's enough to know that the meaning
ful values for attack are multiples of 16, from 16 to 240, while the
meaningful values for decay are the numbers from 1 to 15. To set
up both attack and decay, you choose the numbers you want for
each, add them together, and POKE them in. In other words,
POKE AD,ATTACK+DECAY
SR. The same system works for sustain and release. Sustain
uses the high nybble and release uses the low nybble. The loca
tion in memory is 54278.
WE Waveform is controlled at 54276. There are four options,
represented by the numbers 17, 33, 65, and 129. The lowest num
ber is a fairly pure tone; the highest is noise. You have to hear the
others.
SW. The square waveform, number 65, has another signifi
cant controlling number, the pulse width, controlled at locations
54274 and 54275. In our program, well store 8 in 54275 and allow
the user to modify the number at SW.
13
Starting
Out
10 POKE 54296,15
20 FOR 1=54272 TO 54278:INPUT N:POKE I,N:
NEXT I
30 FOR 1=1 TO 250: NEXT I:POKE 54276,254:
GOTO 20
14
Starting
Out 1
Communication
There are two displays this program will need. First, there should
be a continuous display of what key to press in order to change
each value. Second, there should be a display showing what
values are being POKEd to make the sound the user is hearing.
This display needs to be updated every time a value is changed.
Menus. The display of optional choices and how to select
them is the menu. Especially when your program uses toggles,
there must be a display to show what the toggles are. A simple
program, in which there are only a few choices, usually gets by
15
1 Starting
Out
Main Menu
MeiiuA MenuB
16
Starting
Out 1
17
1 Starting
Out
18
starting
Out 1
1. Assigning variables
Here are the first two lines of our program:
10 Pl=54273:P2=542 72:VL=54296:AD=54277:S
R=54278:WF=54276:SW=54274
20 SC=653:KD=197
19
1 Starting
Out
As long as you aren't pressing any key, the screen will report
values of 64 and 0. Pressing keys will change the values. Notice
that a regular key will return the same code number whether the
SHIFT key is pressed or not. Press the function and cursor keys —
they return the lowest numbers of all, and their codes are all in se
quence. That will be convenient for us later.
2. initialization
The values of the variables assigned so far will never change —
they are permanent. Now, however, we begin to initialize vari
ables that will change. We initialize them so that when the pro
gram begins, it will immediately start creating a sound, and so
that each variable holds a valid value. This will enable our change
routines to work properly from the start.
Line 25 POKEs 54275 with the value 8. This is part of the pulse
width assignment, but we won't be changing it in our program.
The same with the volume assignment, POKE VL,15. This sets
the volume at its loudest. The ADSR envelope will make particu
lar changes within the range of possible volumes, however, so
you'll almost never want to set your volume at anything less.
Line 30 initializes the variables that will change. SI and S2 are
the pitch values that will be POKEd into locations PI and P2.
ATTACK is the attack value, and it will be added to DECAY to be
POKEd into address AD. SUSTAIN and RELEASE will be added
together to be POKEd into SR. SQUARE is the square wave pulse
width, and it will be POKEd into location SW.
WAVE is the value of the waveform, and it will be POKEd into
WF to start the sound. OFF will also be POKEd into WF, but only
at the end of the sound, to turn it off. The value of OFF will al
ways be 254. DUR is the duration of the timing loop. It will not be
POKEd anywhere; it will be used as the counter in a FOR-NEXT
loop to decide how long each note will last.
Line 35 has a variable named TEN. This is a toggle that will
have a value of either 10 or 1. Our program will check the value of
20
Starting'
Out
40 GOSUB 300
With this GOSUB, the program will jump to line 300, which
begins a routine that puts up the menu and the display of values
currently being POKEd. How did I choose line 300? Because I
knew I wanted the main loop to begin at line 100 and figured that
it would finish well before 300.1 like to begin my main subrou
tines on even-hundred lines — it's easier to find them again that
way.
21
1 Starting
Out
Lines 300 through 360 show all the possible choices. But first, in
line 300, the statement PRINT CHR$(147) clears the screen.
What do those cryptic menu entries mean? Fl/2 means that
pressing Fl (function key 1) will give you the first result, and F2
(Fl shifted) will give you the second result. The first result is high
frequency down; shifted, it is high frequency up. F5/6 means that
pressing F5, unshifted, will change the attack; pressing F6,
shifted, willchange the decay.
The layout is reasonably consistent. Whenever a choice in
cludes a down/up option, the unshifted key means down and the
shifted key means up. The ADSR envelope choices are together,
in their proper order — attack, decay, sustain, release — and one
key always controls both halves of a two-nybble choice. The space
bar is used to change the waveform, which has the largest single
effect on the sound. The up/down cursor key controls, not the
quality of the sound, but its duration; the left/right cursor key
controls the most rarely used function, the pulse width of the
square wave. The up-arrow key controls the TEN toggle. And the
RETURN key allows the user to stop the program.
Why provide a key to stop the program? All the user needs to
do is press RUN/STOP and the program will end, won't it? Yes,
22
Starting
Out
but RUN/STOP won't turn off the sound! If you happen to press it
during the middle of a note, the note will keep on sounding for
ever. Pressing RETURN will provide an orderly, quiet end for the
program.
23
1 Starting
Out
change the value of WAVE from 129 to 17, it will look like we
changed it from 129 to 179. The 9 will be left hanging.
And it doesn't help just to put a blank space — " " — after the
variable name. That blank space will simply begin afterihe trail
ing space. The 9 will still be left hanging.
The STR$ solution. The solution, then, is to print the vari
ables, not as numerical variables, but as string variables. And 64
BASIC has a built-in function, STR$, that does it very nicely. In
stead of PRINT WAVE, we say PRINT STR$(WAVE). What STR$
does is evaluate the value of WAVE and turn it into the ASCII
string that expresses that value. It's a trivial difference to human
beings — it comes out looking like the same number to us. But to
the computer, they are not the same thing at all.
One result of that difference is that the computer doesn't skip
leading and trailing spaces when it PRINTs strings. When we
change the value of WAVE from 129 to 17 in the statement
the result, on our screen, is not 129 followed by 179; it is 129 fol
lowed by 17, which is exactly what we want.
Double use of a subroutine. Line 410 ends with the RETURN
statement, which causes the program to jump back to the state
ment after the GOSUB in line 40. You may wonder why the menu
(lines 300-360), which is printed only once, is included as part of
the subroutine that prints the current value display (lines
365-410), which will be updated and rePRINTed often.
It didn't have to be that way. I could have put the menu be
tween lines 40 and 100 and included only 365-410 in the subrou
tine. I did it to show you a technique that you may want to use.
Later in the program, we will reuse that subroutine, but not in a
statement that says GOSUB 300. Instead, the statement will say
GOSUB 365. It will begin executing the subroutine at line 365,
which positions the cursor, and then flow through to line 410,
which RETURNS.
When you have a routine that sometimes includes several
statements and sometimes doesn't, one of the simplest things to
do is group those statements at the beginning of the subroutine,
and then sometimes use an entry point before those statements,
and sometimes use an entry point after them.
There are dangers, though, to having a subroutine do double
duty. Once again, we need to think of revisions. What if you were
24
Starting
Out
Read the keyboard. Line 100 finds out what key, if any, the
user has pressed. The computer finds out the value stored at SC
and assigns it to the variable SH. This will be a 1 if the SHIFT key
is pressed, 2 if the COMMODORE key is pressed, or a 0 if neither
is pressed. Then KD is PEEKed and the value is placed in KEY,
which tells which key has been pressed.
If KEY does not contain a 64, then a key has been pressed,
and we will want the program to do certain things. First, the pro
gram will jump to the subroutine at 500. This is the Change Value
Subroutine that finds out whichkey was pressed and makes
changes accordingly. Then the program will GOSUB to 365 and
update the current value display — this is the second entry point
to that subroutine, which you've already seen.
25
1 Starting
Out
26
starting
Out
Notice that ANDing any number with 254 will turn off only the
rightmost (least significant) bit. All other on bits will stay on.
27
1 Starting
Out
Close the loop. Line 160 closes the main loop by sending the
program back to 100. It will keep doing this forever if the user
never ends the program. That's why a loop made with a GOTO is
called an endless loop.
5. Exit Routine
Line 200 is very simple —- it exits from the program. But it does it
cleanly. First, you can get to this line only when the sound is off.
Every time through the main loop, the sound is off after line 140
and does not turn on again until the loop repeats and reaches line
110. The command that can send us to the exit routine is in line
105. Therefore, you can only reach this routine when the sound is
off.
200 POKE 198#0:END
What is POKE 198,0 doing? Every time you press a key on the
64, the value of the key you pressed is automatically put into a
keyboard buffer. This happens even during a program like this
one, where we aren't accessing the keyboard buffer. Location 198
contains the number of characters stored in the buffer. If we didn't
POKE a 0 there, the values of the keys you had last pressed would
be stored there, and when the program ended, those characters
would be printed on the screen. It wouldn't cause any harm, but
it looks funny and forces the user to move down a line or erase
those characters. So POKE 198,0 just tidies up a bit at the end of
the program.
6. Evaluate key
In lines 500 through 530, the program evaluates the value of KEY
and SH and figures out what subroutine to branch to.
28
Starting
Out 1
Exit flag set. Line 500 checks to see if RETURN was pressed.
If so, it changes KEY to 255 and RETURNS. But why not just end
the program right at line 500? We could enter this line:
500 IF KEY=1 THEN POKE 198,0:END
That line would work just fine. The program would end, and be
cause we can't reach line 500 unless the sound is off, we would be
ending very neatly. If you use this line, you can delete line 105 and
line 200. The program is shorter and runs faster.
I simply have a personal aversion to ending programs in the
middle of an unresolved subroutine. We executed a GOSUB to
get to line 500, and I don't like to end unless the program has exe
cuted a RETURN. It's just a quirk of mine. I like to be neat. This is
the sort of thing that programmers do because they feel like it.
That's why if you assign two programmers to do the identical
task, they will come back with very different programs. People do
things differently.
Toggling TEN. Line 505 checks to see if the key pressed was
the up-arrow key. If it was, then TEN will be changed. If it was 1,
it will become 10; if it was 10, it will become 1.
Look carefully at the expression after the equal sign (=) in
line 505. Let's evaluate that expression the way the computer
would, and see what's going on.
We start inside the parentheses, with the expression
TEN <> 10. If this expression is false, then it will return a value of 0.
If it is true, it will return a value of -1. This is very important! True
expressions equal negative one (-1), and false expressions equal
zero (0). Knowing this can help you make your programs run fast
er, with fewer IF statements. In this case, if TEN does not equal 10,
then the expression is true, and returns a value of -1. If TEN does
equal 10, then the expression is false, and returns a value of 0.
The next step is to multiply the result of TEN <> 10 by 9. If the
expression was false, or 0, then the result of this operation is 0. If it
was true, then the result is -9.
29
1 Starting
Out
30
Starting
Out
540 SQUARE=SQUARE-TEN+2*TEN*ABS(SH=1)
545 SQUARE=SQUARE-256*(ABS(SQUARE>255)-A
BS(SQUARE < 0)):RETURN
550 IF SH=1 THEN RELEASE=RELEASE+1-15*AB
S(RELEASE=15):RETURN
555 SUSTAIN=SUSTAIN+16-240*ABS(SUSTAIN=2
40):RETURN
560 S1=S1-TEN+2*TEN*ABS(SH=1):Sl=Sl-256*
(ABS(S1> 2 5 5)-ABS(Sl< 0)):RETURN
570 S2=S2-TEN+2*TEN*ABS(SH=1):S2=S2-256*
(ABS(S2 > 2 5 5)-ABS(S2 < 0)):RETURN
580 IF SH=1 THEN DECAY=DECAY+1-15*ABS(DE
CAY=15):RETURN
585 ATTACK=ATTACK+16-240*ABS(ATTACK=240)
:RETURN
590 DUR=DUR-25*(ABS(SH=0)-ABS(SH=1)):IF
DUR<25 THEN DUR=25
595 RETURN
600 WAVE=WAVE+16*(INT(WAVE/16)):IF WAVE>
129 THEN WAVE-17
610 RETURN
31
1 Starting
Out
32
Starting
Out
So even if there were a RETURN on the end of the line, the pro
gram would still need to have a RETURN on the next line to end
the subroutine in case the result is false. Since nothing else but
the RETURN will happen on that line, why type in an extra
RETURN? The one will be enough to end each subroutine.
However, in cases like 550 and 555, where we never want both
lines to execute, we need to have a RETURN at the end of each
line so it can't "fall through" and execute the wrong line. Perhaps
the easiest way to see the result of allowing the program to fall
through is to remove one of the RETURNS and then see what
happens to the values when you press the keys — you get more
than you bargained for.
Does this seem like an awful lot to think about every time you
program? Actually, you have to make about as many decisions
whenever you drive a car. It's just a matter of habit. Once you're
used to thinking this way, it won't occur to you that you're even
doing something difficult. And it won't be very long before you
look back at this program and think, 'Is this all?"
Well, it isn't all — it never is. Because once you're comfortable
with my version of the program, you'll start to think of features
you want to add and slow places that you can speed up. It
wouldn't be hard to have three voices going at once and to use the
COMMODORE key to cycle from one voice to the next. Or to
make the screen change colors every time the waveform is
changed. Or to allow direct keyboard entry of certain pitches in
stead of having to rotate through them 1 or 10 values at a time.
When you start customizing programs like that, you've got it.
The following program repeats what has been given, in parts,
throughout this chapter.
64 sound
10 P1=54273:P2=54272:VL=54296:AD=54277:S
R=54278:WF=54276:SW=54274
20 SC=653:KD=197
25 POKE 54275,8:POKE VL,15
30 S1=22:S2=53:ATTACK=16:DECAY=8:SUSTAIN
=16:RELEASE=8:SQUARE=128
35 WAVE=35:DUR=100:OFF=254:TEN=10
40 GOSUB 300
100 SH=PEEK(SC):KEY=PEEK(KD):IF KEY<>64
THEN GOSUB 500:GOSUB 365
105 IF KEY=255 THEN 200
110 POKE PI,SI 2 POKE P2,S2
33
1 starting
out
34
Starting
Out
570 S2=S2-TEN+2*TEN*ABS(SH=1):S2=S2-256*
(ABS(S2>255)-ABS(S2<0)) -.RETURN
580 IF SH=1 THEN DECAY=DECAY+1-15*ABS(DE
CAY=15):RETURN
585 ATTACK=ATTACK+16-240*ABS(ATTACK=240)
:RETURN
590 DUR=DUR-25*(ABS(SH=0)-ABS(SH=1)):IF
DUR<25 THEN DUR=25
595 RETURN
600 WAVE=WAVE+16*(INT(WAVE/16)):IF WAVE>
129 THEN WAVE=17
610 RETURN
35
Chapter 2
BASIC
Programming
BASIC
Programming 2
39
2 BASIC
Programming
J^^^f|^|^
Unique value for the key pressed at the ciirrent jiffy
^^Kiife^^-^^ "■ ■■ ■ ■ . .^r^. v;y^:fe^^^®&
Number of characters in the keyboard buffer
40
BASIC
Programming 2
41
2 BASIC
Programming
This table assumes you want to test if the joystick is pressed a cer
tain way. If you want to test that a certain position is not pressed,
just leave off the last number.
42
BASIC
Programming 2
SHIFT key alone becomes the control key. This has the advantage
of providing a "hands off pause by using the SHIFT LOCK key.
It is also possible to single-step (go through a program line by
line) using the WAIT command. Simply change the WATT to
WAIT 197,64: WAIT 197,64*64
43
2 BAS8C
Programming
rem Revealed
John L. Darling
Did you know that you can prevent someone from easily LISTing your
program? This is one ofseveral hidden secrets of the REM statement. Did
you ever try putting shifted or reverse video characters behind a REM?
The results you get when you LIST may come as a surprise. Try these ex
periments to learn about the tricks you can play with REMs.
44
BASIC
Programming
10 rem a b c d e f
20 rem A B C D E F
30 rem {RVS}a b c d e f{OFF}
40 rem {RVSJa B C D E F{OFF}
list
10 rem a b c d e f
20 rem atn peek len str$ val asc
30 rem a b c d e f
40 rem atn peek len str$ val asc
LIST Blocking
Now we get to the question of how to prevent someone from
easily LISTing your program. Let's examine Rule 2 a little more
closely. Certain characters become "tokens" which cause unusual
effects. One will cause the LIST operation to terminate with a
"syntax error" message when it is encountered. These tokens are
equivalent to a shifted-L.
This can be verified by the following line.
10 rem L
When you attempt to list the line, the result will be:
10 rem
?syntax error
ready.
Up to now, it's just been fun, but there is a reason you might
want to use this line. If this special REM line is the first line in a
program, it prevents a normal LISTing. Let's assume that the first
line in a large program is line 100. Inserting this special REM line
ahead of the program causes the LIST operation to terminate as
soon as it encounters the special shifted character. However, LIST
45
2 BASIC
Programming
Quote Mode
Now, let's examine the quote mode. A new set of rules applies
when the REM characters are enclosed in quotes:
1. Shifted and nonshifted characters LIST as they were typed
in.
2. Reverse video characters are preserved when inside quotes
(they are not stripped, as is the case in the nonquote mode).
3. Some reverse video characters and combinations of charac
ters behave as print control commands when LISTed.
Rules 1 and 2 produce results that you would normally expect
during the LIST operation. They LIST exactly as typed in. No ex
amples are provided for these rules, but try a few experiments to
verify this for yourself.
Here are some interesting examples of Rule 3 in action. (The
comments in brackets are the resultant action produced during
LIST.)
46
BASIC
Programming
10 rem"help ? O333
1 ist
1 0 r s sTi " h e
1,0,SPAC$, R# E,M,",",DEL,RVS,SHIFT-M,
SHIFT-S,Q,Q,Q,Q,OFF,I,SPACE,T,H,I,N,K#
SPACE,I,SPACE,A,M,SPACE,S,RVS,Q,OFF ,I
RVSfQ,OFF#C,RVS,Q,OFF,K,RVS,S,OFF,
SHIFT-L
47
2 BASIC
Programming
Can you guess the results? If you type the line correctly, the
following will happen after you LIST:
1.10 REM" will be printed.
2. A CLEAR SCREEN will be printed, blanking the screen
and also the previous 10 REM".
3. Four cursor-downs will be printed.
4. The message I THINK I AM SICK will be printed with the
I,C,K characters on different lines.
5. A cursor-home will occur.
6. " @ will be printed on the top line followed by a 7SYNTAX
ERROR message on the next line. (Note that the special shifted
character is no longer enclosed in quotes.)
7. Finally, the READY message will appear with the cursor
above the I THINK I AM S line.
The above line could be inserted in most programs, and it will
not affect the program execution performance in the least. You
just can't get a normal USTing of the program.
There are a lot more combinations to try, so have fun. It's like
having a program inside another program. The second program
requires a LIST command for execution instead of a RUN
command.
48
BASIC
programming 2
49
2 BASIC
Programming
fiir,
l^^iil^iili
The 64 Sketchpad
With this data, a simple program can be written that moves a
graphics symbol around the screen under control of the joystick
(Program 1). (Be sure to save this program; we will use it again
later.) Pressing the fire button clears the screen and starts a "fresh
page/' The lines in this program perform the following actions:
Line Action
5 Clear screen.
7 Brown border: black background.
10 Variable JM (Joystick Memory) set for port 2.
20 Set Screen Location and Screen Color to center of screen.
30,40 Put a ball in center and color it green.
50,60 Set variables for No Joystick and directions using Table 2.
70-150 Test JM for direction, set X and Y increment.
155 If Fire Button pressed, erase and start over.
160 No motion; start JM test sequence again.
170 Set new SL.
175,177 Keep SL within limits of screen memory.
180 Set new SC.
185,187 Keep SC within limits of screen color memory.
190 Draw a ball at new SL.
200 Color ball green at new SL.
205 Slow it all down.
210 Begin another loop to find next location.
50
BASIC
programming 2
From this table, you can see that the major points of the com
pass have nonoverlapping binary values and that the diagonals
are the sum of the vertical and horizontal values on either side.
Thus it should be possible to adapt Butterfield's one-line VIC hor
izontal and vertical incrementers to the 64.
Saving Memory
Our sketchpad program can now be shortened considerably with
51
BASIC
Programming
this far more elegant approach. First eliminate lines 50-160 inclu
sive from Program 1. Then add the following lines:
In lines 170 and 180, substitute H for X and V for Y. The pro
gram should perform the same as before with a net saving of nine
lines.
A similar investigation for port 1 reveals that the inverted
directions are the same as for port 2. The only difference is in the
PEEK statement. Substitute the following:
D=(NOT PEEK(56321))+256
Now the Sketchpad program will work for port 1. The Modified
Sketchpad is Program 2.
5 PRINT "{CLR}"
7 POKE53280/9:POKE53281,0
10 JM=56320:REM JOYSTICK MEMORY,PORT 2
20 SL=1524:SC=55796:REM SCREEN LOCATION
& PIXEL COLOR. START IN MID SCREEN
30 POKE SL,81:REM BALL IN MIDDLE OF SCRE
EN
40 POKE SC,5:REM GREEN BALL
50 NJ=127:N=126sNE=118:E=119:SE=117
60 S=125:SW=121:W=123:NW=122:FB=111
70 IF PEEK(JM)=NJ THEN X=0:Y=0
80 IF PEEK(JM)=N THEN X=0:Y=-1
90 IF PEEK (JM)=NE THEN X=1:Y=-1
100 IF PEEK (JM)=E THEN X=1:Y=0
110 IF PEEK (JM)=SE THEN X=1:Y=1
120 IF PEEK (JM)=S THEN X=0:Y=1
130 IF PEEK (JM)=SW THEN X=-1:Y=1
140 IF PEEK (JM)=W THEN X=-1:Y=0
150 IF PEEK (JM)=NW THEN X=-1:Y=-1
155 IF PEEK(JM)=FB THEN GOTO 5
160 IF X=0 AND Y=0 THEN 70:REM NO MOTION
170 SL=SL+X+40*Y:REM NEW LOCATION
52
BASIC
programming 2
5 PRINT "{CLR}"
7 POKE53280,9:POKE53281,0
10 JM=56320:REM JOYSTICK MEMORY,PORT 2
20 SL=1524:SC=55796:REM SCREEN LOCATION
& PIXEL COLOR. START IN MID SCREEN
30 POKE SL,81:REM BALL IN MIDDLE OF SCRE
EN
40 POKE SC,5:REM GREEN BALL
50 D=(NOT PEEK(56320))+128:REM INVERT DI
RECTION BYTES
55 IF D=16 THEN 5:REM FIRE BUTTON.START
OVER
60 H=SGN(D AND 8)-SGN(D AND 4)
70 V=SGN(D AND 2)-SGN(D AND 1)
170 SL=SL+H+40*V:REM NEW LOCATION
175 IF SL>=2023 THEN SL=2023
177 IF SL<=1024 THEN SL=1024
180 SC=SC+H+40*V:REM COLOR @ NEW LOC'N
185 IF SC>=56295 THEN SC=56295
187 IF SC<=55296 THEN SC=55296
190 POKE SL,81:REM BALL @ NEW LOC'N
200 POKE SC,5:REM GREEN BALL
205 FOR DL= 1 TO 50:NEXT DL:REM DELAY
210 GOTO 50:REM DO NEXT BALL LOCATION
220 END
53
2 BASIC
Programming
Menumaker
Richard L. Witkover
The Menu
The answer, of course, is a simple, informational display on the
screen. "Menumaker" is a utility that will print a display starting
at any row or column, or will center the text by row, column, or
both. After the longest line, the program will print a dash. All
shorter lines will be filled with dashes to this point. The last col
umn is used to draw an array of cursor boxes which, along with
the flashing cursor, will move. To allow only a single key to con
trol its motion, the cursor has a wraparound feature. Selection is
made by moving the cursor to the row desired by means of the
cursor UP/DN key (either way), then hitting any key to select the
54
BASIC
Programming 2
The Program
Part 1 extends through line 290. It sets up the various constants
and gets the input values of RI$, CI$, and TE$, which set the posi
tioning of the rows, the columns, and the text lines, respectively.
The variables RI$ and CI$ are tested to see if the automatic center
ing option was chosen, and if not, whether the numerical values
are within the allowed ranges. These are set by the screen charac
ter limits with allowances for the borders of the box, the dash,
and cursor array.
The text input is obtained by lines 170-195, checking that the
maximum character count isn't exceeded. Each line is ended with
a carriage return until a null line ends the loop. As each line is
read in, its length is measured and the largest count is retained as
LW% in line 194.
If the centered option is selected, lines 205-240 will compute
the cursor column number and the text starting column number.
Part 2, lines 320 to 370, prints the text on the screen, and Part
3, lines 510 to 680, draws the bordering box. The final part, lines
800-920, is the cursor routine.
55
2 BASSC
(Programming
the text will add a bit of pizazz. You could use a joystick to move
the cursor or just use the fire button. The variations are endless,
so have some fun and dress up your programs while you make
them easier to use with Menumaker.
Menumaker
7 REM{11 SPACES}MENUMAKER
8 REM {2 SPACES}THIS PROGRAM DISPLAYS UP
TO 22
9 REM{2 SPACES}LINES OF UP TO 35 CHARACT
ERS.
10 REM THE CHOICE IS MADE BY MOVING THE
11 REM CURSOR VERTICALLY (WITH WRAP-
12 REM AROUND) ALONG AN ARRAY IN THE
13 REM LAST COLUMN. HITTING ANY KEY BUT
14 REM THE UP/ON CURSOR WILL ENCODE THE
15 REM THE ROW #.A BOX IS DRAWN AROUND
16 REM THE MENU. THE TOP LEFT-HAND CHAR
17 REM INSIDE THE BOX CAN BE LOCATED
18 REM SPECIFICALLY OR THE BOX CAN BE
19 REM CENTERED IN ROW AND/OR COLUMN.
20 REM*********************************
40 REM ********************************
41 REM
42 REM{4 SPACES}THE FOLLOWING ARE COMPUT
ER
43 REM{7 SPACES}DEPENDENT CONSTANTS:
44 REM
45 REM{7 SPACES}CM=40{2 SPACES}:MAX # CO
LS
46 REM{7 SPACES}RM=24{2 SPACES}:MAX # RO
WS
47 REM{6 SPACES}SC%=1024:ST OF C-64 SCRE
EN
48 REM{7 SPACES}PN=87{2 SPACES}:NORMAL C
URSOR POKE
49 REM{7 SPACES}PR=215 :REV CURSOR POKE
50 REM{7 SPACES}CR=119 :NORMAL CURSOR CH
R$
52 REM
53 REM{2 SPACES}CHANGE AS NEEDED FOR COM
PUTERS
54 REM{2 SPACES}OTHER THAN THE COMMODORE
64.
55 REM
56 rem*********************************
57 REM
56
BASSC
Programming
60 CM=40:RM=24:SC%=1024 2PN=87:PR=215:CR=
119
69 rem*********************************
70 REM
71 REM{5 SPACES}PARAMETER INPUT ROUTINE
72 REM
73 REM{7 SPACES}REQUIRED INPUTS ARE:
74 REM
75 REM{6 SPACES}RI$=STARTING TEXT ROW
76 REM{6 SPACES}CI$=STARTING TEXT COL
77 REM{6 SPACES}TE$=UP TO 22 TEXT LINES
78 REM
79 REM ROUTINE ACCEPTS A NUMBER FOR RI$
80 REM AND CI$, OR 'C'JN WHICH CASE IT
81 REM WILL CENTERS ROWS AND/OR COLS.
82 REM
83 REM TEXT STRINGS CAN BE A MAX OF 35
84 REM CHARACTERS#EACH LINE ENDING WITH
85 REM A CARRAIGE RETURN. TEXT ENTRY
86 REM ENDS WITH A NULL LINE.
87 REM
88 reM*********************************
89 REM
90 REM{2 SPACES}THE FOLLOWING ARE SCREEN
CHAR
91 REM{2 SPACESjCODES FOR THE C-64:
92 REM{8 SPACES}ER$=ERASE SCREEN
93 REM{8 SPACES}CD$=CURSOR DOWN
94 REM{8 SPACES}CL$=CURSOR LEFT
95 REM{8 SPACES}RO$=REVERSE ON
96 REM{8 SPACES}HO$=HOME
97 REM********************************
98 ER$=CHR$(147):CD$=CHR$(17):CL$=CHR$(1
57):RO?=CHR$(18):HO$=CHR$(19)
100 DIM TE$(22)
105 PRINTER$;CD$;CD$;MENTER ROW AND COLU
MN OF START OF TEXT11
110 PRINT"{7 SPACESjFOR CENTERED TEXT EN
TER 'C'"
115 INPUT"{2 DOWN}{8 SPACES}ROW,COL="7RI
$,CI$
120 LW%=0:CS%=0
125 IFCI$="C"THEN140
130 CS%=VAL(CI$)
135 IFCS%<1ORCS%>(CM-5)THEN INPUT"{RVS}C
OL# INVALID- ENTER COL#";CI$:GOTO125
140 IF RI$="C"THEN LM=RM-2:GOTO160
145 RT%=VAL(RI$)
57
2 BASBC
Programming
58
BASIC
programming
409 REM
410 REM{4 SPACES}RT%=# OF TOP INSIDE ROW
411 REM{4 SPACESjNL =# OF INSIDE LINES
412 REM{4 SPACES}LW%=# OF INSIDE CHAR -1
413 REM{4 SPACES}CS%=# OF LEFT INSIDE CO
L
414 REM
415 REM{4 SPACES}LT$=LEFT-TOP CHR$
416 REM{4 SPACES}RT$=RIGHT-TOP CHR$
417 REM{4 SPACES}SD$=SIDE CHR$
418 REM{4 SPACES}DA$=DASH CHR$
419 REM{4 SPACES}LB$=LEFT-BOT CHR$
420 REM{4 SPACES}RB$=RIGHT-BOT CHR$
421 REM
422 rem********************************
500 REM THE FOLLOWING ARE FOR THE C-64
510 LT$=CHR$(117):RT$=CHR$(105)
520 RB$=CHR$(107):LB$=CHR$(106)
530 DA$=CHR?(99):SD$=CHR$(125)
540 IF CS%<>0THENBL%=CS%:GOTO560
550 BL%=INT(CM-LW%)/2
560 BR%=BL%+LW%
570 PRINTHO$-;
580 LF$=CHR$(0):LN$=CHR$(0)
590 IF RT%<=1THEN610
600 FORA=1TORT%-1:LF$=LF$+" {DOWN}11:NEXT
610 FORA=1TOLW%:LN$=LN$+DA$:NEXT
620 PRINTLF?;
630 PRINTTAB(BL%-1);LT$;LN$;RT?
640 FORA=1TONL
650 PRINTTAB(BL%-1)SD$;TAB(BR%);SD$
660 NEXTA
670 PRINTTAB(BL%-1);LB$;LN$;RB$
680 RETURN
700 REM********************************
701 REM
702 REM ROUTINE TO PUT ON CURSOR ARRAY
703 REM WITH FLASHING CURSOR. CURSOR UP
704 REM /DOWN KEY IS USED TO MOVE WITH
705 REM WRAP-AROUND. HIT ON ANY OTHER
59
2 BASIC
Programming
711 REM
712 REM{6 SPACES}RT%=TOP ROW #
713 REM{6 SPACES}NL =# OF ROWS
714 REM{6 SPACES}LW%=COL#-1 OF CURSOR
715 REM{6 SPACES}CS%=COL# OF 1ST CHAR
716 REM{6 SPACES}S% =CURSOR SCREEN LOC
717 REM
718 rem********************************
719 REM
800 RB%=NL+RT%-1:LF$=CHR$(0)
810 IF RT%=1THEN830
820 FORA=1TORT%-1:LF$=LF$+CD$:NEXT
830 PRINTHO$;LF$
840 FORI=1TONL:PRINTTAB(C%);CHR$(CR);"
{OFF}11: NEXT
850 R%=RT%
860 POKES%,PN:FORI=1TO50:NEXT
870 POKES%,PR:FORI=1TO50:NEXT
880 GETB$:IFB$=""THEN860
890 IFB$<>CHR$(145)THEN930
900 POKE S%,PN
910 IFR%>RT%THENR%=R%-1:S%=SC%+C%+R%*CM:
GOTO980
920 S%=SC%+C%+RB%*CM:GOTO980
930 IFB$<>CD$THENRETURN
950 POKE S%,PN
960 IFR%<RB%THENR%=R%+1:S%=SC%+C%+R%*CM:
GOTO980
970 S%=SC%+C%+RT%*CM
980 R%=INT((S%-SC%)/CM):GOTO860
60
BASIC
Programming 2
Data Storage
Ron Gunn
Data storage can be the most perplexing aspect ofprogramming for the
novice. Here are some practical tips which just might save you days of
experimentation.
Types of Data
Commodore computers use three kinds of variables, and it is the
values stored in variables that you will be dealing with when you
save and recall data. The first of these is floating point, repre
sented by a variable like A or A(X). The second is integer, repre
sented by a variable like A% or A%(X).
The third is the string variable, represented by A$ or A$(X).
Any of these varieties can be single: A; or may have subscripts:
A(X); A(X,Y); or A(X,Y,Z). Part of your sense of power in comput
ing comes when you realize just how much data you can pack
and organize into those multiple-subscripted arrays.
When you are putting data out on tape or disk and expecting
to read it back in, you must remember two things: 1. The three
variable types are different and are not interchangeable. 2. They
are put onto the recording medium in series without any identifi
cation and must therefore be read back in, in exactly the same
sequence, to be recovered.
Only the data is recorded, not the variable names them
selves. You can send it onto the tape as A, and can call it B when
reading it back in. That is fair. But if you read data back as B% or
B$, you will get an error message. Some error messages are really
undeserved, as you know. This one is deserved. Don't mix your
data types — integer to integer, string to string, and so on.
61
2 BASIC
Programming
string "0" would be ASCII 48, but that is not what is there. What
is there is a binary, octal, decimal, hex 0 — which, in the special
language of strings, represents a null. Neither the cassette nor the
disk will accept null strings. Result: input rejects it and the data
isn't transferred.
The cure is logical, once it is pointed out: load all string vari
ables, including string arrays, with a string variable that the tape
or disk can recognize. Example: you have dimensioned a string
array A$(20) that may not be filled from your program when you
want to save it. Right after the DIMension statement, do the
following:
The array has now been loaded with a recognizable string ("X")
and can be saved. All unused parts of it will be saved as X and will
not confuse things later.
62
BASIC
Programming 2
12000 DO$=H1:SCORE,S,WM
12010 OPEN 2,8,9,DO$
12020 PRINT#2,A;",";B%;",";C$;CHR$(13);
For reliable records, just don't mix string and numerical vari
ables in a FOR/NEXT loop when saving data. Use an entirely
separate loop to handle the strings. Any potential savings by
avoiding the use of another separate loop to handle the strings
can be costly. This works reliably:
63
2 BASIC
Programming
A Practical Application
Now lefs define and then write a minor cassette or disk data tour-
de-force program. Let's say you need to input two arrays that con
tain names and scores for a tournament. NT$ is the name of the
tournament, TP the number of tournament players, N$(TP) their
names, and S(TP) their scores. We are reading data:
At 15010 the name and size are brought in on the same line.
That's OK. They were put on the record earlier using the neces
sary delimiters. The file is then closed to bring all of the informa
tion in from the buffer.
At 15030, TP is used to dimension the necessary arrays to
hold the data. Then, using loops, the data for names and then for
scores is brought in separately. So, we have stuck to our princi
ples. Single-line data is mixed because it will mix. Array data is
not mixed even though it seems compellingly simple to do so.
Not that we referred to both cassette and disk in this pro
gram. The only difference between input of cassette data and in
put of disk data is the opening statements (i.e., OPEN 1,8 instead
of OPEN 1,1). It is actually practical to have independent opening
64
BASIC
Programming 2
65
Chapter 3
Commodore
64 video
commodore 64
video 3
An introduction
to the
6566 video Chip
Jim Butterfield
Charting the 64
When the video chip goes to memory for its information, it has a
69
Commodore 64
video
• POKE 56576,4 the chip sees RAM from 49152 to 65535. There's
no Character Generator; you'll have to make your own.
• POKE 56576,5 the chip sees RAM from 32768 to 36863 and from
40960 to 49151. The ROM Character Generator is in the slot from
36864 to 40959.
Also note that the chip never has access to RAM at addresses 4096
to 8191 and 36864 to 40959. You will not be able to put screen
memory or sprites there.
Be careful with these. If you move the chip's memory area,
you'd better be sure to move the screen. For example, try the
following:
POKE 648,132:POKE56576,5
70
commodore 64
video
You'll see the screen move vertically, leaving an empty spot near
the top. POKE 53265 back to 27.
POKE 53265,19
Youil see the top and bottom trimmed to half a line each.
Think about using these two features together. If we have a
screen full of information, we would normally scroll when we
wanted to write more — the characters would jump up a line. But
if we can switch to 24 lines, slide the characters up gently, and
then switch back to 25 lines, we'd have a smooth scroll.
POKE 53265 back to 27
High Resolution
The next control bit — value 32 — switches the display to pure
bits. No more characters; the screen will be purely pixels as we
switch to high-resolution mode. Well use a lot of memory for this
one: memory to feed the screen will be 8000 bytes.
71
t Commodore 64
1 Video
Extended Color
If we add 64 to the contents of 53265, well invoke the extended
color mode. This will allow us to choose both background and
foreground colors for each character. Normally, we may choose
only the foreground: the background stays the same throughout
the screen. You lose some colors, but get better combinations.
Try POKE 53265,91. Nothing happens, except that the cursor
disappears, or at least becomes less visible. Why? We've traded
the screen reverse feature for a new background color. Try typing
characters in reverse font, and see what happens. Try choosing
some of the specialized colors — the ones you generate with the
71
commodore 64
video
COMMODORE key rather than CTRL. See how you Uke the ef
fect. Think how you might be able to use it.
Extended color is purely a screen display phenomenon.
POKE 53265,27 will bring all the characters you have typed back
to their normal appearance.
Table 1.
6566 Video Chip:
Control and Miscellaneous Registers
53267
53268
Multi- . Col
D016 unused Reset
Color 53270
Select
f - ~ Interrupt-Enable" *,
D01A unused tight Colliswntwfil Raster 53274
, , Sprite., .Back t| ■
Color Registers
73
Commodore 64
video
Table 2.
Sprite Sprite 6566 Video Chip: Sprite Sprite
0 7
0 7 Sprite Registers
1 1 1 1
53248 53262
D000 DOOE
D017 53271
D01C • ";<--:;-,' ' r' " - TVft^olbr " - . "•_.'-1"";'-' " 53276
74
Commodore 64
video 3
75
Commodore 64
video
76
commodore 64
video 3
Light Pen
Locations 53267 and 53268 (hex D013 and D014) are the light pen
registers. An Atari-style light pen can be plugged into the joystick
port number one; if it sees a suitable signal from the screen, the X
and Y values will be latched into these registers. The light pen can
77
Commodore 64
video
interrupts
Interrupts are for machine language experts — things happen too
fast for BASIC to cope in this area. There are four types of inter
rupts: raster, light pen, and two kinds of sprite collision. (Well
talk about sprites in the next section.) We may use all of them or
none; and even when these signals are not used for interrupt, we
can check them.
Location 53273 (hex D019) tells us which of the four events has
occurred. We don't need to make the interrupts "live"; they will
signal us anytime the particular event happens. The weights are
as follows:
1 (bit 0) — the raster has matched the preset line value;
2 (bit 1) — a sprite has collided with the screen background;
4 (bit 2) — a sprite has collided with another sprite;
8 (bit 3) — the light pen has sensed a signal;
128 (bit 7) — one of the above has triggered a live interrupt.
Once any of the above takes place, the bit will remain stuck
on until you turn it off. How do you turn it off? This may sound
goofy, but you turn an interrupt signal off by trying to turn it on.
Hmmm, let me try that again. Suppose that we have both a raster
and a light pen signal; well see a value of 9 (8 +1) in the interrupt
register. Now suppose further that we are ready to handle the
light pen, so we want to turn its signal off. We do this by storing 8
into location 53273. Huh? Wouldn't that turn it on? Nope, it turns
it off, and leaves the other bit alone. So after storing 8, we look at
the register again, and (you guessed it) we see a value of 1 there.
Honest.
Location 53274 (hex D01A) is the interrupt enable register: it
sets the above signals for "live interrupt." Select bits 0 to 3 corre
sponding to the interrupts you want. Whatever live interrupt you
select will now trigger a processor interrupt and also light up that
high bit of 53273. Don't forget to shut the interrupt flag off when
you service the interrupt, using the method indicated in the
previous paragraph. Otherwise, when you finish the job and re
turn from the interrupt (with KIT), it will reinterrupt you all over
again.
78
commodore 64
video 3
A Little Color
Some of the colors we have mentioned and some we have yet to
discuss are neatly stored in addresses 53280 to 53286 (hex D020 to
D026). We may store only values 0 to 15 here, for the 16 Com
modore 64 colors.
The chart in the previous article shows it all: the exterior
(border) color; then four background colors (they may be selected
as part of multicolor characters or bits); and finally, two colors re
served especially for sprites.
79
Commodore 64
video
Sprites
JimButterfield
MOBS
Sprites are sometimes called Movable Object Blocks (MOBs) —
and that's what they are, movable objects. The nice thing about
them is that they appear on the screen independently of the main
screen image, so that we can have a sprite airplane flying across
the screen, and, after it passes a background object, the object re
appears. This can save a lot of programming.
We noted earlier that the video chip can reach only 16K for its
information. This includes three things: the screen memory (or
video matrix), the Character Generator (or Character Base), and
the sprite information. It all has to come out of the same 16K section.
When we learn how to draw sprites, well discover that each
sprite occupies 63 bytes and uses a 64-byte block. So within 16K,
we could draw up to 128 sprites. We can't use more than eight at a
time, but we can have up to 128 drawings waiting to be used. The
sprite positions number from 0 at address 0, through 1 at address
64, up to 127 at address 8128.
We cannot use all of the 128 sprite positions, of course. For
one thing, the video matrix and the Character Base will use up a
total of 3K of memory, and this space won't be available for us to
use. That cuts us down to 80; and, depending on the 16K block
we have chosen, there may be other forbidden locations.
The normal configuration is for the video chip to access 0 to
16383, and there's a lot of forbidden territory in there. Many of the
first 1024 bytes are busy as the BASIC work area; the screen is
normally 1024 to 2023 (more on that later); the Character Base ap
pears in addresses 4096 to 8191, since there are two complete
character sets; and everything above 2048 that isn't used by the
Character Base is used to store your BASIC program. We haven't
started, but we seem to be out of sprite memory!
80
commodore 64
Video 3
. . X . .
. . X . .
X X . X X
. . X . .
. . X . .
X X
xxxxxxxx xxxxxxxx
There are 24 pixels across (that takes three bytes of eight bits
each) and 21 down. We may analyze the pixel pattern eight at a
time, using a binary system to describe each byte. We end up with
a DATA statement something like:
10 DATA 255,0,255,128,0,1,128,0,1,128,0,
1,128,0,1,128,0,1,128,0,1
20 DATA 0,8,0,0,8,0,0,8,0,0,52,0,0,8,0,0
,8,0,0,8;0
30 DATA 128,0,1,128,0,1,128,0,1,128,0,1,
128,0,1,128,0,1,255,0,255
40 FORJ=0TO62:READ X:POKEJ+832,X:NEXT J
81
Commodore 64
Video
Good. Running the program this far will place the sprite into
slot 13, but it won't do anything. It's just a picture, and nobody is
using it. That's OK. In fact, you'll often want to have dozens of
pictures available, even though you might end up using only one
or two at a time.
Let's tell a sprite to use this drawing. We do it in an odd way:
we don't use the video chip control registers at all. Instead, we use
the video matrix, or "screen memory." You may recall that 1024
addresses are set aside for the video memory, but the screen
holds only 1000 characters. What about the extras? At least some
of them are used to designate which sprite picture to use for a
given sprite. The last 'live" screen address is 2023. We could point
sprite 0 to sprite drawing 13 (the one we have just done) by POKE
2040,13. Better yet, let's point all the sprites at this drawing:
We're almost ready to energize the sprite. But, first, let's give it a
position on the screen. For sprite 0, we set the position by
POKEing to 53248 and 53249. Let's put a value of 99 in each, and
then turn the sprite on. If you've run the above program, you may
do this with a direct command, or give it a program line:
60 POKE53248,99:POKE53249,99:POKE53269,1
Either way, you should get your sprite on the screen. Now we
can play with it and see how easy some things are to do. Notice
how you can see right through the transparent portions of the
sprite to the program listing behind. Now you can try changing
the sprite color as desired by POKEing a value from 0 to 15 into
location 53287. One color will be the same as the background, so
that the sprite will be almost invisible, but not quite, since we can
see when it covers part of the text.
You can move the sprite around at will by changing the values
you have POKEd into 53248 and 53249. Try playing with the
values; you may find that (vertically, at least) you can move the
sprite partly or completely off the screen. If you like, try the fol
lowing command:
and then substitute 53249 for 53248 and try it again. Neat? You
bet. And there's more to come. But first, a small problem to be
resolved.
82
commodore 64
Video 3
83
Commodore 64
video
Four-color Sprites
Our sprite is only one color, the color we selected in 53287. The
other color is "transparent," so it isn't really a color at all. We may
code our sprite in four colors (or three plus transparent, to be ex
act), but we would need to draw it slightly differently. Instead of
one bit representing either "color" or "transparent," a grouping of
two bits will be needed to describe four conditions: the sprite
color (as before), special color #1, special color #2, and trans
parent. These extra special colors, by the way, are kept at 53285
and 53286: they are the same for all sprites; only the sprite color is
individual.
Now we come to the last two registers, which tell you about
collisions. PEEK(53279) will tell you if any sprites have collided
with the background since you last checked. One certainly has, of
course, if you've been messing around with the screen as sug
gested. PRINT PEEK(53279) will yield a value of one: checking
the bit table above tells us that sprite zero has hit the background.
Now, checking this location clears it; but if the sprite is still touch
ing some of the screen text, it will flip right back on again. Move
the sprite to a clear part of the screen. Print the PEEK again — it
will likely still say one, since the sprite has hit characters since it
was last checked. If the sprite is safely in a clear screen area, the
next PEEK will yield a zero.
We've activated only one sprite, so that we won't see any colli
sions between sprites. You would see this in location 53278, but
right now PEEK(53278) will yield zero; unless you have activated
more sprites, there would not have been any collision. Again,
when you get a signal here, you'll know which sprites have
bumped; and testing the location clears it, so that only new
"touches" will be shown on the next test.
A small comment here: these two PEEK locations are marked
'Interrupt." Yet when such collisions occur, they are logged —
they don't do anything. As we discussed earlier, the word inter
rupt has a special meaning to machine language programmers;
and no interrupts seem to be happening. The machine language
programmer who wants interrupt to happen must enable the in
terrupt by storing the appropriate value into address D01A hexa-
84
Commodore 64
Video i
decimal, and then write the appropriate extra coding to make it all
work.
This completes our roster of registers, but the plain mechani
cal facts don't convey the remarkable things that you can do with
the Commodore 64. There's more to come.
85
Commodore 64
video
Program Design
Jim Butterfield
We've examined all the bits in the video chip control registers.
Now let's ease back and look at the 64's video structure. Well talk
a bit about program design considerations.
86
Commodore 64
video
ter Base from another, and sprites from still another. Because we
are restricted, we must do a little planning and design our video
information into our program.
After we have picked the 16K slice, we must set the video
matrix (screen memory) to some point within it. We may pick any
multiple of 1024 as a starting address. The normal 64 configura
tion is set to a value of one, meaning we take the screen informa
tion from memory starting at address 1024. The video matrix, you
may remember, is stored in the high nybble (that means multiply
it by 16) of 53272 (hex D018).
We must pick our Character Base next. If we're in normal
resolution, we may pick any even multiple of 1024 as a starting
address: i.e., 0, 2048,4096, etc. If we're in high-resolution mode,
we must pick only values of zero and eight, meaning that the hi
res starting address will be either 0 or 8192. The normal 64 config
uration is set to four or six for either uppercase/graphics or upper-/
lowercase mode, meaning we take our character set from 4096 to
6144. The Character Base is stored in the low nybble of 53272.
So we'd expect a normal 64 to place into address 53272: a
video matrix of one, times 16, plus a Character Base of four or six,
yielding a total of 20 or 22. You may in fact see 21 or 23 if you PEEK
the location, but the extra bit doesn't matter — it's not used. And
if we switch to high-resolution without changing anything else,
our Character Base of four or six will be trimmed back to zero —
explaining why we saw zero page when we tried POKE 53265,48
in the first article of this series.
Let's try a few specific design jobs.
87
. commodore 64
1 video
POKE 56576#5
POKE 53272#4
POKE 648#128
commodore 64
Video i
And finally, we should set the start and end of BASIC to corre
spond with a 32K PET:
Clear the screen, and the job's done. Zero page usage is still differ
ent, so not all PEEKs and POKEs will automatically work on this
reconfigured system; but BASIC and screen now match the PET.
X will contain the top row of pixels for the letter A. If you like,
you can draw a character's shape with the following program:
89
Commodore 64
video
90
commodore 64
video
The Lunar
Lander: The 64
Jim Butterfield
91
> commodore 64
1 video
We're ready to fly. Let's put the sprite high on the left part of
the screen. Then we'll draw a screen with mines for the player to
avoid.
92
commodore 64
video
370 V=100:H=100:V0=0:H0=0
380 POKE 54296,15:POKE54278,240
390 REM DRAW SCREEN
400 PRINTCHR$(147)
410 FOR J=l TO 18:PRINT:NEXT J
420 FOR J=l TO 4:FOR K=l TO 30
430 C$=IIM:IF RND(1)<.1 AND (K<20 OR K>25
) THEN C$=M#"
440 PRINT C$;:NEXT K:PRINT:NEXT J
450 FOR J=l TO 30:PRINTII=11; :NEXT J
Keyboard Checks
Let's place the sprite, and start the main play by checking the key
board. We check for two different things: a new key (K$), or an
old key still being held down (K):
460 POKE X0,H:POKE Y0,V:POKE XI,H:POKE Y
1,V
470 K=PEEK(203):GET K$
480 REM MAIN FLIGHT LOOP-TEST KEYS
490 IF K$=IMIGOTO 550
500 K0=ASC(K$):V1=.1:H1=0
Let's check for the space bar. If it's on, we want to energize the
rocket and the rocket flame. Our vertical thrust will be upwards
(- .5), and well want to enable the flame video with a note that
EO =3. We'll spot lateral thrust as keys Fl and F7, and set value HI
accordingly.
93
.commodore 64
> video
94
Commodore 64
video
95
Commodore 64
Video
Split Screens
Jim Butterfield
Well need to venture into more technical waters now, but with a
little effort we can perform some minor miracles on the screen.
All the limitations we have learned may be set aside with a little
creative "cheating/' Well have a venture into machine language;
but even if you're not an ML fanatic, it's worth knowing that the
job can be done.
We have learned a number of limitations, largely based on the
idea that the screen can do a lot of things, but only one at a time:
96
commodore 64
video 3
The Task
We're going to write a quick program to split the screen into two
parts, each with a different characteristic. It won't be perfect;
we're just trying to show the technique, not polish up all the
loose ends. The fine points will come later. First, let's plan.
If we set a new interrupt into our machine, well need to make
some careful distinctions. First, when an interrupt happens, we
must establish: who caused this one? Was it the raster, or the tra
ditional interrupt source of 1/60 second timing? Second, if it was a
raster, which part of the screen is involved — the top or the
"switch" point?
The interrupt
Let's start to lay out the machine language program. All interrupts
will come here, and we'll need to sort them out. We'll put the pro
gram into the cassette buffer.
033C AD 19 DO INT LDA $D019
033F 29 01 AND #$01
0341 F0 19 BEQ REGULR
The interrupt has happened and has come here. Check the Raster
Interrupt Bit in $D019 — was this one caused by the raster? We'll
need to mask out the bit we want with an AND. If we get nothing,
it's a regular interrupt — go there.
0343 8D 19 DO STA $D019
We look at the raster scan. If it's less than 127, we're near the
top of the screen, and we don't see the negative byte. So we skip
ahead. If, however, we are at the middle of the screen, well see a
97
Commodore 64
Video
Place the next interrupt point into the raster register. The next in
terrupt will now hit at the right time.
0356 8C 18 DO STY $D018
Place the "character set" value — hex 15 for graphics, hex 17 for
text — into the appropriate register.
0359 4C BC FE JMP $FEBC
We've done our job. We may now exit. Don't give an RTI; instead,
go to a routine that cleans things up nicely, at $FEBC. And what
of our regular interrupt?
035C 4C 31 EA REGULR JMP $EA31
Back to basic
Ready to put all this in BASIC? Here we go:
90 POKE 53265,27
100 FOR J=828 TO 862:READ X
110 T=T+X:POKE J,X
120 NEXT J
130 IF T<>3958 THEN STOP
200 DATA 173,25,208,41,1,240,25,141,25,2
08,162,146,160,21,173,18
210 DATA 208,16,4,162,1,160,23,142,18,20
8,140,24,208,76,188,254,76,49,234
300 POKE 56333,127
310 POKE 788,60:POKE 789,3
320 POKE 56333,129:POKE 53274,129
98
Commodore 64
video
Let's look at the last three lines. Line 300 kills the interrupt for a
moment, so that we can mess with the interrupt vector without
running into disaster. Line 310 changes the interrupt vector to
point at our newly POKEd program. Line 320 restores the inter
rupt and adds an extra one: the raster interrupt.
An Amazing split
Whert the program is run, an amazing thing happens: the screen
becoipes graphic at the top and text at the bottom. Impossible,
you say? Not for us clever — and careful — people. The effect is
permanent: you may NEW the program and start something
else, and the split screen will still be there. You shouldn't use
cassette tape with program in place — it's there in the buffer.
And you may find that LOAD and SAVE don't work quite right.
RUN-STOP/RESTORE will put everything back to its former
state. (Please save this program for use in the next section.)
99
commodore 64
video
Son of
Split Screens
Jim Butterfield
100
commodore 64
video
A Better way
There is an easier way: shut the timer interrupt off completely,
and do its various jobs with our own programs. This seems com
plex, but it's not. We can call the timer interrupt routines our
selves, whenever it's time.
Let's look a little more closely into the timing of these inter
rupts. We expect to cause a raster scan interrupt about 120 times a
second. That's twice as often as the timer interrupt needs to be
handled. So our raster program could occasionally call in the
timer interrupt program.
It seems that we could accomplish the task easily by calling
the timer interrupt routines every second raster interrupt. That
would certainly do the job, but there's a better way.
Even though we've shut off the timer interrupt, it's still signal
ing when the time is ready. Let's review: the timer leaves a signal
in hex address $DC0D (56333) whenever it counts down to zero.
Normally, this signal triggers the interrupt line (IRQ) and causes
the processor to be interrupted. But we may "break" the connec
tion between the timer signal and the interrupt line. In this case,
the timer will not cause an interrupt, but the signal bit will still
flash when the appropriate time has come.
We can see the plan in Figures 1 and 2. We will disconnect the
timer from interrupt and service it ourselves when it flashes.
101
Commodore 64
video
Easier done than said. Let's look at the machine language coding:
033C A9 01 INTR LDA #$01
033E 8D 19 DO STA $D019
Raster interrupt is now the only game in town, so we don't need
to test for it. We must, of course, turn off the raster interrupt flag.
0341 A2 92 LDX #$92
0343 A0 06 LDY #$06
Setup for top of screen. Next interrupt, line 92 hex; new color,
number 6.
0345 AD 12 DO LDA $D012
0348 10 04 BPL MID
BASlC-ally Yours
Here's the same program in BASIC.
90 POKE 53265,27
100 FOR J=828 TO 864:READ X
110 T=T+X:POKE J/X
120 NEXT J
130 IF T<>4077 THEN STOP
102
Commodore 64
video
Raster Timer
Interrupt Interrupt
T
Return Return
From Interrupt From Interrupt
103
commodore 64
video
Raster
Interrupt
Only
No
Return
From Interrupt
104
Chapter 4
Creating
Games
Creating #1
Games ™T
Joysticks
and Sprites
Sheldon Leemon
Fast movement of sprites can increase the appeal ofany game. Try the
demonstration programs here and learn how to add this technique to
your games.
A Fascinating Chip
When I bought the computer, however, I discovered, to my
dismay, that the consumer-oriented design approach did not
seem to carry through to the BASIC interpreter and User's Guide.
Not only was there no BASIC command for reading the joystick
controllers, but the BASIC manual also made no mention
whatever of these ports! This meant that if I discovered how to
use these sticks any time soon, I would have to play hardware
detective.
Fortunately, the 64 is similar to the VIC-20 in a number of
ways. Since the VIC reads the joystick through a VIA (Versatile
Interface Adapter) chip, it stands to reason that the 64 would read
its joystick through the analogous CIA (Complex Interface
Adapter) chip. An early memory map from Commodore shows
CIA #1 to be addressed at location $DC00, or 56320 decimal. The
CIA is a fascinating I/O chip and could well serve as the basis for
an article in itself, but here I'll focus attention on the registers that
read the joysticks.
Like the VIC, the 64 uses Peripheral Data Registers A and B to
read these sticks, and I/O (input/output) through these registers is
controlled by Data Direction Registers A and B. These registers are
107
4 Creating
Games
108
Creating
Games
14
10
11
13
A Keyboard Bonus
The variations on these basic schemes are limited only by your
applications. If you are using the joystick for an action game, for
example, you may want to read the changes in horizontal position
and vertical position separately. You can do this with the follow
ing formulas:
109
4 Creating
Games
Sprite Movement
Program 2 sets up a sprite and moves it around based on the posi
tion of the joystick. The initialization routine, which I have put
out of the way at the back of the program, starting with line 1000,
sets up a flying saucer in double width, and then RETURNS to
the movement loop at line 2. The ON-GOSUB routes the pro
gram to the proper line number without having to test each stick
position, which would slow down the loop.
There are a couple of points to note. First, the registers that
designate sprite horizontal and vertical positions are not write-
only registers, as are the Atari horizontal position registers. This
means that you can find out the current position of the sprite just
by reading those registers, without having to set up separate
RAM variables to keep track of them as must be done on the
Atari. I set up variables X % and Y % in Program 2 only for pur
poses of readability.
To move a sprite one position to the right, we need only read
the current horizontal position, add 1, and POKE that number
back into the horizontal position register. Of course, you must
keep in mind that you can't POKE in a value less than 0 or greater
than 255. If you examine the move-down and move-up
110
creating #1
Games ■#
subroutines at lines 80 and 90, you will see that I have incorpo
rated logical statements to move the sprite to the bottom of the
screen if it hits the upper limit, and which will move it to the top if
the value tries to get below 0. This wraparound feature
guarantees that no errors will result from trying to POKE in an
illegal quantity.
111
4 Creating
Games
112
Creating
Games 4
113
4 Creating
Games
60 SYS(49400):GOTO 60
70 SYS(49413):GOTO 70
1000 FORI=871TO895:POKEI,0:NEXT:FOR 1=83
2TO870:READA:POKEI,A:NEXT:SP=53248
1010 POKESP+21,1:POKE2040,13:POKESP+39,6
:POKESP+29,1:POKESP,160:POKESP+1,10
0
1020 POKESP+32,0:POKESP+33,0:PRINT CHR$(
147)
1030 FORI=1 TO 50:R=1024+INT(RND(0)*1000
):POKE R,46:POKE R+54272,1: NEXT
1040 DATA 0,56,0,0,124,0,0,254,0,0,170,0
,1,171,0,15,255,224,15,255,224,13,8
5,96
1045 DATA 13,85,96,15,255,224,15,255,224
,0,254,0,0,124,0
1050 FOR 1=1 TO 101:READ A:POKE 49151+1,
A:NEXT
1055 FOR 1=1 TO 19:READ A:POKE 49399+1,A
:NEXT:GOTO 20
1060 DATA 173,1,220,74,176,3,206,1,208,7
4,176,3,238,1,208,74,176,38,173
1070 DATA 0,208,208,15,173,16,208,41,1,2
40,12,173,16,208,41,254,141,16
1080 DATA 208,206,0,208,96,173,16,208,9,
1,162,63,141,16,208,142,0,208,96
1090 DATA 74,176,32,238,0,208,240,28,173
,16,208,41,1,240,20,169,64,205
1100 DATA 0,208,208,13,173,16,208,41,254
,162,0,141,16,208,142,0,208,96
1110 DATA 173,16,208,9,1,141,16,208,96
1200 DATA 32,0,192,32,0,192,32,0,192,32,
0,192,96,32,0,192,76,5,193
114
Creating
Games 4
Michael Wasilenko
Preschoolers will love this simple game. The child is required to press the
correct letter in order to start the race.
115
4 Creating
Games
Alfabug
0 PRINT"{CLR}INITIALIZING"
1 POKE52,48:POKE56,48:CLR:POKE56334,PEEK
(56334)AND254:POKE1,PEEK(1)AND251
5 FORN=0TO1279;POKEN+12288,PEEK(N+53248)
:NEXTN:P0KE1,PEEK(1)OR4
6 POKE56334,PEEK(56334)OR1
10 PRINT"{BLK}{CLR}":POKE53281,1
20 DIMY(5),K(5)fO(5),CO(5):AB=64
25 CO(0)=0:CO(1)=3:CO(2)=4:CO(3)=5:CO(4)
=7
30 Z=05:A=45:CR=42:IN=-1:WX=54272
34 SS=12288+(41*8):PORI=0TO15:READQ:POKE
SS+I,Q:NEXTI
36 DATA 36,72,123,254,254,123,72,36,144,
72,123,254,254,123,72,144
40 FORN=0TO4:READY(N):NEXTN
50 DATA 1306,1386,1466,1546,1626
55 FORW=0TO4:K(W)=Y(W):NEXTW
57 PRINT"{WHT}{CLR}":FORP=0TO4:O(P)=48:N
EXTP:X=1264:F=48
60 FORL=0TO5:FORI=0TO39:POKEX+I,A:POKEX+
I+WX,0:{2 SPACESjNEXTI
70 POKEX+I-1,115:X=X+80:NEXTL
7 4 FORG=0TO4:POKEY(G)-1+WX,0:POKEY(G)+WX
,CR:NEXTG
75 FORG=0TO4:POKEY(G)-1,49+G:POKEY(G),CR
:NEXTG
76 REM{3 SPACES}AB=INT(RND(1)*26)+64
77 AB=AB+1:IFAB>90THENAB=65
78 PRINT"{HOME}{BLK}{DOWN}PRESS ";CHR$(1
8)CHR$(AB)CHR$(146);" TO START"
79 GETA$:IFA$=""THEN79
80 IFASC(A$)<>ABTHENGOSUB174:GOTO78
81 POKE53272,(PEEK(53272)AND240)+12: M=3
5:FORC=0TO4:IFK(C)=Y(C)+35THEN105
85 POKEK(C),32
90 E=INT(RND(0)+.5)+1.5:K(C)=K(C)+E:IFK(
C)=>Y(C)+M-1.5THENK(C)=Y(C)+M:F=F+1
100 POKEK(C),CR:POKEK(C)+WX,CO(C):FOR J=
0TOZ:NEXTJ:IFK(C)=Y(C)+MTHEN105
102 GOTO110
105 IFO(C)<>1THENPOKEK(C)+1,F:POKEK(C)+1
+WX,0:POKEK(C),42:O(C)=1:GOSUB200
110 NEXTC
115 CR=CR+IN:IN=IN*-1:IFF<53THEN81
118 POKE53272,21
116
Creating
Games 4
117
Peripherals
5
The Confusing
Catalog
Jim Butterfield
Have you ever wanted to have a program gain control of the disk catalog?
There are a number of ways to use directory information, but getting hold
of it is not as simple as it might seem at first glance.
two Types
When you command LOAD "$",8 you are bringing in a directory
with a LOAD command; it arrives in a certain format. If you
OPEN 1,8,2,"$" within your program, you'll get an entirely differ
ent format. Why?
When you say LOAD, the disk manufactures a directory that
imitates a BASIC program. After all, the next thing you'll say is
LIST, and the only thing that can be listed is BASIC. If you say
OPEN, however, the disk will give you its directory, in binary, just
as it is stored on the disk surface. That seems to be a little better —
until you realize that BASIC has a devil of a time understanding
binary.
You can do an OPEN and get the imitation program. The trick
is to use secondary address 0 — usually reserved for LOADing.
Another Problem
Either way, you get binary. You'll need to translate it and interpret
it; and youil need to cope with that annoying BASIC glitch, in-
121
5 Peripherals
imitation BASIC
This is the easiest and most standard way of obtaining directory
information; it works the same way with all Commodore disk
drives. To understand it, we must see how a BASIC line is
constructed:
First two bytes: forward chain or zero (dummy on directory)
Next two bytes: binary number
Then: text of line
Ending with: binary zero
Program 1 prints the directory. Big deal: you could do that
anyway. But since it's a program, you can change it to do what
ever functions you need. For example, you could dig into the text
part in more detail, extracting the program name and type; that
way, your program would know if a given data file were on the
disk.
It's handy to be able to check how many blocks are free on the
disk. Our program already does this: the last number that line
230 calculates will be the blocks-free value. You can abbreviate this
procedure by making the program skip all the file names. Change
the OPEN statement to read:
100 OPEN 1,8,0,"$0:S%Q"
Now, the program will catalog only those programs whose
name happens to be exactly S%Q. Chances are you won't have
many of these. Your directory is now shortened down to the
header line and the BLOCKS FREE line. Let's telescope our pro
gram into a simple block-free checker. Try Program 2.
We've only scratched the surface. Try your hand at program
ming some directory search function of your choice.
Bit-image Directories
You can get more information from a bit-image directory than
from a BASIC-imitator. For example, you can read the length
parameter of relative files, see deleted files, and view file track
and sector values.
122
Peripherals
5
But this comes with considerable difficulty. You might get any
one of several different formats, depending on the disk. We won't
do the whole job here: you can chase after some of the details for
yourself. Look at Program 3.
Yes, you can go in there and drag out the BAM. Yes, you can
dig useful data out of the stuff we skipped in lines 360-380. Check
your disk manual for details.
It's not easy either way. The "imitation BASIC" is the shortest
and works on all disks: use it when you can. But if you need the
extra power of the bitmap, don't hesitate to go for it.
123
Peripherals
124
Peripherals
5
390 GET#1,L1$,L2$
395 REM WEIRD; 254 BYTLES/8 LEAVES US TWO
BYTES SHORT
400 IF J<8 THEN GET#1,X$,X$
405 REM TO ALLOW US TO TEST END-OF-DIRECT
ORY
410 SW=ST
415 REM NOT A REAL FILE
420 IF F<129 OR F>132 GOTO 480
425 REM NAME AND LENGTH
430 PRINT P$;ASC(L1$+N$)+ASC(L2$+N$)*256
480 NEXT J
500 IF SW=0 GOTO 300
900 CLOSE1
125
Peripherals
Automatic
Procpram
Selector
Steven A. Smith
Here are several ways to make disks easier to use. A disk menu program
that will run your programs automatically is included.
Predefined Menus
A predefined menu is written right into the BASIC menu pro
gram. Because of this, a new program must be written for each
diskette for which you want a menu. However, there are several
advantages to using a predefined menu. First, it's fast. As soon as
you RUN it, the menu program knows what programs should be
on the diskette and can go about the business of displaying the
menu. Also, you can add program descriptions to the menu
screens to show more information about the programs than just
their names.
126
Peripherals
127
Peripherals
ber checking in lines 250-260 if you have more or fewer than eight
menu items.
This line will call the next menu program (here named MENU2) if
RETURN, rather than one of the options shown, is pressed.
While this works quite well, you do have to wait for the new
menu to be loaded each time you chain from one to the next. A
faster way is shown in Program 2. Several menus can be stored in
the same program. By pressing RETURN, you can go from one
menu to the next without waiting to load a new menu program. A
message is added to the bottom of the screen indicating that you
can press RETURN to go on to the next menu. After the last menu
is shown, pressing RETURN again will bring you back to the first
menu. Of course, going to the next menu could itself be made a
menu option, instead of being automatic.
To make menus especially useful to people unfamiliar with
computers, you can make the programs called by the menu call
the menu back when they finish. To do this, find where your pro
gram ends, whether by an END statement or by reaching the last
of the line numbers. Change your END statements to GOTO
62000 and add the following lines:
128
Peripherals
5
menu also works well at parties — you set it up with games which
call back the menu, and you don't have to worry about being
around to show people how to LOAD and RUN their choices.
129
5 Peripherals
130
Peripherals
5
131
5 Peripherals
132
Peripherals
133
5 Peripherals
460 PRINTTAB(12)"{RVS}"RIGHT$(STR$(I),1)"
{OFF} "MID$(AE$(MN*9+I),3,16)"{DOWN}"
470 NEXT:PRINT"{4 SPACES}{RVS}{4 SPACES}C
HOOSE ONE OF THE ABOVE OR{3 SPACES}
{OFF}"
480 PRINT"{4 SPACES}{RVS} PRESS RETURN TO
GO TO NEXT MENU {OFF}"
490 GETC$:IFC$=""THEN490
500 IFC$<>CHR$(13)THEN530
510 MN=MN+1:IFMN*9+1>ANTHENMN=0
520 GOTO440
530 IFVAL(C$)<1 OR VAL(C$)>MM THEN490
540 AE$=AE$(MN*9+VAL(C$))
550 PRINT:PRINT"{CLR}{4 DOWN}MENU ITEM CH
OSEN: #"C$" - "MID$(AE$,3,16)
560 FORI=18TO1STEP-1:FL=I
570 IFASC(MID$(AE$,I,1))<>160THENI=1
580 NEXT:PRINT"{4 DOWN}LOAD"CHR$(34)LEFT$
(AE$,FL)CHR$(34)",8{4 DOWN}"
590 PRINT"RUN":PRINT"{9 UP}"
600 POKE631,13:POKE632,13:POKE198,2:END
134
Peripherals
5
64 DOSirtaker
Charley Kozarski
Changing disks to load DOS 5.1 can at times be inconvenient. You can
use these short programs to save time — by putting the Wedge on your
own disks.
If you've bought a 1541 disk drive for your Commodore 64, you've
probably noticed that the Test/Demo disk which comes with it
contains several useful programs. In particular, there is a program
called "DOS 5.1" which simplifies many disk-handling opera
tions for you. For example, you can just use the symbol for divi
sion (/) followed by the name of a file, and the file will be
LOADed in for you.
Despite the misleading name, DOS 5.1 is not a Disk Operat
ing System (DOS) for the 1541. Like all Commodore disk drives,
the 1541 is "intelligent/' which means that its DOS is contained in
ROM inside the drive itself. DOS 5.1 is actually a DOS support pro
gram which makes the built-in DOS easier to use.
All of the helpful functions of the DOS support program,
however, are available only on that disk. If, for some reason, you
need to turn off power, you've got to reload DOS 5.1 from the
demo disk. Wouldn't it be nice to be able to put this useful pro
gram on any of your disks?
Program 1 must be saved onto each disk on which you want
to put DOS 5.1. It is the "wedge," which ties DOS 5.1 into BASIC.
Type Program 1 in and SAVE it on a disk. Then type NEW and
type in Program 2 which is the DOS 5.1 Creator. SAVE Program 2
to the same disk. It is necessary to SiWE Program 2 to only one of
your disks because after it creates DOS 5.1, it serves no further
purpose. You'll only need Program 1 and DOS 5.1 on each disk.
Now replace your disk with the Test/Demo disk. (Program 2
will get DOS 5.1 from the demo disk.) RUN Program 2 and, after a
few seconds, it will ask if you have replaced the demo disk with
your own. Make that replacement and you're halfway through
creating a new DOS 5.1. When your disk is in the drive, type Y for
yes and hit RETURN. The Creator program will now SAVE DOS
5.1 onto your disk and then erase itself from memory. If you forgot
135
Peripherals
136
Peripherals
5
Backup
1540/1541 Disks
Harvey B. Herman
Disk Backup
1 FORI=828TO883:READA:POKEI,A:NEXTI
10 REM"D=DSAVE"@BACK2",D0:?DS$:CATALOGD0
20 BB=PEEK(44)+27:POKE995,BB
30 POKE998,PEEK(55):POKE999,PEEK(56):POKE
55,0:POKE56,BB:CLR
40 BB=PEEK(995)
50 N=PEEK(999)-BB-1:BA=BB*256:MA=828
60 DIMBM%(35,24)
70 FORJ=0TO7:TA(J)=2tJ:NEXT
80 PRINT"{CLR}{3 RIGHT}{RVS}BACKUP 1541
{OFF}11
90 PRINT"{DOWN}'GOTO10000' IF PROGRAM QUI
TS ABNORMALLY"
100 PRINT"{DOWN}"N"BUFFERS AVAILABLE"
110 OPEN1,8,15
200 REM *** MAIN FUNCTIONS ****
210 GOSUB1000
220 D$="S":GOSUB3200:I2$=IR$
230 IFDR$<>"2A"THENPRINT11 {RVS} ILLEGAL DOS
1.0 DISK{OFF}":GOTO10000
240 IFI2$=I1$THENPRINT"{RVS}SOURCE AND DE
STINATION HAVE SAME ID CODE{OFF}":GOT
010000
250 GOSUB2500
260 T=TS:S=0:NU=1:T1=T:S1=S
270 PRINT#1,"I0":OPEN3,8,3,"#"
280 PRINT"READING BLOCK #";
290 IFBM%(Tl,SI)=0THENGOSUB2000:NU=NU+1:I
FNU>NTHEN320
300 S1=S1+1:IFS1>20THENS1=0:T1=T1+1
310 IFTKTF+1THEN290
320 PRINT"{DOWN}"
330 CL0SE3
340 D$="D":GOSUB3200 2lFIR$<>Il$THENGOTO34
0
350 PRINT#1#"I0":OPEN3,8,3,"#"
360 PRINT"WRITING BUFFER #";
370 NU=1:T1=T:S1=S
380 IFBM%(Tl,SI)=0THENGOSUB2200:NU=NU+1:I
FNU>NTHEN410
390 S1=S1+1:IFS1>20THENS1=0:T1=T1+1
138
Peripherals
5
400 IFTKTF+1THEN380
410 PRINT"{DOWN}"
420 CLOSE3
430 S=S1+1:IFS>20THENS=0:T1=T1+1
440 T=T1:IFT>TFTHEN500
450 D$="S":GOSUB3200:IFIR$<>I2$THEN450
460 NU=1:T1=T:S1=S:GOTO270
500 REM FINISHED XFERS
510 CLOSE1
520 POKE55,PEEK(998):POKE56,PEEK(999):CLR
530 PRINT"{2 DOWNjBACKUP COMPLETE"
540 OPEN1,8,0,"$0"
550 GET#1,A$:IFA$<>"{RVS}MTHEN550
560 PRINTA$;:GOTO610
570 GET#1,A$:SS=ST:A=LEN(A$):IFATHENA=ASC
(A$)
580 GET#1,B$:SS=ST:B=LEN(B$)zIFBTHENA=ASC
(B$)
590 IFSSTHEN660
600 IFA=1ANDB=1THENGOSUB630
610 GET#1,A$:IFA$=""THENPRINT:GOTO570
620 PRINTA$;:GOTO610
630 GET#1,A$:SS=ST:A=LEN(A$):IFATHENA=ASC
(A$)
640 GET*1,B$:SS=ST:B=LEN(B$):IFBTHENB=ASC
(B$)
650 N=B*256+A:PRINTN;:RETURN
660 CLOSE1
670 END
1000 REM HEADER DEST DISK
1010 PRINT"{DOWN}INSERT DESTINATION DISK
TO BE FORMATTED"
1020 INPUT"{2 DOWN}DISK NAME{3 RIGHT}
{SHIFT-SPACE}{16 SPACES}{19 LEFT}";D
N$
1030 IFDN$="{SHIFT-SPACE}"THENPRINT"
{3 UP}";:GOTO1020
1040 IFLEN(DN$)>16THENCLR:GOTO40
1050 F=0:FORJ=1TOLEN(DN$):S1?=MID$(DN$,J,
1)
1060 IFS1$="{SHIFT-SPACE}"ORS1$=CHR$(34)T
HENF=1
1070 NEXTJ:IFFTHENPRINT"{3 UP}";:GOTO1020
1080 INPUT"{DOWN}UNIQUE DISK ID{3 RIGHT}
{SHIFT-SPACE}{20 SPACES}{23 LEFT}";I
1$
1090 IFI1$="{SHIFT-SPACE}"THENPRINT"
{2 UP}";:GOTO1080
1100 IFLEN(I1$)<>2THENPRINT"{2 UP}";:GOTO
1080
139
5 Peripherals
140
Peripherals
2580 T%=(BY-4)/4+l
2590 PRINT"{2 SPACES}";T%;
2600 IFPEEK(BA+BY)=.THENFORJ=.TO20:BM%(T%
, J) = .:NEXT:BY=BY+4:GOTO2650
2610 S=0
2620 BY=BY+1:A0=PEEK(BA+BY):FORJ=.T07:BM%
(T%,S)=A0ANDTA(J):S=S+l:NEXT
2630 IFS<22THEN2620
2640 BY=BY+1
2650 ES=21:IFT%>17THENES=19
2660 IFT%>24THENES=18
2670 IFT%>30THENES=17
2680 FORJ=ESTO24:BM%(T%,J)=-1:NEXT
2690 SM=.:FORJ=.TO20:IFBM%(T%,J)=.THENSM=
SM+1
2700 NEXT:PRINTTAB(12);SM:S9=S9+SM
2710 IFSM=.ANDTS=T%THENTS=TS+1:GOTO2730
2720 IFSM<>.THENTF=T%
2730 IFBY<143THEN2580
2740 CL0SE3
2750 PRINT"START =";TS7" FINISH ="?TF
2760 PRINT"{DOWN}A TOTAL OF";S9;"BLOCKS T
O XFER"
2770 S8=90+25+(.650+.980)*S9
2780 S7=INT(S8/60):PRINT"APPROX";S7":"INT
(S8-S7*60);"FOR COPY"
2790 RETURN
3000 REM READ ERR CH TO ER,ER$
3010 INPUT#1,E0$,El$,E2$,E3$:ER$=E0$+","+
El$+"#"+E2$+"#"+E3$
3020 ER=LEN(E0$):IFERTHENER=VAL(E0$)
3030 RETURN
3200 REM INSTRUCT TO SWAP TO DISK GIVEN I
N D$
3210 IFD$="D"THENS1$="DESTINATION":GOTO32
30
3220 SI$="SOURCE"
3230 PRINT"{DOWN}INSERT ";S1$;" DISK, PRE
SS {RVS}SPACE{OFF}"
3240 GETA$:IFA$<>" "THEN3240
3250 OPEN2,8/0,"$0"
3260 GOSUB3000:IFER>0THEN10000
3270 FORJ=1TO26:GET#2#A$:NEXTJ
3280 GET#2/A$:GET#2,B$:IR$=A$+B$
3290 GET#2/A$:GET#2,A$:GET#2/B$:DR$=A$+B$
3300 CLOSE2:RETURN
10000 REM DROP OUT
10010 POKE55,PEEK(998):POKE56,PEEK(999):C
LR:STOP
141
5 Peripherals
142
Peripherals
5
using the
user Port
John Heilborn
The User Port on the 64 gives you direct access to your computer. This
article explains exactly how to program for and connect to this port.
Located on the back and side of the 64 are several different con
nectors (see Figure 1). Each of them (except one) has a specific
purpose. For example, the video port connects to a television or
monitor; the game ports on the side of the computer connect to
various kinds of game controllers such as paddles or joysticks; the
serial plug on the back of the computer connects to a Commodore
printer or disk drive; and the expander slot accepts program
cartridges.
I—User Port
Cassette Port
Serial Port
Audio/Video
1 Expansion Port
Game Controllers
Power In
143
5 Peripherals
144
Peripherals
5
Video
Interface To Video
Chip Portion of
(VIC-II) Television
or
Monitor
To Sound
SID Portion of
Chip Television
Central or
Processing Monitor
Unit (CPU)
Read-Only Memory
(ROM)
Operating
A System
Kernal Routines
\r BASIC
Character Set
6510
Microprocessor
V Random-
Access
Memory
(RAM)
Expansion
Port
145
5 Peripherals
10 A=6000
20 GET A$: IF A$="n THEN 20
30 IF A$=H*" THEN 70
40 PRINT A$;
50 POKE A# ASC(A$)
60 A=A+1: GOTO 20
70 PRINT
80 FOR R = 6000 TO A
90 PRINT CHR$(PEEK(R));
100 NEXT
146
Peripherals
5
that point the program will skip to line 70, which starts PEEKing
memory locations beginning with location 6000. The characters
stored there will be displayed, one character at a time, up to the
last character we stored.
10 FOR R=0 TO 15
20 POKE 53280, R
30 FOR G=0 TO 500: NEXT
40 NEXT
50 GOTO 10
290 IF(PEEK(53280)ANDA(B))=0THENPOKE53280
,PEEK(53280)+A(B):GOTO310
300 POKE53280,PEEK(53280)-A(B)
330 PRINT11 {HOME} {2 DOWN} {4 SPACES} {HOME}
{2 DOWN}n;PEEK(53280)
148
PeirDplheraDs
5
350 IF((2tJ)AND(PEEK(53280)))=0THENPRINTB
$(7-J):GOTO370
When you run the program now, it will behave quite differ
ently. To begin with, the four left-hand bits (numbered 1-4) are all
on, and cannot be changed by pressing the corresponding keys.
Look at what happens when you toggle the four right-hand
bits. Each time a bit is changed, the screen border changes to an
other color. Notice that the control register limits us to only 16 dif
ferent number combinations — one for each color that can be gen
erated for the screen border. You will find that many of the control
registers have rules such as this governing their use.
B K L M N
149
5 Peripherals
150
Peripherals
5
N/C N/C N/C N/C N/C N/C N/C N/C N/C N/C
7 6 5 4 3 2 1
NC NC
H J K L M N
151
Peripherals
i "
I
3.3K
c >-fAA/V
3.3K
3.3K
3.3K
3.3K
3.3K
33K
3.3K
I I
152
Peripherals
5
When you install this device, be sure you turn off power to
the 64 first, and push the connector all the way onto the User
Port, making sure it fits securely.
153
5 Peripherals
Binary Counter
Video Version. Remember to make the changes to Program 1 as
outlined above before adding the following routine:
Sequential Lights
This program is similar to the previous program, but instead of
performing a full count, it lights the lamps individually.
Video Version.
500 A(0)=128: A(l)=64: A(2)=32:A(3)=16: A
(4)=8: A(5)=4: A(6)=2: A(7)=l
510 IF B>7 THEN B=0
520 POKE 56577, A(B)
530 B=B+1
540 GOTO 330
154
Peripherals
Random Lights
This program lights the LEDs (or screen lights) randomly.
Video Version.
500 A(0)=128: A(l)=64: A(2)=32:A(3)=16: A
(4)=8: A(5)=4: A(6)=2: A(7)=l
510 B = INT(RND(0)*8)
520 POKE 56577, A(B)
530 GOTO 330
Bit Display
10 POKE 53280,0: POKE53281,0
20 A(1)=128:A(2)=64:A(3)=32:A(4)=16:A(5)=
8:A(6)=4:A(7)=2:A(8)=1
21 A$="{HOME}{12 DOWN}"
22 B$="gG§ gMl{DOWN}{3 LEFT}gG| gM3"
23 C$="{RVS}iGl{2 SPACES}{DOWN}{3 LEFT}
BGJJ{2 SPACES}11
24 D$="gM3gG3 EMigGi gM|
gM3gG3 gMigGi gMigGl
30 B$(0)=A$+H{7 RIGHT}M+B$
40 C$(0)=A$+"{7 RIGHT}"+C$
50 B$(1)=A?+"{10 RIGHT}"+B$
60 C$(1)=A$+"{10 RIGHT}"+C$
70 B$(2)=A$+"{13 RIGHT}"+B$
155
5 Peripherals
80 C$(2)=A$+"{13 RIGHT}"+C$
90 B$(3)=A$+"{16 RIGHT}"+B$
100 C$(3)=A$+"{16 RIGHT}"+C$
110 B$(4)=A$+"{19 RIGHT}M+B$
120 C$(4)=A$+"{19 RIGHT}"+C$
130 B$(5)=A$+"{22 RIGHT}"+B$
140 C$(5)=A$+H{22 RIGHT}"+C$
150 B$(6)=A$+"{25 RIGHT}"+B$
160 C$(6)=A$+"{25 RIGHT}"+C$
170 B$(7)=A$+"{28 RIGHT}"+B$
180 C$(7)=A$+"{28 RIGHT}"+C$
190 PRINT" {WHTMcLR}{ 10 DOWN}{8 RIGHT}1
{2 SPACES}2{2 SPACES}3{2 SPACES}4
{2 SPACES}5{2 SPACES}6{2 SPACES}7
{2 SPACES}8{DOWN}";
200 PRINT"{23 LEFT}";
210 PRINT"B24 @3{DOWN}{25 LEFT}";
220 PRINT D$;"{DOWN}{26 LEFT}";
230 PRINT D$;"{DOWN}{29 LEFT}";
240 PRINT"{DOWN}{36 LEFT}i24 T|"
250 GOSUB330
260 GETK$:IFK$=""THEN260
270 IFASC(K$)>57ORASC(K$)<49THEN260
280 B=VAL(K$)
290 IF(PEEK(6000)ANDA(B))=0THENPOKE6000,P
EEK(6000)+A(B):GOTO310
300 POKE6000,PEEK(6000)-A(B)
310 GOSUB330
320 GOTO260
330 PRINT"{HOME}{2 DOWN}{4 SPACES}{HOME}
{2 DOWN}";PEEK(6000)
340 FORJ=0TO7
350 IF((2tJ)AND(PEEK(6000)))=0THENPRINTB$
(7-J):GOTO370
360 PRINTC$(7-J)
370 NEXT
380 RETURN
156
Chapter 6
utilities
utilities
6
Data Searcher
Jerry Sturdivant
Programmers are always looking for ways to make their programs more
''friendly/' easier to use.
This special search routine will accept all kinds of wrong input and
still come up with the right match.
Have you ever searched through a file for something but just
couldn't find it? You know it's in there, but your spelling may be
off by one letter and the strings just won't match?
Or you know the city of Albuquerque is in the program, but
you can't spell it? Or you don't know if you're supposed to add
the state? And if you do need to type the state, should you use the
two-letter abbreviation? Is New Mexico supposed to be NE or
NM?
In short, if a program has to search for a string match, you can
solve all these problems by adding a Truncating Search Routine.
Let's look at the example program. Here a user enters the
name of a city, and the program gives the elevation. If no match is
found for the user's request, rather than having line 120 report
"CITY NOT FOUND": GOTO 70, the program performs a trun
cating search (lines 160 to 210).
The routine searches only that first part of each City string
equal to the length of the Request string. If there is no match, it
shortens the end of the Request string by one letter and searches
the shorter portion of each City string. It will continue to shorten
and search until it finds a match or runs down to two letters. It
will print all matches found for that length Request string.
Suppose the user gets the two-letter abbreviation of Maine
wrong. If the user requests PORTLAND MA rather than ME or
types out the complete word "MAINE", it will still find PORT
LAND ME. If the user requests just PORTLAND, the search will
print both PORTLANDS. As for our Albuquerque problem, the
word can be badly misspelled and still be found. A user who
understands the Truncating Search would just enter ALBU. It's a
very handy and user-friendly routine, especially for poor
spellers.
159
6 Utilities
150 PRINT"SEARCHING
FOR SOMETHING SIMILA
R"
160 FOR Z=LEN(REQUEST?) TO 2 STEP -1
170 FOR 1=1 TO NUMBER OF CITIES
180 IF LEFT?(REQUESTS?,Z)=LEFT?(CITY?(I)
,Z) THEN PRINT CITY?(I),ELEV?(I):T=1
190 NEXT I
200 IF T THEN
70
210 NEXT Z
220 PRINT"CITY NOT FOUND":GOTO 70
250 DATA ALBUQUERQUE NM,4500
260 DATA BISHOP CA,4100
270 DATA PORTLAND MA,45
280 DATA PORTLAND OR, 37
290 DATA THE DALLES OR,85
160
utilities
6
Music Keyboard
Bryan Kattwinkle
The 64 has amazing sound capabilities. This program will allow you to
experiment with sound by creating a music synthesizer with your 64,
The Functions
The filter and pulse rates can vary from 1 to 4095, The band pass
can be varied between 1 and 7 and will interact with the filter. All
the other functions will have a value from 1 to 15,
A quick review of each function:
161
6 Utilities
Music Keyboard
90 REM MUSIC KEYBOARD
100 GOSUB 1000{4 SPACES}:REM SET UP DISP
LAY
102 PRINT TAB(12); "...THINKING..."
110 S=l3*4096+1024 :REM BASE FOR POKES
120 FOR 1=0 TO 28 :POKE S+1,0 :NEXT
130 DIM F(26) :REM FREQUENCY TABLE
140 Fl=7040 :TW=2t(l/l2) :REM CONSTANTS
150 FOR 1=1 TO 26 :F(27-I)=F1*5.8+30 :Fl
=F1/TW :NEXT
160 DIM K(255) :REM KEY TABLE
170 K$="Q2W3ER5T6Y7UI9O0P@-*fet"
180 FOR 1=1 TO LEN(K$) :K(ASC(MID$(K$,I)
))=I :NEXT I
200 GOSUB 1200{4 SPACES}:REM SET UP ADSR
210 FOR 1=0 TO 14 STEP 7 :POKE S+I+5,0 :
POKE S+I+6,0{2 SPACES}:REM TONES OFF
220 WV=32:W=1:M=2:OC=3:HB=256:Z=0:PY=1
225 PRINT "{UP}"? TAB(12)7 "{14 SPACES}"
235 REM ENTER HERE AFTER PARAM CHANGE
240 FOR 1=0 TO 2{4 SPACES}:REM PULSE PAR
AMS
245 POKE S+2+I*7,P(8) AND 255
250 POKE S+3+I*7,P(8)/256
255 NEXT I
260 POKE S+24,P(7)*16 + 15 :REM BP,VOL
270 POKE S+23,P(9)*16 + 7 :REM RES,FV
275 POKE S+22,P(6)/16 :REM FILTER HI
276 POKE S+21,P(6) AND 15 :REM LO
280 AV=P(1) *16+P(2) :REM ATT/DEC
285 SV = P(3) * 16 + P(4) :REM SUS/REL
300 GET A$ :IF A$="" THEN 300
310 FR=F(K(ASC(A?)))/M :T=V*7+S
{9 SPACES}:IF FR=Z THEN 500
315 IF PY=1 THEN V=V+1 :IF V=3 THEN V=0
320 POKE T+6,Z :REM CLEAR SUSTAIN/REL
325 POKE T+5,Z :REM CLEAR ATTACK/DECAY
330 POKE T+4,0 :REM TURN OFF SOUND
162
utilities
6
163
6 Utilities
164
utilities
6
165
6 Utilities
Alarm Clock
Bruce Jaeger
You'll never work too long on your 64 ifyou use "Programmer's Alarm
Clock!'
Have you ever sat down at your computer after dinner to "touch
up that program a bit," only to find again that you've lost all no
tion of time and you've just missed the first half of that movie
you've waited for all week? Or you're supposed to pick someone
up at 6:00, and by the time you look up from the screen it's 7:30?
Me too!
That's why "Programmer's Alarm Clock" came about. When
you first sit down at your computer, LOAD and RUN the pro
gram. It will ask you for the alarm time and current time of day.
You must enter the time based on a 24-hour clock. The following
chart will help you in entering the times.
HHMMSS
000500 12:05AM (and no seconds)
010030 1:00AM (and 30 seconds)
103045 10:30AM (and 45 seconds)
120000 12 noon (and no seconds)
133030 1:30PM (and 30 seconds)
180000 6:00PM (and no seconds)
233000 11:30PM (and no seconds)
As soon as you set the time of day, the clock begins counting
toward the alarm time. When the time of day equals the alarm
time you selected, a beep will sound and the word "QUIT" will be
printed on the screen.
Since the internal clock is affected by using the cassette, the
program will give unpredictable results if you use the cassette
unit. Disk operation and TOOLKIT do not seem to affect the clock.
This program is a good one to study if you are interested in
166
utilities
6
167
Chapter 7
Memory
Memory
A window
on Memory
Gregg Peele
Ready to actually look at the 64 memory? This article will take you on a
visual tour ofyour computer's memory.
171
7 Memory
Kinds of Memory
Memory may have many different functions. From a practical
point of view, these functions can be separated into three differ
ent categories: memory available for user program space, mem
ory used exclusively by the operating system (unavailable to the
user), and memory which provides a connection between the
computer's operating system and the user or his or her programs.
The 64 has the unique ability to "shift" function of its memory
space from one of these functions to the other. (See Jim
Butterfield's "Commodore 64 Architecture/' the next article in
this book.) This chapter will be concerned with the memory func
tions of the computer in its normal configuration.
172
Memory
7
A Picture in Memory
Before embarking on our tour of the Commodore 64's memory,
type in, SjWE, and RUN the program at the end of this section.
The screen should be blank except for the words "LOADING
MAZE/' While the maze is loading, get a pencil or pen and pre
pare to take a few notes. In about one minute you will see a screen
full of what may appear to be random characters.
These characters represent bytes in memory. In the upper-left
corner of the screen is the decimal number of the first location
shown; this number should be flashing. For example, if the flash
ing number is 100, then the first character shown is the character
equivalent to what is stored in byte 100. Notice that the first few
characters in the upper-left corner share the same space with the
decimal number.
If you press the Fl or F3 keys, you can scroll backward and
forward through memory. Use the screen display codes on pages
132-34 in your user's manual to decipher the numbers which rep
resent the characters on the screen.
The Journey
Our journey begins at page zero. Move the display up or down
until the number at the upper-left corner of the screen is at or near
zero. Page zero takes up about one-fourth of the screen. Locations
161 and 162 are the most active locations visible in this area. These
locations provide the internal clock for the system. Location 162
cycles through 256 times for each time that 161 changes.
Just below locations 161 and 162 on the screen are the loca
tions which hold the value for the last key pressed: locations 197
and 203. These locations will change if you press a key. Press a
few keys and watch the values change. The characters produced
do not match the characters on the keys, but they do produce
unique values for each key pressed.
Location 198 contains the number of keystrokes in the key
board buffer. If you press many keys at one time, then this num
ber increments to hold the keystroke values until they can be pro
cessed. Then, as the keystrokes are processed, the buffer grad
ually empties, and the value in location 198 returns to zero.
Page zero contains many locations specifically used by the
operating system. Caution should be the rule when changing
locations in this area.
173
Memory
The Stack
As you move forward within memory, the next activity that you
see occurs in an area known as the stack. This area holds impor
tant information for both BASIC and machine language pro
grams. The BASIC command GOSUB sends a program to the line
indicated. The stack is where the computer stores the necessary
information it needs to RETURN to the proper part in the pro
gram. Since this program contains subroutines which are repeat
edly executing, the contents of the stack also display a pattern of
repeated values.
Continue forward until the screen contains no activity. When
the value in the upper-left corner is around 820, you are looking at
the cassette buffer. The cassette buffer provides a good place for
machine language programs. Since it is unused by the operating
system except for tape input and output, values can be safely
stored in and retrieved from this section of memory. If you scroll
past the cassette buffer, you will find screen memory. Screen
memory provides an interesting phenomenon: like a mirror,
screen memory is now looking at itself. This phenomenon pro
duces a delayed reaction time while the program copies the new
contents of screen memory to itself.
Past screen memory, the contents of the BASIC program are
visible. If you look closely in this area, you can see bits and pieces
of the BASIC program. The BASIC commands are unrecognizable
in their normal form but are "tokenized" into unique numbers.
At the end of our relatively small BASIC program, a pattern of
characters continues until it ceases around 32768. Here, I have
placed a simple interface between the user and memory. Hit the
CLR key. The screen should freeze for a few moments. Continue
forward in memory until you find a clear screen. Now type a few
words and watch them appear on the screen. If you wish to de
lete, merely use the delete key. The cursor control keys work, but
no visible cursor can be found. This display of typed characters
demonstrates how memory is used to store data. Word processors
utilize memory in just this fashion.
174
Memory
A Look at Memory
1 POKE53281,1:00803190:00803300
2 X=0:POKE191,0:POKE55,0:POKE56,128:R=33
024
3 IFPEEK(191)=255ORPEEK(191)=0THENPOKE19
1,PEEK(191)
175
7 Memory
5 GOSUB1000
10 A=PEEK(19 7):IFA=4THENX=X+40:1FX+40 > 2 5
5THENX=X+40-256:Fl=l:GOTO20
11 A=PEEK(197):IFA=3THENX=X+1:IFX+1>255T
HENX=X+l-256:Fl=l:GOTO20
12 A=PEEK(197) : IFA=6THENX=X-1: IFX+K0THE
NX=X+l+256:Fl=l:GOTO20
13 A=PEEK(197):IFA=5THENX=X-40:IFX-40<0T
HENX=2 56+X-40:Bl=l:GOTO25
20 IFPEEK(191)<>255THENIFA=4ANDF1=1THENZ
=1:POKE191,PEEK(191)+Z:Fl=0:GOTO28
21 IFPEEK(191)=255THENIFA=4ANDF1=1THENZ=
1:POKE191,PEEK(191)-256+Z:F1=0:GOTO28
22 IFPEEK(191)=0THENIFA=5ANDB1=1THENZ=-1
:POKE191fPEEK(191)+256+Z:Bl=0:GOTO28
25 IFPEEK(191)<>0THENIFA=5ANDB1=1THENZ=-
1:POKE191,PEEK(191)+Z:B1=0
28 IFPEEK(191)=255ANDPEEK(2)=255THENPOKE
191,0:POKE2,0
35 IFX>255THENX=255
36 IFX<0THENX=0
39 POKE2/X:SYS49152
40 PRINT"{HOME}";PEEK(191)*256+PEEK(2);:
GOTO3
190 FORR=49152TO49152+65:READJ:POKER,J:N
EXT:RETURN
200 DATA 165, 2, 133, 251, 165, 191, 133
, 252, 169, 0, 133
210 DATA 253, 169, 4, 133, 254, 162, 4,
177, 251, 145
220 DATA 253, 200, 208, 249, 230, 252, 2
30, 254, 202, 208
230 DATA 242, 169, 0, 133, 251, 169, 216
, 133, 252, 162
240 DATA 4, 169, 0, 145, 251, 200, 208,
251, 230, 252
250 DATA 202, 208, 246, 96, 0, 255, 255,
0, 0, 255
260 DATA 255, 40, 10, 255, 255
300 DIMA(3)
310 A(0)=2:A(1)=-80:A(2)=-2:A(3)=80
320 WL=160:HL=32:SC=49658:A=SC+81
330 PRINT" {CLRHBLK}LOADING MAZE (C. BON
D)"
340 FORZ=SCTOSC+40:POKEZ,160:NEXT
350 FORM=SCTOSC+3072:POKEM,160:NEXT
360 FORM=SCTOSC+3072STEP40:POKEM,32:NEXT
370 FORM=SC+39TOSC+3072STEP40:POKEM,32:N
EXT
176
Memory
410 POKEA,4
420 J=INT(RND(1)*4):X=J
430 B=A+A(J ) : IFPEEK(B)=WLTHENPOKEB,J:POK
EA+A(J)/2,HL:A=B:GOTO420
440 J=(J+1)*-(J<3):IFJ<>XTHEN430
450 J=PEEK(A):POKEA,HL:IFJ<4THENA=A-A(J)
:GOTO420
500 J=2
510 RETURN
1000 REM
1010 GETD$:IFD$=MIITHEN1040
1011 IFD$=CHR$(20)THENPOKER,32:POKER+1,3
2:R=R-1:GOTO1040
1012 IF D$=CHR$(157)THEN:R=R-1:GOTO1040
1013 JF D$=CHR$(29)THENR=R+1:GOTO1040
1014 IF D$=CHR$(145)THENR=R-41:GOTO1040
1015 IF D$=CHR$(17)THENR=R+39:GOTO1040
1016 IF D$=CHR$(133)ORD$=CHR$(134)THEN10
40
1017 IF D$="{CLR}IITHENFORT=RTOR+1024:POK
ETr32:NEXT:GOTO1040
1020 E=ASC(D$):IFE>64THENE=E-64
1030 R=R+1:IFR<40959ANDR>32768THENPOKER#
E
1040 RETURN
177
Memory
Commodore 64
Architecture
JimButterfield
77ns article allows you a peek inside the structure of the Commodore 64
and demonstrates some of its extraordinary features.
RAM —64K
We start with a full 64K of RAM. That's the maximum amount of
memory that the 6510 microprocessor chip can address.
If we stopped at this point, we'd have problems. First of all,
the screen is fed from memory, but it would contain nonsense.
We'll need to put in two extra things: a video chip, and a character
generator for the video chip to use. Then again, we have no pro
grams of any sort, and no way to get them into RAM.
Building It Out
Here's what we will do: we'll add the extra features we need by
piling them on top of RAM. That way, RAM will be "hidden" — if
we look at that part of memory, we will see the new elements. But
we'll include a set of switches which will allow us to "flip away"
the overlaying material and expose the RAM beneath any time we
choose. More about these later.
Keep in mind: the RAM is still there, but it's hidden behind
the new chips.
input/Output
Well take the block of memory at hexadecimal D000 to DFFF and
reserve it for our interface chips. These include two CIAs for
timing and input/output, a SID chip for sound, and a video chip
to deliver a screen to the television set.
About the 6566 video chip: its "registers" are located at hex
D000 to D02E; these locations control how the chip works. But
when the video chip needs information to put on the screen, it
178
Memory
gets it directly from RAM memory. For example, the usual place
for the screen characters is hex 0400 to 07E7. There's a distinction
here: we control or check the chip by using its register addresses,
but the chip gets display information from almost anywhere it
likes.
The video chip needs to look at RAM to get characters for the
screen. It also needs to look somewhere else to get a "picture" of
each character; this allows it to light up the individual dots, or
"pixels," that make up a character. There needs to be a table which
gives details of each character: what it looks like, and how to draw
it. This table is called the Character Base Table; hardware types
may just call it the character generator.
We could put this Character Base Table in RAM and point the
video chip to it. In fact, we are likely to do this if we want to define
our own graphics. But on a standard 64, we'd just as soon have
these characters built-in, in other words, well put the Character
Base Table into ROM memory.
Now comes the tricky bit. We will put our ROM character
base (it's 4K long when we allow for both graphics and text) into
locations hex D000 to DFFF. Wait a minute! We just put our inter
face chips there!
No problem. We just pile the memory elements higher. The
ROM character base sits above the RAM, and then we put the I/O
on top. Any time we PEEK these locations, well see the I/O. The
video chip, by the way, has a special circuit allowing it to go direct
ly to the ROM character base, so there's no confusion there.
If you wanted to look at the character ROM, you'd have to flip
it to the top somehow. It turns out you are allowed to do this:
clearing bit two of address one will do the trick. But be sure you
disable the interrupt first, or you're in serious trouble. After all,
the interrupt routines expect the I/O to be in place. Bit 2 of
address 0 is called the CHAREN control line.
Let's look at a small part of the character base — in BASIC! Be
sure to do this on a single line, or as part of a program. First, to
turn the interrupt off and back on again:
179
Memory
POKE 56333,127:POKE1,51:X=PEEK(53248):POK
E 1,55:POKE 56333,129:PRINT X
You should see a value of 60; this is the top of the @ character.
To see its pixels, we would write it in binary as 00111100 and to see
the next line of pixels we would repeat the above code with
X=PEEK(53249).
Remember that this is ROM; we can PEEK but can't POKE. If
we wanted a new character set, we would point the video chip to
some new location.
KernalROM
To allow the computer to work at all, we must have an operating
system in place. The 64's system is called the Kernal: it's in ROM,
and placed above RAM at addresses $E000 to $FFFF.
We can flip the Kernal away and expose the RAM beneath by
clearing bit one of address one. Be very careful! The computer
can't exist for long without an operating system. Either put one
into the RAM or be prepared for a crash.
Even if you flip out the Kernal for a moment, you must be
sure to disable the interrupt. The interrupt vectors themselves are
in the Kernal; if the interrupt strikes while the Kernal is flipped
away, well have utter confusion.
Flipping out the Kernal automatically flips out BASIC as well.
So bit one erf address one, called the HIRAM control bit, switches
out both ROMs. We can switch BASIC alone, however, by using
bit zero — the LORAM control bit.
BASIC ROM
To run BASIC, we have another ROM which is placed above RAM
at addresses $A000 to $BFFR We may flip it out by clearing bit zero
(mask one) of address one.
This is a very useful thing to do. When a word processor,
spreadsheet calculator, or other program is in the computer, we
may not need BASIC at all. Flip it away, and we have extra mem
ory for our program.
180
Memory
Run the program. It will take a minute or so. While it's run
ning, let's talk about that curious line 110. What's the point in
POKEing a value into memory identical to what's already there?
Here's the secret: when we PEEK, we see the BASIC ROM; but
when we POKE, we store information into the RAM beneath.
The program should say READY; now we have made a copy
of BASIC in the corresponding RAM. Flip the ROM away with
POKE 1,54. If the cursor is still flashing, we're there. BASIC is
now in RAM. How can we prove this?
Let's try to fix one of my pet peeves (PET peeves?). Whenever
I try to take the ASC value of a null string, BASIC refuses. Try it:
Now, it's my fixation that you should be able to take the ASCII
value of a null string, and have BASIC give you a value of zero.
(Don't ask why; that would take a couple more pages.) By peering
inside BASIC, I have established that the situation can be
changed by modifying the contents of address 46991. There is
usually a value of eight there. Normally, we couldn't change it: it's
in ROM. But now BASIC is in RAM, and we'll change the ASC
function slightly by:
POKE 46991,5
Now try PRINT ASC(" "); it will print a value of zero. In every
other way, BASIC is exactly the same.
Just for fun: you can change some of BASIC'S keywords or
error messages to create your own style of machine. For example,
POKE 41122,69 changes the FOR keyword; you must type the
new keyword to get the FOR action. Say LIST and see how line
100 has changed. Alternatively, POKE 41230,85; now you must
say LUST instead of LIST.
You may go back to ROM BASIC at any time with a POKE
1,55.
181
Memory
Combination Switch
When we use the HIRAM control to flip out the Kernal, BASIC
ROM is also removed. Is there any point in flipping both HIRAM
and LORAM? If you do, the I/O and Character Generator also dis
appear, giving you a solid 64K of RAM. You can't talk to anybody,
since you have no I/O, but you can do it.
We have named three control lines: CHAREN, which flips
I/O with the Character Base; HIRAM, which flips out Kernal and
BASIC ROMs; and LORAM, which controls BASIC. In my
memory maps I've called them D-ROM switch, EF-RAM switch,
and AB-RAM switch in an attempt to make them more
descriptive.
But there are two other control lines, and your program can
not get to them. They are called EXROM and GAME and may be
changed only by plugging a cartridge into the expansion slot.
When these lines are switched by appropriate wiring inside the
cartridge, the memory map changes once again.
But that's another story.
For the first time, the machine's architecture is at your
disposal. If you don't like BASIC, throw it out and replace it with
your own. The same is true of the Kernal operating system; it's ac
cessible or replaceable.
New horizons are opening. Well need to do a lot of traveling
to reach them.
Commodore 64 Memory
Addresses shown in hexadecimal.
FFFF
0000
182
Memory
Commodore 64
Memory Map
Compiled by Jim Butterfield
183
7 Memory
184
Memory
7
185
Memory
186
Memory
7
187
7 Memory
Pulse Width L
D402 D409 D410 54274 5428154288
D403 D40A D411 54275 54282 54289
0 0 0 0 j H
Voice Type
D404 D40B D412 Key 54276 54283 54290
NSE PUL SAW TRI
. j i i i i i
Release Time
D406 D40D D414 Sustain Level 6 ms - 24 sec 54278 54285 54292
i. i i
Voices
(Write Only)
0 0 0 0 0 j L
D415 54293
D416 54294
Filter Frequency H
Filter Voices
Resonance-
D417 I EXT V3 V2 VI 54295
1' - i
fassband Master
D418 V3 LJ0 Volume 54296
Hi Bd
Off,
-L J.
188
Memory
7
Sense
(Read Only)
Special voice features (TEST, RING MOD, SYNC) are omitted from the above diagram.
$DC01 ; Joystick!
J PRB 56321
Keyboard Column Read --.-J -- -"{
•" r'X''
Out Time
$DC0F One Timer CRB 56335
Shot Mode PB7 B Start
\Out;,
i II ■ "- • • ' 1
189
7 Memory
190
Memory
SOft-16
Douglas D. Nicoll
191
7 Memory
Automatic Switching
How does USR(PEEK) work? The statement X =USR(N) in a
BASIC program loads N into the floating point accumulator and
sends the computer to the machine language program pointed to
by the USR vector. The machine language program evaluates the
number in the FP accumulator, switches out BASIC and Kernal
ROM, loads the desired RAM data into the FP accumulator,
switches BASIC and Kernal ROM back in, and finally sets up the
FP accumulator so that X contains the values on return to the
BASIC program. When character ROM is desired, it is switched in
for the manipulation.
The techniques used to dynamically switch between RAM
and ROM have many other uses for programmers who use both
BASIC and machine language. For example, machine language
programs can be LOADed under BASIC or Kernal ROM and run
with BASIC programs — this leaves more space for BASIC pro
grams and variable storage. It is possible to envision LOADing a
BASIC program editor under BASIC ROM and calling it for re
numbering, searching, etc.
Type in the program and, after saving a copy, RUN it to see a
demonstration of how easy it is to use. Then eliminate lines 10-540
and SAS/E it with the name USR(PEEK). To use with your pro
grams, LOAD and RUN USR(PEEK) and then LOAD and RUN
your own BASIC programs that can be constructed to utilize the
additional 16K of RAM data storage.
USR (PEEK)
1 GOSUB1000-.REM SET UP USR(PEEK)
5 REM**{9 SPACES}USR(PEEK){12 SPACES}**
10 PRINT"{CLR}USR(PEEK) AT CHARACTER ROM
ii
20 V$="{HOME}{24 DOWN}"
30 H$=""+"{39 RIGHT}"
40 UC=53248:LC=55296:GC=53760
50 H=0:V=10:L=83*8+UC:GOSUB500
60 H=8:V=10:L=3*8+UC:GOSUB500
70 H=14:V=5:L=85*8+UC:GOSUB500:H=14:V=14
:L=74*8+UC:GOSUB500
80 H=22:V=10:L=54*8+UC:GOSUB500
90 H=30:V=10:L=52*8+UC:GOSUB500
100 PRINTLEFT$(V$,5);LEFT$(H$,18);"SC
{UP}U{2 DOWN}{LEFT}J{UP}64";LEFT$(V$
,22)~
110 PRINT"PRESS ANY KEY TO CONTINUE";
192
Memory
7
120 GETA$:IFA$=""THEN120
130 PRINT"{CLR}USR(PEEK) INTO BASIC HIDD
EN RAM"
140 PRINTLEFT$(V$/5);"INPUT 10 NUMERS(0-
255) TO STORE IN $A000TO $A00A :"
150 FORI=1TO10
160 PRINT"NUMBER ";I;": ";:INPUT"";X
170 IFINT(X)<>XORX<0ORX>255THENPRINT"INV
ALID ENTRY...":GOTO160
180 POKE40959+I,X:NEXT
190 PRINT"{CLR}USR(PEEK) INTO HIDDEN BAS
IC RAM"
200 PRINT:PRINT:PRINT"LOCATION{3 SPACES}
PEEK{3 SPACES}USR(PEEK)"
205 PRINT" "
210 FORI=1TO10:PRINTI+40959,PEEK(1+40959
),USR(1+40959):NEXT
220 PRINTLEFT$(V$,22);"PRESS ANY KEY TO
CONTINUE ";
230 GETA$:IFA$=""THEN230
240 PRINT"{CLR}USR(PEEK) INTO KERNAL HID
DEN RAM"
250 PRINTLEFT$(V$/5);"INPUT 10 NUMERS(0-
255) TO STORE IN $F000TO $F00A :"
260 FORI=1TO10
270 PRINT"NUMBER ";I;": ";:INPUT"";X
280 IFINT(X)<>XORX<0ORX>255THENPRINT"INV
ALID ENTRY*..":GOTO160
290 POKE61439+I,X:NEXT
300 PRINT"{CLR}USR(PEEK) INTO HIDDEN KER
NAL RAM"
310 PRINT:PRINT:PRINT"LOCATION{3 SPACES}
PEEK{3 SPACES}USR(PEEK)"
320 PRINT" "
330 FORI=1TO10:PRINTI+61439,PEEK(1+61439
),USR(1+61439):NEXT
340 END
500 FORJ=LTOL+7:X$="":X=USR(J)
510 FORI=7TO0STEP-l:IFX=>2tlTHENX=X-2tl:
X$=X$+"{WHT}{RVS} {OFF}":GOTO530
520 X$=X$+"{RIGHT}"
530 NEXTI:IFJ=LTHENPRINTLEFT$(V$,V);
540 PRINTLEFT$(H$,H);X$:NEXT:RETURN
1000 POKE785,1:POKE786,192:REM USR VECTO
R
1010 FORI=49153TO49380:READX:POKEI,X:NEX
T
1015 RETURN
193
7 Memory
1020 DATA173,97,0,201,144,208,3,76,188,1
92,56,201,128,176,3,76,163,192,201,
145
1030 DATA144,3,76,163,192,73,128,141,97,
0,56,169,16,237,97,0,240,13,170,24
1040 DATA78,98,0,110,99,0,202,224,0,208,
244,173,98,0,141,78,192,17?,99,0
1050 DATA141,77,192,173,l,0,14l",0,192,12
0,73,7,141,1,0,173,255,255,141,98,0
1060 DATA173,0,192,141,1,0,88,173,98,0,2
01,0,208,3,76,140,192,162,8,173,98,
0
1070 DATA24,42,176,5,202,224,0,208,247,1
06,141,98,0,73,128,141,102,0,138
1080 DATA9,128,141,97,0,169,0,141,99,0,1
41,100,0,141,101,0,96,169,0,141,97,
0
1090 DATA141,99,0,141,100,0,141,101,0,14
1,102,0,169,128,141,98,0,96,169,129
1100 DATA141,97,0,169,128,141,98,0,141,1
02,0,169,0,141,99,0,141,100,0,141,1
01,0
1110 DATA96,56,173,98,0,201,224,144,3,76
,223,192,201,208,176,3,76,223,192,1
69,4
1120 DATA141,72,192,173,97,0,32,26,192,1
69,7,141,72,192,96,173,97,0,76,11,1
92
194
Chapter 8
Advanced
Memory
Advanced
Memory 8
Assembler
BASIC
Ronald Thibault
197
8 Advanced
Memory
BASIC Assembler/Editor
1 REM ASSEMBLER/EDITOR 2.0 -MODIFIED FOR
{SPACE}C-64
2 MEM=50:M2=20
5 PRINT"{CLR}{WHT}":POKE 53281,0:POKE 532
80,11
6 PRINT"INTRUCTIONS ? (Y/N)m;
8 GET Z$:IF Z$="" OR (Z$<>"Y" AND Z$o"N11
) THEN 8
9 IF Z$="Y" THEN GOSUB 11000
10 PRINT"{CLR}"
11 DIM A$(MEM),S$(M2),V(M2)/LI(3)
15 H$="0123456789ABCDEF"
100 LN=1
110 PRINT LN;:TB=5:LT=6:GOSUB 4000:IF IN$
="EXIT" THEN 300
198
Advanced
Memory
199
8 Advanced
Memory
477 NEXT T
478 IF LL+MARK>MEM THEN PRINT"{RVS}NUMBER
OF INSERTIONS TO LARGE":GOTO 300
480 FOR T=MEM-LL TO FL STEP-1:A$(T+LL)=A$
(T):NEXT T
490 FOR T=FL TO FL+LL-1:A$(T)="":NEXT T:G
OTO 300
500 IF CM$o"L" THEN 580
510 INPUT"LINES FIRST,LAST";FL,LL
512 IF FL>LL THEN PRINT"{RVS}INCORRECT LI
NE NUMBERS"2GOTO 300
515 IF FL>MEM OR LL>MEM THEN PRINT"{RVS}L
INE NUMBER TO LARGE"2GOTO 300
517 IF FL<=0 OR LL<=0 TH?EN PRINT"{RVS}LIN
E NUMBER TO SMALL":GOTO 300
521 FOR T=FL TO LL:IF LEN(A$(T))=0 THEN P
RINT T:GOTO 565
525 LI(1)=0:LI(2)=0:LI(3)=0:LI=0:FOR Q=l
{SPACE}TO LEN(A$(T))
540 IF MID$(A$(T),Q,1)=" " THEN LI=LI+1:L
I(LI)=Q
545 NEXT Q:IF LI(3)=0 THEN LI(3)=Q-1
550 PRINT T TAB(5) LEFT?(A$(T),LI(1)) TAB
(13) MID$(A$(T),LI(1)+1,LI(2)-LI(1));
560 PRINT TAB(18) RIGHT?(A$(T),Ll(3)-LI(2
200
Advanced
Memory 8
201
Advanced
' Memory
202
Advanced
Memory 8
4020 PRINT"{RVS} {OFF}{LEFT}";
4030 GET GT$:IF GT$=IIM THEN 4030
4031 IF GT$>"Z" OR GT$<" " AND GT$<> CHR$
(13) AND GT$<>CHR$(20) THEN 4030
4035 NL=NL+1
4040 IF GT$=CHR$(20) OR GT$=CHR$(13) THEN
4100
4045 IF GT$=" " THEN PRINT" ";:RETURN
4050 PRINT GT$;:IN$=IN$+GT$
4060 IF NL=LT THEN 4100
4070 GOTO 4020
4100 IF GT$<>CHR$(20) THEN 4150
4105 IF LEN(IN$)<2 THEN 4120
4110 PRINT" {2 LEFT}";:NL=NL-2:IN$=LEFT$(
IN$,LEN(IN$)-1):GOTO 4020
4120 IF LEN(IN$)=0 THEN NL=NL-l:GOTO 4020
4130 PRINT" {2 LEFT}";:NL^NL-2:IN$="":GOT
O 4020
4150 IF GT$=CHR$(13) THEN PRINT" "
4160 RETURN
5000 DATA ADCN6DS65I69K7DL79P61O71Q75
5010 DATA ANDN2DS25I29K3DL39P21O31Q35
5020 DATA ASLH0AN0ES06K1EQ16
5030 DATA BCCJ90,BCSJB0,BEQJF0
5060 DATA BITN2CS24
5070 DATA BMIJ30,BNEJD0,BPLJ10,BRKG00
5110 DATA BVCJ50,BVSJ70,CLCG18,CLDGD8
5150 DATA CLIG58,CLVGB8
5170 DATA CMPNCDSC5IC9KDDLD9PC1OD1QD5
5180 DATA CPXNECSE4IE0
5190 DATA CPYNCCSC4IC0
5200 DATA DECNCESC6KDEQD6
5210 DATA DEXGCA,DEYG88
5230 DATA EORN4DS45I49K5DL59P41O51Q55
5240 DATA INCNEESE6KFEQF6
5250 DATA INXGE8,INYGC8
5270 DATA JMPN4CM6C
5280 DATA JSRN20
5290 DATA LDANADSA5IA9KBDLB9PA1OB1QB5
5300 DATA LDXNAESA6IA2LBERB6
5310 DATA LDYNACSA4IA0KBCQB4
5320 DATA LSRH4AN4ES46K5EQ56
5330 DATA NOPGEA
5340 DATA ORAN0DS05I09K1DL19P01O11Q15
5350 DATA PHAG48,PHPG08,PLAG68,PLPG28
5390 DATA ROLH2AN2ES26K3EQ36
5400 DATA RORH6AN6ES66K7EQ76
5410 DATA RTIG40,RTSG60
5430 DATA SBCNEDSE5IE9KFDLF9PE1OF1QF5
203
8 Advanced
Memory
204
Advanced
Memory
8020 RETURN
9000 FD=INT(N/4096):N=(N/4096-FD)*4096:SD
=INT(N/256):N=(N/256-SD)*256
9010 TD=INT(N/16):N=INT((N/16-TD)*16):R$=
MID$(H$,FD+1,1)+MID$(H$,SD+1,1)
9020 R$=R$+MID$(H$,TD+1,1)+MID$(H$,N+l,1)
:RETURN
10000 IF A$(T) = IIM THEN OC$=M " :LB$=" " :GOTO
10100
10005 LI(1)=0:LI(2)=0:LI(3)=0:LI=0
10010 FOR R2=l TO LEN(A$(T)):IF MID$(A$(T
),R2,1)=" " THEN LI=LI+1:LI(LI)=R2
10020 NEXT R2:IF Ll(3)=0 THEN Ll(3)=R2-l
10030 LB$=LEFT$(A$(T),LI(1)):OC$=MID$(A$(
10040 OP$=RIGHT$(A$(T),LI(3)-LI(2)+1)
10050 IF LB$=M " THEN LB$=""xGOTO 10070
10060 LB$=LEFT$(LB$/LEN(LB$)-1)
10070 OC$=LEFT$(OC$/LEN(OC$)-1)
10080 IF OP$=" " THEN OP$=IIM:GOTO 10100
10090 OP$=RIGHT$(OP$/LEN(OP$)-1)
10100 RETURN
11000 PRINT"{CLR}":PRINT"{3 SPACES}THE AS
SEMBLER STARTS WITH THE FIRST11
11010 PRINT"LINE OF THE MACHINE PROGRAM T
O BE":PRINT"ENTERED."
11020 PRINT:PRINT"{3 SPACESjTHIS IS INDIC
ATED BY THE NUMBER 1,"
11030 PRINT"AND A WHITE CURSOR BESIDE IT.
THIS"
11040 PRINT"MEANS THAT YOU ARE AT LINE 1
{SPACE}AND IT IS"
11050 PRINT"WAITING FOR INPUT INTO THE LA
BEL FIELD."
11060 PRINT:PRINT"{3 SPACES}IF YOU TYPE T
O THE END OF THE FIELD,"
11070 PRINT"HIT {RVS}SPACE{OFF}, OR HIT
{RVS}RETURN{OFF},YOU WILL JUMP"
11080 PRINT"TO THE NEXT FIELD.":PRINT
11090 PRINT"{3 SPACES}THE LENGTH OF THE
{RVS}LABEL{OFF} FIELD IS"
11100 PRINT"{RVS}6{OFF} CHARACTERS, THE
{RVS}OPCODE{OFF} FIELD IS {RVS}3
{OFF},"
11110 PRINT"AND THE {RVS}OPERAND{OFF} FIE
LD {RVS}10{OFF}."
11120 PRINT:PRINT"{3 SPACES}A {RVS}SPACE
{OFF} OR {RVS}RETURN{OFF} IN THE
{RVS}OPERAND{OFF}"
205
8 Advanced
Memory
206
Advanced
Memory 8
11360 PRINT11 N INSERT CODE. YOU WILL BE A
SKED THE"
11370 PRINT"{4 SPACES}INSERTION POINT AND
THE # OF LINES"
11380 PRINT"{4 SPACESjTO BE INSERTED."
11390 PRINT" L LIST. YOU WILL BE ASKED FO
R THE"
11400 PRINT"{4 SPACES}BEGINING AND ENDING
LINE NUMBERS."
11402 PRINT" S SAVE. YOU WILL BE ASKED FO
R THE"
11404 PRINT"{4 SPACES}FILENAME OF FILE TO
BE SAVED."
11406 PRINT" O LOAD. YOU WILL BE ASKED FO
R THE"
11408 PRINT"{4 SPACES}FILENAME OF FILE TO
BE LOADED."
11410 PRINT" A ASSEMBLE. YOU WILL BE ASKE
D TO PICK"
11420 PRINT"{4 SPACESjSCREEN OR PRINTER.
{SPACE}AFTER ASSEMBLY"
11430 PRINT"{4 SPACESjTHE CODE IS IN MEMO
RY."
11440 PRINT" Q QUIT THE PROGRAM. IF HIT A
CCIDENTALY"
11450 PRINT"{4 SPACESjYOU CAN RETURN TO P
ROGRAM WITH"
11460 PRINT"{4 SPACES}{RVS}GOTO 300{OFF}.
ii
207
8 Advanced
Memory
208
Advanced
Memory 8
209
Advanced
Memory
Decoding basic
Statements
John Heilborn
210
Advanced
Memory 8
PEEK those locations, you would find that they contain two
separate numbers which combine to represent a hexadecimal
number. Let's take a closer look at how this works and why it is
done this way.
Next This °
BASIC Line's
Statement Number
Hexadecimal Numbers
All of the numbers in the computer are actually stored as binary
numbers. These are numbers that are made up of only ones and
zeros. While this may seem like an impractical way to store num
bers, it makes perfect sense to the computer because its circuits
can operate in only one of two conditions — on or off. The ons are
represented as ones and the offs are zeros.
The individual ones and zeros are called bits and the com
bined numbers they make (each of which contains eight bits) are
called bytes. Because there are eight bits in each byte, each byte
can represent any number between 0 and 255. Since program line
numbers in BASIC can be greater than 255, it is necessary to use
two bytes to represent the line numbers. Two bytes together can
represent any number between 0 and 65535, but the largest line
number BASIC allows is 63999.
Looking Ahead
To decode the hexadecimal number, multiply the value stored in
the second byte (high byte) by 256 and add the result to the value
in the first byte (low byte). Enter the following program line:
Now PEEK memory locations 2049 (low byte) and 2050 (high
byte). You'll find that they contain the values 22 and 8. Multiply 8
211
8 Advanced
Memory
by 256 (2048) and add 22 for a total of 2070. Therefore, the next
program line will begin at memory location 2070.
Line Numbers
The next two memory locations (2051 and 2052) contain the pro
gram line number. The values you'll get by PEEKing these loca
tions are 10 and 0. Once again, multiply the second number by
256 and add it to the first number. This time the result is 10 — our
line number!
Now lefs renumber this program. POKE location 2051 with
the value 100:
POKE 2051,100
and LIST the program. The line number should now be 100.
POKEing 100 into location 2052 will cause the line number to
jump to 25700.
Tokens
Every BASIC command has a corresponding token. The token is a
single number that represents the command. For example, if you
PEEK location 2053, the computer will display the tokenized
value for the REM statement, 143. The table below contains all of
the BASIC statements and their tokens.
basic Tokens
END 128 LOAD 147 FN 165 FRE 184
FOR 129 SAVE 148 SPC 166 POS 185
NEXT 130 VERIFY 149 THEN 167 SQR 186
DATA 131 DEF 150 NOT 168 RND 187
INPUT # 132 POKE 151 STEP 169 LOG 188
INPUT 133 PRINT # 152 + 170 EXP 189
DIM 134 PRINT 153 -
171 COS 190
CONT
*
READ 135 154 172 SIN 191
LET 136 LIST 155 / 173 TAN 192
GOTO 137 CLR 156 t 174 ATN 193
RUN 138 CMD 157 AND 175 PEEK 194
IF 139 SYS 158 OR 176 LEN 195
RESTORE 140 OPEN 159 > 177 STR$ 196
GOSUB 141 CLOSE 160 =
178 VAL 197
RETURN 142 GET 161 < 179 ASC 198
REM 143 GET# SGN 180 CHR$ 199
STOP 144 NEW 162 INT 181 LEFT$ 200
ON 145 TAB( 163 ABS 182 RIGHT! 201
WATT 146 TO 164 USR 183 MID$ 202
212
Advanced
Memory 8
Now LIST the program. You have changed the REM statement in
to a PRINT statement! RUN the program to show that the change
is genuine.
ascii Data
The rest of the information in your programs is stored as ASCII
data. In other words, if you PEEK a location that has a standard
character stored in it, it will contain the number that is the ASCII
value of that character. Enter these lines:
zero as a Marker
Each BASIC statement stored in memory ends with a zero (see
the figure), which serves as an "end of statement" marker. Note
213
8 Advanced
Memory
that the marker is a byte with the value of zero, whereas zeroes
within the statement — for example, the two zeroes in the state
ment GOTO 100 — are stored as the ASCII representation of zero,
which is 48.
The zero byte has two other uses in BASIC. The first byte in
the BASIC RAM area (before the first BASIC statement) must con
tain a zero. Try a PEEK(2048) to check this. Also, two zero bytes as
the address of the next program line indicate that the end of the
BASIC program has been reached, so BASIC programs always
end with three zero bytes in a row.
Easy Lister
BASIC program listings as they normally appear on the screen
can be hard to understand. It's difficult to remember what all the
special characters appearing as inverse video symbols are sup
posed to represent. The following program makes listings much
easier to read. It goes through the BASIC program in memory
byte by byte and interprets each BASIC token, special symbol, or
graphics character.
To display all of the special symbols and characters, you need
to generate two tables in memory that contain all the possible
codes that can appear in a program line. In the program below,
these are called table A$ and table B$. Table A$ contains the token-
ized BASIC commands and table B$ contains the CHR$ codes for
the graphics characters and the descriptions of the special
functions.
To use the program, type it in carefully and SAVE it to tape or
disk. You can test the program by having it list itself if you tem
porarily omit line 62040 and type RUN. When you wish to make a
listing, follow these steps to append the Easy Lister program to
the program you wish to list:
1. Tell the computer where the end of your current program is
by typing:
POKE 43,PEEK(45)-2:POKE 44,PEEK(46)
2. LOAD the Easy Lister program from tape or disk.
3. Restore BASIC to its normal starting condition by typing:
RUN 61000
214
Advanced
Memory 8
215
8 Advanced
Memory
62060 A=A+2:GOTO62090
62070 IF(PEEK(A)=0)AND(PEEK(A+1)=0)THEN 6
2130
62080 IF PEEK(A)=0 THEN A=A+3:PRINT#l:GOT
O 62030
62090 IF PEEK(A)=34 THEN C=C*-1
62100 IF C=-l THEN 62120
62110 PRINT#1,A$(PEEK(A));:A=A+1:GOTO6207
0
62120 PRINT#1,B$(PEEK(A));:A=A+1:GOTO6207
0
62130 CLOSE Is END
216
Advanced
Memory 8
Micromon-64
BillYee
Commands
What follows is a listing of all the commands available with
Micromon-64. The listing includes a short explanation and the
format needed.
Assembler
.A 401F AD 14 03 LDA $0314 : CHECK IRQ VECTOR
.A 4022 AE 15 03 LDX $0315
.A 4025 C9 91 CMP #$91
.A 4027 DO 04 BNE $402D
.A 4029
Break set
.B 2000 0010
217
Advanced
' Memory
Compare Memory
.C 2000 2FFF C000
Disassembler
D 4015 401C
, 4015 A9 DF LDA #$DF
, 4017 A2 45 LDX #$45
, 4019 8D 16 03 STA $0316
, 401C 8E 17 03 STX $0317
218
Advanced
Memory 8
Exit Micromon
.E
Restore the IRQ and BRK interrupt vectors, reset the tape buffer to
$033C, and then exit to the BASIC environment. The E command
should be used to exit Micromon when the normal LOAD, S^VE,
and VERIFY commands are to be used in the BASIC environ
ment. Always use SYS49152 to access or reenter Micromon-64
located at $C000.
Fill Memory
.F 2000 3FFF 00
.F 4000 47FF FF
Go Run
.G
.G 2000
219
8 Advanced
Memory
Hunt Memory
.H 1000 5FFF 'ASCII CHARACTER STRING
.H 0000 1000 01 02 03 04 05 06
Search for and, if found, load into memory starting at $4000 the
data file on device #8 named TEST FILE. Device #8 is the 1541
floppy disk which requires that a filename be specified. If the de
vice number is not specified, it defaults to device #1, which is the
cassette tape. For tape, if no filename is specified, the first file
found is loaded. The last address loaded is determined by the
length of the data file. The BASIC memory pointers are not af
fected by this load. When loading from tape, the original memory
addresses and name of the last file read can be inspected by doing
a memory display of the tape buffer, which is located at $0375 for
Micromon.
220
Advanced
Memory 8
Memory Display
M 4E70 4E80
4E70 49 43 32 30 20 4D 49 43 IC20MIC
4E78 52 4F 4D 4F 4E 20 56 31 ROMONV1
4E80 2E 30 20 20 20 42 49 4C .OBIL
M 4E88
4E88 4C 20 59 45 45 20 32 32 LYEE22
New Locater
.N 2000 2003 6000 C000 CFFF
.N 2FB5 2FFE 6000 C000 CFFFW
Calculate the offset for branch instructions. The first address is for
the location containing the branch opcode, and the second
address is the branch target address. Addresses and the resulting
displayed offset byte are in hexadecimal.
221
8 Advanced
Memory
Print Switcher
.p
If the output is to the screen, then switch the output to the RS-232
channel (device #2). If the output is not to the screen, restore the
output to the screen with the RS-232 channel left active until the
RS-232 output buffer is drained. Note that opening the RS-232
channel grabs 512 bytes for I/O buffering from the top of BASIC
memory.
.P 0000
Regardless of the output, clear the RS-232 channel and set output
to the screen.
.P CCBB
This line causes all screen output to go to the VIC printer until
you exit Micromon with either the E or X command. The
SYS49152 is used to access Micromon at $C000.
Quick Trace
Q
.Q 4000
Register Display
.R
PC IRQ SR AC XR YR SP
.; C04E C391 32 32 00 1C F7
222
Advanced
Memory 8
Save memory from $4000 up to, but not including, $5000 onto de
vice #8, which is the 1541 floppy disk. If the device number is not
specified, it defaults to device #1, which is the cassette tape. The
name TEST FILE is placed in the tape file header or in the disk
directory for the file saved. Note that files saved on tape or disk
with the Micromon Save command can be loaded back into the
original memory area while in the BASIC environment. The non-
relocating form of the Load command in BASIC must be used. For
the file saved in the example, executing the line
LOAD 'TEST FILE",8,1
while in BASIC will load the data in TEST FILE back to the $4000
to $4FFF memory area. The BASIC memory pointers will be dis
turbed, so a New command should be executed to reset these
pointers. Note that the BASIC memory pointers are not disturbed
by the Micromon Load, Save, or Verify commands.
Transfer Memory
.T 4000 4FFF 6000
223
8 Advanced
Memory
walk code
.w
.W 4000
Exit tO BASIC
.x
224
Advanced
Memory 8
ASCII Conversion
."B 42 66 0100 0010
Decimal Conversion
.#16706 4142 A B 0100 0001 0100 0010
A decimal number is input to obtain the hexadecimal, ASCII
characters of the two bytes, and binary values for the decimal
number.
Hexadecimal conversion
.$4142 16706 A B 0100 0001 0100 0010
Binary conversion
.%0100000101000010 4142 16706 A B
Checksum Memory
.& C000 CFFF A500
The data for the memory block from $C000 to $CFFF inclusive is
byte-summed and displayed.
225
Advanced
Memory
.)
Disable the command end tone.
Addition
.+ 11H 2222 3333
Subtraction
.- 3333 Ull 2222
Disk Directory
Typing in Micromon-64
In order to enter Micromon-64 you must use the "Machine Lan
guage Editor (MLX)" program found in Appendix A and the
DATA listing found at the end of this article. It is important to read
the article that accompanies the MLX program. It may seem like
extra work at first to have to type in two programs, but you'll save
time later when you end up with a virtually error-free program.
In order to use MLX you must know the starting and ending
addresses of Micromon-64.
226
Advanced
Memory
^ii&B^
Sbditytfp to 8 Sltalytes M k
Modify Image Shown by Register Display
227
Advanced
Memory
3. LOAD Micromon-64
Tape type LOAD "MCROMON-64'ai
Disk type LOAD "MCROMON-64",8,1
Press RETURN
4. Once Micromon-64 is in memory, type NEW and press
RETURN.
5. Type CLR and press RETURN.
6. Type SYS49152 and press RETURN.
Relocation
I located Micromon-64 in the 4K byte address space from $C000 to
$CFFF. This space is above the BASIC ROM area and so is not in
cluded with the contiguous area defined for BASIC RAM. How
ever, you may still want to relocate Micromon-64 elsewhere, and
as with VIC Micromon, this version can be relocated with its own
commands. For example, to relocate it into the $2000 to $2FFF
memory area, use the following sequence of operations.
.T C000 CFFF 2000
228
Advanced
Memory 8
ill
: you have completed all of the operations shown, you
After; yoi can
save ti:
the relocated Micromon code to tape or disk with the
Micromon SJWE command as follows.
For tape:
.S 2000 3000 "NEW FILENAME"
For disk:
.S 2000 3000 "NEW FILENAME" 08
229
8 Advanced
Memory
Micromon-64
49152 .-120,076, 021,192, 169,018,084
49158 2032,210, 255,169, 157,032,093
49164 :210,255, 096,032, 021,253,111
49170 :032,024, 229,169, 223,162,089
49176 022,003, 142,023,040
49182 :003,173, 020,003, 174,021,168
49188 2003,201, 145,208, 004,224,053
49194 :195,240, 009,141, 096,003,214
49200 :142,097, 003,032, 164,200,174
49206 133,178, 169,128,180
49212 002,133, 157,162,025
49218 :215,032, 096,206, 142,072,061
49224 :003,142, 100,003, 088,000,152
49230 :206,061, 003,208, 003,206,253
49236 :060,003, 032,163, 197,162,189
49242 :066,169, 042,076, 077,201,209
49248 :169,063, 032,210, 255,169,226
49254 2000,044, 169,017, 141,004,221
49260 2212,032, 163,197, 169,046,159
49266 2032,210, 255,169, 000,141,153
49272 2078,003, 141,086, 003,141,060
49278 2100,003, 162,127, 154,032,192
49284 2156,200, 201,046, 240,249,200
49290 2201,032, 240,245, 162,036,030
49296 2221,144, 207,208, 019,141,060
49302 2073,003, 138,010, 170,189,221
49308 2 181,207, 133,251, 189,182,019
49314 2207,133, 252,108, 251,000,089
49320 2202,016, 229,076, 096,192,211
49326 2 162,002, 208,002, 162,000,198
49332 2180,251, 208,009, 180,252,236
49338 2 208,003, 238,086, 003,214,170
49344 2252,214, 251,096, 169,000,150
49350 2141,078, 003,032, 019,194,153
49356 2162,009, 032,072, 201,202,114
49362 2208,250, 096,162, 002,181,085
49368 2250,072, 189,083, 003,149,194
49374 2250,104, 157,083, 003,202,253
49380 2208,241, 096,173, 084,003,009
49386 2172,085, 003,076, 244,192,238
49392 2165,253, 164,254, 056,229,081
230
Advanced
Memory 8
231
8 Advanced
Memory
232
Advanced
Memory 8
49986 :133,195,032,165,255,133,211
49992 2 196,164,144,208,062,164,242
49998 :183,136,208,235,166,195,177
50004 2 165,196,032,205,189,169,016
50010 2 032,032,022,231,032,165,092
50016 2 255,166,144,208,038,201,084
50022 2 000,240,024,032,022,231,139
50028 2032,225,255,240,026,032,150
50034 2 228,255,240,232,201,032,022
50040 2 208,228,032,228,255,240,031
50046 2 251,208,221,169,013,032,252
50052 2 022,231,160,002,076,061,172
50058 2 195,032,066,246,076,104,089
50064 2 192,169,204,072,169,119,045
50070 2 072,008,072,072,072,108,042
50076 2 096,003,141,075,003,072,034
50082 2 032,156,200,032,016,201,031
50088 :208,248,104,073,255,076,108
50094 2 114,194,032,032,196,174,148
50100 2 086,003,208,013,032,240,250
50106 2 192,144,008,032,200,195,189
50112 2032,225,255,208,238,076,202
50118 2 014,194,032,163,197,162,192
50124 2 046,169,058,032,030,200,227
50130 2032,072,201,032,008,200,243
50136 2 169,008,032,250,200,169,020
50142 2 008,032,171,195,032,072,220
50148 2 201,032,004,192,234,234,101
50154 2160,008,162,000,161,251,208
50160 2 072,041,127,201,032,104,049
50166 2 176,002,169,046,032,210,113
50172 2 255,169,000,133,212,032,029
50178 2047,201,136,208,231,076,133
50184 2 229,202,032,246,199,169,061
50190 2 008,032,158,195,032,171,098
50196 2 197,032,200,195,169,058,103
50202 2 141,119,002,076,061,197,110
50208 2 032,246,199,133,253,134,005
50214 2 254,032,180,201,240,003,180
50220 2032,251,199,076,163,197,194
50226 2032,065,200,133,253,134,099
50232 2 254,162,000,142,102,003,207
50238 2 032,156,200,201,032,240,155
50244 2 244,157,079,003,232,224,239
50250 2003,208,241,202,048,020,028
50256 2 189,079,003,056,233,063,191
50262 2 160,005,074,110,102,003,028
50268 2110,101,003,136,208,246,128
50274 2 240,233,162,002,032,180,179
233
8 Advanced
Memory
234
)))))))))))))))) D ))))) D 0 ))))))))))))
>Oi^OOtOONS)i^OOtOONO£*OOtOONSl£fc
M M M M M
to O o o o o to s> ro o o o M ,_, O to o o ro M M SI SI o SI o o o SI o o SI o o o to to o o o to
O O O ON cn o ON o cn tO ON cn ON ON CO ON 4^ Si Si o VO o vo 4^ ON o o o ON o ON CO o ON ON o o o vo o •^ CO Si
00 CO CO VO 00 CO o vO H1 ro vo *-* *-* o ro ON vO CO 00 CO SI 00 CO ro »-• ON CO co to cn ro CO o I-1 CO co 00 ON 00 cn Si ON vo to cn
M M M M M
o o to o o to O o ro Si ro M O SI si ro M o o ro o o o o ro o M I-1 o o o to o to M to t-l SI SI
ON vo VO ^ Si o CO cn CO S) vo J—• ONvo o SI 00 ON ON ON ON o cn CO ON o to ON CO I-1 1—* ON o o
00 •^ VO
VO cn CO o co cn cn •-1 CO ro *-* ro *> ro *-• vo to 00 vo *-* 00 CO CO to SI 00 00 o co 4^ CO vO 4^ 4^ 4^ »-• £> ON o vo o o 4^ CO
M M M
S) O o o to O o Q to ro O o SI M Q M s> o H-1 M o O to o o M o o o o 1- to o M o to to o M ,_, O to
to O O O O O ro CO ON st 4^> CO ON ON ro vo ONO o o o o o o 4^ co ro o o o CO •^ •£* cn On o o
00 CO CO 00 ON CO to 00 00 00 ro o to »-• ro vO ON 00 00 CO vO cn CO CO co CO CO CO *-• CO »-" ON to 00 cn cn CO VO *-* M cn o vo *> 4s* 00
M M M M M M M l_.
Q SI o o to SI to O Q ro Q to Q o SI o o o to Q o o o o o o M o to o I-1 SI SI o to Si Hi o o O o
ON VO VO vo O VO o i^ CO O CO Si VO cn o o VO o o CO o ro ro o o •^ o •^ ON ON o o 1—• ON co 1—» CO vo
to to to 00 00 ON ro CO CO CO ro *»» CO to CO cn CO CO to cn to CO 00 vo to cn to ON
M 00 co to M o CO M M
si
ii
II
00
8 Advanced
Memory
236
Advanced
Memory 8
51162 :158,032,065,200,133,253,03s
51168 :134,254,032,082,200,141,043
51174 :084,003,142,085,003,032,067
51180 :156,200,032,085,200,133,018
51186 :251,134,252,096,032,065,048
51192 :200,176,246,032,085,200,163
51198 :176,003,032,082,200,133,112
51204 :253,134,254,096,165,252,134
51210 :032,015,200,165,251,072,233
51216 .-074,074,074,074,032,039,127
51222 :200,170,104,041,015,032,072
51228 :039,200,072,138,032,210,207
51234 :255,104,076,210,255,024,190
51240 :105,246,144,002,105,006,136
51246 :105,058,096,162,002,181,138
51252 :250,072,181,252,149,250,182
51258 :104,149,252,202,208,243,192
51264 :096,169,000,141,089,003,050
51270 :032,156,200,201,032,240,163
51276 :249,032,124,200,176,008,097
51282 :032,156,200,032,103,200,037
51288 :144,007,170,032,103,200,232
51294 :144,001,096,076,096,192,187
51300 :032,116,193,169,000,141,239
51306 :089,003,032,156,200,201,019
51312 :032,208,009,032,156,200,237
51318 :201,032,208,015,024,096,182
51324 :032,145,200,010,010,010,019
51330 :010,141,089,003,032,156,049
51336 :200,032,145,200,013,089,047
51342 :003,056,096,201,058,008,052
51348 :041,015,040,144,002,105,239
51354 :008,096,032,180,201,208,111
51360 :250,076,101,192,169,145,069
51366 :162,195,141,020,003,142,061
51372 :021,003,096,032,180,201,193
51378 :240,055,032,246,199,165,091
51384 :251,005,252,240,034,165,107
51390 :154,201,003,208,158,165,055
51396 :251,141,147,002,165,252,130
51402 :141,148,002,169,002,170,066
51408 :168,032,186,255,032,192,049
51414 2 255,162,002,032,201,255,097
51420 :076,117,192,169,002,032,040
51426 :195,255,169,003,133,154,111
51432 :076,104,192,165,154,201,100
51438 :003,240,220,208,241,141,011
51444 :061,003,142,060,003,096,097
51450 :141,075,003,160,000,032,149
237
8 Advanced
Memory
238
Advanced
239
8 Advanced
Memory
52044 2 252,104,101,251,133,251,144
52050 :104,101,252,133,252,006,162
52056 :251,038,252,165,254,101,125
52062 :251,133,251,169,000,101,231
52068 :252,133,252,096,032,194,035
52074 :203,141,085,003,072,072,170
52080 -.032,072,201,032,072,201,210
52086 :104,032,015,200,032,072,061
52092 :201,104,170,169,000,032,032
52098 :241,202,032,072,201,032,142
52104 :150,202,076,104,192,032,124
52110 :159,203,032,072,201,032,073
52116 :008,200,032,234,202,032,088
52122 2 176,202,076,104,192,162,042
52128 2 015,169,000,133,251,133,093
52134 2 252,032,194,203,032,043,154
52140 2 203,032,188,203,032,034,096
52146 2203,032,188,203,202,208,190
52152 2 247,076,072,201,074,038,124
52158 2 251,038,252,096,032,156,247
52164 2 200,201,032,240,249,096,190
52170 2 169,015,141,024,212,169,164
52176 2 000,141,005,212,169,240,207
52182 2 162,068,160,149,141,006,132
52188 2 212,142,001,212,140,000,159
52194 2 212,076,101,192,000,032,071
52200 2000,200,076,235,199,032,206
52206 2 231,203,024,165,251,101,189
52212 2 253,133,251,165,252,101,119
52218 2 254,133,252,076,013,204,158
52224 2032,231,203,032,240,192,162
52230 2 132,252,173,083,003,133,014
52236 2 251,032,072,201,032,008,096
52242 2 200,076,104,192,169,000,247
52248 2 170,168,141,024,212,076,047
52254 2 218,203,000,120,032,021,112
52260 2 253,088,169,060,133,178,149
52266 2 174,066,003,154,165,115,207
52272 2 201,230,240,149,108,000,208
52278 2 160,032,231,203,032,049,249
52284 2 200,032,072,201,160,000,213
52290 2140,084,003,140,085,003,009
52296 2032,240,192,144,027,172,111
52302 2086,003,208,022,024,177,086
52308 2 251,109,084,003,141,084,244
52314 2003,152,109,085,003,141,071
52320 2085,003,032,047,201,076,028
52326 2 072,204,173,085,003,032,159
52332 2015,200,173,084,003,032,103
240
Advanced
Memory 8
52338 :015,200,076,104,192,173,106
52344 :100,003,208,004,165,198,030
52350 :208,003,076,129,234,173,181
52356 :119,002,201,017,208,125,036
52362 :165,214,201,024,208,240,166
52368 :165,209,133,253,165,210,255
52374 :133,254,169,025,141,094,198
52380 :003,160,001,032,084,206,130
52386 :201,058,240,026,201,044,164
52392 :240,022,201,036,240,018,157
52398 :206,094,003,240,205,056,210
52404 :165,253,233,040,133,253,233
52410 :176,225,198,254,208,221,188
52416 :141,073,003,032,013,206,148
52422 :176,184,173,073,003,201,240
52428 :058,208,017,024,165,251,159
52434 :105,008,133,251,144,002,085
52440 :230,252,032,200,195,076,177
52446 :244,204,201,036,240,026,149
52452 :032,201,205,032,111,194,235
52458 :169,000,141,078,003,160,017
52464 :044,032,019,194,169,000,186
52470 :133,198,076,014,194,076,169
52476 :129,234,032,047,201,032,159
52482 :125,202,076,244,204,201,030
52488 :145,208,240,165,214,208,164
52494 :236,165,209,133,253,165,151
52500 :210,133,254,169,025,141,184
52506 :094,003,160,001,032,084,144
52512 :206,201,058,240,026,201,196
52518 :044,240,022,201,036,240,053
52524 :018,206,094,003,240,021,114
52530 :024,165,253,105,040,133,002
52536 :253,144,225,230,254,208,090
52542 :221,141,073,003,032,013,033
52548 :206,144,003,076,129,234,092
52554 :173,073,003,201,058,240,054
52560 :006,201,036,240,029,208,032
52566 :039,032,208,205,056,165,023
52572 :251,233,008,133,251,176,120
52578 :002,198,252,032,203,195,212
52584 :169,000,133,198,032,008,132
52590 :206,076,112,192,032,208,168
52596 :205,032,178,192,032,128,115
52602 :202,076,104,205,032,208,181
52608 :205,165,251,166,252,133,020
52614 :253,134,254,169,016,141,077
52620 -.094,003,056,165,253,237,180
52626 :094,003,133,251,165,254,022
241
8 Advanced
Memory
242
Advanced
Memory
243
8 Advanced
Memory
53220 :203,237,203,000,204,069,120
53226 :202,096,192,060,202,141,103
53232 :203,055,204,033,204,186,101
53238 :201,022,204,025,195,096,221
53244 :192,096,192,255,000,000,219
244
Appendix A
Using the
Machine
Language
Editor:
MLX
Appendix
A
using the
Machine
Language Editor:
MLX
Charles Brannon
Remember the last time you typed in the BASIC loader for a long
machine language program? You typed in hundreds of numbers
and commas. Even then, you couldn't be sure if you typed it in
right. So you went back, proofread, tried to run the program,
crashed, went back and proofread again, corrected a few typing
errors, ran again, crashed again, rechecked your typing... Frus
trating, wasn't it?
Until now, though, that has been the best way to get machine
language into your computer. Unless you happen to have an
assembler and are willing to wrangle with machine language on
the assembly level, it is much easier to enter a BASIC program
that reads DAIA statements and POKEs the numbers into
memory.
247
A Appendix
It will prevent you from entering the numbers on the wrong line.
In short, MLX will make proofreading obsolete.
Using MLX
Type in and SAVE MLX (you'll want to use it in the future). When
you're ready to type in the machine language program, RUN
MLX. MLX will ask you for two numbers: the starting address
and the ending address. For Micromon-64, these numbers should
be: 49152 and 53247 respectively.
You'll then get a prompt showing the specified starting
address. (For Micromon-64, the prompt will be: 49152)
The prompt is the current line you are entering from the
MLX-format listing. Each line is six numbers plus a checksum. If
you enter any of the six numbers wrong, or enter the checksum
wrong, the 64 will sound a buzzer and prompt you to reenter the
entire line. If you enter the line correctly, a pleasant bell tone will
sound and you may go on to enter the next line.
A Special Editor
You are not using the normal Commodore 64 BASIC editor with
MLX. For example, it will only accept numbers as input. If you
need to make a correction, press the INST/DEL key; the entire
number is deleted. You can press it as many times as necessary,
back to the start of the line. If you enter three-digit numbers as
listed, the computer will automatically print the comma and go
on to accept the next number in the line. If you enter less than
three digits, you can press either the comma, space bar, or
RETURN key to advance to the next number. The checksum will
automatically appear in inverse video; don't worry — it's high
lighted for emphasis.
248
Appendix
A
Done at Last!
When you get through typing, assuming you type your machine
language program all in one session, you can then save the com
pleted and bug-free program to tape or disk. Follow the instruc
tions displayed on the screen. If you get any error messages while
saving, you probably have a bad disk, or the disk was full, or you
made a typo when entering the MLX program. (Sorry, MLX can't
check itself!)
Command Control
What if you don't want to enter the whole program in one sitting?
MLX lets you enter as much as you want, save the completed por
tion, and then reload your work from tape or disk when you
want to continue. MLX recognizes these few commands:
SHIFT-S: Save
SHIFT-L: Load
SHIFT-N: New Address
SHIFT-D: Display
Hold down SHIFT while you press the appropriate key. You
will jump out of the line you've been typing, so I recommend you
do it at a new prompt. Use the Save command to store what
you've been working on. It will write the tape or disk file as if
you've finished. Remember what address you stop on. The next
time you RUN MLX, answer all the prompts as you did before,
then insert the disk or tape containing the stored file. When you
get to the entry prompt (49152: for Micromon-64), press SHIFT-L
to reload the file into memory. You'll then use the New Address
command (SHIFT-N) to resume typing.
249
A Appendix
Tricky Stuff
The special commands may seem a little confusing, but as you
work with MLX, they will become valuable. For example, what if
you forgot where you stopped typing? Use the Display command
to scan memory from the beginning to the end of the program.
When you see a bunch of 170's, stop the listing (press a key) and
continue typing where the 170's start. Some programs contain
many sections of 170's. To avoid typing them, you can use the
New Address command to skip over the blocks of 170's. Be care
ful, though; you don't want to skip over anything you should type.
You can use the Save and Load commands to make copies of
the completed machine language program. Use Load command
to reload the tape or disk, then insert a new tape or disk and use
the Save command to create a new copy.
One quirk about tapes made with the MLX Save command:
when you load them, the message "FOUND program" may ap
pear twice. The tape will load just fine, however.
Programmers will find MLX to be an interesting program
which protects the user from most typing mistakes. Some screen
formatting techniques are also used. Most interesting is the use of
ROM Kernal routines for LOADing and SAVEing blocks of mem
ory. To use these routines, just POKE in the starting address (low
byte/high byte) into memory locations 251 and 252 and POKE the
ending address into locations 254 and 255. Any error code for the
SiWE or LOAD can be found in location 253 (an error would be a
code less than ten).
I hope you will find MLX to be a true labor-saving program.
Since it has been tested by entering actual programs, you can
count on it as an aid for generating bug-free machine language.
Be sure to save MLX; it will be used for future applications in
COMPUTE! Magazine, COMPUTED Gazette and COMPUTE!
Books.
250
Appendix
A
170 POKEV+29,3
180 FORI=0TO23:READA:POKE679+I,A:POKEV+39
,A:POKEV+40,A:NEXT
185 DATA169,251,166,254,164,255,32,216,25
5,133,253,96
187 DATA169,0,166,251,164,252,32,213,255,
133,253,96
190 POKEV+39,7:POKEV+40,7
200 PRINT"{2 DOWN}{PUR}{BLK}{3 SPACES}A F
AILSAFE MACHINE LANGUAGE EDITOR
{5 DOWN}"
210 PRINT"g53{2 UPjSTARTING ADDRESS?
{8 SPACES}{9 LEFT}";:INPUTS:F=1-F:C$=
CHR$(31+119*F)
220 IFS<256OR(S>40960ANDS<49152)ORS>53247
THENGOSUB3000:GOTO210
225 PRINT:PRINT:PRINT
230 PRINT"g53{2 UP}ENDING ADDRESS?
{8 SPACES}{9 LEFT}";:INPUTE:F=1-F:C$=
CHR$(31+119*F)
240 IFE<256OR(E>40960ANDE<49152)ORE>53247
THENGOSUB3000:GOTO230
410 IFN=-206THENPRINT:INPUT"{DOWN}ENTER N
EW ADDRESS";ZZ
415 IFN=-206THENIFZZ<SORZZ>ETHENPRINT"
{RVSjOUT OF RANGE":GOSUB1000:GOTO410
417 IFN=-206THENAD=ZZ:PRINT:GOTO310
420 IF NO-196 THEN 480
430 PRINT:INPUT"DISPLAY:FROM";F:PRINT,"TO
";:INPUTT
251
A Appendix
252
Appendix
253
Appendix B
A Beginners
Guide to Typing
in Programs
Appendix
B
A Beginner's
Guide to Typing
in Programs
what is a Program?
A computer cannot perform any task by itself. Like a car without
gas, a computer has potential, but without a program, it isn't going
anywhere. Most of the programs in this book are written in a
computer language called BASIC. BASIC is easy to learn and is
built into all Commodore 64s.
BASIC Programs
Computers can be picky. Unlike the English language, which is
full of ambiguities, BASIC usually has only one right way of
stating something. Every letter, character, or number is signifi
cant. A common mistake is substituting a letter such as O for the
numeral 0, a lowercase 1 for the numeral 1, or an uppercase B for
the numeral 8. Also, you must enter all punctuation such as
colons and commas just as they appear in the magazine. Spacing
can be important. To be safe, type in the listings exactly as they
appear.
257
Appendix
A Quick Review
1) Type in the program a line at a time, in order. Press RETURN at
the end of each line. Use backspace or the back arrow to correct
mistakes.
2) Check the line you've typed against the line in the printed listing
You can check the entire program again if you get an error when
you RUN the program.
3) Make sure you've entered statements in brackets as the appro
priate control key (see "How To Type Programs" elsewhere in
the book).
258
AppendxC
How TO Type
m Programs
Appendix c
how TO Type
in Programs
Many of the programs which are listed in this book contain spe
cial control characters (cursor control, color keys, inverse video,
etc.). To make it easy to know exactly what to type when entering
one of these programs into your computer, we have established
the following listing conventions.
Generally, any Commodore 64 program listings will contain
words within braces which spell out any special characters:
{DOWN } would mean to press the cursor down key. {5 SPACES }
would mean to press the space bar five times.
To indicate that a key should be shifted (hold down the SHIFT
key while pressing the other key), the key would be underlined in
our listings. For example, S would mean to type the S key while
holding the shift key. This would appear on your screen as a
"heart" symbol. If you find an underlined key enclosed in braces
(e.g., {10 N}), you should type the key as many times as indicated
(in our example, you would enter ten shifted N's).
If a key is enclosed in special brackets, [< >], you should hold
down the Commodore key while pressing the key inside the special
brackets. (The Commodore key is the key in the lower-left corner
of the keyboard.) Again, if the key is preceded by a number, you
should press the key as many times as necessary.
Rarely, you'll see a solitary letter of the alphabet enclosed in
braces. These characters can be entered on the Commodore 64 by
holding down the CTRL key while typing the letter in braces. For
example, {A} would indicate that you should press CTRL-A.
About the quote mode: you know that you can move the cursor
around the screen with the CRSR keys. Sometimes a programmer
will want to move the cursor under program control. That's why
you see all the {LEFT }'s, {HOME }'s, and {BLU }'s in our pro
grams. The only way the computer can tell the difference be
tween direct and programmed cursor control is the quote mode.
Once you press the quote (the double quote, SHIFT-2), you
are in the quote mode. If you type something and then try to
change it by moving the cursor left, you'll only get a bunch of
261
c Appendix
reverse-video lines. These are the symbols for cursor left. The
only editing key that isn't programmable is the DEL key; you can
still use DEL to back up and edit the line. Once you type another
quote, you are out of quote mode.
You also go into quote mode when you INSerT spaces into a
line. In any case, the easiest way to get out of quote mode is to just
press RETURN. You'll then be out of quote mode, and you can
cursor up to the mistyped line and fix it.
Use the following table when entering cursor and color con
trol keys:
Listing Conventions
When You When You
Read: Press: See: Read: Press: See:
{CLEAR} CLR/HOME QP {grn} CTRL 6
{DOWN}
{LEFT}
{RIGHT} {F3}
{RVS} {F4}
{OFF} {F5}
{BLK} {F6}
{WHT} {F7}
{RED} {F8}
4
{PUR} r
262
index
addresses 183-90 files 61,63
ADSR envelope 8-9,13,20-21,22,161 menu 126-34
animation 7 editing 210
arrays 63-64 exclusive-OR39
ASCII 19,146,213 expander slot 143
assembler 197-209 extended background color mode 6,72
attack (see ADSR envelope) fine scrolling (see scrolling)
BASIC 4,180-81,210-16 fire button (see joystick button)
ABS32 flag 26,29
GET 122 game ports (see joystick port)
GOSUB21,24 graphics 4-7,69-104
GOTO 28 high-resolution 6,71-72,89-90
IF... THEN 26 hexadecimal 211-12
LIST 45 jiffy (see also TI$ and timer) 40
ON 30-31 joystick 42,49-53,107-14
REM 44-48 button 108
STR$24 memory locations 49-52,108-10
TAB 23 port 107,143
tokens 212-13 reading 109-10
WATT 39-43 initialization 20-21
BASIC Assembler 197-209 Input/Output Port 3
BASIC Interpreter ROM 3 interrupts 78,97-98,100-3,179
BASIC statement 210-11 IRQ 102
binary numbers 147-48 Kernal3,180
bit 171,211 keyboard code 19
bitmap graphics 6 keyboard control function 213
bitwise AND 27-28 kilobyte 172
byte 172,211 LED 150-51
CATALOG 121 light pen 77-78
Central Processing Unit (CPU) 144 LISTing a program, prevention of 44-48
chained menus 16-17 locations 183-90
character base 76,80,179 logical AND 108
character graphics 5-6 logical NOT 109
character sets (see also redefined memory 171-77,211-13
characters) 5 bit 171,211
chips, Commodore 643 byte 172,211
collision 7,94,95 kilobyte 172
Commodore 64 architecture 70,86,178-82 map 183-90
Commodore 64, similarities with PET 4, nybble 171-72
88-89 organization 171-72,211
Complex Interface Adapter (CIA) 9-10,107, pages 172
144,178,189,190 stack 174
control register 147 memory map 183-90
decay (see ADSR envelope) menus (see also diskette menu) 15-17,54-60
delay loop 26-27 Micromon-64 217-44
DIRECTORY 121 microprocessors
diskette monitor 217-44
backup 137-42 Movable Object Blocks (MOBs) (see sprite)
directory 122-25 multicolor character mode 5-6,75-76
DOS 135-36 music 161-65
263
nested menus 16 sound addresses (see also Sound Interface
Non-Maskable Interrupt (NMI) 220 Device) 13
nybble 171-72 Sound Interface Device (SID) 3,8-9,144,
page flipping 7 161,178,188
pages of memory 172 split screens 96-104
Peripheral Data Register 107-8 sprites 6-7,78,80-85,91-95,107-14
program writing 11-35 memory locations 80,82
feedback 18 movement 83-84,110-12,113-14
initialization 18-19, 20-21 stack 174
main loop 25-28 string variables 61-62
menus 15-17 structured programming 25
organizing 14-15 sustain (see ADSR envelope)
planning 12 symbolic assembler 197-209
user friendly 14-15 tape files 61,64-65
quote mode 46-47 TI$ (see also jiffies and timer) 40,100
RAM 4,144,171,178,191 timer (see also jiffies and TI$) 101-2,103,
raster interrupts 7-8,77,78,97,103-4 166-67
Raster Register 96 tokens 212-13
redefined characters 5,88 trigger (see joystick button)
release (see ADSR envelope) User Port 143-56
ROM 144,148,191,228 edge connector 149
ROM Character Generator 70,86,179 input device 149-50
screen editor 210 memory locations 149
screen memory 69,172 output device 146-47
scrolling 5 peripheral device 150
serial plug 143 programming 153
65023 variable 19-20,61-64
65103,178,188,191 Video Interface Controller (VIC) 5,69-104,
65183 107,144,178-79
65263,9-10,189,190 video matrix 69,76
65663,5,69-104,178,188 video port 143
sound 6-7,12-13,162 waveform (see sound)
264
If you've enjoyed the articles in this book you'll find the
same style and quality in every monthly issue of COMPUTE!
Magazine. Use this form to order your subscription to
COMPUTE!.
COMPUTE!
P.O. Box 5406
Greensboro, NC 27403
My Computer Is:
Commodore 64 □"TI-99/4A □ Timex/Sinclair DVIC-20 DPET
Radio Shack Color Computer □ Apple □ Atari □ Other
E Don't yet have one...
□ $24 One Year US Subscription
□ $45 Two Year US Subscription
□ $65 Three Year US Subscription
Subscription rates outside the US:
$30 Canada
$42 Europe, Australia New Zealand/Air Delivery
$52 Middle East North Africa Central America/Air Mail
$72 Elsewhere/Air Mail
$30 International Surface Mail (lengthy, unreliable delivery)
Name
Address
Country
Payment must be in US Funds drawn on a US Bank International Money
Order, or charge card.
n Payment Enclosed □ VISA
□ MasterCard □ American Express
Ace t. No. Expires /
20-5
COMPUTE! Books
P.O. Box 5406 Greensboro, NC 27403
Name
Address
Country
Allow 4-5 weeks for delivery.
20-5
i _
COMPUTE!*
First Book of Commodore 64
COMPUTE'.'s First Book of the Commodore 64 includes some of the
best articles and programs from COMPUTE! Magazine and
COMPUTE'.'s Gazette, plus many more that have never before ap
peared in print.
There are dozens of complete, ready to type in programs.
And, because you will see and type in every program line, you
will discover many techniques to use in your own programming.
• An explanation of 64 architecture
• How to create programs which use joysticks
• A memory map