Commodore 128 Programmers Reference PDF
Commodore 128 Programmers Reference PDF
PROGRAMMER'S
REFERENCE GUIDE
Bantam Computer Books
Ask your bookseller for the books you have missed
THE AMIGADOS MANUAL HOW TO GET THE MOST OUT OF
by Commodore-Amiga, Inc. COMPUSERVE, 2d ed.
by Charles Bowen and David Peyton
THE APPLE //c BOOK
by Bill O'Brien HOW TO GET THE MOST OUT OF THE
SOURCE
THE ART OF DESKTOP
by Charles Bowen and David Peyton
PUBLISHING
By Tony Bove, Cheryl Rhodes, THE MACINTOSH
and Wes Thomas by Bill O'Brien
ARTIFICIAL INTELLIGENCE MACINTOSH C PRIMER PLUS
ENTERS THE MARKETPLACE by The Waite Group/Stephen W. Prata
by Larry R. Harris and
THE NEW jr. A GUIDE TO IBM'S PCjr
Dwight B. Davis
by Winn L. Rosch
THE BIG TIP BOOK FOR
ORCHESTRATING SYMPHONY
THE APPLE II SERIES
by The Waite Group/Dan Shafer with
by Bert Kersey and
Mary Johnson
Bill Sanders
PC-DOS/MS-DOS
THE COMMODORE 64 SURVIVAL
User's Guide to the Most Popular Operating
MANUAL
System for Personal Computers
by Winn L. Rosch
by Alan M. Boyd
COMMODORE 128 PROGRAMMER'S
POWER PAINTING: COMPUTER GRAPHICS
REFERENCE GUIDE
ON THE MACINTOSH
by Commodore Business Machines, Inc.
by Verne Bauman and Ronald Kidd/
THE COMPUTER AND THE BRAIN illustrated by Gasper Vaccaro
by Scott Ladd/
SMARTER TELECOMMUNICATIONS
The Red Feather Press
Hands-On Guide to On-Line Computer Services
EXPLORING ARTIFICIAL INTELLIGENCE by Charles Bowen and Stewart Schneider
ON YOUR APPLE II
SWING WITH JAZZ: LOTUS JAZZ ON THE
by Tim Hartnell
MACINTOSH
EXPLORING ARTIFICIAL INTELLIGENCE by Datatech Publications Corp./S. Michael McCarty
ON YOUR COMMODORE 64
UNDERSTANDING EXPERT SYSTEMS
by Tim Hartnell
by The Waite Group/Mike Van Horn
EXPLORING ARTIFICIAL INTELLIGENCE
USER'S GUIDE TO THE AT&T PC 6300
ON YOUR IBM PC
PERSONAL COMPUTER
by Tim Hartnell
by David B. Peatroy, Ricardo A. Anzaldua,
EXPLORING THE UNIX ENVIRONMENT H. A. Wohlwend, and Datatech Publications
by The Waite Group/Irene Pasternack Corp.
FRAMEWORK FROM THE GROUND UP
by The Waite Group/Cynthia Spoor and
Robert Warren
COMMODORE 128
PROGRAMMER'S
REFERENCE GUIDE
BANTAM BOOKS
COMMODORE 128 PROGRAMMER'S REFERENCE GUIDE
A Bantam Book / February 1986
Bantam Books are published by Bantam Books, Inc. Its trademark, consisting of
the words "Bantam Books" and the portrayal of a rooster, is Registered in U.S.
Patent and Trademark Office and in other countries. Marca Registrada. Bantam
Books, Inc., 666 Fifth Avenue, New York, New York 10103.
HL 0 9 8 7 6 5 4 3
CONTENTS
Chapter 1
Introduction 1
Chapter 2
BASIC Building Blocks and BASIC 7.0 Encyclopedia 11
Chapter 3
One Step Beyond Simple BASIC 91
Chapter 4
Commodore 128 Graphics Programming 109
Chapter 5
Machine Language on the Commodore 128 123
Chapter 6
How to Enter Machine Language Programs Into the
Commodore 128 181
Chapter 7
Mixing Machine Language and BASIC 197
Chapter 8
The Power Behind Commodore 128 Graphics 207
Chapter 9
Sprites 265
Chapter 10
Programming the 80-Column (8563) Chip 291
Chapter 11
Sound and Music on the Commodore 128 335
Chapter 12
Chapter 13
The Commodore 128 Operating System 401
Chapter 14
CP/M 3.0 on the Commodore 128 477
Chapter 15
The Commodore 128 and Commodore 64 Memory Maps 501
Chapter 16
Appendixes 643
Glossary 731
Index 739
ACKNOWLEDGMENTS
The authors are deeply indebted to the many people who have contributed to the
preparation of this book. Special thanks go to Jim Gracely of Commodore Publications,
who reviewed the entire manuscript for technical accuracy and provided important
corrections, clarifications, and user-oriented suggestions, and to Steve Beats and Dave
Middleton of Commodore Software Engineering for their programming assistance and
expertise.
For their extensive technical reviews of the manuscript, we wish to thank Bob Albright,
Pete Bowman, Steve Lam and Tony Porrazza of Commodore Engineering. We also
thank Dan Baker, Dave Street and Carolyn Scheppner of Commodore Software Techni-
cal Support for providing an always available source of technical assistance. In addition,
we want to acknowledge the valuable contributions of members of Commodore Soft-
ware Quality Assurance, especially Mike Colligon, Karen Mackenzie, Pat McAllister,
Greg Rapp, Dave Resavy, and Stacy English.
We also thank Carol Sullivan and Donald Bein for carefully proofreading various
sections of the text, Michelle Dreisbach for typing the manuscript, Marion Dooley for
preparing the art, Jo-Ellen Temple for the cover design, and Nancy Zwack for overall
coordination assistance.
Finally, we would like to acknowledge the unflagging support and guidance provided by
senior Commodore executives Paul Goheen, Harry McCabe and Bob Kenney.
I
INTRODUCTION
The Commodore 128 Personal Computer is a versatile, multimode computer. The
Commodore 128 is the successor to the commercially successful Commodore 64 com-
puter. The principal features of the Commodore 128 are:
As this Guide shows, the Commodore 128 has many other new or expanded
capabilities and features. Those listed above, however, are the most significant when
assessing the Commodore 128's capabilities against those of the Commodore 64 and
other microcomputers.
The Commodore 128 is actually three computers in one, with the following three
primary operating modes:
• C128 Mode
• C64 Mode
• CP/M Mode
Two of these primary modes (C128 and CP/M) can operate using either a 40- or
80-column screen display. Following is a summary of the major features of each of the
three primary operating modes.
C128 MODE
In C128 Mode, the Commodore 128 Personal Computer provides the capabilities and
memory needed to run sophisticated applications, such as word processing, spreadsheets,
and database programs.
C128 Mode features include:
NOTE: The 40- and 80-column screen displays can be used either singly
or simultaneously with two monitors.
C64 MODE
In C64 Mode, the Commodore 128 retains all the capabilities of the Commodore 64,
thus allowing you to use the wide range of available Commodore 64 software.
C64 Mode features include:
NOTE: The 1571 disk drive will function in C64 Mode, but only
at standard 1541 speed. C64 compatibility requirements make it impossi-
ble for the 1571 to operate in C64 Mode at fast speed.
CP/M MODE
In CP/M Mode, an onboard Z80 microprocessor gives you access to the capabilities of
Digital Research's CP/M Version 3.0, plus a number of new capabilities added by Commodore.
CP/M Mode features include:
The incorporation of CP/M 3.0 (also called CP/M Plus) into the Commodore 128
makes thousands of popular commercial and public domain software programs available
to the user.
HARDWARE COMPONENTS
The Commodore 128 Personal Computer incorporates the following major hardware
components:
PROCESSORS
8502: Main processor in C128, C64 Modes; I/O support for CP/M; 6502 software-
compatible; runs at 1.02 or 2.04 MHz
Z80: CP/M Mode only; runs at 2.04 MHz
MEMORY
ROM: 64K standard (C64 Kernal plus BASIC; C128 Kernal plus BASIC, character
ROMs and CP/M BIOS); one 32K slot available for software
RAM: 128K in two 64K banks; 16K display RAM for 8563 video chip; 2K x 4 Color RAM
VIDEO
8564: 40-column video (separate versions for NTSC and PAL TV standards)
8563: 80-column video
INTRODUCTION
SOUND
6581: SID Chip
INPUT/OUTPUT
6526: Joystick ports/keyboard scan/cassette
6526: User and serial ports
MEMORY MANAGEMENT
8921: PLA (C64 plus C128 mapping modes)
8922: MMU (Custom gate array)
For details on these and other hardware components see Chapter 16, Commodore
128 Hardware Specifications.
COMPATIBILITY WITH
COMMODORE 64
The Commodore 128 system is designed as an upgrade to the Commodore 64. Accord-
ingly, one of the major features of the Commodore 128 design is hardware and software
compatibility with the Commodore 64 when operating in C64 Mode. This means that in
C64 Mode the Commodore 128 is capable of running Commodore 64 application
software. Also, the Commodore 128 in C64 Mode supports Commodore 64 peripherals
except the CP/M 2.2 cartridge. (NOTE: The Commodore 128's built-in CP/M 3.0
capability supersedes that provided by the external cartridge. This cartridge should not
be used with the Commodore 128 in any mode.)
The C128 Mode is designed as a compatible superset to the C64. Specifically, all
Kernal functions provided by the Commodore 64 are provided in the C128 Kernal.
These functions are also provided at the same locations in the jump table of the C128
Kernal to provide compatibility with existing programs. Zero page and other system
variables are maintained at the same addresses they occupy in C64 Mode. This simpli-
fies interfacing for many programs.
Providing Commodore 64 compatibility means that the new features of the Com-
modore 128 cannot be accessed in C64 Mode. For example, compatibility and memory
constraints preclude modifying the C64 Mode Kernal to support the 1571 fast serial disk
drive. As noted previously, C64 Mode sees this drive as a standard serial disk drive. For
the same reason, C64 Mode does not have an 80-column screen editor, and C64 Mode
BASIC 2.0 cannot use the second 64K bank of memory.
SWITCHING FROM MODE TO MODE
As mentioned before, in the C128 and CP/M Modes the Commodore 128 can provide
both 40-column and 80-column screen displays. This means that the Commodore 128
actually has five operating modes, as follows:
Figure 1-1 summarizes the methods used to switch from mode to mode.
FROM
TO
OFF C128 C128 C64 CP/M CP/M
40 COL 80 COL 40 COL 80 COL
CI28 1. Check that 1. Press ESC 1. Check that 1. Check that 1. Check that
40 COL 40/80 key key; 40/80 key 40/80 key 40/80 key
is UP. release. is UP. is UP. is UP.
2. Make sure 2. Press X 2. Turn com- 2. Turn com- 2. Turn com-
that: key. puter OFF, puter OFF, puter OFF,
a)No CP/M OR then ON. then ON. then ON.
system 1. Check that 3. Remove
disk is 40/80 key cartridge
in drive is UP. if present
b)No C64 2. Press
cartridge RESET
is in ex- button.
pansion
port
3. Turn com-
puter ON.
CI28 1. Press 1. Press 1. Press 1. Press 1. Check that
80 COL 40/80 key ESC key; 40/80 key 40/80 key 40/80 key
DOWN. release. DOWN. DOWN. is DOWN.
2. Turn com- 2. Press X 2. Turn com- 2. Remove 2. Remove
puter ON. key. puter OFF, CP/M sys- CP/M sys-
OR then ON. tem disk tem disk
1. Press 3. Remove from from
40/80 key cartridge drive, if drive, if
DOWN. if present. necessary. necessary.
2. Press 3. Turn com- 3. Turn com-
RESET puter OFF, puter OFF,
button. then ON. then ON.
Figure 1-1. Commodore 128 Mode Switching Chart
INTRODUCTION
FROM
TO
OFF C128 C128 C64 CP/M CP/M
40 COL 80 COL 40 COL 80 COL
which the contents vary or change throughout the course of a program. The last way to store
information is to use an array, a series of related memory locations consisting of variables.
Each of these three units of memory storage can have three different types of
information or data assigned. The three data types are INTEGER, FLOATING-POINT
or STRING. Integer data is numeric, whole number data—that is, numbers without
decimal points. Floating-point is numeric data including fractional parts indicated with a
decimal point. String data is a sequential series of alphanumeric letters, numbers and
symbols referred to as character strings. The following paragraphs describe these three
data types and the way each memory storage unit is assigned different data type values.
CONSTANTS: INTEGER,
FLOATING-POINT AND STRING
INTEGER CONSTANTS
The value assigned to a constant remains unchanged or constant throughout a program.
Integer constants can contain a positive or negative value ranging from -32768 through
+ 32767. If the plus sign is omitted, the C128 assumes that the integer is positive.
Integer constants do not contain commas or decimal points between digits. Leading
zeros are ignored. Integers are stored in memory as two-byte binary numbers, which
means a constant requires 16 bits or two bytes of memory to store the integer as a base
two number. The following are examples of integer constants:
I
1000
-32
0
-32767
FLOATING-POINT CONSTANTS
Floating-point constants contain fractional parts that are indicated by a decimal
point. They do not contain commas to separate digits. Floating-point constants may be
positive or negative. If the plus sign is omitted, it is assumed that the number is
positive. Again, leading zeros are unnecessary and ignored. Floating-point constants are
represented in two ways depending on their value:
The mantissa and exponent can be positive or negative. The exponent can be
within the range -39 to +38. If the exponent is negative, the decimal point moves to
the left representing it as a simple number. If the exponent is positive, the decimal
point moves to the right representing it in simple number notation.
The Commodore 128 limits the size of floating-point numbers. The highest
number you can represent in scientific notation is 1.70141183E +38. If you try to
represent a number larger than that, an OVERFLOW ERROR occurs. The smallest
number you can represent in scientific notation is 2.93873588E-39. If you try to
represent a number smaller than that, no error occurs but a zero is returned as the value.
You should therefore test floating-point values in your programs if your calculations are
based on very small numbers and the results depend on future calculations. Here are
examples of floating-point constants in simple number notation and others in scientific
notation:
9.99 22.33E + 20
.0234 99999.234E-23
+10.01 -45.89E-11
-90.23 -3.14E+17
STRING CONSTANTS
A string constant, as mentioned, is a sequential series of alphanumeric characters
(numbers, letters and symbols). A string constant can be as long as a 160-character input
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 15
line, minus the line number and any other information appearing on that program line.
By concatenating strings together, you may form a string as long as 255 characters. The
string may contain numbers, letters, and even decimal points and commas. However,
the string cannot contain the double quote (") character, since this character delimits or
marks the beginning or ending of the string. You can represent a double quote character
within a string using CHR$(34). You can omit the closing double quote character of a
string if it is the last statement in a line of a program.
A string can even be assigned a null value, meaning no characters are actually
assigned to it. Assign a string a null value by omitting characters between the double
quotes and follow the opening double quote directly with a closing double quote. Here
are some examples of string constants:
"Commodore 128"
"qwerl234!#$%()*.:,"
" " (null string)
"John and Joan"
VARIABLES: INTEGER,
FLOATING-POINT AND STRING
Variables are units of memory storage that represent varying data values within a
program. Unlike constants, variables may change in value throughout the course of a
program. The value assigned to a variable can be an integer, a floating-point number, or
a string. You can assign a value to a variable as the result of a mathematical calculation.
Variables are assigned values using an equals sign. The variable name appears to the left
of the equals sign and the constant or calculation appears to the right. When you refer to
a variable in a program before you assign it a value, the variable value becomes zero if
it is an integer or floating-point number. It becomes a null string if the variable is a
string.
Variable names can be any length, but for efficiency you should limit the size
of the variable to a few characters. Only the first two characters of a variable name
are significant. Therefore, do not begin the names of two different variables with
the same two characters. If you do, the C128 will interpret them as the same variable
name.
The first character of a variable name must be a letter. The rest of the
variable name can be any letter or number from zero to nine. A variable name
must not contain any BASIC keyword. If you include a BASIC keyword in
a variable name, a SYNTAX ERROR occurs. BASIC keywords include all
BASIC statements, commands, function names, logical operator names and reserved
variables.
You can specify the data type of a variable by following the variable name with
a percent sign (%) if the variable is an integer value, or a dollar sign if the
variable is a string. If no character is specified, the C128 assumes that the variable
value is a floating-point number. Here are some examples of variables and how they are
assigned:
A = 3.679 (floating-point)
Z% = 714 (integer)
F$ = "CELEBRATE THE COMMODORE 128" (string)
T = A + Z% (floating-point)
Count % = Count % + 1 (integer)
G$ = "SEEK A HIGHER LEVEL OF CONSCIOUSNESS" (string)
H$ = F$ + G$ (string)
ARRAYS: INTEGER,
FLOATING-POINT AND STRING
Although arrays were defined earlier in this chapter as series of related variables or
constants, you refer to them with a single integer, floating point or string variable name.
All elements have the same data type as the array name. To access successive elements
within the array, BASIC uses subscripts (indexed variables) to refer to each unique storage
compartment in the array. For example, the alphabet has twenty-six letters. Assume an
array called "ALPHA" is constructed and includes all the letters of the alphabet. To
access the first element of the array, which is also the first letter of the alphabet (A),
label Alpha with a subscript of zero:
ALPHA$(0) A
To access the letter B, label Alpha with a subscript of one:
ALPHA$(1) B
Continue in the same manner to access all of the elements of the array ALPHA, as in
the following:
ALPHA$(2) C
ALPHA$(3) D
ALPHA$(4) E
ALPHA$(5) Z
10 DIM A(99)
dimensions a one-dimensional floating-point array with 100 elements. The following are
examples of two-, three- and four-dimensional integer arrays:
20 DIM B(9, 9) (100 elements)
30 DIM C(20,20,20) (9261 elements)
40 DIM D(10,15,15,10) (30976 elements)
In theory the maximum number of dimensions in an array is 255, but you cannot
fit a DIMension statement that long on a 160-character line. The maximum number of
DIMension statements you can fit on a 160-character line is approximately fifty. The
maximum number of elements allowed in each dimension is 32767. In practice, the size
of an array is limited to the amount of available memory. Most arrays are one-, two- or
three-dimensional. If an array contains fewer than ten elements, there is no need for a
DIM statement since the C128 automatically dimensions variable names to ten elements.
The first time you refer to the name of the undimensioned array (variable) name, the
C128 assigns zero to the value if it is a numeric array, or a null string if it is a string
array.
You must separate the subscript for each dimension in your DIMension statement
with a comma. Subscripts can be integer constants, variables, or the integer result of an
arithmetic operation. Legal subscript values can be between zero and the highest
dimension assigned in the DIMension statement. If the subscript is referred to outside of
this range, a BAD SUBSCRIPT ERROR results.
The type of array determines how much memory is used to store the integer,
floating-point or string data.
Floating-point string arrays take up the most memory; integer arrays require the
least amount of memory. Here's how much memory each type of array requires:
Keep in mind the amount of storage required for each type of array. If you only
need an integer array, specify that the array be the integer type, since floating-point
arrays require much more memory than does the integer type.
ARITHMETIC EXPRESSIONS
Arithmetic expressions yield an integer or floating-point value. The arithmetic operators
( + ,-,*,/,^) are used to perform addition, subtraction, multiplication, division and
exponentiation operations, respectively.
ARITHMETIC OPERATIONS
An arithmetic operator defines an arithmetic operation which is performed on the two
operands on either side of the operator. Arithmetic operations are performed using
floating-point numbers. Integers are converted to floating-point numbers before an
arithmetic operation is performed. The result is converted back to an integer if it is
assigned to an integer variable name.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 19
ADDITION ( + )
The plus sign ( + ) specifies that the operand on the right is added to the operand on the
left.
EXAMPLES:
2+2
A + B+C
X% + 1
BR+10E-2
SUBTRACTION (-)
The minus sign (-) specifies that the operand on the right is subtracted from the operand
on the left.
EXAMPLES:
4-1
100-64
A-B
55-142
The minus also can be used as a unary minus which is the minus sign in front of a
negative number. This is equal to subtracting the number from zero (0).
EXAMPLES:
-5
-9E4
-B
4-(-2) (same as 4 + 2)
MULTIPLICATION (*)
An asterisk (*) specifies that the operand on the left is multiplied by the operand on the
right.
EXAMPLES:
100*2
50*0
A*X1
R%*14
DIVISION (/)
The slash (/) specifies that the operand on the left is divided by the operand on the
right.
EXAMPLES:
10/2
6400/4
A/B
4E2/XR
EXPONENTIATION ( ^ )
The up arrow ( ^ ) specifies that the operand on the left is raised to the power specified
by the operand on the right (the exponent). If the operand on the right is a 2, the number
on the left is squared; if the exponent is a 3, the number on the left is cubed, etc. The
exponent can be any number as long as the result of the operation gives a valid
floating-point number.
EXAMPLES:
2 ^ 2 Equivalent to 2*2
3 ^ 3 Equivalent to 3*3*3
4 ^ 4 Equivalent to 4*4*4*4
AB ^ CD
3 ^ -2 Equivalent to1/3*1/3
RELATIONAL OPERATORS
The relational operators ( < , = , > , < = ,> = , < > ) are primarily used to compare the
values of two operands, but they also produce an arithmetic result. The relational
operators and the logical operators (AND, OR, and NOT), when used in comparisons,
produce an arithmetic true/false evaluation of an expression. If the relationship stated in
the expression is true, the result is assigned an integer value of - 1 . If it's false a value of
0 is assigned. Following are the relational operators:
EXAMPLES:
5-4=1 result true (-1)
14>66 result false (0)
15>=15 result true (-1)
Relational operators may be used to compare strings. For comparison purposes,
the letters of the alphabet have the order A < B < C < D , etc. Strings are compared by
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 21
evaluating the relationship between corresponding characters from left to right (see
string operations).
EXAMPLES:
"A" < "B" result true (-1)
" X " = "YY" result false (0)
BB$ < > CC$ result false (0) if they are the same
Numeric data items can only be compared (or assigned) with other numeric items.
The same is true when comparing strings; otherwise, the BASIC error message ?TYPE
MISMATCH occurs. Numeric operands are compared by first converting the values of
either or both operands from integer to floating-point form, as necessary. Then
the relationship between the floating-point values is evaluated to give a true/false
result.
At the end of all comparisons, you get an integer regardless of the data type
of the operand (even if both are strings). Because of this, a comparison of two
operands can be used as an operand in performing calculations. The result will
be -1 or 0 and can be used as anything but a divisor, since division by zero is
illegal.
LOGICAL OPERATORS
The logical operators (AND, OR, NOT) can be used to modify the meaning of the
relational operators or to produce an arithmetic result. Logical operators can produce
results other than -1 and 0, although any nonzero result is considered true when testing
for a true/false condition.
The logical operators (sometimes called Boolean operators) also can be used to
perform logical operations on individual binary digits (bits) in two operands. But when
you're using the NOT operator, the operation is performed only on the single operand to
the right. The operands must be in the integer range of values (-32768 to +32767)
(floating-point numbers are converted to integers) and logical operations give an integer
result.
Logical operations are performed bit-by-corresponding-bit on the two operands.
The logical AND produces a bit result of 1 only if both operand bits are 1. The logical
OR produces a bit result of 1 if either operand bit is 1. The logical NOT is the opposite
value of each bit as a single operand. In other words, "If it's NOT 1 then it is 0. If it's
NOT 0 then it is 1."
The exclusive OR IF (XOR) doesn't have a logical operator but it is performed as
part of the WAIT statement or as the XOR function. Exclusive-OR means that if the
bits of two operands are set and equal, then the result is 0; otherwise the result is 1.
Logical operations are defined by groups of statements which, when taken to-
gether, constitute a Boolean "truth table" as shown in Table 2-1.
The AND operation results in a 1 only if both bits are 1:
1 AND 1 = 1
0 AND 1 = 0
1 AND 0 = 0
0 AND 0 = 0
The logical operators AND, OR and NOT specify a Boolean arithmetic operation
to be performed on the two operand expressions on either side of the operator. In the
case of NOT, only the operand on the right is considered. Logical operations (or
Boolean arithmetic) aren't performed until all arithmetic and relational operations in an
expression have been evaluated.
EXAMPLES:
IF A = 100 AND B = 100 THEN 10 (if both A and B have a value of 100 then
the result is true)
A = 96 AND 32: PRINT A (A = 32)
IF A = 100 OR B = 100 THEN 20 (if A or B is 100 then the result is true)
A = 64 OR 32: PRINT A (A = 96)
X = NOT 96 (result is -97 (two's complement))
HIERARCHY OF OPERATIONS
All expressions perform the different types of operations according to a fixed hierarchy.
Certain operations have a higher priority and are performed before other operations. The
normal order of operations can be modified by enclosing two or more operands within
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 23
STRING EXPRESSIONS
Expressions are treated as if an implied " < > 0 " follows them. This means that if an
expression is true, the next BASIC statement on the same program line is executed. If
the expression is false, the rest of the line is ignored and the next line in the program is
executed.
Just as with numbers, you can perform operations on string variables. The only
arithmetic string operator recognized by BASIC 7.0 is the plus sign ( + ) which is used
to perform concatenation of strings. When strings are concatenated, the string on the
right of the plus sign is appended to the string on the left, forming a third string. The
result can be printed immediately, used in a comparison, or assigned to a variable name.
If a string data item is compared with (or set equal to) a numeric item, or vice-versa, the
BASIC error message ?TYPE MISMATCH occurs. Some examples of string expres-
sions and concatenation are:
10 A$="FILE": B$="NAME"
20 NAM$ = A$ + B$ (yields the string "FILENAME")
30 RES$ = "NEW" + A$ + B$ (yields the string "NEWFILENAME")
ORGANIZATION OF THE
BASIC 7.0 ENCYCLOPEDIA
This section of Chapter 2 lists BASIC 7.0 language elements in an encyclopedia
format. It provides an abbreviated list of the rules (syntax) of Commodore 128
BASIC 7.0, along with a concise description of each. Consult the Commodore 128
System Guide BASIC 7.0 Encyclopedia (Chapter 5) included with your computer for a
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 25
more detailed description of each command. BASIC 7.0 includes all the elements of
BASIC 2.0.
The different types of BASIC operations are listed in individual sections, as
follows:
1. Commands and Statements: the commands used to edit, store and erase
programs, and the BASIC program statements used in the numbered lines of a
program.
2. Functions: the string, numeric and print functions.
3. Reserved Words and Symbols: the words and symbols reserved for
use by the BASIC 7.0 language, which cannot be used for any other
purpose.
COMMAND AND
STATEMENT FORMAT
The command and statement definitions in this encyclopedia are arranged in the follow-
ing format:
EXAMPLES:
AUTO 10 Automatically numbers program lines in incre-
Example(s)— ments of 10.
AUTO 50 Automatically numbers lines in increments of 50.
AUTO Turns off automatic line numbering.
The boldface line that defines the format consists of the following elements:
DLOAD "program name" [,D0,U8]
^^
keyword argument additional arguments
(possibly optional)
The parts of the command or statement that must be typed exactly as shown are in
capital letters. Words the user supplies, such as the name of a program, are not
capitalized.
When quote marks (" ") appear (usually around a program name or filename), the
user should include them in the appropriate place, according to the format example.
Keywords are words that are part of the BASIC language. They are the central part of a
command or statement, and they tell the computer what kind of action to take.
These words cannot be used as variable names. A complete list of reserved words
and symbols is given at the end of this chapter.
Keywords, also called reserved words, appear in upper-case letters. Key-
words may be typed using the full word or the approved abbreviation. (A full list
of abbreviations is given in Appendix I). The keyword or abbreviation must be
entered correctly or an error will result. The BASIC and DOS error messages are
defined in Appendices A and B, respectively.
Arguments, also called parameters, appear in lower-case letters. Arguments comple-
ment keywords by providing specific information to the command or statement.
For example, the keyword LOAD tells the computer to load a program while the
argument "program name" tells the computer which specific program to load. A
second argument specifies from which drive to load the program. Arguments
include filenames, variables, line numbers, etc.
Square Brackets [ ] show optional arguments. The user selects any or none of the
arguments listed, depending on requirements.
Angle Brackets < > indicate the user MUST choose one of the arguments listed.
A Vertical Bar | separates items in a list of arguments when the choices are limited to
those arguments listed. When the vertical bar appears in a list enclosed in
SQUARE BRACKETS, the choices are limited to the items in the list, but the
user still has the option not to use any arguments. If a vertical bar appears within
angle brackets, the user MUST choose one of the listed arguments.
Ellipsis . . . (a sequence of three dots) means an option or argument can be repeated more
than once.
Quotation Marks " " enclose character strings, filenames and other expressions.
When arguments are enclosed in quotation marks, the quotation marks must be
included in the command or statement. In this encyclopedia, quotation marks are
not conventions used to describe formats; they are required parts of a command or
statement.
Parentheses () When arguments are enclosed in parentheses, they must be included in
the command or statement. Parentheses are not conventions used to describe
formats; they are required parts of a command or statement.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 27
Variable refers to any valid BASIC variable names, such as X, A$, T%, etc.
Expression refers to any valid BASIC expressions, such as A + B + 2,.5*(X + 3),
etc.
APPEND
Append data to the end of a sequential file
APPEND #logical file number,"filename"[,Ddrive number][<ON|,>Udevice]
EXAMPLES:
Append # 8, "MYFILE" OPEN logical file 8 called "MYFILE", and prepare
to append with subsequent PRINT # statements.
Append #7,(A$),D0,U9 OPEN logical file named by the variable in A$ on
drive 0, device number 9, and prepare to APPEND.
AUTO
Enable/disable automatic line numbering
AUTO [line#]
EXAMPLES:
AUTO 10 Automatically numbers program lines in increments of 10.
AUTO 50 Automatically numbers lines in increments of 50.
AUTO Turns off automatic line numbering.
BACKUP
Copy the entire contents from one disk to another on a dual disk drive
BACKUP source Ddrive number TO destination Ddrive number [<ON|,>
Udevice]
BANK
Select one of the 16 BASIC banks (default memory configurations), numbered 0-15 to
be used during PEEK, POKE, SYS, and WAIT commands.
BANK bank number
BANK CONFIGURATION
0 RAM(O) only
1 RAM(l) only
2 RAM(2) only (same as 0)
3 RAM(3) only (same as 1)
4 Internal ROM , RAM(0), I/O
5 Internal ROM , RAM(1), I/O
6 Internal ROM , RAM(2), I/O (same as 4)
7 Internal ROM , RAM(3), I/O (same as 5)
8 External ROM , RAM(0), I/O
9 External ROM , RAM(l), I/O
10 External ROM , RAM(2), I/O (same as 8)
11 External ROM , RAM(3), I/O (same as 9)
12 Kernal and Internal ROM (LOW), RAM(0), I/O
13 Kernal and External ROM (LOW), RAM(0), I/O
14 Kernal and BASIC ROM, RAM(0), Character ROM
15 Kernal and BASIC ROM, RAM(0), I/O
Banks are described in detail in Chapter 8, The Power Behind Commodore 128
Graphics and Chapter 13, The Commodore 128 Operating System.
BEGIN / BEND
A conditional statement like IF . . . THEN: ELSE, structured so that you can include
several program lines between the start (BEGIN) and end (BEND) of the structure.
Here's the format:
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 29
BLOAD
Load a binary file starting at the specified memory location
BLOAD "filename"[,Ddrive number][<ON|,U>device number] [,Bbank
number] [,Pstart address]
where:
EXAMPLES:
BLOAD "SPRITES", B0, P3584 LOADS the binary file "SPRITES"
starting in location 3584 (in BANK 0).
BLOAD "DATA1", DO, U8, Bl, P4096 LOADS the binary file "DATA 1"
into location 4096 (BANK 1) from
Drive 0, unit 8.
BOOT
Load and execute a program which was saved as a binary file
BOOT "filename"[,Ddrive number][<ON|,>Udevice][,PaIt LOAD ADD]
EXAMPLE:
BOOT BOOT a bootable disk (CP/M Plus for ex-
ample).
BOOT "GRAPHICS 1", DO, U9 LOADS the binary program "GRAPHICS 1"
from unit 9, drive 0, and executes it.
BOX
Draw box at specified position on screen
EXAMPLES:
BOX 1, + 10, + 10 Draw a box 10 pixels to the right and 10 down from
the current pixel cursor location.
Any parameter can be omitted but you must include a comma in its place, as in the last
two examples.
BSAVE
Save a binary file from the specified memory locations
BSAVE "filename"[,Ddrive number][<ON|,U>device number] [,Bbank
number],Pstart address TO Pend address
where:
• start address is the starting address where the program is SAVEd from
EXAMPLES:
BSAVE "SPRITE DATA",B0, Saves the binary file named "SPRITE DATA",
P3584 TO P4096 starting at location 3584 through 4095 (BANK
0).
BSAVE "PROGRAM.SCR",D0, Saves the binary file named "PROGRAM.
U9,B0,P3182 TO P7999 SCR" in the memory address range 3182
through 7999 (BANK 0) on drive 0, unit 9.
CATALOG
Display the disk directory
CATALOG [Ddrive number][<ON|,>Udevice number][,wildcard string]
EXAMPLE:
CATALOG Displays the disk directory on drive 0.
CHAR
Display characters at the specified position on the screen
CHAR [color source],X,Y[,string][,RVS]
This is primarily designed to display characters on a bit mapped screen, but it can also
be used on a text screen. Here's what the parameters mean:
EXAMPLE:
10 COLOR 2,3: REM MULTI-COLOR 1 RED
20 COLOR 3,7: REM MULTI-COLOR 2 BLUE
30 GRAPHIC 3,1
30 CHAR 0,10,10, "TEXT",0
CIRCLE
Draw circles, ellipses, arcs, etc., at specified positions on the screen
CIRCLE [color source],X,Y[,Xr][,Yr] [,sa][,ea][,angle][,inc]
where:
sa
EXAMPLES:
CIRCLE 1. 160,100,65,10 Draws an ellipse.
CIRCLE 1, 160,100,65,50 Draws a circle.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 33
You may omit a parameter, but you must still place a comma in the appropriate
position. Omitted parameters take on the default values.
CLOSE
Close logical file
CLOSE file number
EXAMPLE:
CLOSE 2 Logical file 2 is closed.
CLR
Clear program variables
CLR
CMD
Redirect screen output to a logical disk or print file.
CMD logical file number [,write list]
EXAMPLE:
OPEN 1,4 Opens device 4 (printer).
CMD 1 All normal output now goes to the printer.
LIST The LISTing goes to the printer, not the screen—even the word
READY.
PRINT#1 Sends output back to the screen.
CLOSE 1 Closes the file.
COLLECT
Free inaccessible disk space
COLLECT [Ddrive number][<ON|,>Udevice]
EXAMPLE:
COLLECT DO Free all available space which has been incorrectly allocated to
improperly closed files. Such files are indicated with an asterisk
on the disk directory.
COLLISION
Define handling for sprite collision interrupt
COLLISION type [statement]
type Type of interrupt, as follows:
1 = Sprite-to-sprite collision
2 = Sprite-to-display data collision
3 = Light pen (VIC screen only)
statement BASIC line number of a subroutine
EXAMPLE:
Collision 1, 5000 Enables a sprite-to-sprite collision and program control sent to
subroutine at line 5000.
Collision 1 Stops interrupt action which was initiated in above example.
Collision 2, 1000 Enables a sprite-to-data collision and program control directed
to subroutine in line 1000.
COLOR
Define colors for each screen area
COLOR source number, color number
AREA SOURCE
1 Black 9 Orange
2 White 10 Brown
3 Red 11 Light Red
4 Cyan 12 Dark Gray
5 Purple 13 Medium Gray
6 Green 14 Light Green
7 Blue 15 Light Blue
Yellow 16 Light Gray
Color Numbers in 40-Column Output
EXAMPLES:
COLOR 0,1: Changes background color of 40-column screen to black.
COLOR 5,8: Changes character color to yellow.
CONCAT
Concatenate two data files
CONCAT "file 2" [,Ddrive number] TO "file 1"
t,Ddrive number][<ON|,>Udevice]
EXAMPLE:
Concat "File B " to "File A" FILE B is attached to FILE A, and the combined
file is designated FILE A.
Concat (A$) to (B$), Dl, U9 The file named by B$ becomes a new file with
the same name with the file named by A$ at-
tached to the end of B$. This is performed on
Unit 9, drive 1 (a dual disk drive).
Whenever a variable is used as a filename, as in the last example, the filename variable
must be within parentheses.
CONT
Continue program execution
CONT
COPY
Copy a file from one drive to another within a dual disk drive. Copy one file to
another with a different name within a single drive
COPY [Ddrive number,]"source fiIename"TO[Ddrive number,]"destination
filename"[<ON|,>Udevice]
NOTE: Copying between two single or double disk drive units cannot be
done. This command does not support unit-to-unit copying.
EXAMPLES:
COPY DO, "TEST" TO Dl, "TEST PROG" Copies "test" from drive 0 to drive
1, renaming it "test prog" on drive 1.
COPY DO, "STUFF" TO Dl, "STUFF" Copies "STUFF" from drive 0 to
drive 1.
COPY DO TO Dl Copies all files from drive 0 to drive
1.
COPY "WORK.PROG" TO "BACKUP" Copies "WORK.PROG" as a file
called "BACKUP" on the same disk
(drive 0).
DATA
Define data to be used by a program
DATA list of constants
EXAMPLE:
DATA 100, 200, FRED, "HELLO, MOM",, 3, 14, ABC123
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 37
DCLEAR
Clear all open channels on disk drive
DCLEAR [Ddrive number][<ON|,>Udevice]
EXAMPLES:
DCLEAR DO Clears all open files on drive 0, device number 8.
DCLEAR D1,U9 Clears all open files (channels) on drive 1, device number 9.
DCLOSE
Close disk file
DCLOSE [#logical file number][<ON|,>Udevice]
EXAMPLES:
DCLOSE Closes all channels currently open on unit 8.
DCLOSE #2 Closes the channel associated with the logical file number 2 on
unit 8.
DCLOSE ON U9 Closes all channels currently open on unit 9.
DEF FN
Define a user function
DEF FN name (variable) = expression
EXAMPLE:
l0 DEF FNA(X) = 12*(34.75-X/.3) + X
20 PRINT FNA(7)
The number 7 is inserted each place X is located in the formula given in the DEF
statement. In the example above, the answer returned is 144.
NOTE: If you plan to define a function in a program that will use BASIC
7.0 graphics commands, invoke the GRAPHIC command before defining
your function. The portion of memory where functions are defined and
where the graphics screen is located is shared. Once you allocate your
graphics area, the function definitions are safely placed somewhere else
in memory. If you don't take this precaution and you invoke the GRAPHIC
command after you define a function, the function definition (between
$1C00 and $4000) is destroyed.
DELETE
Delete lines of a BASIC program in the specified range
DELETE [first line] [-last line]
EXAMPLES:
DELETE 75 Deletes line 75.
DELETE 10-50 Deletes lines 10 through 50, inclusive.
DELETE-50 Deletes all lines from the beginning of the program up to and
including line 50.
DELETE 75- Deletes all lines from 75 to the end of the program, inclusive.
DIM
Declare number of elements in an array
DIM variable (subscripts) [,variable(subscripts)] . . .
EXAMPLE:
10 DIM A$(40),B7(15),CC%(4,4,4)
Dimension three arrays where arrays A$, B7 and CC% have 41 elements, 16 elements
and 125 elements respectively.
DIRECTORY
Display the contents of the disk directory on the screen
DIRECTORY [Ddrive number][<ON|,>Udevice][,wildcard]
EXAMPLES:
DIRECTORY Lists all files on the disk in unit 8.
DIRECTORY Dl, U9, "WORK" Lists the file named "WORK," on drive 1 of
unit 9.
DIRECTORY "AB*" Lists all files starting with the letters " A B "
like ABOVE, ABOARD, etc. on unit 8. The
asterisk specifies a wild card, where all files
starting with " A B " are displayed.
DIRECTORY DO, "?.BAK" The ? is a wild card that matches any single
character in that position. For example: FILE
l.BAK, FILE 2.BAK, FILE 3.BAK all match
the string.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 39
NOTE: To print the DIRECTORY of the disk in drive 0, unit 8, use the
following example:
LOAD"$0",8
OPEN4,4:CMD4:L1ST
PRINT#4:CLOSE4
DLOAD
Load a BASIC program from the disk drive, device 8.
DLOAD "filename" [,Ddrive number][<ON|,>Udevice number]
EXAMPLES:
DLOAD "BANKRECS" Searches the disk for the program "BANKRECS"
and LOADS it.
DLOAD (A$) LOADS a program from disk in which the name is
stored in the variable A$. An error message is given if
A$ is null. Remember, when a variable is used as a
filename, it must be enclosed in parentheses.
DOPEN
Open a disk file for a read and/or write operation
DOPEN # logical file number,"filename[,<type>]"[,Lrecord length]
[,Ddrive number][<ON|,>Udevice number][,W]
where type is:
S = Sequential File Type
P = Program File Type
U = User File Type
R = Relative File Type
L = Record Length = the length of records in a relative file only
W = Write Operation (if not specified a read operation occurs)
EXAMPLES:
DOPEN#1, "ADDRESS",W Create the sequential file number 1 (ADDRESS)
for a write operation
DOPEN#2 "RECIPES",D1,U9 Open the sequential file number 2 (RECIPES)
for a read operation on device number 9, drive 1
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 41
DRAW
Draw dots, lines and shapes at specified positions on the screen
DRAW [color source] [,X1, Y1][TO X2, Y2] . . .
where:
EXAMPLES:
DRAW 1, 100, 50 Draw a dot.
DRAW , 10,10 TO 100,60 Draw a line.
DRAW , 10,10 TO 10,60 TO 100,60 TO 10,10 Draw a triangle.
DRAW 1, 120;45 Draw a dot 45° relative and 120 pixels
away from the current pixel cursor
position.
DRAW Draw a dot at the present pixel cursor
position. Use LOCATE to position the
pixel cursor.
You may omit a parameter but you still must include the comma that would have
followed the unspecified parameter. Omitted parameters take on the default values.
DSAVE
Save a BASIC program file to disk
DSAVE "filename" [,Ddrive number][<ON|,>Udevice number]
EXAMPLES:
DSAVE "BANKRECS" Saves the program "BANKRECS" to disk.
DSAVE (A$) Saves the disk program named in the variable A$.
DSAVE "PROG 3",D1,U9 Saves the program "PROG3" to disk on unit num-
ber 9, drive 1.
DVERIFY
Verify the program in memory against the one on disk
DVERIFY "filename"[,Ddrive number][<ON|,>Udevice number]
To verify Binary data, see VERIFY "filename",8,1 format, under VERIFY command
description.
EXAMPLES:
DVERIFY "C128" Verifies program "C128" on drive 0, unit 8.
DVERIFY "SPRITES",D0,U9 Verifies program "SPRITES" on drive 0, de-
vice 9.
END
Define the end of program execution
END
ENVELOPE
Define a musical instrument envelope
ENVELOPE n[,atk] [,dec] [,sus] [,rel][,wf] [,pw]
where:
n Envelope number (0-9)
atk Attack rate (0-15)
dec Decay rate (0-15)
sus Sustain (0-15)
rel Release rate (0-15)
wf Waveform: 0 = triangle
1 = sawtooth
2 = variable pulse (square)
3 = noise
4 = ring modulation
pw Pulse width (0-4095)
See the " T " option in the PLAY command to select an envelope in a PLAY string.
EXAMPLE:
ENVELOPE 1, 10, 5, 10, 0, 2, 2048 This command sets envelope 1 to Attack
= 10, Decay = 5, Sustain = 10, Release
= 0. waveform = variable pulse (2), and
the pulse width = 2048
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 43
FAST
Sets the 8502 microprocessor at a speed of 2MHz.
FAST
This command initiates 2MHz mode, causing the VIC 40-column screen to be turned off.
All operations are speeded up considerably, Graphics may be used, but will not be visible
until a SLOW command is issued. The Commodore 128 powers up in 1MHz mode. The
DMA operations (FETCH, SWAP, STASH) must be performed at 1MHz (slow) speed.
FETCH
Get data from expansion (RAM module) memory
FETCH #bytes, intsa, expsa, expb
where bytes = Number of bytes to get from expansion memory (0-65535) where 0 =
64K (65535 bytes)
intsa = Starting address of host RAM (0-65535)
expb = 64K expansion RAM bank number (0-7) where expb = 0-1 for 128K
and expb = 0-7 for up to 512K.
expsa = Starting address of expansion RAM (0-65535)
The host BANK for the ROM and I/O configuration is selected with the BANK
command. The DMA(VIC) RAM bank is selected by bits 6 and 7 of the RAM
configuration register within the MMU($D506).
FILTER
Define sound (SID chip) filter parameters
FILTER [freq][,lp] [,bp] [,hp] [,res]
where:
freq Filter cut-off frequency (0-2047)
lp Low-pass filter on (1), off (0)
bp Band-pass filter on (1), off (0)
hp High-pass filter on (1), off (0)
res Resonance (0-15)
Unspecified parameters result in no change to the current value.
EXAMPLES:
FILTER 1024,0,1.0,2 Set the cutoff frequency at 1024, select the band pass
filter and a resonance level of 2.
FILTER 2000,1,0,1,10 Set the cutoff frequency at 2000, select both the low
pass and high pass filters (to form a notch reject) and set
the resonance level at 10.
FOR / TO / STEP / NEXT
Define a repetitive program loop structure.
FOR variable = start value TO end value [STEP increment] NEXT variable
The logic of the FOR/NEXT statement is as follows. First, the loop variable is set to the
start value. When the program reaches a program line containing the NEXT statement, it
adds the STEP increment (default = 1) to the value of the loop variable and checks to
see if it is higher than the end value of the loop. If the loop variable is less than or equal
to the end value, the loop is executed again, starting with the statement immediately
following the FOR statement. If the loop variable is greater than the end value, the loop
terminates and the program resumes immediately following the NEXT statement. The
opposite is true if the step size is negative. See also the NEXT statement.
EXAMPLE:
10 FOR L = 1 TO 10
20 PRINT L
30 NEXT L
40 PRINT " I ' M DONE! L = " L
This program prints the numbers from one to 10 followed by the message I'M DONE!
L = 11.
EXAMPLE:
10 FOR L = 1 TO 100
20 FOR A = 5 TO 11 STEP .5
30 NEXT A
40 NEXT L
The FOR . . . NEXT loop in lines 20 and 30 are nested inside the one in line 10 and 40.
Using a STEP increment of .5 is used to illustrate the fact that floating point indices are
valid. The inner rested loop must lie completely within the outer rested loop (lines 10
and 40).
GET
Receive input data from the keyboard, one character at a time, without waiting for a key
to be pressed.
GET variable list
EXAMPLE:
10 DO:GETA$:LOOP UNTIL A$ = " A " This line waits for the A key to be
pressed to continue.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 45
20 GET B, C, D GET numeric variables B,C and D from the keyboard without
waiting for a key to be pressed.
GETKEY
Receive input data from the keyboard, one character at a time and wait for a key to be
pressed.
GETKEY variable list
EXAMPLE:
10 GETKEY A$
This line waits for a key to be pressed. Typing any key continues the program.
10 GETKEY AS,B$,C$
This line waits for three alphanumeric characters to be entered from the keyboard.
GET#
Receive input data from a tape, disk or RS232
GET# logical file number, variable list
EXAMPLE:
10 GET#1,A$ This example receives one character, which is stored in the
variable AS, from logical file number 1. This example assumes
that file 1 was previously opened. See the OPEN statement.
GO64
Switch to C64 mode
GO64
To return to C128 mode, press the reset button, or turn off the computer power and
turn it on again.
GOSUB
Call a subroutine from the specified line number
GOSUB line number
EXAMPLE:
20 GOSUB 800 This example calls the subroutine beginning at line 800 and executes
it. All subroutines must terminate with a RETURN statement.
800 PRINT "THE C128 WAS WORTH THE WAIT!": RETURN
GOTO / GO TO
Transfer program execution to the specified line number
GOTO line number
EXAMPLES:
10 PRINT"COMMODORE" The GOTO in line 20 makes line 10 repeat continu-
20 GOTO 10 ously until RUN/STOP is pressed.
GOTO 100 Starts (RUNs) the program starting at line 100,
without clearing the variable storage area.
GRAPHIC
Select a graphic mode
1) GRAPHIC mode [,clear][,s]
2) GRAPHIC CLR
This statement puts the Commodore 128 in one of the six graphic modes:
MODE DESCRIPTION
EXAMPLES:
GRAPHIC 1,1 Select standard bit map mode and clear the bit map.
GRAPHIC 4,0,10 Select split screen multi-color bit map mode, do not clear the
bit map and start the split screen at line 10.
GRAPHIC 0 Select 40-column text.
GRAPHIC 5 Select 80-column text.
GRAPHIC CLR Clear and deallocate the bit map screen.
GSHAPE
See SSHAPE.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 47
HEADER
Format a diskette
HEADER "diskname" [,1 i.d.] [,Ddrive number]
[<ON|,>Udevice number]
Before a new disk can be used for the first time, it must be formatted with the HEADER
command. The HEADER command can also be used to erase a previously formatted
disk, which can then be reused.
When you enter a HEADER command in direct mode, the prompt ARE YOU
SURE? appears. In program mode, the prompt does not appear.
The HEADER command is analogous to the BASIC 2.0 command;
OPEN l,8,15,"N0:diskname,i.d."
EXAMPLES:
HEADER "MYDISK",I23, DO This headers "MYDISK" using i.d. 23
on drive 0, (default) device number 8.
HEADER "RECS", 145, Dl ON U9 This headers "RECS" using i.d. 45, on
drive 1, device number 9.
HEADER "C128 PROGRAMS", DO This is a quick header on drive 0, device
number 8, assuming the disk in the drive
was already formatted. The old i.d. is
used.
HEADER (A$),I76,D0,U9 This example headers the diskette with
the name specified by the variable A$,
and the i.d. 76 on drive 0, device num-
ber 9.
HELP
Highlight the line where the error occurred
HELP
The HELP command is used after an error has been reported in a program. When HELP
is typed in 40-column format, the line where the error occurs is listed, with the portion
containing the error displayed in reverse field. In 80-column format, the portion of the
line where the error occurs is underlined.
IF / THEN / ELSE
Evaluate a conditional expression and execute portions of a program depending on the
outcome of the expression
IF expression THEN statements [:ELSE else-clause]
THE IF . . . THEN statement evaluates a BASIC expression and takes one of two
possible courses of action depending upon the outcome of the expression. If the
expression is true, the statement(s) following THEN is executed. This can be any
BASIC statement or a line number. If the expression is false, the program resumes with
the program line immediately following the program line containing the IF statement,
unless an ELSE clause is present. The entire IF . . . THEN statement must be contained
within 160 characters. Also see BEGIN/BEND.
The ELSE clause, if present, must be on the same line as the IF . . . THEN
portion of the statement, and separated from the THEN clause by a colon. When an
ELSE clause is present, it is executed only when the expression is false. The expression
being evaluated may be a variable or formula, in which case it is considered true if
nonzero, and false if zero. In most cases, there is an expression involving relational
operators ( = , < , > , < = , > = , < > ) .
EXAMPLE:
50 IF X > 0 THEN PRINT "OK": ELSE END
This line checks the value of X. If X is greater than 0, the statement immediately
following the keyword THEN (PRINT "OK") is executed and the ELSE clause is
ignored. If X is less than or equal to 0, the ELSE clause is executed and the statement
immediately following THEN is ignored.
INPUT
Receive a data string or a number from the keyboard and wait for the user to press
RETURN
EXAMPLE:
INPUT #
Input data from an I/O channel into a string or numeric variable
INPUT# file number, variable list
EXAMPLE:
10 OPEN 2,8,2
20 INPUT#2, A$, C, D$
This statement INPUTs the data stored in variables A$, C and D$ from the disk file
number 2, which was OPENed in line 10.
KEY
Define or list function key assignments
KEY [key number, string]
The maximum length for all the definitions together is 241 characters. (p. 3-41)
EXAMPLE:
KEY 7, "GRAPHIC0" + CHR$(13) + "LIST" + CHR$(13)
This tells the computer to select the (VIC) text screen and list the program whenever the
F7 key is pressed (in direct mode). CHR$(13) is the ASCII character for RETURN and
performs the same action as pressing the RETURN key. Use CHR$(27) for ESCape.
Use CHR$(34) to incorporate the double quote character into a KEY string. The keys
may be redefined in a program. For example:
10 KEY 2,"PRINT DS$" + CHR$(13)
This tells the computer to check and display the disk drive error channel variables
(PRINT DS$) each time the F2 function key is pressed.
10 FOR I=1 to 7 STEP 2
20 KEY I, CHR$(I + 132):NEXT
30 FOR I = 2 to 8 STEP 2
40 KEY I, CHR$(I + 132):NEXT
This defines the function keys as they are defined on the Commodore 64.
LET
Assigns a value to a variable
[LET] variable = expression
EXAMPLE:
10 LET A = 5 Assign the value 5 to numeric variable A.
20 B = 6 Assign the value 6 to numeric variable B.
30 C = A * B + 3 Assign the numeric variable C, the value resulting from 5
times 6 plus 3.
40 D$ = "HELLO" Assign the string "HELLO" to string variable D$.
LIST
List the BASIC program currently in memory
LIST [first line] [- last line]
In C128 mode, LIST can be used within a program without terminating program execution.
EXAMPLES:
LIST Shows entire program.
LIST 100- Shows from line 100 until the end of the program.
LIST 10 Shows only line 10.
LIST -100 Shows all lines from the beginning through line 100.
LIST 10-200 Shows lines from 10 to 200, inclusive.
LOAD
Load a program from a peripheral device such as the disk drive or Datassette
LOAD "filename" [,device number] [,relocate flag]
This is the command used to recall a program stored on disk or cassette tape. Here, the
filename is a program name up to 16 characters long, in quotes. The name must be
followed by a comma (outside the quotes) and a number which acts as a device number
to determine where the program is stored (disk or tape). If no number is supplied, the
Commodore 128 assumes device number 1 (the Datassette tape recorder).
EXAMPLES:
LOAD Reads in the next program from tape.
LOAD "HELLO" Searches tape for a program called HELLO, and
LOADs it if found.
LOAD (A$),8 LOADs the program from disk whose name is
stored in the variable AS.
LOAD"HELLO",8 Looks for the program called HELLO on disk drive
number 8, drive 0. (This is equivalent to DLOAD
"HELLO").
LOAD"MACHLANG",8,1 LOADs the machine language program called
"MACHLANG" into the location from which it
was SAVEd.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 51
LOCATE
Position the bit map pixel cursor on the screen
LOCATE X,Y
The LOCATE statement places the pixel cursor (PC) at any specified pixel coordinate on
the screen.
The pixel cursor (PC) is the coordinate on the bit map screen where drawing of
circles, boxes, lines and points and where PAINTing begins.
EXAMPLE:
LOCATE 160,100 Positions the PC in the center of the bit map screen. Noth-
ing will be seen until something is drawn.
LOCATE +20,100 Move the pixel cursor 20 pixels to the right of the last PC
position and place it at Y coordinate 100.
LOCATE - 3 0 , + 20 Move the PC 30 pixels to the right and 20 down from the
previous PC position.
The PC can be found by using the RDOT(0) function to get the X-coordinate and
RDOT(l) to get the Y-coordinate. The color source of the pixel at the PC can be found
by PRINTing RDOT(2).
MONITOR
Enter the Commodore 128 machine language monitor
MONITOR
See Chapter 6 for details on the Commodore 128 Machine Language Monitor.
MOVSPR
Position or move sprite on the screen
1) MOVSPR number,X,Y Place the specified sprite at absolute
sprite coordinate X,Y.
2) MOVSPR number, +/-X, +/-Y Move sprite relative to the position
of the sprite's current position.
3) MOVSPR number,X;Y Move sprite distance X at angle Y
relative to the sprite's current position.
4) MOVSPR number, angle # speed Move sprite at an angle relative to
its current coordinate, in the clock-
wise direction and at the specified
speed.
where:
number is sprite's number (1 through 8)
X,Y is coordinate of the sprite location.
angle is the angle (0-360) of motion in the clockwise direction relative to the
sprite's original coordinate.
speed is a speed (0-15) in which the sprite moves.
EXAMPLES:
MOVSPR 1,150,150 Position sprite 1 near the center of the screen, x,y
coordinate 150,150.
MOVSPR 1,+20,-30 Move sprite 1 to the right 20 coordinates and up 30
coordinates.
MOVSPR 4, -50, + 100 Move sprite 4 to the left 50 coordinates and down 100
coordinates.
MOVSPR 5, 45 #15 Move sprite 5 at a 45 degree angle in the clockwise
direction, relative to its original x and y coordinates.
The sprite moves at the fastest rate (15).
NOTE: Once you specify an angle and a speed as in the fourth example
of the MOVSPR statement, the sprite continues on its path (even if the
sprite display is disabled) after the program stops, until you set the speed
to 0 or press RUN/STOP and RESTORE. Also, keep in mind that the
SCALE command affects the MOVSPR coordinates. If you add SCALing
to your programs, you also must adjust the sprites' new coordinates so
they appear correctly on the screen.
NEW
Clear (erase) BASIC program and variable storage
NEW
BASIC BUILDING BLOCKS AND BASIC 7,0 ENCYCLOPEDIA 53
ON
Conditionally branch to a specified program line number according to the results of the
specified expression
ON expression <GOTO/GOSUB> line # 1 [, line # 2 , . . .]
EXAMPLE:
10 INPUT X:IF X<0 THEN 10
20 ON X GOTO 30, 40, 50, 60 When X = 1, ON sends control to the first line
25 STOP number in the list (30). When X = 2, ON sends
30 PRINT "X = 1" control to the second line (40), etc.
40 PRINT "X = 2 "
50 PRINT "X = 3 "
60 PRINT "X = 4 "
OPEN
Open files for input or output
OPEN logical file number, device number [,secondary address] [<,"filename
[,filetype[, [mode"]]|<,cmd string>]
EXAMPLES:
OPEN the screen as file number
10 OPEN 3,3 3.
OPEN the keyboard as file num-
20 OPEN 1,0 ber 1.
OPEN the cassette for reading, as
30 OPEN 1,1,0,"DOT' file number 1, using "DOT" as
the filename.
OPEN 4,4 OPEN the printer as file number 4.
OPEN 15,8,15 OPEN the command channel on
the disk as file 15, with secondary
address 15. Secondary address 15
is reserved for the disk drive error
channel.
5 OPEN 8,8,12,"TESTFILE,S,W' OPEN a sequential disk file for
writing called TESTFILE as file
number 8, with secondary address
12.
See also: CLOSE, CMD, GET#, INPUT#, and PRINT# statements and system
variables ST, DS, and DS$.
PAINT
Fill area with color
PAINT [color source],X,Y[,mode]
where:
The PAINT command fills an area with color. It fills in the area around the specified
point until a boundary of the same specified color source is encountered. For example, if
you draw a circle in the foreground color source, start PAINTing the circle where the
coordinate assumes the background source. The Commodore 128 will only PAINT
where the specified source in the PAINT statement is different from the source of the x
and y pixel coordinate. It cannot PAINT points where the sources are the same in the
PAINT statement and the specified coordinate. The X and Y coordinate must lie
completely within the boundary of the shape you intend to PAINT, and the source of the
starting pixel coordinate and the specified color source must be different.
EXAMPLE:
10 CIRCLE 1, 160,100,65,50 Draws an outline of a circle.
20 PAINT 1, 160,100 Fills in the circle with color from source 1 (VIC
foreground), assuming point 160,100 is colored in
the background color (source 0).
10 BOX 1, 10, 10, 20, 20 Draws an outline of a box.
20 PAINT 1, 15, 15 Fills the box with color from source 1, assuming
point 15,15 is colored in the background source
(0).
30 PAINT 1, + 10, + 10 PAINT the screen in the foreground color source
at the coordinate relative to the pixel cursor's
previous position plus 10 in both the vertical and
horizontal positions.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 55
100 PAINT 1, 100;90 Paint the screen area 90° relative to and 100
pixels away from the current pixel cursor co-
ordinate.
PLAY
Defines and plays musical notes and elements within a string or string variable.
PLAY "Vn,On,Tn,Un,Xn,eIements, notes"
where the string or string variable is composed of the following
Vn = Voice (n = 1-3)
On = Octave (n = 0-6)
Tn = Tune Envelope Defaults (n = 0-9)
0 = piano
1 = accordion
2 = calliope
3 = drum
4 = flute
5 = guitar
6 = harpsichord
7 = organ
8 = trumpet
9 = xylophone
Un = Volume (n = 0-8)
Xn = Filter on (n = 1), off(n = 0)
notes: A,B,C,D,E,F,G
elements: # Sharp
$ Flat
W Whole note
H Half note
Q Quarter note
I Eighth note
S Sixteenth note
Dotted
R Rest
M Wait for all voices currently playing to end
the current "measure"
The PLAY statement gives you the power to select voice, octave and tune envelope
(including ten predefined musical instrument envelopes), the volume, the filter, and the
notes you want to PLAY. All these controls are enclosed in quotes. You may include
spaces in a PLAY string for readability.
All elements except R and M precede the musical notes in a PLAY string.
EXAMPLES:
PLAY "V1O4T0U5X0CDEFGAB" Play the notes C,D,E,F,G,A and B
in voice 1, octave 4, tune envelope
0 (piano), at volume 5, with the
filter off.
PLAY"V3O5T6U7X1#B$AW.CHDQEIF" Play the notes B-sharp, A-flat, a
whole dotted-C note, a half D-note,
a quarter E-note and an eighth
F-note.
A$ = "V3O5T6U3ABCDE": PLAY A$ PLAY the notes and elements within
A$.
PLAY "V1CV2EV3G" Plays a chord in the default setting.
POKE
Change the contents of a RAM memory location
POKE address, value
EXAMPLE:
10 POKE 53280,1 Changes VIC border color
PRINT
Output to the text screen
PRINT [print list]
The word PRINT can be followed by any of the following:
EXAMPLES: RESULTS
10 PRINT "HELLO" HELLO
20 A$ = "THERE":PRINT "HELLO";A$ HELLO THERE
30 A = 4:B = 2:?A + B 6
40 J = 41:PRINT J;:PRINT J - 1 41 40
50 PRINT A;B;:D = A + B:PRINT D;A-B 4 2 6 2
PRINT#
Output data to files
PRINT# file number[, print list]
PRINT# is followed by a number which refers to the data file previously OPENed.
EXAMPLE:
10 OPEN 4,4 Outputs the data "HELLO THERE"
20 PRINT#4,"HELLO THERE!",A$,B$ and the variables A$ and B$ to the
printer.
10 OPEN 2,8,2 Outputs the data variables A, B$, C
20 PRINT#2,A,B$,C,D and D to the disk file number 2.
PRINT USING
Output using format
PRINT [#file number,] USING"format list"; print list
This statement defines the format of string and numeric items for printing to the text
screen, printer or other device.
EXAMPLE:
5 X = 32: Y = 100.23: A$ = "CAT"
10 PRINT USING " $ # # . # # # ";13.25,X,Y
20 PRINT USING " # # # > # " ; " C B M " , A $
EXAMPLE:
10 PRINT USING " # # # # " ; X
A = 12.34 12
A = 567.89 568
A = 123456 ****
For a STRING item, the string data is truncated at the bounds of the field. Only as many
characters are printed as there are pound signs (#) in the format item. Truncation occurs
on the right.
EXAMPLES:
FIELD EXPRESSION RESULT COMMENT
PUDEF
Redefine symbols in PRINT USING statement
PUDEF "nnnn"
Where "nnnn" is any combination of characters, up to four in all. PUDEF allows you to
redefine any of the following four symbols in the PRINT USING statement: blanks, commas,
decimal points and dollar signs. These four symbols can be changed into some other char-
acter by placing the new character in the correct position in the PUDEF control string.
Position 1 is the filler character. The default is a blank. Place a new character here
for another character to appear in place of blanks.
Position 2 is the comma character. Default is a comma.
Position 3 is the decimal point. Default is a decimal point.
Position 4 is the dollar sign. Default is a dollar sign.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 59
EXAMPLES:
10 PUDEF"*" PRINT * in the place of blanks.
20 PUDEF''< " PRINT < in the place of commas.
READ
Read data from DATA statements and input it into a numeric or string variable)
READ variable list
This statement inputs information from DATA statements and stores it in variables,
where the data can be used by the RUNning program.
In a program, you can READ the data and then re-read it by issuing the
RESTORE statement. The RESTORE sets the sequential data pointer back to the
beginning, where the data can be read again. See the RESTORE and DATA statements.
EXAMPLES:
10 READ A, B, C READ the first three numeric variables from
20 DATA 3, 4, 5 the closest data statement.
10 READ A$, B$, C$ READ the first three string variables from
20 DATA JOHN, PAUL, GEORGE the nearest data statement.
10 READ A, B$, C READ (and input into the C128 memory) a
20 DATA 1200, NANCY, 345 numeric variable, a string variable and an-
other numeric variable.
RECORD
Position relative file pointers
RECORD# logical file number, record number [,byte number]
This statement positions a relative file pointer to select any byte (character) of any
record in the relative file.
When the record number value is set higher than the last record number in the file,
the following occurs:
For a write (PRINT#) operation, additional records are created to expand the file
to the desired record number.
For a read (INPUT#) operation, a null record is returned and a "RECORD NOT
PRESENT ERROR occurs". See your disk drive manual for details about relative
files.
EXAMPLES:
10 DOPEN#2,"FILE"
20 RECORD#2,10,1
30 PRINT#2,A$
40 DCLOSE#2
This example opens an existing relative file called "FILE" as file number 2 in
line 10. Line 20 positions the relative file pointer at the first byte in record number 10.
Line 30 actually writes the data, A$, to file number 2.
REM
Comments or remarks about the operation of a program line
REM message
EXAMPLE:
10 NEXT X:REM THIS LINE INCREMENTS X.
RENAME
Change the name of a file on disk
RENAME "old filename" TO "new filename" [,Ddrive number][<ON!,>
Udevice number]
EXAMPLES:
RENAME "TEST" TO "FINALTEST",D0 Change the name of the file
"TEST" to "FINAL TEST".
RENAME (A$) TO (B$),D0,U9 Change the filename specified in
A$ to the filename specified in B$
on drive 0, device number 9. Re-
member, whenever a variable name
is used as a filename, it must be
enclosed in parentheses.
RENUMBER
Renumber lines of a BASIC program
RENUMBER [new starting line number][,increment][,old starting line
number]
EXAMPLES:
RENUMBER Renumbers the program starting at 10, and increments
each additional line by 10.
RENUMBER 20, 20, 1 Starting at line 1, renumbers the program. Line 1 be-
comes line 20, and other lines are numbered in incre-
ments of 20.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 61
RESTORE
Reset READ pointer so the DATA can be reREAD
RESTORE [line#]
If a line number follows the RESTORE statement, the READ pointer is set to the first
data item in the specified program line. Otherwise the pointer is reset to the beginning of
the first DATA statement in the BASIC program.
EXAMPLES:
10 FOR I = 1 TO 3 This example READs the data in line 70 and stores it in
20 READ X numeric variable X. It adds the total of all the numeric
30 ALL = X + ALL data items. Once all the data has been READ, three
40 NEXT cycles through the loop, the READ pointer is RE-
50 RESTORE STOREd to the beginning of the program and it returns
60 GOTO 10 to line 10 and performs repetitively.
70 DATA 10,20,30
10 READ A,B,C Line 50 of this example RESTORES the DATA pointer
20 DATA 100,500,750 to the beginning data item in line 40. When line 60 is
30 READ X,Y,Z executed, it will READ the DATA 36,24,38 from line
40 DATA 36,24,38 40, and store it in numeric variables S, P, and Q,
50 RESTORE 40 respectively.
60 READ S,P,Q
RESUME
Define where the program will continue (RESUME) after an error has been trapped
RESUME [line number | NEXT]
This statement is used to restart program execution after TRAPping an error. With no
parameters, RESUME attempts to re-execute the statement in which the error occurred.
RESUME NEXT resumes execution at the statement immediately following the one indi-
cating the error. RESUME followed by a line number will GOTO the specific line and
resume execution from that line number. RESUME can only be used in program mode.
EXAMPLE:
10 TRAP 100
15 INPUT " ENTER A NUMBER";A
20 B = 100/A
40 PRINT'THE RESULT = ";B
50 INPUT "DO YOU WANT TO RUN IT AGAIN (Y/N)";Z$:IF Z$ = " Y "
THEN 10
60 STOP
100 INPUT"ENTER ANOTHER NUMBER (NOT ZERO)";A
110 RESUME 20
RETURN
Return from subroutine
RETURN
EXAMPLE:
10 PRINT "ENTER MAIN PROGRAM"
20 GOSUB 100
30 PRINT "END OF PROGRAM"
90 STOP
100 PRINT "SUBROUTINE 1"
110 RETURN
This example calls the subroutine at line 100 which prints the message "SUBROU-
TINE 1" and RETURNS to line 30, the rest of the program.
RUN
Execute BASIC program
1) RUN [line number]
2) RUN "filename" [,Ddrive number][<ON|,>Udevice number]
EXAMPLES:
RUN Starts execution from the beginning of the program.
RUN 100 Starts program execution at line 100.
RUN"PRG1" DLOADs "PRG1" from disk drive 8, and runs it from the
starting line number.
RUN(A$) DLOADs the program named in the variable A$.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 63
SAVE
Store the program in memory to disk or tape
SAVE ["filename"][,device number][,EOT flag]
EXAMPLES:
SAVE Stores program on tape, without a name.
SAVE "HELLO" Stores a program on tape, under the name HELLO.
SAVE A$,8 Stores on disk, with the name stored in variable A$.
SAVE "HELLO",8 Stores on disk, with name HELLO (equivalent to
DSAVE "HELLO").
SAVE "HELLO", 1, 2 Stores on tape, with name HELLO, and places an END
OF TAPE marker after the program.
SCALE
Alter scaling in graphics mode
SCALE n [,Xmax,Ymax]
where:
n = 1 (on) or 0 (off)
Coordinates may be scaled from 0 to 32767 (default = 1023) in both X and Y (in either
standard or multicolor bit map mode), rather than the normal scale values, which are:
EXAMPLES:
10 GRAPHIC 1,1 Enter standard bit map, turn scaling
20 SCALE 1:CIRCLE 1,180,100,100,100 on to default size (1023, 1023) and
draw a circle.
10 GRAPHIC 1,3 Enter multi-color mode, turn scaling
20 SCALE 1,1000,5000 on to size (1000, 5000) and draw a
30 CIRCLE 1,180,100,100,100 circle.
The SCALE command affects the sprite coordinates in the MOVSPR command. If
you add scaling to a program that contains sprites, adjust the MOVSPR coordinates
accordingly.
SCNCLR
Clear screen
SCNCLR mode number
The modes are as follows:
This statement with no argument clears the graphic screen, if it is present, otherwise the
current text screen is cleared.
EXAMPLES:
SCNCLR 5 Clears 80 column text screen.
SCNCLR 1 Clears the (VIC) bit map screen.
SCNCLR 4 Clears the (VIC) multicolor bit map and 40-column text split screen.
SCRATCH
Delete file from the disk directory
SCRATCH "filename" [,Ddrive number][<ON|,>Udevice number]
EXAMPLE:
SCRATCH "MY BACK", DO
SLEEP
Delay program for a specific period of time
SLEEP N
where N is seconds 0< N < = 65535.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 65
SLOW
Return the Commodore 128 to 1MHz operation
SLOW
SOUND
Output sound effects and musical notes
SOUND v,f,d[,dir][,m][,s][,w][,p]
EXAMPLES:
SOUND 1,40960,60 Play a SOUND at frequency 40960 in voice 1
for 1 second.
SOUND 2,20000,50,0,2000,100 Output a sound by sweeping through frequen-
cies starting at 2000 and incrementing upward
in units of 100 up to 20,000. Each frequency is
played for 50 jiffies.
SOUND3,5000,90,2,3000,500,1 This example outputs a range of sounds start-
ing at a minimum frequency of 3000, through
5000, in increments of 500. The direction of
the sweep is back and forth (oscillating). The
selected waveform is sawtooth and the voice
selected is 3.
SPRCOLOR
Set multi-color 1 and/or multi-color 2 colors for all sprites
SPRCOLOR [smcr-l][,smcr-2]
where:
smcr-1 Sets multi-color 1 for all sprites.
smcr-2 Sets multi-color 2 for all sprites.
Either of these parameters may be any color from 1 through 16.
EXAMPLES:
SPRCOLOR 3,7 Sets sprite multi-color 1 to red and multi-color 2 to blue.
SPRCOLOR 1,2 Sets sprite multi-color 1 to black and multi-color 2 to white.
SPRDEF
Enter the SPRite DEFinition mode to create and edit sprite images.
SPRDEF
The SPRDEF command defines sprites interactively
Entering the SPRDEF command displays a sprite work area on the screen which
is 24 characters wide by 21 characters tall. Each character position in the grid corre-
sponds to a sprite pixel in the sprite displayed to the right of the work area. Here
is a summary of the SPRite DEFinition mode operations and the keys that perform
them:
SPRITE
Turn on and off, color, expand and set screen priorities for a sprite
PARAMETER DESCRIPTION
EXAMPLES:
SPRITE 1,1,3 Turn on sprite number 1 and color it red.
SPRITE 2,1,7,1,1,1 Turn on sprite number 2, color it blue, make it pass
behind objects on the screen and expand it in the vertical
and horizontal directions.
SPRITE 6,1,1,0,0,1,1 Turn on SPRITE number 6, color it black. The first 0
tells the computer to display the sprites in front of objects
on the screen. The second 0 and the 1 following tell the
C128 to expand the sprite vertically only. The last 1
specifies multi-color mode. Use the SPRCOLOR com-
mand to select the sprite's multi-colors.
SPRSAV
Copy sprite data from a text string variable into a sprite or vice versa, or copy data from
one sprite to another.
SPRSAV <origin>,<destination>
Either the origin or the destination can be a sprite number or a string variable but they
both cannot be string variables. They can both be sprite numbers. If you are storing a
string into a sprite, only the first 63 bytes of data are used. The rest are ignored since a
sprite can only hold 63 data bytes.
EXAMPLES:
SPRSAV 1,A$ Transfers the image (data) from sprite 1 to the string named AS.
SPRSAV B$,2 Transfers the data from string variable B$ into sprite 2.
SPRSAV 2,3 Transfers the data from sprite 2 to sprite 3.
SSHAPE/GSHAPE
Save/retrieve shapes to/from string variables
SSHAPE and GSHAPE are used to save and load rectangular areas of bit map
screens to/from BASIC string variables. The command to save an area of the bit map
screen into a string variable is:
SSHAPE string variable, X1, Y1 [,X2,Y2]
where:
string variable String name to save data in
X1,Y1 Corner coordinate (0,0 through 319,199) (scaled)
X2,Y2 Corner coordinate opposite (X1,Y1) (default is the PC)
The command to retrieve (load) the data from a string variable and display it on
specified screen coordinates is:
GSHAPE string variable [X,Y][,mode]
where:
The replacement mode allows you to change the data in the string variable so you can
invert it, perform a logical OR, exclusive OR (turn off bytes that are on) or AND
operation on the image.
EXAMPLES:
SSHAPE A$,10,10 Saves a rectangular area from the coordinates 10,10
to the location of the pixel cursor, into string vari-
able A$.
SSHAPE B$,20,30,43,50 Saves a rectangular area from top left coordinate
(20,30) through bottom right coordinate (43,50) into
string variable B$.
SSHAPE D$, + 10, + 10 Saves a rectangular area 10 pixels to the right and
10 pixels down from the current position of the pixel
cursor.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 69
NOTE: Beware using modes 1-4 with multi-color shapes. You may
obtain unpredictable results.
STASH
Move contents of host memory to expansion RAM
STASH #bytes, intsa, expsa, expb
Refer to FETCH command for description of parameters.
STOP
Halt program execution
STOP
SWAP
Swap contents of host RAM with contents of expansion RAM
SWAP #bytes, intsa, expsa, expb
Refer to FETCH command for description of parameters.
SYS
Call and execute a machine language subroutine at the specified address
SYS address [,a][,x][,y][,s]
This statement calls a subroutine at a given address in a memory configuration previously
set up according to the BANK command. Optionally, arguments a,x,y and s are loaded into
the accumulator, x, y and status registers, respectively, before the subroutine is called.
The address range is 0 to 65535. The 8502 microprocessor begins executing the
machine-language program starting at the specified memory location. Also see the
BANK command.
EXAMPLES:
SYS 32768 Calls and executes the machine-language routine at location 32768
($8000).
SYS 6144,0 Calls and executes the machine-language routine at location 6144
($1800) and loads zero into the accumulator.
TEMPO
Define the speed of the song being played
TEMPO n
where n is a relative duration between (1 and 255)
The default value is 8, and note duration increases with n.
EXAMPLES:
TEMPO 16 Defines the Tempo at 16.
TEMPO 1 Defines the TEMPO at the slowest speed.
TEMPO 250 Defines the TEMPO at 250.
TRAP
Detect and correct program errors while a BASIC program is RUNning
TRAP [line number]
The RESUME statement can be used to resume program execution. TRAP with no line
number turns off error trapping. An error in a TRAP routine cannot be trapped. Also see
system variables ST, EL, DS and DS$.
EXAMPLES:
. 100 TRAP 1000 If an error occurs, GOTO line 1000.
TROFF
Turn off error tracing mode
TROFF
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 71
TRON
Turn on error tracing
TRON
TRON is used in program debugging. This statement begins trace mode. When you
RUN the program, the line numbers of the program appear in brackets before any action
for that line occurs.
VERIFY
Verify program in memory against one saved to disk or tape
VERIFY "filename" [,device number][,relocate flag]
Issue the VERIFY command immediately after you SAVE a program.
EXAMPLES:
VERIFY Checks the next program on the tape.
VERIFY "HELLO" Searches for HELLO on tape, checks it against memory.
VERIFY "HELLO",8,1 Searches for HELLO on disk, then checks it against
memory.
VOL
Define output level of sound for SOUND and PLAY statements
VOL volume level
EXAMPLES:
VOL 0 Sets volume to its lowest level.
VOL 15 Sets volume for SOUND and PLAY statements to its highest output.
WAIT
Pause program execution until a data condition is satisfied
WAIT <location>, <mask-1> [,mask-2>]
where:
location = 0-65535
masks = 0-255
The WAIT statement causes program execution to be suspended until a given memory
address recognizes a specified bit pattern or value.
The first example below WAITs until a key is pressed on the tape unit to
continue with the program. The second example will WAIT until a sprite collides with
the screen background.
EXAMPLES:
WAIT 1, 32, 32
WAIT 53273, 2
WAIT 36868, 144, 16
WIDTH
Set the width of drawn lines
WIDTH n
EXAMPLES:
WIDTH 1 Set single width for graphic commands
WIDTH 2 Set double width for drawn lines
WINDOW
Define a screen window
WINDOW top left col,top left row,bot right col,bot right row[,clear]
This command defines a logical window within the 40 or 80 column text screen. The
coordinates must be in the range 0-39/79 for 40- and 80-column values respectively and
0-24 for row values. The clear flag, if provided (1), causes a screen-clear to be
performed (but only within the limits of the newly described window).
EXAMPLES:
WINDOW 5,5,35,20 Defines a window with top left corner coordinate as
5,5 and bottom right corner coordinate as 35,20.
WINDOW 10,2,33,24,1 Defines a window with upper left corner coordinate
10,2 and lower right corner coordinate 33,24. Also
clears the portion of the screen within the window as
specified by the 1.
BASIC FUNCTIONS
The format of the function description is:
FUNCTION (argument)
where the argument can be a numeric value, variable or string.
Each function description is followed by an EXAMPLE. The first line appearing
below the word "EXAMPLE" is the function you type. The second line without bold is
the computer's response.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 73
ABS
Return absolute value of argument X
ABS (X)
EXAMPLE:
PRINT ABS (7*(-5))
35
ASC
Return CBM ASCII code for the first character in X$
ASC(X$)
This function returns the CBM ASCII code of the first character of X$.
EXAMPLE:
X$ = "C128":PRINT ASC (X$)
67
ATN
Return the arctangent of X in radians
ATN (X)
The value returned is in the range - PI/2 through PI/2.
EXAMPLE:
PRINT ATN (3)
1.24904577
BUMP
Return sprite collision information
BUMP (N)
To determine which sprites have collided since the last check, use the BUMP function.
BUMP(l) records which sprites have collided with each other, and BUMP(2) records
which sprites have collided with other objects on the screen. COLLISION need not be
active to use BUMP. The bit positions (0-7) in the BUMP value correspond to sprites 1
through 8 respectively. BUMP(n) is reset to zero after each call.
Here's how the sprite numbers and BUMP values that are returned correspond:
BUMP Value: 128 64 32 16 8 4 2 1
Sprite Number: 8 7 6 5 4 3 2 1
EXAMPLES:
PRINT BUMP (1) 12 indicates that sprites 3 and 4 have collided.
PRINT BUMP (2) 32 indicates the sprite 6 has collided with an object on the screen.
CHR$
Return character for specified CBM ASCII code X
CHR$(X)
The argument (X) must be in the range 0-255. This is the opposite of ASC and returns the
string character whose CBM ASCII code is X. Refer to Appendix E for a table of CHR$ codes.
EXAMPLES:
PRINT CHR$ (65) Prints the A character.
A
PRINT CHR$ (147) Clears the text screen.
COS
Return cosine for angle of X in radians
COS(X)
EXAMPLE:
PRINT COS (PI/3)
.5
FNxx
Return value from user defined function xx
FNxx(X)
This function returns the value from the user defined function xx created in a DEF
FNxx statement
EXAMPLE:
10 DEF FNAA(X) = (X-32)*5/9
20 INPUT X
30 PRINT FNAA(X)
RUN
?40 (? is input prompt)
4.44444445
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 75
FRE
Return number of available bytes in memory
FRE (X)
where X is the RAM bank number. X = 0 for BASIC program storage and X = 1 to
check for available BASIC variable storage.
EXAMPLES:
PRINT FRE (0) Returns the number of free bytes for BASIC programs.
58109
PRINT FRE (1) Returns the number of free bytes for BASIC variable storage.
64256
HEX$
Return hexadecimal string equivalent to decimal number X
HEX$(X)
EXAMPLE:
PRINT HEX$(53280)
D020
INSTR
Return starting position of string 2 within string 1
INSTR (string 1, string 2 [,starting position])
EXAMPLE:
PRINT INSTR ("COMMODORE 128","128")
11
INT
Return integer form (truncated) of a floating point value
INT(X)
This function returns the integer value of the expression. If the expression is positive,
the fractional part is left out. If the expression is negative, any fraction causes the next
lower integer to be returned.
EXAMPLES:
PRINT INT(3.14)
3
PRINT INT(-3.14)
-4
JOY
Return position of joystick and the status of the fire button
JOY(N)
when N equals:
1 JOY returns position of joystick 1.
2 JOY returns position of joystick 2.
Any value of 128 or more means that the fire button is also pressed. To find the joystick
position if the fire button is pressed subtract 128 from the JOY value. The direction is
indicated as follows.
1
8 2
7 0 3
6 4
5
EXAMPLES:
PRINT JOY (2) Joystick 2 fires to the left.
135
IF (JOY (1) > 127) THEN PRINT "FIRE" Determines whether the fire button
is pressed.
DIR = JOY(l) AND 15 Returns direction (only) of joystick 1.
LEFT$
Return the leftmost characters of string
LEFTS (string,integer)
EXAMPLE:
PRINT LEFT$("COMMODORE",5)
COMMO
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 77
LEN
Return the length of a string
LEN (string)
The returned integer value is in the range 0-255.
EXAMPLE:
PRINT LEN ("COMMODORE 128")
12
LOG
Return natural log of X
LOG(X)
The argument X must be greater than 0.
EXAMPLE:
PRINT LOG (37/5)
2.00148
MID$
Return a substring from a larger string
MID$ (string,starting position[,length])
This function extracts the number of characters specified by length (0-255), from string,
starting with the character specified by starting position (1-255).
EXAMPLE:
PRINT MID$("COMMODORE 128",3,5)
MMODO
PEEK
Return contents of a specified memory location
PEEK(X)
The data will be returned from the bank selected by the most recent BANK command.
See the BANK command.
EXAMPLE:
10 BANK 15:VIC = DEC("D000")
20 FOR I = 1 TO 47
30 PRINT PEEK(VIC + I)
40 NEXT
This example displays the contents of the registers of the VIC chip (some of which
are ever-changing).
PEN
Return X and Y coordinates of the light pen
PEN(n)
where n = 0 PEN returns the X coordinate of light pen position on any VIC screen.
n = 1 PEN returns the Y coordinate of light pen position on any VIC screen.
n = 2 PEN returns the character column position of the 80 column display.
n = 3 PEN returns the character row position of the 80 column display.
n = 4 PEN returns the (80-column) light pen trigger value.
The VIC PEN values are not sealed and are taken from the same coordinate plane as
sprites use. Unlike the 40 column (VIC) screen, the 80 column (8563) coordinates are
character row and column positions and not pixel coordinates like the VIC screen. Both
the 40 and 80 column screen coordinate values are approximate and vary, due to the
nature of light pens. The 80-column read values are not valid until PEN(4) is true.
Light pens are always plugged in to control port 1.
EXAMPLES:
10 PRINT PEN(0);PEN(l) Displays the X and Y coordinates of the light
pen (for the 40 column screen).
10 DO UNTIL PEN(4):LOOP Ensures that the read values are valid (for the
80 column screen).
20 X = PEN(2)
30 Y = PEN(3)
40 REM:REST OF PROGRAM
PI symbol
Return the value of pi (3.14159265)
EXAMPLE:
PRINT PI This returns the result 3.14159265.
POINTER
Return the address of a variable
POINTER (variable name)
This function returns a zero if the variable is not defined.
EXAMPLE:
A = POINTER (Z) This example returns the address of variable Z.
NOTE: Address returned is in RAM BANK 1.
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 79
POS
Return the current cursor column position within the current screen window
POS(X)
The POS function indicates where the cursor is within the defined screen window. X is a
dummy argument, which must be specified, but the value is ignored. The values
returned range from 0-39 on the VIC screen and 0-79 on the 80-column screen.
EXAMPLE:
FOR I = 1 to 10 : ?SPC(I); POS(O): NEXT
This displays the current cursor position within the defined text window.
POT
Returns the value of the game-paddle potentiometer
POT (n)
when:
The values for POT range from 0 to 255. Any value of 256 or more means that the fire
button is also depressed.
EXAMPLE:
10 PRINT POT(l)
20 IF POT(l) > 256 THEN PRINT "FIRE"
This example displays the value of game paddle 1.
RCLR
Return color of color source
RCLR(N)
This function returns the color (1 through 16) assigned to the color source N (0< = N = <
6), where the following N values apply:
SOURCE DESCRIPTION
0 40-column background
1 bit map foreground
2 multi-color 1
3 multi-color 2
4 40-column border
5 40- or 80-column character color
6 80-column background color
EXAMPLE:
10 FOR I = 0 TO 6
20 PRINT "SOURCE";I;"IS COLOR CODE";RCLR(I)
30 NEXT
This example prints the color codes for all six color sources.
RDOT
Return current position or color source of pixel cursor
RDOT (N)
where:
N = 0 returns the X coordinate of the pixel cursor
N = 1 returns the Y coordinate of the pixel cursor
N = 2 returns the color source (0-3) of the pixel cursor
This function returns the location of the current position of the pixel cursor or the
current color source of the pixel cursor.
EXAMPLES:
PRINT RDOT(0) Returns X position of pixel cursor
PRINT RDOT( 1) Returns Y position of pixel cursor
PRINT RDOT(2) Returns color source of pixel cursor
RGR
Return current graphic mode
RGR(X)
This function returns the current graphic mode. X is a dummy argument, which must be
specified. The counterpart of the RGR function is the GRAPHIC command. The value
returned by RGR(X) pertains to the following modes:
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 81
EXAMPLE:
PRINT RGR(0) Displays the current graphic mode; in this case, standard bit
1 map mode.
PRINT RGR(0) Both multi-color bit map and 80-column text modes are enabled.
8
RIGHT$
Return sub-string from rightmost end of string
RIGHT$(string, numeric)
EXAMPLE:
PRINT RIGHT$("BASEBALL",5)
EBALL
RND
Return a random number
RND (X)
EXAMPLES:
PRINT RND(0) Displays a random number between 0 and 1.
.507824123
PRINT INT(RND(l)*100 + 1) Displays a random number between 1 and 100.
89
RSPCOLOR
Return sprite multicolor values
RSPCOLOR (X)
When:
X = 1 RSPCOLOR returns the sprite multi-color 1.
X = 2 RSPCOLOR returns the sprite multi-color 2.
The returned color value is a value between 1 and 16. The counterpart of the RSPCOLOR
function is the SPRCOLOR statement. Also see the SPRCOLOR statement.
EXAMPLE:
10 SPRITE 1,1,2,0,1,1,1
20 SPRCOLOR 5,7
30 PRINT "SPRITE MULTI-COLOR 1 IS";RSPCOLOR(1)
40 PRINT "SPRITE MULTI-COLOR 2 IS";RSPCOLOR(2)
RUN
SPRITE MULTI-COLOR 1 IS 5
SPRITE MULTI-COLOR 2 IS 7
In this example line 10 turns on sprite 1, colors it white, expands it in both the X and Y
directions and displays it in multi-color mode. Line 20 selects sprite multi-colors 1 and 2
(5 and 7 respectively). Lines 30 and 40 print the RSPCOLOR values for multi-color 1 and 2.
RSPPOS
Return the speed and position values of a sprite
RSPPOS (sprite number,position|speed)
where sprite number identifies which sprite is being checked, and position and speed
specifies X and Y coordinates or the sprite's speed.
When position equals;
0 RSPPOS returns the current X position of the specified sprite.
1 RSPPOS returns the current Y position of the specified sprite.
When speed equals:
2 RSPPOS returns the speed (0-15) of the specified sprite.
EXAMPLE:
10 SPRITE 1,1,2
20 MOVSPR 1.45#13
30 PRINT RSPPOS (1.0);RSPPOS (1,1);RSPPOS (1,2)
This example returns the current X and Y sprite coordinates and the speed (13).
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 83
RSPRITE
Return sprite characteristics
RSPRITE (sprite number,characteristie)
RSPRITE returns sprite characteristics that were specified in the SPRITE command.
Sprite number specifies the sprite (1-8) you are checking and the characteristic specifies
the sprite's display qualities as follows:
RSPRITE RETURNS
CHARACTERISTIC THESE VALUES:
EXAMPLE:
10 FOR I = 0 TO 5 This example prints all 6 characteristics of sprite 1.
20 PRINT RSPRITE (1,I)
30 NEXT
RWINDOW
Returns the size of the current window or the number of columns of the current
screen
RWINDOW (n)
When n equals:
0 RWINDOW returns the number of lines in the current window.
1 RWINDOW returns the number of rows in the current window.
2 RWINDOW returns either of the values 40 or 80, depending on the current
screen output format you are using.
The counterpart of the RWINDOW function is the WINDOW command.
EXAMPLE:
10 WINDOW 1,1,10,10
20 PRINT RWINDOW(0);RWINDOW(1);RWINDOW(2)
RUN
9 9 40
This example returns the lines (10) and columns (10) in the current window. This
example assumes you are displaying the window in 40 column format.
SGN
Return sign of argument X
SGN(X)
EXAMPLE:
PRINT SGN(4,5);SGN(0);SGN(-2.3)
1 0- 1
SIN
Return sine of argument
SIN(X)
EXAMPLE:
PRINT SIN (PI/3)
.866025404
SPG
Skip spaces on printed output
SPC (X)
EXAMPLE:
PRINT "COMMODORE";SPC(3);" 128'
COMMODORE 128
SQR
Return square root of argument
SQR (X)
EXAMPLE:
PRINT SQR(25)
5
STR$
Return string representation of number
STR$ (X)
BASIC BUILDING BLOCKS AND BASIC 7.0 ENCYCLOPEDIA 85
EXAMPLE:
PRINT STR$(123.45)
123.45
PRINT STR$(-89.03)
-89.03
PRINT STR$(1E20)
1E + 20
TAB
Moves cursor to tab position in present statement
TAB (X)
EXAMPLE:
10 PRINT"COMMODORE"TAB(25)"128"
COMMODORE 128
TAN
Return tangent of argument in radians
TAN(X)
This function returns the tangent of X, where X is an angle in radians
EXAMPLE:
PRINT TAN(.785398163)
1
USR
Call user-defined subprogram
USR(X)
When this function is used, the BASIC program jumps to a machine language program
whose starting point is contained in memory locations 4633($1219) and 4634($121A), (or
785($0311) and 786($0312) in C64 mode). The parameter X is passed to the machine-
language program in the floating-point accumulator ($63-$68 in C128 mode). A value is
returned to the BASIC program through the calling variable. You must direct the value
into a variable in your program in order to receive the value back from the floating-point
accumulator. An ILLEGAL QUANTITY ERROR results if you don't specify this
variable. This allows the user to exchange a variable between machine code and
BASIC.
EXAMPLE:
10 POKE 4633,0
20 POKE 4634,48
30 A = USR(X)
40 PRINT A
Place starting location ($3000 = 12288:$00 = 0:$30) = 48 of machine language
routine in location 4633 and 4634. Line 30 stores the returning value from the floating-
point accumulator. The USER vector is assumed to be in BANK 15. Your machine
language routine MUST be in RAM bank 0 below address $4000.
VAL
Return the numeric value of a number string
VAL(X$)
EXAMPLE:
10 A$ = "120"
20 B$ = " 3 6 5 "
30 PRINT VAL (A$ + B$)
RUN
485
XOR
Return exclusive OR value
XOR (nl,n2)
This function returns the exclusive OR of the numeric argument values nl and n2.
X = XOR (nl,n2)
where n l , n2, are 2 unsigned values (0-65535)
EXAMPLE:
PRINT XOR( 128,64)
192
Reserved variable names are names reserved for the variables DS, DS$, ER, EL,
ST, TI and TI$, and the function ERRS. Keywords such as TO and IF or any other
names that contain keywords, such as RUN, NEW or LOAD cannot be used.
ST is a status variable for input and output (except normal screen/keyboard
operations). The value of ST depends on the results of the last I/O operation. In general,
if the value of ST is 0, then the operation was successful.
TI and TI$ are variables that relate to the real time clock built into the Commodore
128. The system clock is updated every l/60th of a second. It starts at 0 when the
Commodore 128 is turned on, and is reset only by changing the value of TI$. The
variable TI gives the current value of the clock in l/60th of a second. TI$ is a string that
reads the value of the real time clock as a 24-hour clock. The first two characters of TI$
contain the hour, the third and fourth characters are minutes and the fifth and sixth
characters are seconds. This variable can be set to any value (so long as all characters
are numbers) and will be updated automatically as a 24-hour clock.
EXAMPLE:
TI$ = "101530" Sets the clock to 10:15 and 30 seconds (AM).
The value of the clock is lost when the Commodore 128 is turned off. It starts at
zero when the Commodore 128 is turned on, and is reset to zero when the value of the
clock exceeds 235959 (23 hours, 59 minutes and 59 seconds).
The variable DS reads the disk drive command channel and returns the current
status of the drive. To get this information in words, PRINT DS$. These status variables
are used after a disk operation, like DLOAD or DSAVE, to find out why the error light
on the disk drive is blinking.
ER, EL and the ERR$ function are variables used in error trapping routines. They
are usually only useful within a program. ER returns the last error number encountered
since the program was RUN. EL is the line where the error occurred. ERR$ is a
function that allows the program to print one of the BASIC error messages. PRINT
ERR$(ER) prints out the proper error message.
SYMBOL USE(S)
SYMBOL USE(S)
CREATING A MENU
A menu is a list of choices you select to perform a specific operation within an
application program. A menu directs the computer to a particular part of a program.
Here is a general example of a menu program:
The SCNCLR 0 command in line 10 clears the 40-column screen. (Use SCNCLR
5 if you are using the 80-column screen. The easiest selection is by a number. You may
use as many selections as can fit on the screen. Line 100 displays a message to the user.
The GETKEY command in line 110 forces the computer to wait for a key to be pressed.
Since a key represents a character symbol, A$ is a string variable. So that it can be
interpreted as a numeric value in an ON GOTO statement, the string variable is
converted to a number with the VAL function in line 120. The IF . . . THEN statement
in line 120 screens user errors by preventing the user from selecting a number that is not
in the range of numbers used for choices (4). Line 130 directs control to the appropriate
section (i.e., line number) in your program. Since four selections are offered in this
example, you must include at least four line numbers. Line 1999 returns to the menu at
the end of each subroutine that you add at lines 1000, 2000, 3000 and 4000 in the menu
skeleton.
ONE STEP BEYOND SIMPLE BASIC 93
BUFFER ROUTINE
The C128 keyboard buffer can hold and dispense up to ten characters from the
keyboard. This is useful in a word processing program where it is possible at certain
moments to type faster than the software can actually process. The characters that
haven't been displayed yet are temporarily stored in the keyboard buffer. The computer
can hold the next instruction in the buffer for use when the program is ready. This buffer
allows a maximum of ten characters in queue. To see the buffer in action, enter the
command SLEEP 5 and immediately press ten different letter keys. After five seconds,
all ten characters are displayed on the screen.
Here is a buffer routine that allows you to put items in the keyboard buffer
from within a program so they are dispensed automatically as the computer is able to act
upon them.
In line 10, memory location 208 (198 in C64 mode) is filled with a number
between 0 and 10—the number of keyboard characters in the keyboard buffer. In line
20, memory locations 842 through 851 (631-640 in C64 mode) are filled with any ten
characters you want placed there. In this example, seven characters are in the buffer,
each a carriage RETURN character. CHR$(13) is the character string code for the
carriage return character.
Line 40 places the text "?CHR$(156)" on the screen, but does not execute the
instruction. Line 50 displays the word "LIST" on the screen. Neither command is
executed until the program ends. In the C128, the keyboard buffer automatically empties
when a program ends. In this case, the characters in the buffer (carriage return) are
emptied and act as though you are pressing the RETURN key manually. When this occurs
on a line where the commands from lines 40 and 50 are displayed, they are executed
as though you typed them in direct mode and pressed the RETURN key yourself. When
this program ends, the character color is changed to purple and the program is LISTED
to the screen. This technique is handy in restarting programs (with RUN or GOTO).
The next section gives a practical example of using the buffer routine.
LOADING ROUTINE
The buffer can be used in automatic loader routines. Many programs often involve the
loading of several machine code routines as well as a BASIC program. The results of
the following loader are similar to many found on commercial software packages.
2 COLOR 4,1:COLOR 0,1:COLOR 5,1
5 A$="PICTURE"
10 SCNCLR:PRINT:PRINT:PRINT:PRINT"LOAD"CHR$(34)A$CHR$(34)",8,1'
15 PRINT:PRINT:PRINT"NEW"
25 B$="FILE3.BIN"
30 PRINT:PRINT:PRINT"LOAD"CHR$(34)B$CHR$(34)",8,1"
45 PRINT:PRINT:PRINT:PRINT:PRINT:PRINT"SYS12*256"
90 PRINT CHRS(5):PRINT" GREETINGS FROM COMMODORE"
100 PRINT" PLEASE STAND BY - LOADING":PRINT CHR$(144)
200 PRINT CHR$(19)
300 POKE208,7:FORI=842TO851:POKEI,13:NEXT
Line 2 colors the border, screen and characters black. Line 5 assigns A$ the
filename "PICTURE", which in this example assumes that it is an 8K binary file of a
bit-mapped screen. Line 10 places the LOAD instruction for the picture file on the
screen, but does not execute it. A carriage return from the keyboard buffer executes the
load instruction once the program ends and the keyboard buffer empties. Line 15 prints
the word "NEW" on the screen. Again, this operation is not carried out until a carriage
return is executed on the same line once the keyboard buffer empties. After loading a
machine language program, a NEW is performed to set pointers to their original
positions and clear the variable storage area. Line 30 displays the second load instruc-
tion for the machine language program "FILE3.BIN". This hypothetical program
enables the bit mapped PICTURE, and anything else you want to supply in the program.
Line 45 initiates (SYS12*256), the "FILE3.BIN" program starting at 3072 ($0C00)
once the keyboard buffer empties. This is only a template sample for you to follow.
"PICTURE" and "FILE3.BIN" are programs you supply and are only used to illustrate
one technique of automatic loading. Since the previous character color was black, all the
loading instructions are displayed in black on a black background, so they can't be seen.
The CHR$(5) in line 90 changes the character color to white, so the only visible
messages are the ones in white in lines 90 and 100, while the disk drive is loading
"PICTURE" and "FILE3.BIN". Line 300 is the buffer routine.
If you were to do each step manually it would require seven "RETURNS". This
program places seven carriage return characters in the keyboard buffer, and they are
dispensed automatically when the program ends. As each RETURN is accepted, the
corresponding screen instruction is enacted automatically as if you had pressed the
RETURN key manually.
PROGRAMMING THE
C128 FUNCTION KEYS
As each of the function keys (F1 through F8) is pressed, the computer displays a BASIC
command on the screen and in some cases acts immediately. These are known as the
default values of the function keys. Enter a KEY command to get a list of function key
values at any time.
ONE STEP BEYOND SIMPLE BASIC 95
NOTE: All eight KEY definitions in total must not exceed 246 characters.
ELIMINATING SPACES
In most BASIC commands, spacing is unnecessary, except inside quotes when you want
the spaces to appear on the screen. Although spaces improve readability, the extra space
consumes additional memory. Here is an instructional line presented both ways:
10INPUT"FIRST NAME";N$:FOR T = A TO M.PRINT "OK":
10INPUT"FIRST NAME";N$:FORT = ATOM:PRINT"OK":
USING MULTIPLE INSTRUCTIONS
Colons allow you to place several instructions within a single program line. Each
program line consumes additional memory. Be careful, however, crunching IF state-
ments. Any instruction after the IF statement with the same line number can be bypassed
along with the IF . . . THEN condition. The following line is the equivalent of five
lines:
(A)
10 PRINTX:INPUTY:PRINTY:SCNCLR0:?J
(B)
10 PRINTX
20 INPUTY
30 PRINTY
40 SCNCLR0
50 PRINTJ
Example A requires less space in memory and on disk. Example B requires 16
additional bytes; 2 bytes for each additional line number and 2 bytes for the link to the
next line number.
SYNTAX RELIEF
Some BASIC syntax is very flexible and this flexibility can be used to your advantage.
The LET statement, for example, can be written without LET. LET Y= 2 is the same as
Y = 2. Although it is good practice to initialize all variables to zero, it is not necessary
since the computer automatically sets all variables to zero, including subscripted vari-
ables. DIMension all arrays (subscripted variables) to have twelve or more elements. The
C128 automatically dimensions each variable to have eleven subscripted elements if no
dimension is specified following DIM and the variable names. Often semicolons are not
required in PRINT statements. Both of these perform the same results:
10 PRINT"A";Z$;"WORD";CHR$(65);"NOW $"
20 PRINT"A"Z$"WORD"CHR$(65)"NOW $"
USING VARIABLES
Replace repeated numbers with a variable. This is especially important with large
numbers such as memory addresses. POKEing several numbers in sequence conserves
memory if a variable is used, such as POKE 54273 + V, etc. Of course, single-letter
variable names require the least memory. Reuse old variables such as those used in FOR
. . . NEXT loops. Whenever possible, make use of integer variables since they consume
far less memory than floating-point variables.
ONE STEP BEYOND SIMPLE BASIC 97
MASKING BITS
Any of the bits within a byte can be controlled individually, using the Boolean operators
AND and OR. Calculations with AND and OR are based on a truth table (Table 3-1)
showing the results given all possible true and false combinations of the arguments X and Y.
X Y X AND Y X OR Y
0 0 0 0
0 1 0 1
1 0 0 1
1 1 1 1
With " 0 " representing False and " 1 " Truth, Table 3-1 shows how the operators
AND and OR work. The result of an AND operation between two bits is only true if
both bits are true (1). Otherwise the combination is false. Any bit combination with a
zero yields a zero in an AND operation. The result of an AND operation is only true
(equal to 1) if both bits are true (equal to 1).
The result of an OR operation is only false if each bit is false. Otherwise the result
is true. Any bit combination with a one yields a one in an OR operation. ONLY two
zeros result in a zero.
Observe the following example with the numbers 5 and 6 in binary form. When
you type the command PRINT 5 AND 6, the result is 4. Here's why:
5= 0000 0101
6= 0000 0110
byte in question with an operand byte of all ON bits except the bit you want turned off.
Bits to remain on will not be affected. To turn off bit 5, AND the byte in question with
the mirror image of 00100000 or the operand byte 11011111. In decimal this value is
always 255 minus the value of the bit(s) you want to turn off. Thus:
POKEV,PEEK(V) AND (255-32)
turns off bit 5.
Use OR to turn bits ON
Use AND to turn bits OFF
EXAMPLES:
POKEW,PEEK(W) OR 129 Turns ON bits 0 and 7 of memory address W.
POKES,PEEK(S) AND 126 Turns OFF bits 0 and 7 of memory register S
(Remember 255-129 = 126)
POKEC,PEEK(C)AND254 Turns OFF bit 0
POKEC,PEEK(V)OR63 Turns ON all bits except 6 and 7
DEBUGGING PROGRAMS
No program when first written is free of "bugs" or errors. The process of finding errors
and removing them, debugging, combines editing with problem solving.
SYNTAX ERRORS
Syntax errors result from misspelling or misusing the guidelines and formats of BASIC
commands. An error message is displayed on the screen defining the line where the
error occurs. Typing HELP <RETURN> or pressing the HELP key also highlights the
line with the error. Common syntax errors include misspelled BASIC terms, misplaced
punctuation, unpaired parentheses, reserved variable names such as TI$, use of line
numbers that do not exist, etc.
LOGIC ERRORS
Sometimes errors exist in the program logic, with the result that the program doesn't do
exactly what you think it is supposed to do. Some logic errors are caused by the order of
instructions. One common fault occurs when you forget that anything on a line after an
IF statement is affected by the IF condition.
Some errors in logic require a trial-and-error investigation. This is best initiated by
asking the computer for help in BASIC.
USING A DELAY
Where the computer responds rapidly, it often helps to see a response by inserting a
SLEEP command for a temporary time delay. This gives you a chance to see exactly
what is happening in the program.
USING PRINT AND STOP
Insert STOP statements within your program prior to the suspect instruction line. Good
locations are at the end of specific tasks. Run the program. After the STOP statement
puts you into direct mode, use the PRINT command to identify clues to the problem by
determining the values of the various variables, especially those within loops. Check
these with what you expect. Continue the program with CONT to the next STOP
statement until you modify your program.
TRAPPING AN ERROR
Debugging is the art of detecting the source of problem. The following program is
perfectly valid; however, it produces an error when B equals zero.
10 INPUT A,B
20 PRINT A/B
30 GOTO 10
Although in this case the computer defines the error as a DIVISION BY ZERO
error, it is not always obvious how the variable B became a zero. It could have been
derived from a complex formula embedded in your program, or directly inputting the
value zero into a variable.
The BASIC TRAP command has a technique of trapping such an error in a
program without crashing. Since you can't always foresee all the possible values of the
variable B, you can screen the probable error of division of zero by including a TRAP at
the beginning of the program.
5 TRAP 50
10 INPUT A,B
20 PRINTA/B
30 GOTO 10
50 PRINT''DIVISION BY ZERO IS NOT POSSIBLE"
60 PRINT"ENTER ANOTHER NUMBER FOR B BESIDES ZERO"
70 RESUME
RESUME is required after the TRAP response in order to reactivate the TRAP. If
you include the option to enter a replacement for B, RESUME without a line number
returns to the cause of the error—line 20—and executes it as follows:
65 INPUT B
The use of RESUME NEXT proceeds with the next line after the TRAP command,
i.e., line 10.
TRAP tells the computer to go to a specific line number whenever an error occurs.
Do NOT use TRAP until you have removed all syntax errors first. TRAP can only catch
the error condition it is looking for. An error in the syntax or the logic of your TRAP
routine may cause an error, or may not catch the error that you are looking for. In other
words, TRAP routines are sensitive to errors, too.
ONE STEP BEYOND SIMPLE BASIC 101
ERROR FUNCTIONS
Several reserved variables inherent in the system store information about program
errors. ER stores the error number. EL stores the relevant program line number.
ERR$(N) returns the string representing ER or EL. In the example of division by zero,
ERR$(ER) returns "DIVISION BY ZERO" and ERR$(EL) returns "BREAK". Add
this to the program in the previous section. See Appendix A for a complete listing of
errors.
D O S ERRORS
Information on disk errors is determined from the variables DS and DS$ where DS is the
error number (See Appendix B) and DS$ provides the error number, error message, and
track and sector of the error. DS$ reads the disk error channel and is used during a disk
operation to determine why the disk drive error light is blinking.
Trying to read a directory without a disk in place results in the following error
when the PRINT DS$ command is issued:
74, DRIVE NOT READY, 00, 00
Appendix B highlights specific causes of errors. To convert a function key to read
the disk-drive error channel automatically, use:
KEY 1, "PRINT DS$ + CHR$( 13)
TRACING AN ERROR
Some programs have many complex loops that are tedious to follow. A methodical
step-by-step trace is useful. The BASIC TRON and TROFF commands can be used
within a program as a debugging tool to trace specific routines.
Some errors can only be found by acting like the computer and methodically
following each instruction step-by-step, and then doing all the calculations until you
discover something wrong. Fortunately the Commodore 128 can trace errors for you.
Enter the direct command TRON prior to running a program. The program displays each
line number as they occur in brackets, followed by each result. (To slow down the
display, hold the Commodore (C= ) key down.)
Try it with this double loop:
10 FORA=1TO5
20 FOR B = 2TO6
30 C = B*A:K = K + C:PRINTK
40 NEXTB:NEXTA
50 PRINTK
The results will start off like this:
[10] [20] [30] [30] [30]2
[40] [30] [30] [30]5
meaning the first printed result is the number 2 after operations in lines 10, 20, 30 are
performed. Then lines 40 and 30 result in 5, etc. Notice three activities were performed
in line 30. The Trace function is turned off with the direct command TROFF.
WINDOWING
The standard screen display size is 40- or 80-columns by 25 lines. It is often convenient
to have a portion of the screen available for other work. The process of producing and
isolating small segments of your screen is called "windowing."
DEFINING A WINDOW
There are two ways to create a window—either directly or within a program using the
WINDOW command. Using the ESCape key followed by a T or B is all that is
necessary to describe and set a window.
Here's how to define a window in direct mode:
1. Move the cursor to the upper-left corner position of the proposed window.
Press the (ESC) escape key, then press the letter T key.
2. Move the cursor to the bottom right corner and press the escape key (ESC)
then press the letter B key.
Now that your window is in effect, all commands and listings remain in the
window until you exit by pressing the HOME key twice. This is useful if you have a
listing on the main screen and wish to keep it while you display something else in a
window. See Chapter 13, the Commodore 128 Operating System, under the screen
editor for special ESCape controls within a window.
Although it is possible to define several windows simultaneously on the screen, only
one window can be used at a time. The other windows remain on the display, but they are
inactive. To re-enter a window you have exited, define the top and bottom corners of the
window with the ESC T and ESC B commands, respectively, as you did originally.
The second way to define a window is with the BASIC window command. The
command:
WINDOW 20,12,39,24,1
establishes a window with the top-left corner at column 20, row 12, and the bottom-
right corner at column 39, row 24. The 1 signifies the area to be cleared. Once this
command is specified, all activities are restricted to this window.
Use the window command within a program whenever you want to perform an
activity in an isolated area on the screen.
ONE STEP BEYOND SIMPLE BASIC 103
ADVANCED BASIC
PROGRAMMING TECHNIQUES
FOR COMMODORE MODEMS
The following information tells you how to:
The programming procedures operate in C128 or C64 modes with the Modem/300.
In C128 mode, select a bank configuration which contains BASIC, I/O, and the Kernal.
To generate these tones in BASIC with your Commodore 128, follow this procedure:
1. Initialize the sound (SID) chip with the following BASIC statements:
SID = 54272
POKE SID + 24,15:POKE SID + 4,16
POKE SID + 11,16:POKESID + 5,0:POKE SID + 12,0
POKE SID + 6,15*16:POKE SID + 13,15*16:POKE SID + 23,0
2. Next, select one row and one column value for each digit in the telephone
number. The POKE statement for each row and column are as follows:
Column 1: POKE SID, 117:POKE SID + 1,77
Column 2: POKE SID,152:POKE SID + 1,85
Column 3: POKE SID, 161, POKE SID + 1,94
Row 1: POKE SID + 7,168:POKE SID + 8,44
Row 2: POKE SID + 7,85,:POKE SID + 8,49
Row 3: POKE SID + 7,150:POKE SID + 8,54
Row 4: POKE SID + 7,74 :POKE SID + 8,60
For example, to generate a tone for the number 1, POKE the values for row
1, column 1 as follows
POKE SID + 7,168:POKE SID + 8,44:REM ROW 1
POKE SID,117:POKE SID + 1,77:REM COLUMN 1
3. Turn on the tones and add a time delay with these statements:
POKE SID + 4,17:POKESID + 11,17:REM ENABLE TONES
FOR I = 1 TO 50:NEXT:REM TIME DELAY
4. Turn off the tones and add a time delay with the following statements:
POKE SID + 4,16:POKE SID + 11,16:REM DISABLE TONES
FOR I= 1 TO 50:NEXT:REM TIME DELAY
5. Now repeat steps 2 through 4 for each digit in the telephone number you are
dialing.
6. Finally, disable the sound chip with this statement:
POKE SID + 24,0
1. Set the modem's answer/originate switch to the " O " for originate.
2. Program the telephone to be OFF the hook.
3. Wait 2 seconds (FOR I = 1 to 500:NEXT:REM 2-SECOND DELAY)
4. Dial each digit and follow it with a delay (FOR I = 1 TO 50:NEXT)
5. When a carrier (high pitched tone) is detected, the Modem/300 automatically
goes on-line with the computer you are connecting with.
6. Program the phone to hang up when you are finished.
DETECTING CARRIER
Your Commodore Modem/1200 and Modem/300 are shipped from the factory with the
ability to detect a carrier on the Commodore 128.
That ability is useful in an unattended auto-answer mode. By monitoring the
carrier detect line, the computer can be programmed to hang up after loss of carrier.
Since a caller may forget to hang up, your program should monitor the transmit and
receive data lines. If there is no activity for five minutes or so, the modem itself should
hang up.
To detect carrier on the Commodore 128, the following statement can be used in a
BASIC program:
OH = 56577:
IF ((PEEK (OH) AND 16) = 0) THEN PRINT "CARRIER DETECTED"
If bit 4 of location 56577 contains a value other than 0, then no carrier is detected.
To perform any of the escape capabilities within a program, use a line such as:
10150 PRINT CHR$(27) + " U "
to create an underline cursor (in 80-column only). For example, to clear from the cursor
to the end of a window:
10160 PRINT CHR$(27) + " @ "
(See the Screen Editor section of Chapter 13 for all the escape and control codes
available on the Commodore 128.)
RELOCATING BASIC
To relocate the beginning or ending of BASIC (in C128 mode) for additional memory or
to protect machine-language programs from being overwritten by BASIC text, it is
necessary to redefine the starting and ending pointers in required memory addresses.
The Start of BASIC pointer is located at address 45($2D) and 46($2E). The Top
of BASIC pointer is at addresses 4626($1212) and 4627($1213). The following instruc-
tion displays the default locations of the beginning and end of BASIC text, respectively
(when a VIC bit-mapped screen is not allocated):
PRINT PEEK(45),PEEK(46),PEEK(4626),PEEK(4627)
1 28 0 255
Since the second number in each case is the high byte value, the default start of
basic is 28*256 plus 1 or 7169 while the top is 255*256 or 65280.
The following command reduces the size of BASIC text (program) area by 4K by
lowering the top of BASIC to address 61184 (239*256):
POKE4626,239:POKE4627,0:NEW
To move the beginning of BASIC up in memory by 1K, from 7168 to 8192, use
this command line:
POKE 46,32:POKE45,1:NEW
This is the case only when a bit-mapped graphics screen is not allocated. Remem-
ber, the beginning of BASIC starts at 16384($4000) when a bit-mapped screen is
allocated, and other parts of memory are shifted around.
ONE STEP BEYOND SIMPLE BASIC 107
The Commodore 128 is capable of producing two types of video signals: 40-
column composite video, and 80-column RGBI video. The composite video signal,
channeled through a VIC II (Video Interface Controller) chip (8564)—similar to that
used in the Commodore 64—mixes all of the colors of the spectrum in a single signal to
the video monitor. The 8563 separates the colors red, green and blue to drive separate
cathode ray guns within the video monitor for a cleaner, crisper and sharper image than
composite video.
The VIC II chip supports all of the Commodore BASIC 7.0 graphics commands,
SPRITES, sixteen colors, and the graphic display modes mentioned before. The 80-
column chip, primarily designed for business applications, also supports sixteen colors
(a few of which are different from those of the VIC chip), standard text mode, and bit
map mode. Sprites are not available in 80-column output. Bit map mode is not
supported by the Commodore BASIC 7.0 language in 80-column output. The 80-column
screen can be bit mapped through programming the 8563 video chip with machine
language programs. See Chapter 10, Programming the 80-Column (8563) Chip, for
information on bit mapping the 80-column screen.
COMMODORE 128 GRAPHICS PROGRAMMING 111
This chapter discusses how to use the Commodore 128 graphics features through
BASIC using the VIC (40-column) screen. Except for the sprite commands, each
graphic command is listed in alphabetical order. The sprite commands are covered in
Chapter 9. Following the format of each command are example programs that illustrate
the features of that command. Wherever possible, machine language routines are
included to show how the machine language equivalent of a BASIC graphics command
operates.
Chapter 8, The Power Behind Commodore 128 Graphics, is a description of the
inner workings of the Commodore 128 graphics capabilities. It explains how screen,
color and character memory are used and how these memory components store and
address data in each display mode. Chapter 9 then explains how to use sprites with the
new BASIC commands. Chapter 9 also discusses the inner workings of sprites, their
storage and addressing requirements, color assignments, and describes how to control
sprites through machine language.
TEXT DISPLAY
Text display shows only text or characters, such as letters, numbers, special symbols
and the graphics characters on the front faces of most C128 keys. The C128 can display
text in both 40-column and 80-column screen formats. Text display includes standard
character mode, multi-color character mode and extended background color mode.
The Commodore 128 normally operates in standard character mode. When you
first turn on the Commodore 128, you are automatically in standard character mode. In
addition, when you write programs, the C128 is in standard character mode. Standard
character mode displays characters in one of sixteen colors on a background of one of
sixteen colors.
Multi-color character mode gives you more control over color than the standard
graphics modes. Each screen dot, a pixel, within an 8-by-8 character grid can have one
of four colors, compared with the standard mode which has only one of two colors.
Multi-color mode uses two additional background color registers. The three background
color registers and the character color register together give you a choice of four colors
for each dot within an 8-by-8 dot character grid.
Each pixel in multi-color mode is twice as wide as a pixel in standard character
mode and standard bit map mode. As a result, multi-color mode has only half the
horizontal resolution (160 x 200) of the standard graphics modes. However, the
increased control of color more than compensates for the reduced horizontal resolution.
Extended background color mode allows you to control the background color and
foreground color of each character. Extended background color mode uses all four
background color registers. In extended color mode, however, you can only use the first
sixty-four characters of the screen code character set. The second set of sixty-four
characters is the same as the first, but they are displayed in the color assigned to
background color register two. The same holds true for the third set of sixty-four
characters and background color register three, and the fourth set of sixty-four characters
and background color register four. The character color is controlled by color memory.
For example, in extended color mode, you can display a purple character with a yellow
background on a black screen.
Each of the character display modes receives character information from one of
two places in the Commodore 128 memory. Normally, character information is taken
from character memory stored in a separate chip called ROM (Read Only Memory).
However, the Commodore 128 gives you the option of designing your own characters
and replacing the original characters with your own. Your own programmable characters
are stored in RAM.
COMMAND SUMMARY
Following is a brief explanation of each graphics command available in BASIC 7.0:
The following paragraphs give the format and examples for each of the non-sprite
BASIC 7.0 graphic commands. For a full explanation of each of these commands, see
the BASIC 7.0 Encyclopedia in Chapter 2.
BOX
Draw a box at a specified position on the screen.
BOX [color source], X1, Yl[,X2,Y2][,angle][,paint]
where:
color source 0 = Background color
1 = Foreground color
2 = Multi-color 1
3 = Multi-color 2
X1, Yl Top left corner coordinate (scaled)
X2, Y2 Bottom right corner opposite X1, Yl, is the pixel cursor
location (scaled)
angle Rotation in clockwise degrees; default is 0 degrees
paint Paint shape with color
0 = Do not paint
1 = Paint
EXAMPLES:
CHAR
Display characters at the specified position on the screen,
CHAR [color source],X,Y[,string][,RVS]
This is primarily designed to display characters on a bit mapped screen, but it can also
be used on a text screen. Here's what the parameters mean:
EXAMPLE:
10 COLOR 2,3: REM multi-color 1 =Red
20 COLOR 3,7: REM multi-color 2 = Blue
30 GRAPHIC 3,1
40 CHAR 0,10,10, "TEXT",0
CIRCLE
Draw circles, ellipses, arcs, etc. at specified positions on the screen.
CIRCLE [color source],X,Y[,Xr][,Yr]
[,sa][,ea][,angle][,inc]
where:
color source 0 = background color
1 = foreground color
2 = multi-color 1
3 = multi-color 2
X,Y Center coordinate of the CIRCLE
Xr X radius (scaled)
Yr Y radius (default is xr)
sa Starting arc angle (default 0 degrees)
ea Ending arc angle (default 360 degrees)
angle Rotation in clockwise degrees (default is 0 degrees)
inc Degrees between segments (default is 2 degrees)
EXAMPLES:
CIRCLE 1, 160,100,65,10 Draws an ellipse.
CIRCLE1, 160.100,65,50 Draws a circle.
CIRCLE1, 60,40,20,18,,,,45 Draws an octagon.
CIRCLE1, 260,40,20,,,,,90 Draws a diamond.
CIRCLE1, 60,140,20,18,,,, 120 Draws a triangle.
CIRCLE1,+ 2 , + 2,50,50 Draws a circle (two pixels down and two to
the right) relative to the original coordinates of
the pixel cursor.
SAMPLE PROGRAMS:
10 REM SUBMARINE TRACKING SYSTEM
20 COLOR 0,1:COLOR 4,1:COLOR 1,2:REM SELECT BKGRND, BRDR,SCREEN COLORS
30 GRAPHIC 1,1:REM ENTER BIT MAP MODE
40 BOX 1,0,0,319,199
50 CHAR 1,7,2 4,"SUBMARINE TRACKING SYSTEM" :REM DISPLAY CHARS ON BIT MAP
60 COLOR 1,3:REM SELECT RED
70 XR=0:YR=0:REM INIT X AND Y RADIUS
80 DO
90 CIRCLE 1,160,100,XR,YR,0,360,0,2:REM DRAW CIRCLES
100 XR=XR+10:YR=YR+10:REM UPDATE RADIUS
110 LOOP UNTIL XR=90
120 DO
130 XR= 0:YR= 0
140 DO
150 CIRCLE 0,160,100,XR,YR,0,360,0,2 :REM ERASE CIRCLE
160 COLOR 1,2 :REM SWITCH TO WHITE
170 DRAW 1,160,100+XR:DRAW 0,160,100+XR:REM DRAW SUBMARINE BLIP
180 COLOR 1,3:REM SWITCH BACK TO RED
190 SOUND 1,16000,15:REM BEEP
200 CIRCLE 1,160,100,XR,YR,0,360,0,2 :REM DRAW CIRCLE
210 XR=XR+10:YR=YR+10 :REM UPDATE RADIUS
220 LOOP UNTIL XR=90 :REM LOOP
230 LOOP
COLOR
Define colors for each screen area.
COLOR source number, color number
This statement assigns a color to one of the seven color areas:
AREA SOURCE
0 40-column (VIC) background
1 40-column (VIC) foreground
2 multi-color 1
3 multi-color 2
4 40-column (VIC) border
5 character color (40- or 80-column screen)
6 80-column background color
1 Black 9 Orange
2 White 10 Brown
3 Red 11 Light Red
4 Cyan 12 Dark Gray
5 Purple 13 Medium Gray
6 Green 14 Light Green
7 Blue 15 Light Blue
8 Yellow 16 Light Gray
EXAMPLE:
SAMPLE PROGRAM:
DRAW
Draw dots, lines and shapes at specified positions on screen.
EXAMPLES:
SAMPLE PROGRAMS:
GRAPHIC
Select a graphic mode.
This statement puts the Commodore 128 in one of the six graphic modes:
MODE DESCRIPTION
0 40-column text
1 standard bit map graphics
2 standard bit map graphics (split screen)
3 multi-color bit map graphics
4 multi-color bit map graphics (split screen)
5 80-column text
EXAMPLES:
GRAPHIC 1,1 Select standard bit map mode and clear the bit map.
GRAPHIC 4,0,10 Select split screen multi-color bit map mode, do not clear
the bit map and start the split screen at line 10.
GRAPHIC 0 Select 40-column text.
GRAPHIC 5 Select 80-column text.
GRAPHIC CLR Clear and deallocate the bit map screen.
SAMPLE PROGRAM:
10 REM GRAPHIC MODES EXAMPLE
20 COLOR 0,1:COLOR 4,1:COLOR 1,7
30 GRAPHIC 1,1:REM ENTER STND BIT MAP
40 CIRCLE 1,160,100,60,60
50 CIRCLE 1,160,100,30,30
60 CHAR 1,9,24,"STANDARD BIT MAP MODE"
70 SLEEP 4
80 GRAPHIC 0,l:REM ENTER STND CHAR MODE
90 COLOR 1,6:REM SWITCH TO GREEN
100 FOR I=1 TO 2 5
110 PRINT"STANDARD CHARACTER MODE"
120 NEXT
130 SLEEP 4
140 GRAPHIC 2,1:REM SELECT SPLIT SCREEN
150 CIRCLE 1,160,70,50,50
160 CHAR 1,14,1,"SPLIT SCREEN"
170 CHAR 1,8,16,"STANDARD BIT MAP MODE ON TOP"
180 FOR I=1 TO 25
190 PRINT" STANDARD CHARACTER MODE ON THE BOTTOM"
200 NEXT
210 SLEEP 3:REM DELAY
220 SCNCLR:REM CLEAR SCREEN
230 GRAPHIC CLR:REM DE-ALLOCATE BIT MAP
GSHAPE
Retrieve (load) the data from a string variable and display it on a specified coordinate.
LOCATE
Position the bit map pixel cursor (PC) on the screen.
LOCATE X, Y
EXAMPLE:
Position the PC in the center of the bit map screen.
LOCATE 160,100
Nothing will be seen until something is drawn.
Move the PC 20 pixels to the right of the last PC position
LOCATE +20,100
and place it at Y coordinate 100.
Move the PC 30 pixels to the right and 20 down from
LOCATE+30,+ 20
the previous PC position.
PAINT
Fill area with color.
PAINT [color source],X,Y[,mode]
COMMODORE 128 GRAPHICS PROGRAMMING 121
where:
color source 0 Bit map background
1 Bit map foreground (default)
2 Multi-color 1
3 Multi-color 2
X,Y starting coordinate, scaled (default at pixel cursor (PC))
mode 0 = paint an area defined by the color source selected
1 = paint an area defined by any non-background source
EXAMPLE:
10 CIRCLE 1, 160,100,65,50 Draws an outline of a circle.
20 PAINT 1, 160,100 Fills in the circle with color from source 1 (VIC
foreground), assuming point 160,100 is colored
in the background color (source 0).
10 BOX 1, 10, 10, 20, 20 Draws an outline of a box.
20 PAINT 1, 15, 15 Fills the box with color from source 1, assuming
point 15,15 is colored in the background source
(0).
30 PAINT 1, +10, +10 PAINT the screen in the foreground color source
at the coordinate relative to the pixel cursor's
previous position plus 10 in both the vertical and
horizontal positions.
SCALE
Alter scaling in graphics mode.
SCALE n [,Xmax,Ymax]
where:
n = 1 (on) or 0 (off)
X max = 320-32767
(default = 1023)
Y max = 200-32767
(default = 1023)
The default scale values are:
Multi-color mode X = 0 to 159 Y = 0 to 199
Bit map mode X = 0 to 319 Y = 0 to 199
EXAMPLES:
10 GRAPHIC 1,1 Enter standard bit map, turn scaling
20 SCALE 1:CIRCLE 1,180,100,100,100 on to default size (1023, 1023) and
draw a circle.
10 GRAPHIC 1,3 Enter multi-color mode, turn scaling
20 SCALE 1,1000,5000 on to size (1000,5000) and draw a
30 CIRCLE 1,180,100,100,100 circle.
SSHAPE
Save shapes to string variables.
SSHAPE and GSHAPE are used to save and load rectangular areas of multi-color or bit
mapped screens to/from BASIC string variables. The command to save an area of the
screen into a string variable is:
SSHAPE string variable, XI, Yl [,X2,Y2]
where:
string variable String name to save data in
X1,Y1 Corner coordinate (0,0 through 319,199) (scaled)
X2,Y2 Corner coordinate opposite (X1,Y1) (default is the PC)
EXAMPLES:
SSHAPE A$, 10,10 Saves a rectangular area from the coordinate 10,10
to the location of the pixel cursor, into string vari-
able A$.
SSHAPE B$, 20,30,47,51 Saves a rectangular area from top left coordinate
(20,30) through bottom right coordinate (47,51) into
string variable B$.
SSHAPE D$,+ 10,+ 10 Saves a rectangular area 10 pixels to the right and 10
pixels down from the current position of the pixel
cursor.
Also, see the example program under GSHAPE for another example.
WIDTH
Set the width of drawn lines.
WIDTH n
This command sets the width of lines drawn using BASIC'S graphic commands to either
single or double width. Giving n a value of 1 defines a single width line; a value of 2
defines a double width line.
EXAMPLES:
WIDTH 1 Set Single width for graphic commands
WIDTH 2 Set double width for drawn lines
5
MACHINE
LANGUAGE
ON THE
COMMODORE 128
This chapter introduces you to 6502-based machine language programming. Read this
section if you are a beginner or novice machine language programmer. This section
explains the elementary principles behind programming your Commodore 128 in machine
language. It also introduces you to the 8502 machine language instruction set and how
to use each instruction. If you are already an experienced machine language program-
mer, skip this section and continue to the 8502 Instruction and Addressing Table at the
end of the chapter for reference material on machine language instructions. The 8502
instruction set is exactly the same as the 6502 microprocessor instruction set.
Programs such as those used in arcade games cannot operate in the relatively slow
speed of BASIC, so they are written in machine language. Other instances dictate the
use of machine language simply because those programming operations are handled
better than in a high-level language like BASIC. But some programming functions such
as string operations are easier in BASIC than in machine language. In these cases,
BASIC and machine language can be used together. You can find information on how to
mix machine language with BASIC in Chapter 7.
Inside your computer is a perpetually running program called the operating
system. The operating system program controls every function of your computer. It
performs functions at lightning speeds you are not even aware of.
The operating system program is written entirely in machine language and is
stored in a portion of the computer called the Kernal ROM. (Chapter 13 describes how
to take advantage of the machine language programs within the Kernal, and how to use
parts of the operating system in your own machine-language programs.)
Though machine language programming may seem more complicated and difficult
than BASIC at first, think back to when you didn't know BASIC or your first
programming language. That seemed difficult at first, too. If you learned BASIC or
another programming language, you can learn machine language. Although it's a good
idea to learn a higher-level language such as BASIC before you start machine language,
it's not absolutely necessary.
EXAMPLES OF
MACHINE-LANGUAGE INSTRUCTIONS
LDA $100 ; Absolute addressing
LDA $10 ; Zero page absolute addressing
LDA ($FA),Y ; Indirect indexed addressing
LDA $2000,X ; Indexed addressing (absolute)
LDA #$10 ; Immediate addressing (constants)
MACHINE LANGUAGE ON THE COMMODORE 128 127
Accumulator
X index register
Y index register
Status register
Program counter
Stack pointer
THE ACCUMULATOR
The accumulator is one of the most important registers within the 8502 microprocessor.
As the name implies, it accumulates the results of specific operations. Think of
the accumulator as the doorway to your microprocessor. All information that enters
your computer must first pass through the accumulator (or the X or Y register).
For example, if you want to store a value within one of the RAM locations, you must
first load the value into the accumulator (or the X or Y register) and then store it into the
specified RAM location. You cannot store a value directly into RAM, without placing it
into the accumulator or the index registers first. (The index registers are described in the
following section.)
DATA
DIRECTION P0---P6
REGISTER
PERIPHERAL
11
< = >
AEC
Ao
ill
A,
A, ITT
A,
A, DC
STACK
POINT
LU REGIS T £R
LL
A,
CD
A, CO
CO
LU
A, oc
a
D
A, ACCUMULATOR
A, CO
UJ
oc
I On IN
An
A, 2 INPUT
DATA
LATCH
EGE NO
ft BIT UN DATA
BUS
= 1 BIT UN
All mathematical operations are performed within the arithmetic logic unit (ALU)
and stored in the accumulator. It is considered a temporary mathematical work area. For
example, you want to add two numbers, 2 + 3. First, load the accumulator with the 2.
Next add 3 with the ADC mnemonic. Now, you want to perform another operation. You
must store the answer from the accumulator into a RAM location before you perform the
next math operation. If you don't, your original answer is erased.
The accumulator is so important that it has an addressing mode of its own. All the
instructions using this mode pertain specifically to the accumulator. The following three
sample instructions pertain solely to the accumulator in its own addressing mode:
Details on all of the accumulator addressing commands are given later in this chapter.
. CARRY 1 = TRUE
-ZERO 1 = RESULT ZERO
• IRQ DISABLE 1 = DISABLE
DECIMAL MODE 1 = TRUE
BRK COMMAND
-••OVERFLOW 1 = TRUE
• • NEGATIVE 1 x NEG
The Carry bit (0) is set if an addition operation carries a bit into the next position
to the left of the leftmost bit. The Carry bit is set by other conditions, of which this is
one. The SEC instruction sets the Carry bit. CLear the Carry bit with the CLC
instruction.
The Zero bit (1) is set if the result of an operation equals zero. The command BEQ
stands for Branch on result EQual to Zero. The command BNE stands for Branch on
Result Not Equal to zero. If the zero bit in the status register is set, the program
branches to the address relative to the current program counter value (for a BEQ
instruction). Otherwise, the BEQ command is skipped and the program resumes with the
instruction immediately following the BEQ statement.
The IRQ Disabled bit (2) is set if your program requests interrupts to be dis-
abled with the SEI command (Set Interrupt Disable Status). The Disable Interrupt
Status bit is cleared with the CLI command (CLear Interrupt Disable bit) to permit
interrupts to occur. You will learn more about programming interrupts in the section
entitled TYPES OF INSTRUCTIONS and in the Raster Interrupt program explanation in
Chapter 8.
The microprocessor sets the Decimal Mode bit (3) if you instruct the microproces-
sor to SEt Decimal Mode with the SED instruction. CLear the Decimal Mode bit with
the CLD instruction, CLear Decimal Mode.
The BRK flag (bit 4) operates similar to the IRQ disable flag. If a BRK instruction
occurs, it is set to 1. Like an IRQ interrupt, the BRK causes the contents of the
program counter to be pushed onto the stack. The contents of the status register is
pushed on top of the stack and evaluated. If the BRK flag is set, the operating system
or your application program must evaluate whether or not a BRK or interrupt has
occurred.
If the BRK flag is cleared once the status register is pushed onto the stack, the
processor handles this as an interrupt and services it. Unlike an interrupt, the BRK flag
causes the address of the program counter plus two to be saved. The microprocessor
expects this to be the address of the next instruction to be executed. You may have to
adjust this address since it may not be the actual address of the next instruction within
your program.
The Overflow flag (bit 6) is set by a signed operation overflowing into the sign
bit (bit 7) of the status register. You can clear the Overflow bit in the status register with
the CLV instruction (CLear Overflow flag). You can conditionally branch if the
Overflow bit is set with the BVS (Branch Overflow Set) instruction. Similarly, you can
conditionally branch if the overflow bit is clear with the BVC (Branch Overflow Clear)
instruction. The BIT instruction can be used to intentionally set the overflow flag.
The microprocessor sets the negative flag (bit 7) if the result of an arithmetic
operation is less than 0. You can conditionally branch if the result of an arithmetic
operation is negative, using the BMI instruction, (Branch on result Minus) or positive
using the BPL instruction, (Branch on Result Positive).
The status register indicates seven important conditions within the microprocessor
while your machine language program is executing. Your program can test for certain
conditions, and act upon the results. It gives you a way to conditionally control certain
machine level functions depending on the value of the status flags.
address where the interrupt or subroutine occurs is pushed on top of the stack. Once
the interrupt or subroutine is serviced, the address where it occurred is popped off
the stack and the computer continues where it left off when the interrupt or subroutine
occurred.
16-BIT ADDRESSING:
THE CONCEPT OF PAGING
The Commodore 128 contains 128K of Random Access Memory (RAM). This means
you have two banks of 65536 (64K) RAM memory locations (minus two for locations 0
and 1, which are always present in a RAM bank). Since the 8502 is an 8-bit micropro-
cessor, it needs two 8-bit bytes to represent any number between 0 and 65535. One
eight-bit byte can only represent numbers between 0 and 255. Your computer needs a
way to represent numbers as large as 65535 in order to address all the memory
locations.
Here's how your computer represents the largest number in one 8-bit byte. The
computer stores it as a binary number. You usually represent it as a hexadecimal number
in your machine-language programs. Figure 5-3 shows the relationship between binary,
hexadecimal and decimal numbers.
A byte contains eight binary digits (bits). Each bit can have a value of 0 or 1. The
largest number your computer can represent in eight binary digits is 1 1 1 1 1 1 1 1,
which equals 255 in decimal. This means all eight bits are set, or equal to 1. A
bit is considered off if it is equal to 0. In converting binary to decimal, all the binary
digits that are set are equal to 2 raised to the power of the bit position. The bit
positions are labeled 0 through 7 from right to left. Figure 5-4 provides a visual
representation of converting binary to decimal.
27
One binary byte = 1 1 1 1 1 1 1 1
The byte in decimal = 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 =255
Figure 5 - 4 . Binary/Decimal Conversion
The top of each column represents the value of 2 raised to the power of the bit
position. Since each bit is turned on when you represent the largest number in one byte,
add all the values at the bottom of each to obtain the decimal equivalent. Figure 5-5
shows another example that converts the binary number 1 1 0 0 1 0 1 0 to decimal.
27 2 6
2 s
2 4
2 3
2 2
21 2°
One binary byte = 1 1 0 0 1 0 1 0
T h e b y t e i nd e c i m a l = 1 2 8 + 6 4 + 0 + 0 + 8 + 0 + 2 + 0 = 202
Remember, only add the values of two raised to the bit position if the bit is set.
If a bit is off, it equals zero.
Now that you can convert one byte from binary to decimal, you are probably
wondering what this has to do with 16-bit addressing. We mentioned before that the
program counter—the register responsible for storing the address of the next instruction
to be executed—is 16 bits wide. This means it uses two bytes side-by-side to calculate
the address.
You just learned about the low byte, the lower half of the 16 bits used to represent
an address. The upper half of the 16-bit address is called the high byte. The high byte
calculates the upper half of the address the same way as the low byte, except the bit
position numbers are labeled from 8 on the right to 15 on the left. When you raise 2 to
the power of these bit positions, and add the resulting values to the low byte of the
address, you arrive at addresses that go up to 65535. This allows your computer
to represent any number between 0 and 65535, and address any memory location
within each 64K RAM bank. Figure 5-6 is an illustration of a 16-bit address in
decimal:
2io
High Byte 21S 214 213 212
2n 29 28
One binary bvte = 1 1 1 1 1 1 1 1
The byte in
decimal = 3 2 7 6 8 + 16384+ 8192 + 4096 + 2048 + 1024 + 512 + 2 5 6 = 65280
Low Byte 27 26 25 24 23 22 21 2°
One binary b y t e = 1 1 1 1 1 1 1 1
The byte in
decimal = 128 + 6 4 + 32 16 H- 8 -(- 4 Hh 2 -1- 1 = 255-255
65535
You can see that the highest number of the high byte of the 16-bit address is
65280. And you know that the highest number of the low byte of the 16-bit address
equals 255. Add the highest high-byte and the highest low-byte number (65280 + 255),
to arrive at 65535, the highest address within each of the two 64K RAM banks.
When the microprocessor calculates the address of the next instruction, it looks at
the high byte of the 16-bit program counter. Try to think of the high byte of the address
as just another 8-bit byte. If this was the case, the bit positions would be labeled from 0
on the right through 7 on the left, just like the low byte of the address. Therefore, the
largest number this 8-bit byte can represent again is 255 decimal.
The value in the high byte determines which 256-byte block is accessed. These
256-byte blocks are referred to as pages. The high byte determines the page boundary of
the address, so the high byte is calculated in increments of 256 bytes. The high byte of
the program counter determines which of the possible 256 pages is being addressed. If
you multiply the number of possible pages, 255 by 256 bytes, you realize the highest
page starts at location 65280, decimal, the same number as in the high byte in Figure
5-6. Location 65280 is the highest page boundary addressable.
What if you want to address a memory location that does not lie on a page
boundary? That's where the low byte of the 16-bit address comes in.
The high byte of the program counter represents the 256-byte page boundary.
All addresses between boundaries are represented by the low byte. For example, to
address location 65380 decimal represent the high byte as 255, since 255 times
256 equals 65280. You still have to move 100 addresses higher in memory to location
65380.
The low byte contains the value 100 decimal. The low byte value is added to the
high byte to find the actual, or effective address.
When you look at the memory map of your Commodore 128, you will see
references to the low byte and high byte pointers or vectors to certain machine-language
routines within the operating system or to important system memory locations, like the
start of BASIC.
You can find out the contents of these addresses and where the routines reside in
your Commodore 128's memory by using the PEEK command in BASIC, or the
Memory command in the Machine Language Monitor. To find the effective address
using BASIC, look in the memory map for the reference to a specific routine or system
function, sometimes called a vector. PEEK the high byte, the page number of the
routine. Multiply by 256 to find the page boundary. Then PEEK the low byte and add it
to the page boundary to arrive at the effective decimal address.
Keep in mind that all the address calculations are performed in binary. They are
explained in decimal so they're easier to understand. In your machine language pro-
grams, you will usually reference memory in hexadecimal notation, explained in the
next section.
HEXADECIMAL NOTATION
Your 8502 microprocessor only understands the binary digits 0 and 1. Although machine
language usually requires hexadecimal notation and BASIC processes decimal numbers,
those numbers are translated and processed as binary numbers. Your computer uses
three different number systems, binary (base 2), hexadecimal (base 16) and decimal
(base 10). The machine-language monitor also uses the octal number base. A number
base is also referred to as a radix; therefore, the C128 uses four radices, but the
microprocessor only understands binary at machine level.
BASIC understands decimal numbers because they are easiest for people to use.
Although BASIC doesn't process as fast as machine language, the ease of use makes up
for the loss of speed.
Machine language uses hexadecimal notation because it is closer to the binary
number system and easier to translate than decimal. Hexadecimal representation is also
used usually by machine-level programmers because it is easier for people to think of a
group of eight binary digits (a whole byte) than it is to think of them as separate digits
by themselves. How do you find it easier to represent this value:
UNDERSTANDING HEXADECIMAL
(HEX) NOTATION
The key behind understanding hexadecimal (base 16) numbers is to forget about decimal
(base 10). Hexadecimal digits are labeled from 0 through 9 and continuing with A
through F, where F equals 15 in decimal. By convention, hexadecimal numbers are
written with a dollar sign preceding the value so that they can be distinguished from
decimal values. Figure 5-7 provides a table of the hexadecimal digits and their decimal
and binary equivalents:
MACHINE LANGUAGE ON THE COMMODORE 128 137
$0 0 0000
$1 1 0001
$2 2 0010
$3 3 0011
$4 4 0100
$5 5 0101
$6 6 0110
$7 7 0111
$8 8 1000
$9 9 1001
$A 10 1010
$B 11 1011
$C 12 1100
$D 13 1101
$E 14 1110
$F 15 mi
Figure 5—7. Hexadecimal Decimal Binary Conversion
Each hex digit represents four bits. The highest number you can represent with
four bits is 15 decimal. In machine language, you usually represent operands and
addresses as two or four hex digits. Since each hex digit of a four-digit hexadecimal
address takes up four bits, four of them represent 16 bits for addressing.
At first you'll find yourself converting decimal addresses and operands into
hexadecimal. Then you'll want to convert the other way. See the HEX$ and DEC
functions for quick and easy decimal to HEX conversions. In the machine language
monitor, use the ( + ) plus sign to represent decimal numbers. Use the conversions for
now, but eventually you should find yourself thinking hexadecimal notation instead of
always converting from decimal to hexadecimal.
ADDRESSING MODES IN
THE COMMODORE 128
Addressing is the process by which the microprocessor references memory. The 8502
microprocessor has many ways to address the internal locations in memory. The
different addressing modes require either one, two or three bytes of storage depending
on the instruction. Each instruction has a different version and op-code. For example,
LDA (LoaD the Accumulator) has eight versions, each with a different op-code to
specify the various addressing modes. See the 8502 Instruction and Addressing Table
section for the different versions of all the 8502 machine-language instructions.
ACCUMULATOR ADDRESSING
Accumulator addressing implies that the specified operation code operates on the
accumulator. The operand field is omitted since the instruction can only perform the
operation on the accumulator. Accumulator instructions require only one byte of stor-
age. Here are some examples of accumulator addressing instructions:
IMMEDIATE ADDRESSING
Immediate addressing specifies that the operand be a constant value rather than the
contents of a particular address. The operand is the data, not a pointer to the data. At
machine level, the microprocessor actually interprets an operand field constant
and an address in the operand field as two different op-codes, so the pound sign gives
the programmer a way to distinguish between the data and a pointer to the data.
Immediate addressing instructions require two bytes of storage. Here are some immedi-
ate addressing instruction examples:
ABSOLUTE ADDRESSING
Absolute addressing allows you to access any of the memory locations within either 64K
RAM bank. Absolute addressing requires three bytes of storage; the first byte for the
op-code, the second for the low byte of the address and the third for the high byte. Here
are some examples of absolute addressing instructions:
MACHINE LANGUAGE ON THE COMMODORE 128 139
ZERO-PAGE ADDRESSING
Zero-page addressing requires two bytes of storage; the first byte is used for the opcode
and the second for the zero-page address. Since zero page ranges from addresses 0
through 255, the computer only needs the low byte to represent the actual address. The
high byte is assumed to be 0; therefore, it is not specified. When addressing a zero-page
location, you can still use absolute addressing; however, the execution time is not as fast
as zero-page addressing. Here are some examples:
LDA $FF $A5 Load the accumulator with the contents of zero-page
location $FF (255)
ORA $E4 $05 OR the accumulator with the contents of location
$E4
ROR $0F $66 Rotate the contents of location $0F one bit to the
right
IMPLIED ADDRESSING
In implied addressing mode, no operand is specified because the op-code suggests the
action to be taken. Since no address or operand is specified, an implied instruction
requires only one byte for the op-code. Some examples are:
Figure 5-8 lists the (A) code on the left as it appears in symbolic assembly
language. The code (B) in the middle is the actual machine-level machine code
as it appears in the machine language monitor. The (C) code to the right is the symbolic
machine language as it appears in the monitor as executable code.
In this program segment, the first instruction LoaDs the Accumulator with 1.
STA is the op-code for STore the contents of the Accumulator in the variable
TEMP. The third instruction, DEC, decrements the contents of the variable TEMP. In
the third instruction, START is a label which marks the beginning of the conditional
loop. The branch instruction (BEQ) checks to see if the value stored in TEMP equals
0 as a result of the DECrement instruction. The instruction marks the end of the
loop.
The first time through this loop, the result in TEMP equals 0 so program control
branches back to the instruction specified by the label START.
The second time through the loop, TEMP is less than zero; therefore, the zero
flag in the status register is cleared, the program does not branch to START and
continues with the statement directly following the branch instruction (LDX #$01).
MACHINE LANGUAGE ON THE COMMODORE 128 141
Because of the way this program segment is written, a branch can occur only once, the
first time through the loop.
Under relative addressing, the first byte of the instruction is the op-code and the
second is the operand, representing an offset of a number of memory locations. The
location to branch back to is not interpreted as an absolute address but an offset relative to
the location of the branch instruction in memory.
The offset ranges from -128 through 127. If the condition of the branch is met,
the offset is added to the program counter and the program branches to the address in
memory.
In the example in Figure 5-8, notice that the operand in the branch instruction is
only one instruction past the label START. The operand START is interpreted by the
computer as an offset of three bytes backward in memory since the DEC instruction use
2 bytes and the BEQ op-code uses one byte. The 8502 can only branch forward 127
bytes and branch backward by 128 bytes.
If you enter the machine-language monitor and disassemble the machine-language
code, you'll see how the computer represents a branch instruction operand as in part (B)
of Figure 5-8. The symbolic code in part (C) operand field represents the operands as
absolute addresses but the assembled hexadecimal code to the left in part (B) of the op
code stores the operand using one byte, a number plus or minus the address of the
branch instruction. The largest number for a forward branch is $7F. A backward branch
is represented by hex numbers greater than $80. When you are within the machine-
language monitor, subtract the operand offset from 255 ($FF) to find the actual value of
the negative offset. In this case $FF minus 3 equals $FC, which is the operand in the
branch instruction in part (B) of Figure 5-8.
Here are some examples of relative addressing branch instructions:
JMP ($0326)
zero-page memory address. The contents of the pointer and the contents of the Y
register are added to arrive at the low byte of the effective address. The contents of the
pointer act as the base address and the contents of the Y register act as the displacement.
The carry, if any, is added to the memory location directly following the low-byte
address which becomes the high byte of the effective address. This is true indexing,
designed specifically for manipulating tables of data. In order to access different table
values, just change the contents of the Y register since the base address is already
established. Here's an example:
LDY #$08
LDA #$00
STA ($EA),Y
The first instruction loads the Y register with $08. The second instruction loads
the accumulator with 0. The third instruction stores the contents of the accumulator in
the effective address.
To find the effective address, add the contents of the zero page memory location
(base address) specified in the instruction to the contents of the Y register (displace-
ment). In this example, the contents of the address SEA equals $F0. Add $F0 to the
contents of the Y register ($08) to arrive at $F8, the low byte of the effective address of
the next instruction. The high byte of the effective address is obtained by adding the
carry (none in this case) to the zero-page memory location immediately following the
low-byte address. For example, location $F9 contains the value $3F. Since the low byte
is $F8 and the high byte equals $3F, the effective address is S3FF8.
Notice the difference between indirect indexed and indexed indirect addressing
modes as they can be confusing. Remember, the most important difference between the
two addressing modes is the way the effective address is calculated. Indexed indirect is
X indexing, which is indexed prior to the arrival of the effective address. Indirect
indexed is post-indexed with the Y register.
You have just covered all the addressing modes in the Commodore 128. Each calls
for different circumstances and you should use the correct mode whenever circum-
stances dictate it to obtain optimal performance from the microprocessor. For example,
use indexed zero-page addressing when you are manipulating zero-page locations in-
stead of using indexed absolute.
TYPES OF INSTRUCTIONS
This section explains all the types of machine-language instructions available in the
Commodore 128. They are first covered by type of instruction, such as REGISTER TO
MEMORY and COMPARE instructions; then they are listed alphabetically by op-code
mnemonic with all the different addressing options. This section provides important
information on programming in machine language on the Commodore 128 (or any
6502-based microcomputer).
Use this information as a reference for background on each instruction. Figure 5-9
provides an alphabetized list of the 8502 microprocessor op-code mnemonics. For
detailed, quick-reference information, see the following section for an alphabetic list of
instructions, their hexadecimal op-codes, the different versions of the instructions for
each addressing mode and the way they affect the flags in the status register.
NOP No Operation
MACHINE LANGUAGE ON THE COMMODORE 128 147
REGISTER TO MEMORY
INSTRUCTIONS
The REGISTER TO MEMORY instructions are:
LDA STA
LDX STX
LDY STY
The register to memory instructions either place a value into the accumulator, X
register or Y register from memory, or store a value from a register (A, X, or Y) into a
memory address.
LDX #$0A
LDX $2000
LDX #$FB
COUNTER INSTRUCTIONS
The COUNTER instructions are
INC DEC
INX DEX
INY DEY
Counter instructions can be used to keep track of or count the number of times an
event occurs. These instructions are used for mathematical manipulations or indexing a
MACHINE LANGUAGE ON THE COMMODORE 128 149
series of addresses. The counter instruction, INC, increments the contents of a memory
address by a value of 1 each time it is encountered. These instructions are used primarily
within a program loop and in conjunction with a branch instruction. Here's an example
of a loop and how INC keeps track of a number of occurrences of an event:
LDX #$00
TXA
START STA $2000,X
INX
BNE START
The first instruction loads a 0 into the X register. The second instruction transfers
the contents of the X register into the accumulator (without erasing the X register).
Instruction three stores the contents of the accumulator (0) into location $2000 the first
time through the loop. The fourth instruction increments the contents of the X register.
The last instruction branches to the instruction specified by the label START, until the
value of the X register equals 0.
This program segment stores O's in an entire page (256 locations) starting at $2000
and ending at $20FF. When the contents of the X register equals 255 and it is
incremented again, it is reset to 0, since it can only hold an eight-bit number. When this
occurs, the branch is skipped and the program continues with the instruction directly
following the branch instruction.
The INY instruction operates in the same way as INX, since it also only uses
implied addressing. The INC instruction, on the other hand, uses several different
addressing modes including absolute, which uses 16-bit addresses. With the INC
instruction, you can count past the capacity of an 8-bit number, though you must
separate the counter into a high byte and a low byte. For example, the low byte counts
the increments of less than a page and the high byte keeps track of the number of pages.
When low-byte counter is at 255 and is incremented, it is set back to 0. When this
occurs, increment the high-byte counter. To count up to 260 (decimal), the high-
byte value equals 1 and the low byte equals 4. Here's an equation to illustrate the point:
(1 * 256) + 4 = 260
Here's the machine-language code that does this:
LDA #$00
STA HIGH
STA LOW
LOOP INC LOW
BNE LOOP
INC HIGH
LOOP 2 INC LOW
LDA LOW
CMP #$04
BNE LOOP2
The DECrement instructions operate the same way as the increment instructions.
They are the negative number counterparts of the increment counters.
COMPARE INSTRUCTIONS
The Commodore 128 has three compare instructions that check the contents of a register
with the contents of memory. A compare operation can be used to determine which
instructions to execute as a result of a conditioned value. The compare instructions are:
CMP
CPX
CPY
The CMP instruction compares the contents of the accumulator with the contents
of the specified address in the instruction. Compare instructions essentially subtract
memory from a register value but change neither—they just set status flags. CPX
compares the contents of the X register with the specified address. CPY compares the
contents of the Y register with the specified memory location.
All three instructions have versions that will operate in immediate, zero-page and
absolute addressing modes. This means you can compare the contents of a register
(A,X, or Y) with the contents of a zero-page location, any other address above zero page,
or against a constant. Here's an example:
LDX #$00
LDA #$00
ONE STA $DF,X
INX
CPX #$0A
BNE ONE
The preceding program segment stores 0's in 10 consecutive memory addresses
starting at $DF. The first instruction loads the X register with 0, the second loads 0 into
the accumulator. The third instruction stores 0 in location $DF plus the contents of the X
register. The fourth instruction increments the X register. The fifth instruction compares
the contents of the X index register with the constant $0A (10 decimal). If the contents
of the X register does not equal $0A, the program segment branches back to the store
instruction specified by the label ONE. After the loop cycles ten times, the X register
and the constant $0A are equal. Therefore the processor does not take the branch
and the program continues with the instruction immediately following BNE.
You can compare the value of a register with the contents of an absolute memory
address. Here's the same example as above using the contents of a memory address
instead of a constant:
LDA #$0A
STA $FB
LDX #$00
LDA #$00
ONE STA $DF,X
INX
CPX $FB
BNE ONE
MACHINE LANGUAGE ON THE COMMODORE 128 151
Remember, if you want to compare numbers larger than eight bits can represent
(greater than 255 decimal), you must separate the number into a low byte and a
high byte.
The BIT instruction can also be used for comparisons. See the logical instructions
next.
ARITHMETIC AND
LOGICAL INSTRUCTIONS
The accumulator is responsible for all mathematical and logical operations performed in
your computer. The mathematical and logical instructions available in machine language are:
ADC EOR
AND ORA
BIT SBC
Here's what each instruction means:
ADC—Add the contents of the specified memory address to the contents of the
accumulator with a carry. It is considered a good programming practice to clear
the carry bit with the CLC instruction before performing any addition. This avoids
adding the carry into the result.
AND—Perform the logical AND operation with the contents of the accumulator and the
contents of the specified memory address.
BIT—Compare the bits in the specified memory address with those in the accu-
mulator. Bits 6 and 7 are transferred to the status register flags. Bit 7 is trans-
ferred to the negative status flag bit and bit 6 is sent to the overflow status flag bit.
EOR—Perform the exclusive OR operation with the contents of the specified memory
address and the contents of the accumulator.
ORA—Perform the logical OR operation with the contents of the specified memory
address and the contents of the accumulator.
SBC—Subtract the contents of the specified memory address from the contents of the
accumulator with a borrow. (It is a good practice to set the carry flag before
performing subtraction. This avoids subtracting the borrowed bit from the result.)
ARITHMETIC INSTRUCTIONS
(ADC, SBC)
The addition and subtraction instructions are easy to understand. Here's an example:
CLC
LDA #$0A
STA $FB
ADC #$04
SEC
SBC #$06
ADC $FB
STA $FD
This program segment essentially performs the following mathematical operation:
(10 + 4)-6+ 10= 18.
The first instruction clears the carry bit. The second instruction loads the accumu-
lator with $0A (10 decimal). The third instruction stores the value in address $FB for
later use. The fourth instruction adds the constant $04 to the value already in the
accumulator. The SBC instruction subtracts the constant $06 from the contents of the
accumulator. The next instruction, ADC $FB, adds the contents of memory location
$FB to the contents of the accumulator. The resulting value (18($12)) of all the
mathematical operations is stored in address $FD.
LOGICAL INSTRUCTIONS
(AND, EOR, AND ORA)
These instructions operate on the contents of a memory address and a register. The AND
operation is a binary (Boolean) algebra operation having two operands that can result in
one of two values, 0 or 1. The only way an AND operation can result in a 1 is if both
the operands equal 1; otherwise the result is 0. For example, the two operands are the
contents of a specified memory address and the contents of the accumulator. Here's an
illustration of this concept:
As noted, the result of an AND operation is (true) 1, only if the two operands are
equal to 1; otherwise the result is 0. Notice bit 7 (high-order bit) equals 1 because both
bit 7's in the operands are 1. The only other resulting bit equal to 1 is bit 1, since both bit
l's are equal to 1. The rest of the bits are equal to zero since no other bit positions in
both operands are equal to 1. A 1 and a 0 equals 0, as does a 0 and a 0.
The Boolean OR works differently. The general rule is:
If one of the operands equals 1, the resulting Boolean value equals 1.
For example, the two operands are the contents of a specified memory address and
the contents of the accumulator. Each individual bit can be treated as an operand. Here's
an illustration.
For all the bit positions that equal one in either operand, the resulting value of that
bit position equals 1. The result is 1 if either operand or both operands are equal to 1.
The exclusive OR works similarly to the OR operation, except if both operands
equal 1, the result is zero. This suggests the following general rule:
MACHINE LANGUAGE ON THE COMMODORE 128 153
If either of the operands equals 1, the resulting Boolean value is 1. except if both
operands are 1, then the result equals 0.
In this example, the operands are the same as in the previous OR example. Notice
bits 0 and 7 are now equal to 0 since both operands are equal to 1. All other bit values
remain the same.
BIT
The BIT instruction performs a logical AND operation on the contents of the specified
memory address and the contents of the accumulator, but the resulting value is not
stored in the accumulator. Instead, the zero flag in the status register is set by the result
of the operation. The BIT instruction compares the contents of the accumulator and the
contents of the memory address, bit-for-bit. If the result of the operation of the
accumulator being ANDed by a memory location is 0, then the zero flag (in the status
register) is set to a 1. Otherwise the zero flag is 0.
Your machine language program can then act conditionally depending on the
result of the zero flag in the status register. In addition, bits 7 and 6 from the specified
memory address are moved into the negative-flag and overflow-flag bit positions in the
status register, respectively. These flags can also be used to perform conditional
instructions depending on the value of the flag. For example, the BIT instruction
performs the following:
7 0
NV Rl) 17,r
Contents of Memory Address = 10101001
Contents of Accumulator = 11001101 --» 1 0 0
Since the resulting bit pattern is not 0, the zero flag in the status register is 0.
In addition, bits 7 and 6 are placed in the bit positions of the negative and overflow
flags, respectively, in the status register. Notice the result of the BIT instruction's AND
operation is not stored in the accumulator. The original contents of the accumulator
remain intact. See the following example of 2-bit pattern operands that result in 0 when
ANDed:
7 0
NV BDIZC
Contents of Memory Address = 01111010
Contents of Accumulator = 10000100 -» 01 1
This time the bit patterns result in 0. Therefore, the zero flag in the status register
is set to 1. Bits 7 and 6 are also placed into their respective negative and overflow status
register bit positions from their positions in the memory location.
Now you know how each of the arithmetic and logical instructions operate. The
next section discusses branching instructions. Branching instructions are designed so
you can conditionally execute a certain set of instructions, depending on the result of a
condition. Many times the conditions are contingent on the results of an arithmetic or
logical operation, which affects the flags in the status register. The branching instruc-
tions then act according to the flags in the status register.
BRANCHING INSTRUCTIONS
The 8502 microprocessor has many conditional branching instructions. By definition, a
branch temporarily redirects the otherwise sequential execution of program instructions.
It transfers control to a location of a machine-language instruction other than the one
immediately following the branch instruction in memory.
The conditional branch instructions cause the microprocessor to examine a particu-
lar flag in the status register. The processor, depending on the value of the tested flag,
either takes the branch and transfers control of the program to another location or skips
the branch and resumes with the instruction immediately following the branch.
Think of a conditional branch as a test. For example, if the condition passes the
test, the program branches or shifts control to an instruction that is not the next
sequential instruction in the computer's memory. If it fails the test, the branch is skipped
and program control resumes with the instruction immediately following the branch
instruction in memory. Remember that program control can also be shifted to an
instruction that is out of sequential order if it fails a test. This means you can transfer
control of the execution of your program depending on the conditions you create. You
may set a condition that branches if the value of a certain flag (operand) is zero.
In another instance, you may set a condition to branch if a specific flag is set
to 1.
The conditional branch instructions available in the 8502 microprocessor are:
BCC BNE
BCS BPL
BEQ BVC
BMI BVS
Here's what the conditional branch instructions mean. The phrases in parentheses
are the literal translations of the op-code mnemonics. The remainder explains the
meaning behind the op-codes.
MACHINE LANGUAGE ON THE COMMODORE 128 155
BCC—(Branch on Carry Clear) Branch if the Carry flag in the status register equals 0.
BCS—(Branch on Carry Set) Branch if the Carry flag in the status register equals 1.
BEQ—(Branch on result EQual zero) Branch if the zero flag in the status register equals 1.
BMI—(Branch on result Minus) Branch if the negative flag in the status register equals 1,
BNE—(Branch on result Not Equal to zero) Branch if the zero flag in the status register
equals 0.
BPL—(Branch on result PLus) Branch if the negative flag in the status register equals 0.
BVC—(Branch on oVerflow Clear) Branch if the overflow flag in the status register
equals 0.
BVS—(Branch on oVerflow Set) Branch if the overflow flag in the status register
equals 1.
As you can see, all branching instructions depend on the value of a flag in the
status register.
Here are some branching examples.
READY.
MONITOR
PC SR AC XR YR SP
; FB000 00 00 00 00 F8
This program segment keeps track of the low and high pointers in SFA and $FB
respectively. The first instruction (INC $FA) increments the low byte address pointer.
Next, the contents of $FA is loaded into the accumulator. The branch instruction (BNE
$1830) evaluates the value of the accumulator. If the value is not equal to zero, the
branch is taken to the instruction located at address $1830 (INY). In this case the high
byte pointer is not yet ready to be incremented, so the INC $FB instruction is skipped. If
the value in the accumulator is equal to zero, the branch is skipped and the high byte
address pointer is incremented.
This is an example of the BPL (Branch on Result Plus) instruction.
READY.
MONITOR
PC SR AC XR YR SP *
; FB000 00 00 00 00 F8
. 01858 8E 00 D6 STX $D600
. 0185B 2C 00 D6 BIT $D600
. 0185E 10 FB BPL S185B
. 01860 8D 01 D6 STA $D601
This example is a routine that checks the update ready status bit for the 8563
address register, and ensures that data is valid before writing a value to an 8563 register.
The first instruction stores the contents of the X register, which was previously loaded
with an 8563 register number, into the 8563 address register. The BIT instruction places
bit 7 of location SD600 into the negative flag in the 8502 status register. The BPL
instruction branches to the BIT instruction in location S185B as long as the value of the
negative flag is equal to 0. To the 8563 chip, this means the data is not yet valid and
cannot be written to or read from until bit 7 is set. This loop continues until the value of
bit 7 is 1, then it is transferred to the negative flag. The result now becomes negative
so the branch is skipped and control is passed to the next instruction in memory, which
stores the data into the 8563 data register. Refer to Chapter 10, Writing to an 8563
Register for an expanded version of this program.
The TXS and TSX instructions transfer values from the X index register to the
stack pointer and vice versa. This is useful if you need to take a value off the stack
temporarily, in a mathematical operation (for example, to operate on it and then replace
it on the stack). Another use is to take a value off the stack, place it in the X register for
temporary storage, add a new value on the stack, and then place the old value back on
top. This could be the case when you need to sort values in ascending order.
SHIFT INSTRUCTIONS
The shift instructions are useful when evaluating the value of a single bit at a time in a
series of bits that control your program. For example, a joystick read routine is an
example that calls for the shift instruction. Locations SDC00 and $DC01 control the
joystick direction (bits 0-3), and the joystick fire button (bit 4). One way to evaluate
these values is to shift them to the right. This causes the value to be passed to the carry
MACHINE LANGUAGE ON THE COMMODORE 128 157
flag. If the carry flag is enabled (1), then the joystick is being pushed in the direction
corresponding to that bit. Here is a joystick read routine that uses the LSR instruction to
evaluate the direction of the joystick:
READY.
MONITOR
PC SR AC XR YR SP
; FB000 00 00 00 00 F8
ROTATE INSTRUCTIONS
The rotate instructions operate a little differently. Instead of the shifted bit falling into
the carry flag, the bit "falling off the edge" is placed in the carry bit, then the carry bit
is placed at the opposite end of the byte. For example, if the ROR (rotate right)
instruction is specified, each bit is moved one position to the right. Now bit 7 is placed in
the carry bit and the carry bit is rotated around to the left and placed in the bit 7 bit
position. The ROL instruction operates in the same manner, except the rotation is
leftward rather than to the right. See Figure 5-10 to visualize the rotation concept of the
ROR (rotate right) instruction:
Bit Position
07654321
Each of these instructions applies to a flag in the status register that controls a
particular microprocessor condition. Notice that each clear instruction has a counterpart
which sets the condition, except for CLV (Clear Overflow Flag). The overflow flag can
be set by the BIT instruction or from the result of a signed mathematical operation
overflowing into the sign bit.
Figure 5-11 shows the 8502 status register:
-^.CARRY 1 x TRUE
•••ZERO 1 = RESULT ZERO
- » • IRQ DISABLE 1 = DISABLE
-B» DECIMAL MODE 1 = TRUE
-«•• BRK COMMAND
The flags of the status register are set for various reasons. For example, set
decimal mode when you want to perform calculations in binary coded decimal (BCD)
notation rather than hexadecimal. Set the carry flag when you are performing subtrac-
tion. Set the interrupt disable bit when you want to prevent interrupts from occurring.
An example of a split screen, smooth scrolling raster interrupt routine is given at the end
of Chapter 8.
The clear instructions operate in the reverse of the set instructions. To make sure
that a carry does not occur during an addition operation, clear the carry flag before
MACHINE LANGUAGE ON THE COMMODORE 128 159
These instructions both redirect control of the microprocessor to a location other than
the one immediately following it in memory. The first instruction, JMP, is a one-way trip
to the location specified in the operand field, or the contents of it (indirect). For example:
JMP $1800
jumps to location $1800 and executes the instruction contained in that location. This is a
direct jump.
You can also jump indirectly. For example:
JMP ($1800)
jumps to the address specified in the contents of location $1800. For instance, location
$1800 contains the value $FE and location $1801 contains the value $C0. Therefore, the
above instruction jumps to location $C0FE, and not location $1800. Jumping indirectly
is always denoted by parentheses around the address in the operand field, and it means
to jump to the location specified by the CONTENTS OF the address in the operand field.
The JSR instruction calls subroutines and saves the return address to the stack, so
when an RTS instruction is encountered at the end of the subroutine, the microprocessor
knows where to resume processing in the main (calling) program. Program control
resumes with the instruction in memory immediately following the JSR instruction. In
short, JSR is a round trip, while JMP is one way. For example:
jumps to the subroutine starting at location $1858. The return address is saved on the
stack, so when the RTS instruction is encountered in this subroutine:
01858 8E 00 D6 STX $D600
0185B 2C 00 D6 BIT $D600
0185E 10 FB BPL $185B
01860 8D 01 D6 STA $D601
01863 60 RTS
the processor resumes with the main program instruction (LDX #$0C) in location $1807.
RETURN INSTRUCTIONS
The 8502 instruction set has two return instructions:
The first instruction returns from your interrupt service routine after the interrupt
disable bit is cleared (CLI) and the interrupt occurs. The RTI is the last instruction in the
interrupt service routine. The interrupt service routine is the series of instructions which
are performed on the occurrence of an interrupt. Refer to Chapter 8, Raster Interrupt
Split Screen Program with Horizontal Scrolling for a working example of an interrupt
service routine.
The RTS instruction is the last instruction in a machine language subroutine called
from BASIC or by the machine language JSR instruction. See the Jump instructions
above for an example.
STACK INSTRUCTIONS
Four stack instructions are included in the 8502 instruction set to manipulate the values
on the stack. These instructions are as follows:
The term push means to place a value on the stack, while pull means to remove
a value from the stack. The only values pushed or pulled on to or off the stack are the
contents of the status register or the accumulator. The manipulation of the stack values
is important to the programmer when processing interrupts. The Raster Interrupt Split
Screen Program with Horizontal Scrolling section in Chapter 8 illustrates the manipula-
tion of the stack values prior to returning from the interrupt.
1. OP-CODE
2. Brief definition
3. Operation notation
4. Status flags
5. Flags affected
6. Addressing Modes
7. Assembly language form
8. OP-CODE (in hex)
9. Number of bytes
10. Number of instruction cycles
A Accumulator
X,Y Index Registers
M Memory
P Processor Status Register
S Stack Pointer
V
/ Change
- No Change
+ Add
A Logical AND
- Subtract
-V- Logical Exclusive Or
t Transfer from Stack
1 Transfer to Stack
Transfer to
Transfer from
V Logical OR
PC Program Counter
PCH Program Counter High
PCL Program Counter Low
OPER OPERAND
# IMMEDIATE ADDRESSING MODE
ADC Add memory to accumulator with carry ADC
Operation: A + M H- C - » A, C N E C I D V
V V V
Accumulator ASL A OA 1 2
Zero Page ASL Oper 06 2 5
Zero Page, X ASL Oper, X 16 2 6
Absolute ASL Oper 0E 3 6
Absolute, X ASL Oper, X IE 3 7
Operation: Branch o n C = 0 N Z C I D V
Operation: Branch on C = 1 N Z C I D V
Operation: Branch o n Z = l N Z C I D V
Operation: Branch o n N = 0 N Z C I D V
Implied BRK 00 1 7
Operation: Branch on V = 0 N Z C I D V
Operation: Branch on V = 1 N Z C I D V
Operation: 0 N Z C I D V
— — 0 — — —
Implied CLC 18 1 2
Operation: 0 D N Z C I D V
- - - - 0 -
Implied CLD D8
Operation: 0 —» I N Z C I D V
- - - 0 - -
Implied CLI 58 1 2
Operation: 0 —* V N Z C I D V
- - - - - 0
Implied CLV B8 1 2
MACHINE LANGUAGE ON THE COMMODORE 128 167
Implied DEX CA
Implied DEY 88
Operation: X N Z C I D V
Implied INX E8
Operation: Y + 1 -» Y N Z C I D V
Implied INY C8
Accumulator LSR A 4A 1 2
Zero Page LSR Oper 46 2 5
Zero Page, X LSR Oper, X 56 2 6
Absolute LSR Oper 4E 3 6
Absolute, X LSR Oper, X 5E 3 7
Implied NOP EA 1 2
ORA ORA "OR" memory with accumulator ORA
Operation: A V M A N Z C I D V
Implied PHA 48
Implied PHP 08 1 3
Operation: A "f N Z C I D V
Implied PLA 68
MACHINE LANGUAGE ON THE COMMODORE 128 173
Implied PLP 28 1 4
Accumulator ROL A 2A 1 2
Zero Page ROL Oper 26 2 5
Zero Page, X ROL Oper, X 36 2 6
Absolute ROL Oper 2E 3 6
Absolute, X ROL Oper, X 3E 3 7
Accumulator ROR A 6A 1 2
Zero Page ROR Oper 66 2 5
Zero Page, X ROR Oper, X 76 2 6
Absolute ROR Oper 6E 3 6
Absolute, X ROR Oper,X 7E 3 7
RTI RTI Return from interrupt RTI
Operation: P f PC t Z C I D
From Stack
Implied RTI 40 1 6
Operation: PC f , PC + 1 -» PC N Z C I D V
Implied RTS 60
Operation: A - M - C A N Z C I D V
Note: C = Borrow
Operation: 1 —> C N Z C I D V
Implied SEC 38
Operation: 1 —» D N X C I D V
Implied SED F8 1
Operation: N Z C I D V
_ _ _ 1 _ _
Implied SEI 78
Operation: X M N Z C I D V
Operation: Y —* M N Z C I D V
Implied TAX AA 1
Implied TAY A8 1
MACHINE LANGUAGE ON THE COMMODORE 128 177
Implied TSX BA 1
Implied TXA 8A 1
Implied TXS 9A 1
Implied TYA 98 1 2
INSTRUCTION ADDRESSING MODES AND
RELATED EXECUTION TIMES (in clock cycles)
ADC . 2 3 4 . 4 4* 4* . . 6 5*
AND . 2 3 4 . 4 4* 4* . . 6 5*
ASL 2 . 5 6 . 6 7
BCC 2** . .
BCS 2** . .
BEQ 2** . .
BIT . . 3 . . 4
BMI 2** . .
BNE 2** . .
BPL 2** . .
BRK
BVC 2** . .
BVS 2** . .
CLC 2 .
CLD 2 . . .
CLI 2 . . .
CLV 2 . . .
CMP . 2 3 4 . 4 4* 4* . . 6 5*
CPX . 2 3 . . 4
CPY . 2 3 . . 4
DEC . . 5 6 . 6 7
DEX 2 . . .
DEY 2 . . .
EOR . 2 3 4 . 4 4* 4* . . 6 5*
INC . . 5 6 . 6 7
INX 2 . . .
INY 2 . . .
JMP 3
JSR 6
LDA . 2 3 4 . 44* 4* . . 6 5*
LDX . 2 3 . 4 4 . 4*
LDY . 2 3 4 . 4 4 *
LSR 2 . 5 6 . 6 7
NOP 2 .
ORA . 2 3 4 . 4 4* 4* . . 6 5*
PHA 3 . . .
PHP 3 . . .
MACHINE LANGUAGE ON THE COMMODORE 128 179
< w a a w a ta; a- r ^ c C a
3 < ? 5 < f c f c b a> H M fc
g S a . t . a . ^ ^ s ap S i g
u s a a a o s s t a sa zz so
< S S J N S i < < < SO! = 5 <
PLA 4 . . . .
PLP 4 . . . .
ROL 2 . 5 6 . 6 7
ROR 2 . 5 6 . 6 7
RTI 6 . . . .
RTS 6 . . . .
SBC . 2 3 4 . 4 4* 4* . . 6 5 * .
SEC 2 . . . .
SED 2 . . . .
SEI 2 . . . .
STA . . 3 4 . 4 5 5 . . 6 6 .
STX . . 3 . 4 4
STY . . 3 4 . 4
TAX 2 . . . .
TAY 2 . . . .
TSX 2 . . . .
TXA 2 . . . .
TXS 2 . . . .
TYA 2 . . . .
A clock cycle is the speed at which the processor operates as determined by the
number of bytes transferred from one internal logic component to another. The 8502
operates at a default speed of 1 MHz, which is equivalent to 1,000,000 cycles per
second.
6
HOW TO ENTER
MACHINE LANGUAGE
PROGRAMS INTO THE
COMMODORE 128
Now that you know about addressing modes, types of instructions and opcodes, you
need to know how to actually enter machine language instructions into the Commodore
128 memory. The C128 offers three methods of inputting instructions so that they may
be operated on by the microprocessor. You can enter machine language instructions by:
1. Using the built-in machine language monitor (available in C128 mode only).
2. POKEing the translated decimal opcode values into memory with a BASIC
program (C128 and C64 modes).
3. Using an additional software program called an assembler.
All three methods have advantages and disadvantages. For instance, the built-in
machine language monitor is easy to use and allows you to program in machine
language without any additional aids such as an assembler. It makes merging BASIC
and machine language easy. In addition, you can save machine language programs as
binary files with the monitor SAVE command. Since you are already working in an
object code, there is no need to compile from source code into an object code, as is
necessary with an assembler.
Though these are powerful features, the monitor does not allow the use of symbolic
operand names or commented code. The monitor produces executable (object) code;
hence, no source files are produced. The resulting coded program contains actual
(absolute) address references, whereas an assembler source code file allows the use of
symbolic addresses and arguments as well as comments. When you display a machine
language program in the monitor, you do not have the luxury of comments or symbolic
address variables, so you really have to know what you are looking for when reading
other people's code. On the other hand, an assembler source file must be compiled into
executable object code, then used often with an additional program called a loader. This
requires three steps, whereas the monitor's machine language is ready to run as soon as
you finish writing the program.
The second method, POKEing translated decimal opcode data into memory with a
BASIC program, is an alternative usually implemented only when the first two options
are not available. This is the case if you have no assembler and are writing a machine
language routine in Commodore 64 mode, which does not make the built-in monitor
available to you. However, it is sometimes handy to POKE small routines from
BASIC if the application program you are writing is more suited for BASIC and you
need the speed of machine language for only a small portion of the program (though for
the most part, this method is tedious, bulky and time-consuming). Use it only if you
have no alternative, since once it is POKED into memory, you cannot display a listing
of the machine language routine as in the monitor or the assembler.
This chapter explains how to enter machine language programs in the first two
methods described above. The third method, using an assembler, requires an additional
software package similar to the Commodore 64 Assembler Development System. For
specific details on how to enter machine language programs with the assembler, refer to
the manual that is packed with the assembler software package you buy.
HOW TO ENTER MACHINE LANGUAGE PROGRAMS INTO THE COMMODORE 128 183
Now you can begin to enter machine language instructions. The ASSEMBLE
command within the monitor enters the instructions into the specified memory location.
To enter instructions, follow the format of this example:
A 01800 LDA #$00
Make sure to leave at least one space between each of the fields. Here's what each
part of the instruction means:
<Assemble> <Address in memory where opcode is stored> <Opcode> <Operand>
The A stands for ASSEMBLE an opcode. The second part (field) is the address
where the opcode in the instruction is placed in the Commodore 128 memory. Notice
the 5-digit hexadecimal number specifying the address. The leftmost digit (0-F) speci-
fies the configuration of the Commodore 128 memory layout. This is the same as the
BANK command in BASIC.
Once the entire machine language program is entered, reference the address that is
contained in the first instruction you entered to start execution of the program. Execute
the program with the GO command in the monitor, or exit the monitor with the X
(EXIT) command and issue the SYS command from BASIC. If you SYS to the start of
the program, you must use the decimal equivalent of the hexadecimal address, which
appears in the first instruction you entered. You must have an RTS instruction at the end
of the routine if you want to return to BASIC. Often, the Kernal must be resident in the
current configuration in context in order to obtain results.
The opcode is the 8502 instruction that is carried out by the microprocessor when
your program is running. See the 8502 Instruction Set Table in Chapter 5 for allowable
instructions.
The operand is the address or value that is acted upon by the opcode in the
instruction. If the operand field is preceded by a pound sign (#), the opcode will act
upon a constant value. If no pound sign is specified, the microprocessor assumes the
opcode will act upon an address.
Remember to separate each field in the instruction with at least one space. If you
don't, the computer indicates that an error has occurred by displaying a question mark at
the end of the instruction.
Once a routine is displayed on the screen, the monitor allows shortcuts in entering
instructions. To display a listing of a machine language program, issue the DISASSEM-
BLE command as follows:
D 04000 04010 RETURN
The " D " stands for disassemble. The first number (04000) specifies the starting
memory location in which you want the contents displayed. The second number
specifies the end address in which to display.
Now for the shortcut. Since the address where the opcodes are stored is already on
the screen, you can simply move the cursor to the opcode field, type over the exist-
ing opcode and operand on the screen, erase any unwanted characters and press
RETURN . The computer registers the instruction in memory by displaying the
hexadecimal values for the opcode and operand directly to the left of the opcode
mnemonic you just entered. This is a faster and easier way of entering machine-
language routines, rather than typing the ASSEMBLE command and the address each
time you enter an instruction.
EXECUTING (RUNNING)
YOUR MACHINE-LANGUAGE PROGRAM
Once you have finished entering your machine language routine, you may execute it in
three different ways. Within the monitor, issue the GO or JUMP to Subroutine com-
mand as follows:
G F1800 (JMP)
J F1800 (JSR)
The G stands for GO, or go to the start address of the machine language program
in memory, and begin executing it at the specified address. The value following the
letter G refers to the start address of your routine. The J stands for Jump to Subrou-
tine, similar to the JSR mnemonic in machine language.
The third way to invoke a machine language routine is to exit the monitor by
HOW TO ENTER MACHINE LANGUAGE PROGRAMS INTO THE COMMODORE 128 185
pressing the X key and R E T U R N . This places you back within the control of the
BASIC language. Next, issue the SYS command and reference the starting address in
decimal as follows:
BANK 15
SYS 6144
This SYS command is the same as the GO command (G F1800) example above.
The BANK 15 command and the leading F in the 5-digit hexadecimal number F1800
specify memory configuration 15. The Kernal, BASIC and other ROM code are
resident in this configuration. The only difference is that it executes the machine
language routine from BASIC, instead of within the monitor.
The machine language routine given below clears the text screen. Starting at
location 1024 ($0400), the value 32 ($20) is stored in each screen location. The
character string value 32 is the space character, which blanks out each character position
on the screen. When finished, an RTS instruction returns control to BASIC. Here's the
main BASIC program and the machine language screen-clear subroutine as it appears in
the machine language monitor.
10 FOR 1= 1 TO 2 5
20 PRINT"FILL THE SCREEN WITH CHARACTERS"
30 NEXT
40 PRINT:PRINT
50 PRINT"NOW CALL THE MACHINE LANGUAGE"
60 PRINT" ROUTINE TO CLEAR THE SCREEN"
70 SLEEP 5
80 SYS DEC("1800")
90 PRINT"THE SCREEN IS NOW CLEARED"
READY.
MONITOR
PC SR AC XR YR SP
; FB000 00 00 00 00 F8
In this sample program, the SYS command executes the subroutine to clear the
text screen. Once the text screen is cleared, control of the microprocessor is returned to
BASIC by the RTS instruction, and the READY prompt is displayed.
MACHINE LANGUAGE
MONITOR COMMANDS
The C128's built-in machine language monitor has several additional commands that
manipulate your machine language routines once they are entered into memory. Figure
6-1 is a summary of all the commands available to you in the machine language
MONITOR.
SUMMARY OF MONITOR
FIELD DESCRIPTORS
The following designators precede monitor data fields (e.g., memory dumps). When
encountered as a command, these designators instruct the monitor to alter memory or
register contents using the given data.
The following designators precede number fields (e.g., address) and specify the radix
(number base) of the value. Entered as commands, these designators instruct the monitor
simply to display the given value in each of the four radices.
<null> (default) precedes hexadecimal values.
$ <dollar> precedes hexadecimal (base-16) values.
+ <plus> precedes decimal (base-10) values.
& <ampersand> precedes octal (base-8) values.
% <percent> precedes binary (base-2) values.
The following characters are used by the monitor as field delimiters or line terminators
(unless encountered within an ASCII string).
COMMAND: A
PURPOSE: Enter a line of assembly code.
SYNTAX: A <address> <opcode mnemonic> <operand>
<address> A number indicating the location in memory to
place the opcode. (See 5-digit address note on
previous page.)
<opcode> A standard MOS technology assembly language
mnemonic, e.g., LDA, STX, ROR.
<operand> The operand, when required, can be any of the
legal addresses or constants.
EXAMPLE:
.A 01200 LDX #$00
.A 01202
EXAMPLE:
.02000 LDA #$23
HOW TO ENTER MACHINE LANGUAGE PROGRAMS INTO THE COMMODORE 128 189
COMMAND:
PURPOSE: Compare two areas of memory.
SYNTAX: C <address 1> <address 2> <address 3>
<address 1 > A number indicating the start address of the area
of memory to compare against.
<address 2> A number indicating the end address of the area
of memory to compare against.
< address 3> A number indicating the start address of the other
area of memory to compare with. Addresses that
do not agree are printed on the screen.
COMMAND: D
PURPOSE: Disassemble machine code into assembly language mnemonics and
operands.
SYNTAX: D [<address>] [<address 2>]
<address> A number setting the address to start the dis-
assembly.
<address 2> An optional ending address of code to be dis-
assembled.
The format of the disassembly differs slightly from the input format of an assembly. The
difference is that the first character of a disassembly is a period rather than an A (for
readability), and the hexadecimal value of the op-code is listed as well.
A disassembly listing can be modified using the screen editor. Make any changes
to the mnemonic or operand on the screen, then hit the carriage return. This enters the
line and calls the assembler for further modifications.
A disassembly can be paged. Typing a D R E T U R N causes the next page
of disassembly to be displayed.
EXAMPLE:
D3000 3003
.03000 A9 00 LDA #$00
.03002 FF ???
.03003 DO 2B BNE $3030
COMMAND: F
PURPOSE: Fill a range of locations with a specified byte.
SYNTAX: F <address 1> <address 2> <byte>
<address 1> The first location to fill with the <byte>.
<address 2> The last location to fill with the <byte>.
<byte value> A 1- or 2-digit hexadecimal number to be written.
This command is useful for initializing data structures or any other RAM area.
EXAMPLE:
F0400 0518 EA
Fill memory locations from $0400 to $0518 with $EA (a NOP instruction).
COMMAND: G
PURPOSE: Begin execution of a program at a specified address.
SYNTAX: G [<address>]
<address> An address where execution is to start. When
address is left out, execution begins at the current
PC. (The current PC can be viewed using the R
command.)
The GO command restores all registers (displayable by using the R command) and
begins execution at the specified starting address. Caution is recommended in using the
GO command. To return to the Commodore 128 MONITOR after executing a machine
language program, use the BRK instruction at the end of the program.
EXAMPLE:
G 140C
Execution begins at location $140C in configuration (BANK)O. Certain applica-
tions may require that Kernal and/or I/O be present when execution begins.
Precede the four-digit hexadecimal number with the hex configuration number
which contains those appropriate portions of memory.)
COMMAND: H
PURPOSE: Hunt through memory within a specified range for all occurrences of a
set of bytes.
SYNTAX: H <address 1> <address 2> <data>
<address 1> Beginning address of hunt procedure.
<address 2> Ending address of hunt procedure.
<data> Data set to search for data may be hexadecimal
for an ASCII string.
EXAMPLE:
H A000 A101 A9
Search for data $A9 from A000 to A101.
H2000 9800 'CASH'
Search for the alpha string "CASH".
COMMAND: J
PURPOSE: Jump to a machine language subroutine.
SYNTAX: J <address>
The JUMP to SUBROUTINE command directs program control to the machine language
HOW TO ENTER MACHINE LANGUAGE PROGRAMS INTO THE COMMODORE 128 191
subroutine located at the specified address. This command saves the return address as
does the 8502 instruction JSR (Jump to Subroutine). In other words, the JUMP
command is a two-way instruction, where the application gains control of the computer.
Only after the subroutine encounters an RTS instruction does the machine language
monitor regain control.
EXAMPLE:
J2000
Jump to the subroutine starting at $2000 in configuration 0.
COMMAND: L
PURPOSE: Load a file from cassette or disk.
SYNTAX: L <"file name">[,<device>[,alt load address]]
<"file name"> Any legal Commodore 128 file name.
<device> A number indicating the device to load from. 1 is
cassette. 8 is disk (or 9, A, etc.).
[alt load address] Option to load a file to a specified address.
The LOAD command causes a file to be loaded into memory. The starting address is
contained in the first two bytes of the disk file (a program file). In other words, the
LOAD command always loads a file into the same place it was saved from. This is very
important in machine language work, since few programs are completely relocatable.
The file is loaded into memory until the end of file (EOF) is found.
EXAMPLE:
L "PROGRAM",8 Loads the file name PROGRAM from the disk.
COMMAND: M
PURPOSE: To display memory as a hexadecimal and ASCII dump within the
specified address range.
SYNTAX: M [<address 1>] [<address 2>]
<address 1> First address of memory dump. Optional. If omit-
ted, one page is displayed. The first digit is the
bank number to be displayed, the next four digits
are the first address to be displayed.
<address 2> Last address of memory dump. Optional. If omit-
ted, one page is displayed. The first digit is the
bank number to be displayed; the next four digits
are the ending address to be displayed.
EXAMPLE:
M 21C00
>21C00 41 4A 4B 4C 4D 4E 4F 50 :AJKLMNOP
COMMAND: R
PURPOSE: Show important 8502 registers. The status register, the program counter,
the accumulator, the X and Y index registers and the stack pointer are
displayed. The data in these registers is copied into the microprocessor
registers when a " G " or " J " command is issued.
SYNTAX: R
EXAMPLE:
R
PC SR AC XR YR SP
: 01002 01 02 03 04 F6
COMMAND: S
PURPOSE: Save the contents of memory onto tape or disk.
SYNTAX: S <"filename">,<device>,<address 1>, <address 2>
<"filename"> Any legal Commodore 128 filename. To save
the data, the file name must be enclosed in dou-
ble quotes. Single quotes cannot be used.
<device> A number indicating on which device the file is
to be placed. Cassette is 01; disk is 08, 09, etc.
<address 1> Starting address of memory to be saved.
<address 2> Ending address of memory to be saved + 1. All
data up to, but not including, the byte of data at
this address is saved.
HOW TO ENTER MACHINE LANGUAGE PROGRAMS INTO THE COMMODORE 128 193
The file created by this command is a program file. The first two bytes contain the
starting address <address 1> of the data. The file may be recalled, using the L
command.
EXAMPLE:
S "GAME",8,0400,00)0
Saves memory from $0400 to SOBFF onto disk.
COMMAND: T
PURPOSE: Transfer segments of memory from one memory area to another.
SYNTAX: T <address 1> <address 2> <address 3>
<address 1> Starting address of data to be moved.
<address 2> Ending address of data to be moved.
<address 3> Starting address of new location where data will
be moved.
Data can be moved from low memory to high memory and vice versa. Additional
memory segments of any length can be moved forward or backward. An automatic
"compare" is performed as each byte is transferred, and any differences are listed by
address.
EXAMPLE:
T1400 1600 1401
Shifts data from $1400 up to and including $1600 one byte higher in memory.
COMMAND: V
PURPOSE: Verify a file on cassette or disk with the memory contents.
SYNTAX: <"filename">[,<device>][,alt start address]
<"filename"> Any legal Commodore 128 file name.
<device> A number indicating which device the file is on.
Cassette is 01; disk is 08, 09, etc.
[alt start address] Option to start vertification at this address.
The VERIFY command compares a file to memory contents. If an error is found, the
words VERIFY ERROR are displayed; if the file is successfully verified, the cursor
reappears without any message.
EXAMPLE:
V" WORKLOAD" ,08
COMMAND: X
PURPOSE: Exit to BASIC.
SYNTAX: X
COMMAND: > (greater than)
PURPOSE: Can be used to assign values for one to eight memory locations at a time
(in 40-column mode; up to 16 in 80-column mode).
SYNTAX: > <address> <data byte 1> <data byte 2 . . . 8>
<address> First memory address to set.
<data byte 1> Data to be put at address.
<data byte 2 . . . 8>Data to be placed in the successive memory
locations following the first address (optional)
with a space preceding each data byte.
EXAMPLES:
checks disk status
00, OK, 00, 00
(2,1 initializes drive 8
@,$ displays disk directory on unit 8.
(a,$0:F* display all files on Drive 0, unit 8 starting with the letter F.
As a further aid to programmers, the Kernal error message facility has been automati-
cally enabled, while in the Monitor. This means the Kernal will display 'I/O ERROR#'
and the error code, should there be any failed I/O attempt from the MONITOR. The
message facility is turned off when exiting the MONITOR.
by placing the ASCII values of the characters in memory locations within a program.
To modify a memory dump using the screen editor, issue the MEMORY com-
mand with the address range in which you want to place the character string informa-
tion. For example, suppose you want to place the word "TEXT" in memory starting at
location $2000. First, enter the machine language monitor with the MONITOR com-
mand. Next, issue the memory command containing the address $2000 as follows:
M 2000
The 128 responds with this display:
02000 FF 00 FF 00 FF 00 FF 00: Tr.ir.Tr.TT.
The entire screen is filled with the contents of the memory (dump) locations $2000
through $205F. For illustrative purposes, only one line of the memory dump is shown.
This line pertains to the address range $2000 through $2007. At the right of the screen is
an area that displays the corresponding ASCII character for each value within a memory
location in that line of the memory dump. The left character in the display area
corresponds to location $2000, the second character position to the right pertains to
address $2001, and so on. To place the word "TEXT" in memory starting at location
$2000, move the cursor up to the first line of the memory dump, move the cursor right
to the memory address that pertains to address $2000, and place the ASCII character
string code for the letter T in this position. To do this, type over the characters that are
there and replace them with the hexadecimal equivalent of decimal 84 ($54) and press
R E T U R N . Notice that the letter T is now displayed at the right of the screen.
Refer to Appendix E, ASCII and CHR$ Codes, for a list of the Commodore ASCII
codes for each character available in the Commodore 128.
Now do the same procedure for the letters E, X and T. When you are through, the
word "TEXT" is displayed in the display area. The first line of the memory dump now
looks like this:
02000 54 45 58 54 FF 00 FF 00: TEXT IT. IT.
Now the character string you wish to manipulate is in memory, starting at address
$2000. Your machine language routine can now act upon the characters of the word
"TEXT" in order to display them on the screen. An efficient way of manipulating
entire words is to use the start address in memory where the text begins, in this case
$2000. Determine the length of the string, and use an index register as an offset to the
end of the word. See the section Raster Interrupt Split Screen Program with Horizontal
Scrolling in Chapter 8, for a working example of manipulating text. This chapter has
described the use of machine language. For additional information on machine language
topics, see Chapter 5, 7, 8, 9, 10, 11, and 13.
7
MIXING
MACHINE
LANGUAGE
AND BASIC
WHY MIX B A S I C AND
MACHINE LANGUAGE?
Certain application programs are better suited for a high-level language such as BASIC
rather than low-level machine language. In other cases, however, certain portions of a
program, such as displaying graphics, may require the speed of machine language while
the rest of the program lends itself to the use of BASIC. This is the main reason for
mixing BASIC programs with machine language subroutines. Another reason may be
the lack of an alternative in programming machine language. For example, in C64
mode, a machine language monitor is not ordinarily available to the user. In addition,
you may not have an assembler package, so the only alternative is to enter machine
language programs through the BASIC language. This method has disadvantages; it can
be tedious and time-consuming, and once the routine is entered into memory, you have
no way of listing it to the screen for editing. This method is recommended only if no
alternative is available.
Although the DATA statement in the example in Step 4 does not show it, all
machine language subroutines must end with an RTS instruction so you can return to
BASIC. The decimal code for an RTS machine language instruction is 96. Your last
decimal data item in the final data statement in your program must be 96, unless you use
a terminator like -999; then -999 will be your last decimal data item.
Figure 7-1 shows a step-by-step translation from the machine language screen-
clear routine as it appears in the monitor and a complete program that mixes the clear
screen routine with the BASIC program that POKEs in the data and executes the
machine language subroutine. It only operates in the 40-column (VIC) screen.
MIXING MACHINE LANGUAGE AND BASIC 201
Symbolic
Address Hex Opcode Instruction Decimal Equivalent
1 st Byte 2nd Byte 3rd Byte
(Opcode) (Operand)
. 02000 A2 00 LDX #$00 162 0
. 02002 A9 20 LDA #$20 = 169 32
. 02004 9D 00 04 STA $0400, X 157 0 4
. 02007 9D 00 05 STA $0500, X 157 0 5
. 0200A 9D 00 06 STA $0600, X 157 0 6
. 0200D 9D E7 06 STA $06E7, X 157 231 6
. 02010 E8 I NX = 232
. 02011 DO Fl BNE $2004 = 208 241
. 02013 60 RTS — 96
To find the hexadecimal opcodes, refer to the 8502 Instruction and Address-
ing Table in Chapter 5. Notice in Figure 7-1 that the hexadecimal opcodes are displayed
within the monitor, directly to the left of the symbolic instruction. These hexadecimal
numbers are the codes that you translate into decimal data items in a BASIC program.
Notice that the second byte in the BNE instruction is the value 241. In a branch
instruction, the operand is not an absolute address, but is instead an offset to the
instruction to which it will branch. In this case, the BNE instruction branches backward
to location $2004; therefore, it branches backward 15 locations in memory to the first
store (STA) instruction.
You're probably wondering how the code 241 tells the computer to branch
backward by 15. The number 241 (decimal) is the 2's complement of the value 15.
When bit 7 is enabled, the microprocessor branches backward. The number 241
signifies to branch backward by 15 memory locations and execute the instruction in that
location. To find the root value of a 2's complement number, do this:
10 ALPHA=8192
20 1 = 0
30 DO
40 : READ A
45 ; IF A=-999 THEN EXIT
50 : POKE ALPHA+I,A
60 : 1=1+1
7 0 LOOP
80 PRINT"ALL DATA IS NOW IN MEMORY"
85 SLEEP 1
90 SYS 8192
1000 DATA 162,0,169,32,157,0,4,157,0,5,157,0,6,157,231,6
2000 DATA 232,208,241,96,-999
Here is the corresponding program in C64:
10 ALPHA=8192
20 FOR 1=0 TO 19
40 : READ A
50 : POKE ALPHA+I,A
60 NEXT
80 PRINT"ALL DATA IS NOW IN MEMORY"
85 FOR 1=1 TO 2500:NEXT
90 SYS 8192
1000 DATA 162,0,169,32,157,0,4,157,0,5,157,0,6,157,231,6
2000 DATA 232,208,241,96
When you run this program, the computer READs the DATA, POKEs it into
memory, and executes the machine language, clear-screen subroutine with the SYS
command. After you RUN the program, enter the machine language monitor (assuming
you are currently in C128 mode) and disassemble the code in the range $2000 through
$2015 with this command:
D 2000 2015
Notice that the subroutine you POKEd in through BASIC is the same as the
subroutine that appears in Figure 7-1. The two different methods accomplish the same
goal—programming in 8502 machine language.
Management Unit (MMU). For detailed information, refer to the sections on the
Registers of the Memory Management Unit (specifically, the discussion of the Configu-
ration Register) in Chapter 13.
BANK CONFIGURATION
0 RAM(O) only
1 RAM(l) only
2 RAM(2) only
3 RAM(3) only
4 Internal ROM, RAM(O), I/O
5 Internal ROM, RAM(l), I/O
6 Internal ROM, RAM(2), I/O
7 Internal ROM, RAM(3), I/O
8 External ROM, RAM(O), I/O
9 External ROM, RAM(l), I/O
10 External ROM, RAM(2), I/O
11 External ROM, RAM(3), I/O
12 Kernal and Internal ROM (LOW), RAM(O), I/O
13 Kernal and External ROM (LOW), RAM(O), I/O
14 Kernal and BASIC ROM, RAM(O), Character ROM
15 Kernal and BASIC ROM, RAM(O), I/O
If you want to place a machine language subroutine in memory while the BASIC
language is running, put the subroutine in a bank that contains RAM, preferably bank 0
since this bank is composed entirely of RAM. If you place the machine language
subroutine in a bank other than 0, not all of the RAM is available for pro-
grams, since ROM overlays some of the RAM. You must check the value of the
Configuration Register within that bank to see which addresses within these banks
contain ROM. Check the value of the Configuration Register within each of the sixteen
configurations and compare the value with the table in Figure 13-5 to see exactly where
ROM maps in.
Follow this procedure when calling machine language subroutines from BASIC:
1. Place the subroutine, preferably in bank 0, either through the monitor or by
POKEing in the code through BASIC. Jf the Kernal, BASIC, and I/O are
required, execute your program from configuration (BASIC Bank) 15. If you
enter the subroutine through the monitor, place the routine in bank 0 by
placing the digit 0 before the 4-digit hexadecimal address where the instruc-
tions are stored. If you are POKEing the codes in through BASIC (not the
preferred method), issue the BANK 0 command within your program, assum-
ing you are placing the routine into BANK 0; then POKE in the decimal data
for the opcodes and operands. The recommended memory range to place
machine language routines in conjunction with BASIC is between $1300 and
S1BFF. The upper part of BASIC text is also available, provided your BASIC
program is small and does not overwrite your routine.
2. Now, to process the rest of your BASIC program, return to bank 15 (the
default bank) with this command:
BANK 15
3. Now call the subroutine with the SYS command. SYS to the start address
where the first machine language instruction of your program is stored in
memory. In this case, assume the subroutine starts at hex location $2000
(assuming the VIC bit map screen is not used) and enter:
SYS 8192
The RAM in configuration 0 in Figure 7-2 is the same RAM that appears in configura-
tions (BANKS) 4, 8, 12, 13, 14, and 15. For example, you can enter programs into
BANK 15, but you must make sure that no ROM overlays your program area.
NOTE: If you plan to return to BASIC, make sure your subroutine ends
with an RTS instruction.
via the BASIC command, so it becomes your responsibility to manage the memory
configurations by manipulating the Configuration Register in your application program.
Figure 13-5, on page 462, defines the values to place in the configuration register to
arrive at the different memory configurations.
When you switch out the BASIC ROMs, the address range where BASIC usually
resides ($4000 through $7FFF for BASIC low and $8000 through $BFFF for BASIC
high), is available for your machine language programs. Be careful when switching out
the Kernal, since the Kernal controls the entire operation of the C128, including routines
that seem transparent to the user (i.e., routines that you may take for granted).
At certain points within your machine language programs, you may need to
disable the I/O operation of the C128 temporarily. For instance, if you want to copy
portions of the character ROM into RAM when programming your own characters, you
must switch out the I/O registers $D000 through $DFFF of the C128, transfer the
character data into RAM, and then switch the I/O back in.
See the section discussing the Configuration Register, in Chapter 13, for a full
explanation of how the C128 RAM and ROM memory is configured.
This chapter has described the use of BASIC and machine language together. For
material on using BASIC alone, see Chapters 2, 3 and 4. For material on using machine
language see Chapters 5, 6, 8, 9, 10, 11 and 13.
8
THE POWER
BEHIND
COMMODORE 128
GRAPHICS
THE RELATIONSHIP BETWEEN
VIDEO BANKS, RAM BANKS
AND MEMORY CONFIGURATIONS
Many of you are familiar with how the Commodore 64 manages memory. This section
explains how the Commodore 128 manages video memory, and how the video banks
relate to the currently selected memory configuration.
BANK CONFIGURATION
0 RAM(O) only
1 RAM(l) only
2 RAM(2) only (same as 0)
3 RAM(3) only (same as 1)
4 Internal ROM , RAM(O), I/O
5 Internal ROM , RAM(l), I/O
6 Internal ROM , RAM(2), I/O (same as 4)
7 Internal ROM , RAM(3), I/O (same as 5)
8 External ROM , RAM(O), I/O
9 External ROM , RAM(l), I/O
10 External ROM , RAM(2), I/O (same as 8)
11 External ROM , RAMP), I/O (same as 9)
12 Kernal and Internal ROM (LOW), RAM(O), I/O
13 Kernal and External ROM (LOW), RAM(O), I/O
14 Kernal and BASIC ROM, RAM(O), Character ROM
15 Kernal and BASIC ROM, RAM(O), I/O
64K
64K
the VIC RAM bank is selected by the RAM configuration register (bits 6 and 7). This
also is covered in detail in Chapter 13.
The configuration determined by the configuration register can be composed of
RAM and ROM, where the ROM portion overlays the RAM layer underneath, as
illustrated in Figure 8-3.
Write
Operation
(POKE, STA $ ) •READ Operation (PEEK, LDA $ )
ROM ROM
RAM
65535
memory
A read (PEEK) operation returns a ROM value, and a write (POKE) operation
bypasses the ROM and stores the value in the RAM underneath.
Many different combinations of memory can be constructed to comprise a 64K
configuration of accessible memory. Bits six and seven of the configuration register
specify which RAM bank lies beneath the ROM layers specified by bits zero through
five. The underlying RAM bank can be switched independently of any ROM layers on
top. For instance, you may switch from RAM Bank 0 to RAM Bank 1, while
maintaining the Kernal, BASIC and I/O.
3 video bank 3
2 video bank 2
64K
1 video bank 1
0 video bank 0
3 video bank 3
2 video bank 2
64K
1 video bank 1
0 video bank 0
Figure 8-4. Video Banks within RAM Banks
The four video banks in each 64K RAM bank are set up in the memory ranges
specified in Figure 8-5:
BINARY DECIMAL
0 $0-$3FFF 11= 3 (DEFAULT)
1 $4000-$7FFF 10= 2
2 $8000-$BFFF 01= 1
3 $C000-$FFFF 00= 0
1. BASIC and the Machine Language Monitor have sixteen 64K memory con-
figurations that give you sixteen different combinations of memory layouts.
The MMU chip, particularly the value in the configuration register, controls
most of the memory management in the Commodore 128. In order to PEEK
(read) from or POKE (write) to a particular portion of memory, you must
choose a BASIC or monitor configuration that contains the desired section of
memory. Figure 8-1 lists the sixteen default memory configurations available
in BASIC and the Machine Language Monitor.
2. The 128K of memory is divided into two 64K RAM banks. Only one bank is
addressable at a time by the microprocessor. RAM bank selection is con-
trolled by the MMU configuration register (bits 6 and 7), which is part of the
C128 I/O memory. The VIC chip and 8502 microprocessor can each access a
different 64K RAM bank. Figure 8-2 illustrates the two separate and indepen-
dent 64K RAM banks.
3. Each 64K RAM bank is divided into four 16K video segments. The screen
and character memory must both lie within the selected 16K video segment in
order to successfully display graphics and characters on the screen. For each
16K video bank higher than zero, remember to add $4000 (16384 decimal) to
the start address of screen and character memory. Figure 8 ^ shows how four
16K video banks fit into each of the two 64K RAM banks.
Here's how the banks fit together and operate within the Commodore 128. One
64K RAM bank is always mapped into memory. Within BASIC or the Machine
Language Monitor, sixteen different memory configurations are available in a 64K bank.
To change the configuration, issue the BASIC BANK command, or precede the four
digit hexadecimal address in the Machine Language Monitor with an additional hexadec-
imal digit 0 through F. Outside of BASIC or the monitor, you can select other
configurations, by changing the value in the configuration register at location $FF00
(or $D500). See Chapter 13 for details.
Within the selected configuration, and part of the current 64K RAM bank, is a
16K range reserved for a video bank. The 16K video bank must encompass IK of screen
memory, and either 4K of character ROM or an 8K block of memory for the bit map
data. All these components must be present in order for graphics to operate.
THE POWER BEHIND COMMODORE 128 GRAPHICS 213
In essence, the bank concept can be thought of in this way: The C128 has a 16K
(VIC) video bank within a selected memory configuration within a 64K RAM bank.
Figures 8-28 through 8-32 at the end of this chapter provides a graphics program-
ming summary.
Because the split-screens switch from one display mode to another at a given
time, the screen editor must be interrupt-driven. The interrupt indicates at what point
the mode is to be switched. At that point, the VIC chip is loaded with preset values
already contained in RAM. These preset values are known as shadow registers. Each
time an interrupt occurs, certain video-chip registers are cleared and refreshed with the
values in the shadow registers. These shadow registers add a variation in programming
the VIC chip compared to the way the Commodore 64 handles it.
The primary intermediate storage locations for VIC chip programming are:
GRAPHM BIT 7 - 216 (S00D8) BIT 4 - 53270 (SD016) Multicolor Mode Bit
GRAPHM BIT 5 - 216 ($00D8) BITS -S3265 ($D011) Bit Map Mode Bit
VM1* BITS 7-4 - 2604 ($0A2C) BITS 7-4 - 53272 (SD018) Video Matrix (screen memory) Pointer
VM1 BITS 3-0 - 2604 ($0A2C) BITS 3-0 - 53272 ($D018) Character Base Pointer
VM2** BITS 7-4 - 2605 ($0A2D) BITS 7-4 - 53272 ($D018) Video Matrix (screen memory) Pointer
VM2 BITS 3-0 - 2605 ($0A2D) BITS 3-0 - 53272 ($D018) Bit Map Pointer
LDA #$FF
STA $00D8
Since disabling the interrupt allows you to program the VIC chip in the same way
as the Commodore 64, you can store values directly to the actual registers. You do not
have to address the indirect storage locations for VIC chip programming. However, if
you don't disable the interrupt, it is still active and your values will be cleared upon the
first occurrence of the raster interrupt.
Remember, you must either disable the interrupt or address the indirect storage
locations. Failure to do one or the other can cause serious problems in your program.
The 80-column chip indirect memory locations are discussed in Chapter 10,
Programming the 80-Column 8563 Chip. Certain other I/O functions require the use of
indirect locations also. These are covered in Chapter 12, Input/Output Guide.
C128 BASIC
In Commodore 128 BASIC, the character screen memory is located in the default address
range 1024 ($0400) through 2023 ($07E7). The text screen memory can be moved.
Remember, certain addresses use indirect memory locations to change the value of the
actual address. The shadow register for the pointer to the text screen memory is location
2604 ($0A2C). The actual location is 53272, but the screen editor uses a shadow since
the VIC screen is interrupt-driven. A direct poke to 53272 ($D018) is changed back to
its original value every sixtieth of a second. Here's how to change the location of screen
memory in C128 BASIC:
POKE, 2604 (PEEK(2604) AND 15) OR X
where X is a value in Figure 8-6.
If you move the screen memory, make sure that the screen and character memory
do not overlap. In addition, make sure to add an offset of $4000 to the start address of
screen and character memory for each bank above 0. Additional commands are required
to make the program work. Details follow in the discussion of each graphic mode, as
well as program examples.
LOCAT ION*
0 ooooxxxx 0 $0000
16 0001XXXX 1024 $0400 (DEFAULT)
32 0010XXXX 2048 $0800
48 0011XXXX 3072 $0C00
64 0100XXXX 4096 $1000
80 0101XXXX 5120 $1400
96 0110XXXX 6144 $1800
112 0111XXXX 7168 $1COO
128 1000XXXX 8192 $2000
144 1001XXXX 9216 $2400
160 1010XXXX 10240 $2800
176 1011XXXX 11264 $2C00
192 1100XXXX 12288 $3000
208 1101XXXX 13312 $3400
224 1110XXXX 14336 $3800
240 1111XXXX 15360 $3C00
•Remember that the BANK ADDRESS offset of $4000 per
video bank must be added if changing to a higher video
bank above 0.
This register also controls where character memory is placed in memory. The
upper four bits control the screen, the lower four control character memory. The "AND
15" in the POKE 2604 statement ensures that the lower nybble is not upset. (If it had
been, you would not see the correct character data.)
In Commodore 128 bit map mode (standard or multi-color), the default bit map
screen memory (video matrix) is located between 7168 ($lC00) and 8167 ($1FFF).
Screen memory is interpreted differently in bit map mode than in text mode. The video
matrix in bit map mode actually supplies color information to the bit map. This is
explained in detail in the Standard Bit Map Mode section elsewhere in this chapter. To
change the location of the bit map screen memory (video matrix), use this command:
POKE 2605, (PEEK(2605) AND 15) OR X
THE POWER BEHIND COMMODORE 128 GRAPHICS 2!7
where X is a value in Figure 8-6. Location 2605 is also a shadow register for 53272, but
only for bit map mode. When you move the video matrix you must ensure that it does
not overlap the bit map (data). In addition, be sure to add an offset of $4000 to the start
address of the video matrix and the bit map for each video bank above zero.
C64 BASIC
In C64 mode, the text screen defaults to locations 1024 ($0400) through 2023
($07E7). In bit map mode, the video matrix (screen memory) also defaults to this range
though the screen memory is interpreted differently in either mode. Commodore 64
BASIC allows you to move the location of the video matrix to any one of the sixteen
locations specified in Figure 8-6. The upper four bits of location 53272 ($D018) control
the location of the screen memory. To change the location of screen memory, use the
following command:
POKE 53272, (PEEK(53272) AND 15) OR X
where X is equal to one of the values in Figure 8-6
NOTE: The following paragraph pertains to both C128 and C64 modes.
Bits zero and one of location 56576 (SDD00) control which of the four video
banks is selected. The default bank is 0. If you change to another video bank (from 0 to
1, for example), then for each bank higher than bank zero, you must add an offset of
$4000 to the starting video matrix (screen memory) address in Figure 8-6. This yields
the actual address of the video matrix. For example, if you're changing from bank 0 to
bank 1, add $4000. If you are going to bank 2, add $8000; if you are changing to bank
3, add $C000. Remember, this is true for both C128 and C64 modes.
MACHINE LANGUAGE
In machine language, use the commands listed under A in Figure 8-7 to move the C128
(VIC) text screen. Use the commands under B to move the C128 bit map screen memory
(video matrix). Use the commands under C to move the C64 text or bit map screen
memory (video matrix).
COLOR RAM
C128 BASIC
Color RAM within the Commodore 128 is always stationary in memory. It occupies the
address range 55296 ($D800) through 56295 ($DBE7). In standard character mode,
screen RAM and color RAM correspond to one another on a one-to-one basis. Location
1024 gets color data from 55296, 1025 gets color from 55297 and so on. Multi-color
character mode utilizes color RAM also, but in a different manner. Additional explana-
tions and examples are provided in the Standard Character Mode section of this chapter.
C64 BASIC
In standard character mode, color RAM is located in the same place as in C128 mode:
55296 ($D800) through 56295 (SDBE7).
In bit map mode, C64 BASIC receives color information from screen memory (the
THE POWER BEHIND COMMODORE 128 GRAPHICS 219
video matrix) as does C128 mode, though the default location for screen memory is
1024 ($0400) through 2023 ($07E7).
MACHINE LANGUAGE
In machine language or in BASIC, standard character mode color data always comes
from the same place. Color RAM is used for multi-color character mode. In
standard bit map mode, however, color data originates from screen memory, so wher-
ever you place screen memory, the color data for the bit map comes from the specified
screen memory (video matrix) range. Multi-color bit map mode receives color from three
places: color RAM, screen memory and background color register 0. This is explained in
depth in the sections on the multi-color character and multi-color bit map modes.
ADDR ESS
VIC*
BLOCK DECIMAL HEX IMAGE CONTENTS
VALUE
OFZ BITS DECIMAL HEX
0 xxxxooox 0 $0000-$07FF
2 XXXX001X 2048 $0800-$0FFF
4 XXXX010X 4096 $1000-$17FF ROM IMAGE in BANK 0 & 2
(default)*
6 XXXX011X 6144 $18OO-$1FF ROM IMAGE in BANK 0 & 2*
8 XXXX100X 8192 $2000-$27FF
10 XXXX101X 10240 $2800-$2FFF
12 XXXX110X 12288 $3000-$37FF
14 XXXX111X 14336 $3800-$3FFF
* = in C64 mode only.
As with the other graphic system components, character data behaves differently in
bit map mode than in text mode.
Remember, the upper nybble controls where the screen memory maps in, so make
sure not to upset those bits. The AND 240 in the POKE statement above takes care of
preserving the upper four bits.
In C128 mode the character sets are available in all video banks depending on the
value of CHAR ENable
MACHINE LANGUAGE
There are three ways to select the placement of character memory, as shown in Figure
8-11. Example A places character memory using the shadow register $0A2C in place of
the actual $D018 register. Example B specifies the start of the bit map at $2000 (using
shadow register $0A2D). Example C specifies the start of the C64 bit map or character
memory.
A B C
COLUMN
10 20
11
024——•» —
064
104
1144
184
1224
1264 1J
1304
344
.384 1v
.424 10 §
1464
504
1544
.584 1 j_ _
1624
1664
1704
1744
1784
1824
1864 !
1904
1944
1984 j
t
2023
Figure 8-12. Screen Memory Map
different due to the way they are stored in the character ROM. Notice in Appendix D
that the screen code for an at-sign (@) is 0. The (5> is numbered 0 because it is the first
character to be stored in the character ROM. The letter " A " is the second character
ROM; therefore its code is 1. The letter " B " is the third character in the character
ROM, etc. The screen code is actually an index from the starting location of the
character ROM, beginning with zero.
If you want to POKE a character directly into screen memory, use the screen code
rather than the ASCII character string (CHR$) code. The same holds true for the
machine language monitor. For example:
POKE 1024,1
places the letter A in the HOME position on the VIC screen. From the monitor, placing
the value 1 in location $0400 (decimal 1024) also displays the letter A in the HOME
position on the VIC screen.
COLOR DATA
In standard character mode, color information comes from color RAM, in the address
range 55296 ($D800) through 56295 ($DBE7). This memory determines the color of the
characters in each of the 1,000 screen locations. The background color of the screen is
determined by the background color register 0 which is location 53281.
The color RAM and the screen RAM locations correspond on a one-to-one basis.
Screen location 1024 pertains to color RAM location 55296; screen location 1025
corresponds to color location 55297, etc. Figure 8-13 is the color RAM memory map.
The map shows how color RAM corresponds to the locations in screen RAM and the
placement on your video display.
COLOR MEMORY MAP
COLUMN
20 39
55335
55296- 1 1
1
55336
55376
55416
55456
55496
55536
i [
55576
55616
\
55656
55696 10 §
55736
55776 —I—
55816
55856
_ I
55896
— 1
55936
55976
56016 j I
56056
56096
56136
56176
56216
56256
0 Black 8 Orange
1 White 9 Brown
2 Red 10 Light Red
3 Cyan 11 Dark Gray
4 Purple 12 Medium Gray
5 Green 13 Light Green
6 Blue 14 Light Blue
7 Yellow 15 Light Gray
Figure 8-14. Color Codes—40 Columns
Notice these color code values are one less than the color codes used by the
keyboard and BASIC. If you want to store a value directly into COLOR RAM, store the
values in the table above, not the color codes used by BASIC and the keyboard. For
example:
POKE 55296,1
colors the character in the HOME position white. From the monitor, place the value 1 in
location $D800, and the same results occur.
Remember, these color codes only control the color of the foreground character.
The background color is controlled by background color register 0 (53281). The pixels
that make up the character image are enabled by bits in character memory. If the bit is
enabled, the pixel in the foreground is turned on in the foreground color, and is
therefore controlled by color RAM. If the bits making up the character are turned off,
they default to the color in background color register 0. The combination of on and off
bits makes up the image of the character. The value of these bits determines whether the
color data comes from color RAM or background color register 0. You'll learn more
about character patterns in the next few paragraphs.
CHARACTER MEMORY
In standard character mode, the C128 receives character data from the CHARACTER
ROM. The character ROM is stored in the range 53248 ($D000) through 57343
(SDFFF). Since the VIC chip is capable of accessing 16K at a time, the C128 needs a
way to have the character ROM available in the 16K VIC range. In C128 mode, the
character ROM is available in any VIC bank in C128 mode, based on the value of
THE POWER BEHIND COMMODORE 128 GRAPHICS 227
CHAREN. See the chapter set availability in the Character Memory section in the
beginning of this chapter.
In C64 mode the character ROM is available only in banks 0 and 2. This is
accomplished by having a ROM IMAGE of the character ROM (53248-57343) mapped
into memory in place of RAM, in the range 4096-8191 ($1000-$1FFF) in video BANK
0, and 36864-40959 ($9000-$9FFF) in video BANK 2. In banks 1 and 3, the character
ROM is not available to the VIC chip.
Notice that the range where the character ROM is actually stored (53248-57343)
is also occupied by the I/O registers but not at the same time. When the VIC chip
accesses the character ROM, the character ROM is switched into the currently selected
video bank as a ROM image (in C64 mode only). When the character ROM is not
needed, the I/O registers are available in the usual range. It is important to note the
ROM image applies only to the character data as seen by the VIC chip. The RAM loca-
tions where the ROM image maps in are still usable for programs and data. The locations
where the VIC chip looks for the character data are relocatable. See the Character
Memory section elsewhere in this chapter for information on moving character memory.
A DDR ESS
VIC-II
BLOCK DECIMAL HEX IMAGE CONTENTS
Bytel 0 0 1h 1 1 0 0 $D000
Byte 2 0 1 1 0 0 1 1 0 $D001
Byte 3 0 711 |o 1 1 1 0 $D002
Byte 4 0 1 1 0 1 1 1 0 $D003
Byte 5 0 1 1 0 0 0 0 0 $D004
Byte 6 0 1 1 0 0 0 1 0 $D005
Byte 7 0 0 1 1 1 1 0 0 $D006
Byte 8 oio 0 0 0 0 0 0 $D007
Character on Character as
the Screen Represented
in Character ROM
In Figure 8-16, the first eight bytes of character ROM, ($D000-$D007) are equal
to 60,102,110,110,96,98,60 and 0. These decimal numbers are calculated from the
binary value of the eight bytes that pertain to each row of pixels in the character. For
each bit that is equal to one, raise two to the bit position (0-7). For example, the first
byte of character ROM ($D000) is equal to 60, which is calculated by raising two to the
following bit positions:
22 + 23 + 2 4 + 25 = 4 + 8+16 + 32 = 60
The bits that are set (on) correspond to pixels that are enabled on the screen in the
foreground color. Bits that are clear correspond to pixels that are disabled, which are
displayed in the background color, according to background color register 0 at location
53281.
The second byte (row of pixels) of the at-sign (@) character is equal to 102
(decimal) and is obtained by the following:
THE POWER BEHIND COMMODORE 128 GRAPHICS 229
21 + 2 2 + 25 + 2 6 = 102
The last byte of the at-sign character is equal to zero, since no bits are set.
Therefore, each pixel on the screen is displayed in the background color. The values of
the binary digits on the right in Figure 8-16 are directly related to the image of the
character as it appears on the screen on the left in Figure 8-16.
C128 BASIC
To access character ROM in C128 BASIC, type and run the following program:
10 BANK 14
20 FOR 1=53248 TO 53248+7:PRINTPEEK(I);:NEXT
3 0 BANK 15
Enter Bank 14, the only BASIC bank where the character ROM is accessible.
Then print the PEEK value of the first eight bytes of the character ROM. When
finished, return to Bank 15.
MACHINE LANGUAGE
To access character ROM in C128 Machine Language, type and run the following
program:
MONITOR
PC SR AC XR YR SP
; FB000 00 00 00 00 F6
. 01800 A9 01 LDA #$01
. 01802 8D 00 FF STA $FF00
. 01805 A2 00 LDX #$00
. 01807 BD 00 DO LDA $D000,X
. 0180A 9D 40 18 STA $1840,X
. 0180D E8 INX
. 0180E E0 07 CPX #$07
. 01810 DO P5 BNE $1807
. 01812 A9 00 LDA #$00
. 01814 8D 00 FF STA SFFOO
. 01817 60 RTS
10 SYS 6144
20 FOR 1=6208 TO 6208 +7:PRINTPEEK(I);:NEXT
These machine language and BASIC routines accomplish the same task as the preceding
four-line BASIC program. The first two machine language instructions switch in the
character ROM, and switch out I/O. The next six instructions transfer the first eight
bytes of character ROM into locations 6208 ($1840) through 6215 ($1847). The last
three instructions switch out the character ROM, replace it with the I/O registers and
return from the machine language subroutine to BASIC.
The BASIC routine activates the machine language subroutine, then prints the
values that were temporarily stored in 6208 through 6215. See Chapter 6, How to
Enter Machine Language Programs, for details on how to input machine language
instructions on the C128.
C64 BASIC
To access character ROM in C64 BASIC, enter and run the following program:
Line 40 turns off the interrupt timer. Line 50 switches out I/O and replaces it with
character ROM. Line 80 transfers the first eight bytes of character ROM (53248-53255)
to 6144—6151. Line 90 switches out character ROM, and replaces it with the I/O
registers. Line 105 turns on the interrupt timer. Line 130 prints the first eight character
ROM values that were temporarily stored in 6144 through 6151.
You may need to transfer parts of the character ROM data into RAM if you are
creating your own character set, and you want the remainder to be from the C128
character set. This is covered in more detail later in the chapter. These methods of
looking at the character ROM demonstrate how the character ROM is accessed, what the
patterns of the characters look like and why you would want to access the character
ROM.
The next section explains how to program your own custom characters in C128
mode.
PROGRAMMABLE CHARACTERS
The Commodore 128 has a feature that allows you to redefine the character set into
custom characters of your own. In most cases, you'll want to redefine only a few
characters at most, while obtaining the rest of the character set from the Commodore
128 character ROM.
With programmable characters, you tell the C128 to get character information
from RAM. Usually, characters are taken from the character ROM. If you only want
certain characters, you can choose the ones you want, copy the character patterns into
RAM and leave the rest in ROM. You cannot write to the character data in ROM;
however, the character data placed in RAM can be redefined.
The first step in programming your own characters is to define the image. In the
THE POWER BEHIND COMMODORE 128 GRAPHICS 231
Standard Character Mode section, you saw how a character on the screen is stored in the
character ROM. Each character requires eight bytes of storage. Each byte corresponds to
a row of pixels on the visible screen within the 8 by 8 character matrix; therefore, eight
rows of pixels make up one character.
This section shows how to customize an uppercase cursive (script) character set
for the letters A through H. Figure 8—17 shows the design for the uppercase cursive
letter A. The grid in the figure demonstrates how the character appears on the screen
within the 8 by 8 pixel matrix. Each row of the grid determines which bits are on within
the character bit pattern, and, hence, which corresponding pixels are enabled on the
screen. The eight-bit binary strings to the right of the grid are the bit patterns as stored
in RAM. The numbers to the right of the binary strings are the decimal equivalents of
the binary bit patterns. This decimal value is the data you POKE into RAM in order to
display the character.
/ b 4 3 2 1 0
0 0 0 0 = 00001110 = 14
1 e 0 = 00010001 = 17
2 0 = 00100000 = 32
3 0 0 = 01000010 = 66
4 • o = 10000010 = 130
5 0 e = 10000100 = 132
6 • 0 0 = 10001010 = 138
7 0 0 s 0 = 01110001 = 123
The following program creates and displays the upper-case cursive characters A
through H. Enter it into the computer and RUN it. You'll see the letters A through H
change from uppercase block letters to uppercase cursive letters. When you press the
newly defined lettered keys, they are displayed in cursive form.
Line 10 selects the uppercase character set, the set being redefined. Line 20
protects the character set from being overwritten by the BASIC program and prepares a
location in RAM in which to place your character set. The end of user BASIC text and
the top of string storage is moved from 65280 to 12288 (decimal), which substantially
cuts down the size of BASIC programming space. The character set will be placed
beginning at location 12288, but it does not have to be located there. The character set
does have to be within the first 16K of memory unless another bank is selected. The
VIC chip can only access 16K at a time so each video bank consists of 16K of memory.
10 PRINT CHR$(142) :REM SELECT UPPER CASE
20 POKE54,48:POKE58,48:CLR:REM PROTECT CHAR SET
30 BANK 14 :REM SWITCH TO BANK 14 FOR CHARACTER ROM
40 FORI=1 TO 511:POKEI+12288,PEEK(1+53248):NEXT:REM ROM TO RAM TRANSFER
50 BANK 15:REM SWITCH TO DEFAULT BANK
60 POKE 2604,(PEEK(2604) AND 240)+12:REM START CHAR BASE AT 12288
70 F0RJ=12288TO12288+71 :REM PLACE CHARACTER DATA IN RAM
80 READ A
90 POKEJ,A
100 NEXT J
110 SCNCLR
120 DATA 0,0,0,0,0,0,0,0:REM ?
130 DATA 14,17,32,66,130,132,138,123:REM A
140 DATA 124,66,66,124,66,81,225,126:REM B
150 DATA 62,67,130,128,128,128,131,126:REM C
160 DATA 125,9 8,125,65,6 5,193,161,254:REM D
170 DATA 225,6 6,6 4,56,120,65,66,124:REM E
180 DATA 12 7,12 9,2,4,14,2 28,6 8,56:REM F
190 DATA 193,163,253,3 3,2 49,65,99,190:REM G
200 DATA 227,165,36,36,126,36,37,231:REM H
You can leave yourself more BASIC text area, but to do this you must enter a video
bank higher than zero. This sample program operates in Bank 0. If you place your
character set in a higher video bank, remember to add an offset of 16384 ($4000) to the
start of RAM character memory for each bank above video Bank 0.
The CLR in line 20 clears out memory starting at 12288 because, prior to the
placement of the character set there, the memory locations are filled with random bytes.
The random bytes must be cleared before new character information can be stored.
. Line 30 selects BANK configuration 14. This configuration makes the character
ROM visible with a PEEK command or within the machine language monitor, and
temporarily switches out the I/O registers. Both the I/O functions and the 4K character
ROM share the same locations ($D000-$DFFF). Depending on whether bit 0 in the
configuration register (location $FF00) is on or off, the C128 addresses the I/O registers
or the character ROM. Normally the C128 powers up with bit 1 turned off; therefore,
the I/O registers in locations $D000-$DFFF are addressed. The BANK command in line
30 sets bit 0 in location $FF00; therefore, the character ROM in locations 53248-57343
($D000-$DFFF) is addressed. The character ROM is accessed in order to make the
transfer of characters to RAM.
Line 40 makes the actual transfer from ROM to RAM. Since the character ROM is
accessed in line 30, it now begins at location 53248. The first 512 bytes (the uppercase
character set) from the character ROM are POKEd into the 512 bytes of RAM beginning
at location 12288 and ending at 12800. At this point the character set is ready to be
redefined to custom characters.
Line 50 switches the I/O registers back in, meaning the character ROM is no
longer available.
Line 60 specifies the start of the character set base at location 12288. The character
set base can be stored in locations other than 12288. (See the Character Memory section
earlier in this chapter for more information on moving character memory.) Location
2604 is the intermediate memory location that the interrupt-driven C128 screen editor
uses to point to screen and character memory in character mode. You must use this
indirect location to change the value of the actual register that points to the screen and
character memory 53272. If you try to POKE directly to location 53272, the interrupt will
THE POWER BEHIND COMMODORE 128 GRAPHICS 233
change the value back to the original one within a sixtieth of a second. (You can, how-
ever, disable the interrupt-driven screen editor. See the Shadow Register section for details.)
The value (AND 240) or 12 is placed in address 2604 to tell the C128 to point to
character memory in RAM, starting at address 12288. If the value (AND 240) or 8 is
placed into 2604, the character set will begin at 8192 and your BASIC program must be
less than 6K, but the complete 4K of characters can be redefined. If the value (AND 240)
or 14 is placed into that location, the character set starts at 14336. Your BASIC program
then must be less than 2K, since the programmable character set must reside within a
single 16K block, but the BASIC program that creates the characters can be almost 14K.
If a number other than 12 is POKED into 2604, other program lines must be modified.
Lines 70 through 100 start a loop at the beginning of the character base (12288),
read the values from the data statements which define the new characters (lines 120 and
200), and POKE them (line 90) into the locations allocated for the character set base,
starting at location 12288. The value 12288 + 71 in line 70 sets aside seventy-two
storage locations for the data values in lines 120 through 200 for storage in locations
12288 through 12359. When more data statements are added, the value (12288 + 71)
must be increased to 12288 plus the number of data values in the data statements minus
1. For example, if more characters were defined and there were twenty data statements
with eight values in each, then line 70 would read:
70 FOR J = 12288 TO 12288+ (160-1)
Figure 8-18. " A t " Sign ((a ) Character as It Appears on the Screen
THE POWER BEHIND COMMODORE 128 GRAPHICS 23S
0 0 111 1 1 0 0
0 1 1 0 0 1 1 0
1 0 1
1
0 1 1 0
0 1 1 0 "I "I 1 0
0 1 1 0 0 0 o0
0 1 1 0 0 0 1 0
0 0 1 1 1 1 0 0
0 0 0 0 0 0 0 0
Figure 8-19. Bit Patterns of the "At" Sign (@) Character as They Appear in
Character ROM
00 11 11 00
01 10 01 10
01 10 11 10
01 10 11 10
01 10 00 00
01 10 00 10
00 11 11 00
00 00 00 00
Figure 8-20. Bit Patterns of the "At" Sign (@) Character as They Are Grouped
in Pairs in Multi-Color Character Mode
The bits are grouped in pairs, since the horizontal resolution is only half as wide in
multi-color mode. The bit pair determines the color assignments for the pixels within the
character on the screen. The following section describes how the colors are assigned in
multi-color character mode.
COLOR DATA
The color of the pixels in a multi-color character originate from four sources, depending
on the bit pairs. Since the bit pairs have four color possibilities, two bits are needed to
represent four values: 00, 01, 10 and 11. In Figure 8-21, the value of the four bit pair
combinations determines the color assignments for the pixels in a multi-color character.
8 Orange
9 Brown
10 Light Red
11 Dark Gray
12 Medium Gray
13 Light Green
14 Light Blue
15 Light Gray
Remember, the multi-color bit (bit 3) must be set to display multi-color characters.
The following program illustrates multi-color character mode.
Lines 10, 20 and 30 place the color codes for black, white and red into background
color registers 0, 1 and 2, respectively. Lines 31 through 33 print the letters of the
THE POWER BEHIND COMMODORE 128 GRAPHICS 237
alphabet on the screen twenty-five times. Line 35 fills the last 512 bjfles of color RAM
with yellow. Line 37 disables the IRQ VIC screen editor. Line 40 enables multi-color
mode. At this point, all the screen locations corresponding to the color RAM locations
which have a color code greater than or equal to 8 are displayed in multi-color mode.
Since the yellow color code is 7, all the color RAM locations having this code are
placed in standard character mode. The default color for color RAM is code 13 (light
green) for C128 mode, and code 14 (light blue) for C64 mode. Line 85 fills color RAM
with the light blue color code. The multi-color characters displayed on the screen are
red, white and blue on a black background.
SCREEN LOCATION
The screen location in extended background color mode is the same as the standard
character and multi-color character modes, 1024 ($0400) through 2023 ($07E7). This
screen range can be relocated. See the SCREEN MEMORY section for details.
HOW TO INTERPRET SCREEN DATA
The data in screen memory is interpreted as screen codes, which are actually the indexes
into the character ROM. Instead of representing the data as ASCII characters, the screen
codes represent the index into the character ROM which provide the ASCII codes. The
first character in character ROM is the at sign ((2); therefore the first screen code, 0, is the
code for the at sign.
Remember, since extended background color mode only uses five bits to deter-
mine the screen code value, only the first 64 screen code characters (0-63) are available.
COLOR DATA
The color assignments for the three colors on the screen stem from three sources. Just as
in standard character mode, the foreground color is assigned by COLOR RAM, in the
range 55296 (SD800) through 563295 (SDFE7). As described in the standard character
mode section, each color RAM location has a direct one-to-one correspondence with the
screen memory locations. See the Standard Character Mode section for screen and color
memory maps and an explanation of how the two sections of memory correspond to one
another.
The screen background color is assigned by background color register zero (location
53281 ($D021)). This is the color of the entire screen, on which the foreground and an
additional 8 by 8 character matrix background is placed.
The additional 8 by 8 character matrix background colors are determined by the
value of bits 6 and 7 of the screen code character value. Depending on the value of these
bits, the extended background color (the color within the 8 by 8 character matrix for
each character), comes from one of the four background color registers. Since there are
four choices for the extended background color, the computer needs two bits to
represent the four color choices. Figure 8-23 shows the four-bit combinations and the
corresponding background color registers associated with them.
BACKGROl' ND COLOR
CHAR A C T ER CODE R EGIS T ER
For example, POKE the screen code for the letter A (1) into screen location 1024.
Now POKE the screen value 65 into screen location 1025. You might expect the
character to be a reverse A, the second character of the second screen code character set.
THE POWER BEHIND COMMODORE 128 GRAPHICS 239
However, in this mode, you can only represent the first sixty-four characters, since you
only have five bits to represent screen characters. By trying to represent the screen code
65, bit 6 is enabled, which tells the computer to select the background color register 1
(location 53282 (SD022)), and display the same character, but with the extended
background color specified by background color register 1.
Here's a program that illustrates how extended background color mode operates:
5 SCNCLR
10 COLOR 0,1 :REM BKGRD=BLACK
20 COLOR 2,1 :REM MULTICOLOR 1
3 0 COLOR 3,2 :REM MULTICOLOR 2
40 POKE 53284,3:REM BACKGRD COLOR 3
45 POKE 53265,PEEK(53265) OR 64:REM SET EXTENDED BKGRND BIT
50 FOR 1=1024 TO 1256:POKE I,1-1023:NEXT
60 PRINT:PRINT:PRINT:PRINT
In the program, line 5 clears the screen. Lines 10 through 40 assign colors to the
four background color registers: black, white, red and cyan, respectively. Line 45
enables extended background color mode. Line 50 POKEs 232 characters into screen
memory. Each time sixty-four characters are stored into the screen memory, the same
set of sixty-four characters is POKEd into the next sixty-four screen locations. However,
the next extended background color is displayed. First, the sixty-four characters are
displayed with a black extended background, then a white extended background, then
red, then cyan.
CHARACTER DATA
Character data is interpreted the same way as in standard character mode, except only
the first 64 characters of the screen character set are available. The character data is also
located in the same range as in standard character mode. See standard character mode
for more information on character data.
Y Coordinate
0,199 319,199
Figure 8-24. Bit Map Screen Coordinates
($07E7). The video matrix can be moved, however. See the Screen Memory section
elsewhere in this chapter for information on relocating the video matrix.
X Coordinate
\ 319,0
Y Coordinate
8200
8201
8203
8204
8205
8206
8207
Now you know how bit map mode operates internally within your C128. However,
you need an easy way to turn on and off pixels in the bit map in order to display
graphics on the screen. The new, high level BASIC 7.0 commands such as DRAW,
CIRCLE, BOX and PAINT allow you to control the turning on and off of bits and their
corresponding screen pixels. The use of the X and Y coordinates on the bit map
coordinate plane easily orient you to displaying graphics. You can display high-
resolution graphics in other ways, outside of the BASIC 7.0 graphics commands.
This includes using commercial software packages that employ graphics tablets or
joysticks to draw on the screen, writing your own draw routines using a joystick or
paddle, or physically entering data into the bit map (which is painfully tedious and not
recommended).
THE POWER BEHIND COMMODORE 128 GRAPHICS 243
Another way to display graphics, which involves manipulating bits in the bit map,
is through mathematical equations, using geometry. Several books are available which
offer geometrical equations on how to draw three-dimensional objects and to move them.
Refer to the Suggestions for Further Reading the back of the book for sources on graphics.
COLOR RAM
In standard bit map mode, color RAM is not used since the color information for the bit
map is taken from the upper and lower nybble of screen RAM. Color RAM is used,
however, in multi-color bit map mode.
MACHINE LANGUAGE
To select multi-color bit map mode in C128 machine language, perform the following
instructions:
LDA $A0; enables bits 4 and 5 of GRAPHM, the shadow location
STA $00D8
In C64 machine language, enter:
LDA $D011
ORA #$20; select Bit map mode
STA $D011
LDA $D016
ORA #$10; select multi-color mode
STA $D016
In both cases, you must clear the screen, color RAM and the bit map in your own
program.
COLOR RAM
In multi-color bit map mode, color RAM is used if the bit pair from the bit map equals
11 (binary). Each color RAM location may have one of sixteen color codes, which
means that one 8 by 8 bit map area can have black, red, white and blue colors,
respectively, for the background color register 0, the upper nybble, the lower nybble, and
the color RAM. The 8 by 8 multi-color bit map area next to it can have black, red, white
and green colors, since each color RAM location is independent of any other. The other
three color sources usually remain constant throughout a bit map screen, though you can
change the upper and lower nybbles of the video matrix. The background color register
is almost always the same throughout a bit map screen.
The C128 has powerful and varied graphics display capabilities. Certain applica-
tions call for one type of display over another. Experiment with them all and see which
one meets your needs best. Figures 8-28 through 8-32 provide a graphics programming
summary that should be helpful in understanding graphics on the C128.
SPLIT-SCREEN MODES
The Commodore 128 has a split-screen feature that allows you to display the top portion
of the screen in bit map mode and the bottom portion in character mode. This allows you to
enter a BASIC graphics program and RUN it while the BASIC program listing is
present and the bit map image is displayed, which saves time switching back and forth
between bit map and character modes.
Before, you would have had to enter the graphics program (in machine language),
RUN it and switch back to the text screen to make a change. Now you can display the
graphic image and have your text screen available to you all at the same time. You can
alter the program while your bit map image is still on the screen, RUN it and see the
immediate results without losing the text screen.
Without the Commodore 128's split-screen capabilities, you would have to pro-
gram a split screen yourself. This involves raster interrupts which utilize either two
screen memories in two different video banks, or a fairly choppy single-screen memory,
usually with a visible raster line. With the C128 split-screen mode, all you have to do to
enter a split-screen mode is to issue the GRAPHIC command in BASIC. For example,
the command:
GRAPHIC 2,1
sets up a standard bit map screen on top and a text screen on the bottom. Similarly, the
command:
GRAPHIC 4,1
constructs a multi-color bit map screen on the top portion of the screen and a text screen
on the bottom portion. The " 1 " in these commands clears the bit map screen. To leave
the bit map screen intact, once you have already displayed an image, replace the " 1 "
with a zero (0).
The GRAPHIC command has an additional parameter that allows you to define
where the split occurs. The split-screen starting location is defined in terms of a
character row, as if the C128 were in a character display mode. For example,
GRAPHIC 4,1,15
selects a split screen with multi-color bit map mode on top of the screen and the text
screen on the bottom, starting at character row 15. If the start of the split screen is not
defined, the C128 defaults the start to line 19.
COLOR DATA
Each of the standard bit map, multi-color bit map and standard character modes interpret
color differently. See each section for detailed information on color assignments.
MACHINE LANGUAGE
In machine language, you must program a split screen yourself. This is not the easiest of
programming tasks, since it involves raster interrupt processing, which can be tricky. In
C128 mode, bit 6 in the GRAPHM register is the split screen bit. If bit 6 of $0008
(GRAPHM) is set, a split screen is displayed. Otherwise, bit 6 is clear (0) and a single
screen is displayed.
The C64 mode has no corresponding split screen bit. C64 mode is programmed
differently for split screens. See the Raster Interrupt Split-Screen Program at the end of
the chapter to learn how to program a split screen in machine language.
RASTER INTERRUPT
SPLIT SCREEN PROGRAM
WiTH HORIZONTAL SCROLLING
This section explains how and provides a program to perform split screen raster
interrupts in machine language. The program is explained as it applies to Commodore
64 mode, but it can be modified to run in Commodore 128 mode.
You already have a way to split the screen in C128 mode with the BASIC
GRAPHIC command. The program provided in this section splits the screen in machine
language in C64 mode. See the figure in the shadow register section to see which
addresses must be changed to make this program work in C128 Mode. A few differ-
ences will occur in the timing of the raster. In Commodore 128 mode, all interrupts
occur according to the position of the raster beam as it scans the screen. This is why
shadow registers are necessary for certain graphics locations, since the C128 screen
editor is interrupt driven to allow the split screen modes in BASIC.
The program in this section also scrolls text on the bottom quarter of a standard
character screen, while the top three quarters are displayed in multi-color bit map mode.
The standard character screen resides in video bank 0 ($0400-$07E7) while the multi-
color bit map video matrix is stored in video bank 1 starting at $5C00 ($1COO +
$4000 = $5C00). Every time an interrupt occurs, the program changes video banks,
display modes, the character memory and video matrix pointers. This program supplies
the data that scrolls at the bottom of the screen, but it assumes you have placed an 8000
byte bit map starting at address 8192 ($2000) plus an offset of 16384 ($4000) for the
change of video banks. This makes the absolute start address of the bit map 24576 ($6000).
An 8000 byte bit map is just too large to present in this book. However, the easy
way to place a bit map in this area is as follows:
THE POWER BEHIND COMMODORE 128 GRAPHICS 249
1. First start in C128 mode, and enter split screen (multi-color) bit map
mode through BASIC with this command:
GRAPHIC 4,1
2. Now draw on the screen with the BOX, CIRCLE, DRAW and PAINT
commands either in a program or in direct mode.
3. When you are finished drawing, enter the machine language monitor either by
pressing the F8 function key or by typing the MONITOR command.
4. Now transfer the video matrix and bit map from the C128 default locations of
$1COO through $1FFF and $2000 through $3FFF respectively, to $5C00 through
$5FFF and $6000 through $7FFF respectively. The new start addresses are
the default locations plus an offset of $4000 for both the video matrix and bit
map pointers. The new start of the video matrix is at $5C00 ($lC00 +
$4000). The new bit map begins at address $6000 ($2000+ $4000). This
transfer can be accomplished with a single transfer command within the
machine language monitor as follows:
T 1C00 3FFF 5C00
This command transfers the contents of memory locations $lC00 through $3FFF
to $5C00 through $7FFF. Since the default locations of the video matrix and bit map are
continuous in memory, the transfer can be done with a single command. If the default
addresses of the video matrix and bit map had not been contiguous, two transfers would
have been necessary. See Chapter 6 for details on using the Machine Language Monitor.
Now that you are still within the control of the Machine Language Monitor, begin
entering the machine language instructions in the listing provided in the next few pages.
Start entering the program at address $0C00. The program, including the scrolled data
occupies memory up to address $0DF9, which means the program is a total of 505 bytes,
or almost half a kilobyte (K).
Now save the program you just painstakingly entered with the Monitor Save (S)
command as follows:
S "filename", 08, 0C00, 0DFF
If you have a C128 assembler, create a source file, assemble and load it. If your
assembler allows it, save the program as a binary file.
The rest of the RAM memory is allocated for other purposes and the contents
change from mode to mode. There are other particular bytes that are preserved from
mode to mode, but these small chunks of memory are not worth mentioning here. The
blocks of memory mentioned above provide enough of a clue to the RAM used by both
modes. Remember, however, that the RAM is only preserved if you switch from C128
mode to C64 mode with the GO 64 command, or you switch from C64 to C128 mode
with the reset button (warm start). If you perform a cold start, turn the computer power
off, then on again, all RAM is cleared and none is preserved.
Notice that the address ranges where you placed your program, the video
matrix and the bit map are in the portions of RAM that are preserved from mode to
mode.
Now start (run) the program from C64 BASIC with this command:
SYS 12*256
The top three quarters of the screen is the bit map screen you created with the
C128 BASIC graphics commands, the lower quarter is horizontally scrolling text.
The following program is the listing that performs the split screen and scrolling.
THE POWER BEHIND COMMODORE 128 GRAPHICS 251
1750
1760
1770 CHECK LDA FLAG2
1780 BPL CHECK
1790 LDA #500
1800 STA FLAG 2
1810 ;
1820 LDX #39
1830 LDY #39
1840 SHIFT LDA (TXTPTR),Y
1850 STA $0770,X
1860 DEX
1870 DEY
1880 BPL SHIFT
1890 INC TXTPTR
1900 BNE MVTIME ;TIME TO RESET POINTER
1910 INC TXTPTR+1
1920 MVTIME LDA TXTPTR ;ARE WE AT THE END OF THE TEXT YET
1930 CMP #<ENDTXT
1940 BNE CHECK
1950 LDA TXTPTR+1
1960 CMP #>ENDTXT
1970 BNE CHECK
1980 LDA #<FRANK ;SET POINTER BACK TO THE BEGINNING
1990 STA TXTPTR
2000 LDA #>FRANK
2010 STA TXTPTR+1
2020 JMP CHECK
2030 •
2040 FRANK .BYT
2050 .BYT
2060 .BYT 'THIS IS AN EXAMPLE OF SCROLLING
2070 .BYT 'IN THE HORIZONTAL (X) DIRECTION.
2080 .BYT 'ONCE THE DATA HAS BEEN DISPLAYED,
2090 .BYT 'SCROLLING STARTS AGAIN FROM T H E '
2100 .BYT 'BEGINNING.'
2110 •
2120 ENDTXT .BYT
2130 .BYT
2140 ;
2150 ; INTERRUPT SERVICE ROUTINE
2160 ;
2170 MINE LDA $D019
2180 STA SD019
2190 ;
2200 LDA FLAG ; FLAG =0 . A=0
2210 EOR #1 ;FLAG =0 .A=l
2220 STA FLAG ;FLAG =1 .A=l
2230 TAX ;.X=l .A=l
2240 LDA POINT,X ;.X=1 .A=200
2250 STA RASTRO ;.X=1 RASTRO=200
2260 CPX #1
22 70 BNE BOTTOM
2 2 80 ;
2290 LDA $D011 ;BIT MAP MODE
2300 ORA #$2 0
2310 STA $D011 ;BMM
2320 LDA $D018
2330 ORA #$78 ;CHAR=$2000+$4000
2340 STA $D018 ;SCR=$1C00+540O0
2350 LDA $D016
2360 ORA #$10
2370 STA $D016;SET MULTICOLOR
THE POWER BEHIND COMMODORE 128 GRAPHICS 2S3
2380
2390 LDA $DD00 ;SELECT BANK 1
2400 AND #$FE
2410 STA $DD00
2420
2430 LDA SREG ;SET SCRRREG
2440 AND #$F8
2450 ORA #$03
2460 STA SREG
2470 ;
2480 LDA #14
2490 STA $D021
2500 *
2510 PLA
2520 TAY
2530 PLA
2540 TAX
2550 PLA
2560 RTI
2570
2580
2590 BOTTOM LDA $D011 ; SET TEXT MODE
2600 AND #$FF-$20
2610 STA $D011
2620 •
For readability, the program is listed as a source file, as though it was entered
through an assembler editor. It is easier to understand as a source file rather than a
listing from the Machine Language Monitor. To enter this program into the Machine
Language Monitor, reference the actual address in place of the variable operand ad-
dresses. Most of the actual addresses are listed in the beginning of the program (lines
1010 through 1100). Keep in mind that these are only line numbers for an assembler
editor. You will enter the program into a memory location number (address) in the
Machine Language Monitor. In this case, the program is stored in memory starting at
address S0C00. Line 1120 specifies this start address with:
* = $ocoo
Here's an instruction-by-instruction explanation of the scrolling split screen program.
Line 1010 assigns the variable IVEC to the address $0314, the hardware interrupt
request (IRQ) vector. The interrupt vector is the means by which the Commodore 128
displays split screens and scrolling. By wedging your own routine into the hardware
interrupt vector (in this case scrolling and splitting the screen), it enables you to perform
operations that usually take too long for the microprocessor to perform under an
application program not using interrupts. The interrupt vector is checked for an interrupt
routine every 60th of a second. In this program, the screen is split 60 times per second,
so it appears you have two different screens displayed at the same time. You could not
split the screen without requesting an interrupt; the microprocessor is not able to perform
all the required operations fast enough to keep up with the raster scan of the video
controller. The speed that the screen is continually updated, known as the raster scan,
also occurs at the speed of 60 times per second. For a split screen to occur, you tell the
computer the point on the screen where one type of display ends and the new one (bit
map for example) begins. The way you tell the computer this is by placing the number
of a pixel row, also called a raster row, in the raster compare register located at address
SD012. Line 1030 assigns this address to the variable RASTRO.
You'll see later in the program that the value placed in the Raster Compare Register
starts the text screen at raster row 201. The raster scan is again interrupted at raster row
50 at the top of the screen to display the bit map screen. This is repeated 60 times every
second, so it appears to the human eye that two different display modes are active at the
same time.
On with the program explanation. Line 1040 defines the BACOL variable for the
background color register zero, located at address $D021. Line 1050 assigns the variable
POINT to location $1802. POINT is used to store the raster row value where the text
screen begins. Line 1060 assigns the variable FLAG to location $FC. FLAG is used later
in the program (lines 2200-2270) to determine where the interrupt occurred, either raster
row 50 or raster row 200.
Lines 1070 and 1080 assign the variables FLAG2 to location $FD and SCROLL to
location $FE respectively. Both FLAG2 and SCROLL store the value of the scrolling
register. SREG is assigned to location $D016, the scrolling register. Only bits 0 through
2 are used as the scrolling bits. The other bits in this address are used for other
purposes. Three scrolling bits are necessary since characters that are scrolled are moved
over seven pixels then shifted to the next character position to the left or right, then
scrolled smoothly again seven more pixels.
Line 1100 assigns the variable TXTPTR to address $FA. This variable marks the
starting address in memory where the scrolled characters are stored.
As was mentioned earlier, line 1120 specifies where the program storage begins in
memory. This is the address where the execution of the program begins in memory. You
THE POWER BEHIND COMMODORE 128 GRAPHICS 2SS
will SYS to this address to start the program in BASIC, or GO to this address from the
Machine Language Monitor.
The first sequence of program instructions starting at line 1140 places the contents
of the address (named FRANK) of the beginning of the scrolling text into the memory
locations ($FA and $FB) called TXTPTR and TXTPTR+ 1. FRANK is the label in line
2040 which marks the location where the first scrolled character is stored. In this
program the first character is a space; in fact the first forty characters that are scrolled
across the screen are spaces. The forty-first character marks the beginning of the data
'THIS IS AN EXAMPLE OF SCROLLING' in line 2060. The scrolled data in lines
2040 through 2130 is stored starting at location $0C98, once this source file is
assembled into object code. In this case, the low byte stored in $FA is $98 and the high
stored in $FB is $0C. The full 16-bit address $0C98 is important, since this is the base
address which you increment as you scroll each letter across the VIC screen. When the
text pointer (TXTPTR) reaches the end of the scrolling text, the base address S0C98 is
again stored in TXTPTR.
The second sequence of instructions starting at line 1190 sets the high value of the
two scrolling variables SCROLL ($FE) and FLAG2 (SFD) to 7. These are used and will
be explained later in the program.
Sequence three starting at line 1230 sets the data direction register to output.
The next module of instructions in lines 1280 through 1300 set the screen size to
38 columns, reducing the screen width by a column on each side. In order to scroll
smoothly, you must set the screen size to 38 columns. Clearing bit 3 of location $D016
sets 38 column size. Setting bit 3 restores the VIC screen to its normal 40 column size.
The extra column on each side of the screen border provides a place for the
scrolled data to scroll smoothly to and from offscreen. This program scrolls left, so each
newly scrolled character is placed in column 39 on the right, before it becomes visible in
column 38. At the same time, the lead character on the left scrolls from column 2 to
offscreen column 1. This occurs in lines 1770 through 2020 and is explained as the
program progresses.
Lines 1330 through 1380 set the text screen color RAM to a white fore-
ground. The lower four bits specify the foreground character color in standard
character mode.
The screen memory is stored in video bank 0 where the scrolling text appears at
the bottom fourth of the screen. The bit map and video matrix are stored in video bank
1, the 16K range between $4000 and $7FFF.
The reason only 200 color RAM locations are filled is because only the lower five
rows are visible on the text screen. There is no point clearing the other 800 locations
since they are not visible.
Lines 1410 through 1700 make up the interrupt initialization routine. Line 1430,
labeled LOOP1, sets the interrupt disable bit in the status register. When this bit is set,
interrupts are disabled and none can occur. Only when the interrupt disable bit is cleared
(0) can interrupts occur. The last line (1720) of the interrupt initialization routine clears
the interrupt disable and allows interrupts to occur.
Lines 1440 through 1470 store the original contents of the Interrupt Request (IRQ)
vector into temporary storage locations TEMP (low byte $1806) and TEMP + 1 (high
byte $1807). This is necessary in order to store the original contents of the IRQ vector
so you can jump back to this location once the interrupt is serviced as in line 2900.
Lines 1480 through 1510 store the starting location of the interrupt service routine
into the IRQ vector. In this case, MINE is the source file label in line 2170 where the
interrupt service routine begins. In the assembled object file, as in the Machine
Language Monitor, the low byte is $71 and the high byte is $0D, to form the 16 bit
address $0D71. Once the interrupt disable bit is cleared and an interrupt occurs, the
8502 microprocessor finishes executing its current instruction and sets the interrupt
disable status bit, so no other interrupts can occur. The processor then places the
contents of the high byte and low byte of the program counter and the status register on
the stack respectively. Finally, the 8502 fetches the address contained in the IRQ vector
and executes the routine starting at this address, in this case S0D71.
Lines 1530 and 1540 disable the CIA timer in location $DC0E. In addition, line
1550 initializes the variable FLAG to zero. This variable is used later in the program to
figure out where the raster interrupt has occurred, either at the top of the screen (raster
row 49) for bit map mode or near the bottom fourth of the screen (raster row 201) for
standard character mode.
The instructions in lines 1570 through 1590 define the variable POINT ($1802) as
the value of the raster row 49 ($31) where the interrupt occurs to select bit map mode. In
addition, this value is also stored in the Read/Write Raster Register ($D012) for raster
row comparisons later in the program.
The C128 VIC screen consists of 200 raster rows, each row one pixel tall, having
320 pixel columns. You know how BASIC addresses the bit map coordinates on a
coordinate plane of 0,0 in the top left corner and 319,199 in the bottom right. However,
the visible raster rows are not labeled in the same way. The visible raster rows start at
50 at the top of the screen and end at 250 at the bottom. These are the same row
numbers as sprites use. Notice there are still 200 rows but that they offset the bit map
coordinate row number by 50. The raster row numbers below 50 and above 250 are off
the visible screen. These offscreen raster rows are referred to as the vertical retrace.
The instructions in lines 1610 and 1620 define the variable POINT + 1 ($1803) as
the value of the raster row 201 ($C9) where the interrupt occurs to select standard
character mode.
Lines 1650 and 1660 enable the raster IRQ Mask Register. Line 1670 sets the
Raster Compare IRQ Flag. By setting bit one in these registers, the raster interrupt
attached to the IRQ line is allowed to occur (once lines 1680 through 1720 are
executed), depending upon whether the physical raster row compares and matches with
either of the values in POINT or POINT+1. If either of these match, the interrupt
occurs.
The instructions in lines 1680 through 1700 clear the raster compare high bit (bit
8). This is an extra bit from location $D012 for raster compares.
THE POWER BEHIND COMMODORE 128 GRAPHICS 257
The instruction in line 1720 clears the interrupt disable status bit, which enables
interrupts to occur. This is the last operation to be performed by the interrupt initializa-
tion routine. Now interrupts are ready to occur and be serviced.
Lines 1770 through 1800 check the value of FLAG2. If FLAG2 is positive, the
program branches to the label CHECK in line 1770 and checks the value of FLAG2
again. The value stored in FLAG2 represents the value of the lower three bits in the
horizontal scrolling register at location $D016. The variable SCROLL is also associated
with the variable FLAG2. In the interrupt service routine (in lines 2760 through 2810),
the value in SCROLL is decremented and stored in FLAG2. This value pertains to the
value placed in the actual horizontal scrolling register at $D016. The reason this is
counted is as follows.
The direction of the scrolling is right to left; therefore, you must place the
maximum value (7) in the lower three bits of SD016 and decrement that value by one. If
the program had scrolled left to right, you would initialize the scrolling register to zero
and increment the lower three bits. When the scrolling register value is decremented, the
characters in the screen memory locations which are to be scrolled are moved to the left
by one pixel. Each time the scrolling register is decremented, the characters move
another pixel to the left. When the value (the lower three bits) of the scrolling register
equals zero, you must move the scrolled characters up in screen memory by one location.
This routine is contained in lines 1840 through 1880. After the shift, the lower three bits
of the scrolling register are set back to 7, the characters are again shifted by the VIC
chip 7 pixels to the left and your routine shifts the characters up in memory again by
one. The additional details are covered in the explanation of lines 2760 through 2900.
The instructions in lines 1820 through 1880 shift the text to be scrolled up in
memory by one location for each cycle of the loop. First the X and Y registers are
loaded with the decimal value 39 ($27). The instruction in line 1840 loads the value of
the memory location where the scrolled text begins using indirect Y addressing. The
address is calculated by taking the contents of zero page memory variable TXTPTR
($98) and adding the offset 39 to its contents to arrive at $BF. The effective address
gives the low byte where the scrolled data begins. The first scrolled character is actually
a space. Subsequent data elements are accessed by modifying the value of the Y register.
The store instruction in line 1850 stores the first character of the scrolling text in
screen location 1943 ($0770 + $27), which is the fortieth column of the twenty-third
row. This column is not visible when the screen size is set to 38 columns for horizontal
scrolling. Each newly scrolled character must be placed in this position in order to scroll
smoothly from the offscreen location. Lines 1860 and 1870 decrement the X and Y
registers respectively. Line 1880 branches to the label SHIFT if the Y register is positive
(greater than zero).
The second time through the loop, the low byte of the scrolled character (at
location $98 + $26 = $BE) is stored in screen location 1942 ($0770+ $26). so the
(space) character in $0CBE is stored in screen location $0796. The third time through
the loop, $0CBD is stored in $0795 and so on. This process continues until the X and
Y registers equal zero. So far, only the series of 39 space characters in lines 2040 and
2050 have been shifted across the screen.
Once the X and Y registers have been decremented to zero, the TXTPTR is
incremented in line 1890 so that subsequent characters such as "THIS IS AN EXAM-
PLE . . . " can be scrolled. In the first 39 cycles through the loop fin lines 1840 through
1880) 39 spaces are shifted (scrolled) one character position on the twenty-third character
row on the screen. The next 39 cycles shift 38 spaces and the letter " T " in "THIS" one
character position across the screen. The next 39 cycles, 37 spaces and the letters " T H "
in "THIS" are shifted in memory and scrolled one character position on the screen and
so on. This process occurs until all characters in the data (in lines 2040 through 2130)
are scrolled.
Line 1900 branches to the label MVTIME while TXTPTR (the low byte of the
start of scrolled data) is greater than zero, otherwise TXTPTR + 1 incremented to update
the high byte. Lines 1920 through 1970 check to see if the text pointers are at the end of
the scrolled character data ($0D70 in the assembled program). If the pointers are not at
the end of the character data, the program branches to the label CHECK and the data is
shifted by the VIC chip by seven pixels and the scrolling process repeats again. If the
text pointers are at the end of the scrolled character data, lines 1980 through 2010 set the
text pointers to the beginning of the scrolled data in memory and the process is repeated
continuously as specified by the JMP CHECK instruction.
Lines 2040 through 2130 represent the data to be scrolled by the program. The
data is stored in .BYTE statements as it appears in the Commodore Assembler 64
Development System. In your case, the Machine Language Monitor handles data by
simply storing it in an absolute memory range. In the assembled object code program
the data turns out to be stored in the range $0C98 through $0D70. You will refer to the
data with these addresses and not with a label as in this explanation.
Lines 2200 through 2270 determine the location (raster row) in which the raster
interrupt has occurred. Line 2200 loads the value of FLAG, which was initialized to
zero, into the accumulator. Line 2210 XOR's the accumulator with 1, which effectively
places a one in the accumulator for the first pass through this routine. This value is then
stored back into FLAG. In each subsequent occurrence of an interrupt, the value of both
the accumulator and FLAG are toggled between zero and one. The accumulator is then
transferred to the X register in line 2230. Line 2240 loads the value of POINT or POINT
+ 1 depending upon the value in the X register. If the X register equals 0, POINT is
loaded into the accumulator, which specifies the interrupt to occur at raster row 49. If
the X register equals 1, POINT +1 is loaded into the accumulator, which specifies the
interrupt to occur at raster row 201. Line 2250 stores the accumulator value into the
variable RASTRO. The X register is compared with 1 in line 2260. If the X register
equals 1, the interrupt has occurred at raster row 201 and the program branches to the
instructions in lines 2590. If the value of the X register equals 0, the branch in line 2270
falls through and the instructions in lines 2290 through 2650 are performed.
The instructions in lines 2290 through 2560 perform the operations associated with
bit map mode. Lines 2290 through 2310 select bit map mode. Lines 2320 through 2340
set the video matrix at $!C00 and the bit map at $2000. Both of these start addresses are
offset by the compulsory $4000, since this screen appears in video bank 1 ($4000-$7FFF).
Lines 2350 through 2370 set multi-color mode. Lines 2390 through 2410 select video
bank 1. Lines 2430 through 2460 set the lower two bits of the scrolling register (to the
value 3).
The instructions in 2510 through 2550 restore the original values of the X, Y and
A (accumulator) registers. Line 2560 returns from the interrupt and exits the interrupt
service routine.
Lines 2590 through 2900 perform all the associated text mode operations. Lines
2590 through 2610 select standard character mode. Lines 2630 through 2650 changes
back to video bank 0, the default bank ($0000-$3FFF). Lines 2670 through 2690 disable
multi-color mode, and return to the standard color mode. Lines 2710 and 2720 set the
default screen location 1024 ($0400) and the default start of character memory, with the
decimal value 23 ($17). All numbers which are not preceded by a dollar sign are
assumed to be decimal in this particular assembler editor. Lines 2740 and 2750 set the
background color for the text screen to black.
Lines 2760 through 2890 set the value of the scrolling register, which scrolls the
characters across the screen by 7 pixels, before they are shifted in memory with the
routine in lines 1840 through 1880.
Finally, line 2900 jumps to the default IRQ vector which was saved early in the
program into the variable TEMP. This allows the 8502 to process the normal interrupt
services as though this program's service routine had not occurred.
Although this program example is long and complex, it contains useful routines
and explanations that have never appeared before in any Commodore text. Study these
routines carefully and add them into your own programs. This section includes a wealth
of information for the novice and experienced software developer alike. Figures 8-28
through 8-32 on the following four pages provide a summary of graphics programming.
CHANGING VIDEO BANKS MOVING SCREEN RAM
BIT MAP
POKE 2605, (PEEK(2605 AND 15)
ORX
WHERE X IS A VALUE IN
TABLE 8-29 ON P. 262
L O C A T I O N OF C H A R A C T E R M E M O R Y *
VALUE
OFZ BITS DECIMAL HEX
0 XXXXOOOX 0 $0000-$07FF
2 XXXX001X 2048 $0800-$0FFF
4 XXXX010X 4096 $1000-$17FF ROM IMAGE in BANK 0 & 2
(default)*
6 XXXX011X 6144 $18OO-$1FFF ROM IMAGE in BANK 0 & 2*
8 XXXX100X 8192 $2000-$27FF
10 XXXX101X 10240 $2800-$2FFF
12 XXXX110X 12288 $3000-$37FF
14 XXXX111X 14336 $3800-$3FFF
Remember to add an offset of $4000 to the start address of character memory for each
bank above 0; for bank 3 add 3*$4000 = SCOOO
* = in C64 mode only.
Figure 8—31. Character Memory Locations
THE POWER BEHIND COMMODORE 128 GRAPHICS 263
BASIC 7.0
SPRITE COMMAND SUMMARY
Here's a brief description of each BASIC 7.0 sprite command:
COLLISION: Defines the type of sprite collision on the screen, either sprite to sprite or
sprite to data collision
MOVSPR: Positions or moves sprites from one screen location to another
SPRCOLOR: Defines colors for multi-color sprites
SPRDEF: Enters sprite definition mode to edit sprites
SPRITE: Enables, colors, sets sprite screen priorities, and expands a sprite
SPRSAV: Stores a text string variable into a sprite storage area and vice versa or
copies data from one sprite to another
SSHAPE: Stores the image of a portion of the bit-map screen into a text-string variable
BASIC 7.0
SPRITE COMMAND FORMATS
COLLISION
Define sprite collision priorities
where:
COLLISION type ^statement]
type Type of collision, as follows:
1 = Sprite-to-sprite collision
2 = Sprite-to-display data collision
3 = Light pen (40 columns only)
statement BASIC line number of a subroutine
EXAMPLE:
COLLISION 1,5000 Detects a sprite-to-sprite collision and program control sent
to subroutine at line 5000.
COLLISION 1 Stops interrupt action which was initiated in above example.
COLLISION 2,1000 Detects sprite-to-data collision and program control directed
to subroutine in line 1000.
MOVSPR
Position or move sprite on the screen (using any of the following four formats):
where:
number is sprite's number (1 through 8)
X,Y> is coordinate of the sprite location.
ANGLE is the angle (0-360) of motion in the clockwise direction relative to the sprite's
original coordinate.
SPEED is the speed (0-15) at which the sprite moves.
This statement positions a sprite at a specific location on the screen according to
the SPRITE coordinate plane (not the bit map plane). MOVSPR also initiates sprite
motion at a specified rate. This chapter contains a diagram of the sprite coordinate
plane.
EXAMPLES:
MOVSPR 1, 150, 150 Position sprite 1 at coordinate 150,150.
MOVSPR 1, +20, +30 Move sprite 1 to the right 20 (X) coordinates and down
30 (Y) coordinates.
MOVSPR 4, 50; 100 Move sprite 4 by 50 coordinates at a 100 degree
angle.
MOVSPR 5, 45 #15 Move sprite 5 at a 45 degree angle in the clockwise
direction, relative to its original x and y coordinates.
The sprite moves at the fastest rate (15).
NOTE: Once you specify an angle and a speed in the fourth form of the
MOVSPR statement, the sprite continues on its path (even if the sprite
is disabled) after the program stops, until you set the speed to zero (0)
or press RUN/STOP and RESTORE.
SPRCOLOR
Set multi-color 1 and/or multi-color 2 colors for all sprites
SPRCOLOR [smcr-1] [,smer-2]
where:
SPRITES 269
EXAMPLES:
SPRCOLOR 3,7 Sets sprite multi-color 1 to red and multi-color 2 to blue.
SPRCOLOR 1,2 Sets sprite multi-color 1 to black and multi-color 2 to white.
SPRDEF
Enter the SPRite DEFinition mode to create and edit sprite images.
SPRDEF
1-8 keys Selects a sprite number at the SPRITE NUMBER? prompt only.
A Turns on and off automatic cursor movement.
CRSR keys Moves cursor.
RETURN key Moves cursor to start of next line.
RETURN key Exits sprite designer mode at the SPRITE
NUMBER? prompt only.
HOME key Moves cursor to top left
corner of sprite work area.
CLR key Erases entire grid.
1-4 keys Selects color source and enables sprite pixels.
CTRL key, 1-8 Selects sprite foreground color (1-8).
Commodore key, 1-8 Selects sprite foreground color (9-16).
STOP key Cancels changes and returns to prompt.
SHIFT RETURN Saves sprite and returns to
SPRITE NUMBER? prompt.
X Expands sprite in X (horizontal) direction.
Y Expands sprite in Y (vertical) direction.
M Multi-color sprite.
C Copies sprite data from one sprite to another.
1. Clear the work area by pressing the shift and CLR/HOME keys at the same
time.
2. If you want a multi-color sprite, press the M key and the cursor ( + ) appears
twice as large as the original one. The double-width cursor appears since
multi-color mode actually turns on two pixels for every one in standard
sprite mode. Multi-color sprites have only half the horizontal resolution of
standard sprites.
3. Select a sprite color. For colors between 1 and 8, hold down the CONTROL
key and press a key between 1 and 8. To select color codes between 9 and
16* hold down the Commodore (CO key and press a key between 1 and 8.
4. Now you are ready to create the shape of your sprite. The numbered keys 1
through 4 fill the sprite and give it shape. For a single-color sprite, use the 2
key to fill a character position within the work area. Press the 1 key to erase
what you have drawn with the 2 key. If you want to fill one character
SPRITES 271
position at a time, press the A key. Now you have to move the cursor
manually with the cursor keys. If you want the cursor to move automatically
to the right while you hold it down, press the A key again. As you fill in a
character position within the work area, you can see the corresponding pixel
in the displayed sprite turn on. The sprite image changes as soon as you edit
the work area.
In multi-color mode, the 2 key fills two character positions in the work
area with the multi-color 1 color, the 3 key fills two character positions with
the multi-color 2 color.
You can turn off (color the pixel in the background color) filled areas
within the work area with the 1 key. In multi-color mode, the 1 key turns
off two character positions at a time.
5. While constructing your sprite, you can move freely in the work area
without turning on or off any pixels using the RETURN, HOME and cursor
keys.
6. At any time, you may expand your sprite in both the vertical and horizontal
directions. To expand vertically, press the Y key. To expand horizontally,
press the X key. To return to the normal size sprite display, press the X or Y
key again.
When a key turns on AND off the same control, it is referred to as
toggling, so the X and Y keys toggle the vertical and horizontal expansion of
the sprite.
7. When you are finished creating your sprite and are happy with the way it
looks, save it in memory by holding down the SHIFT key and pressing the
RETURN key. The Commodore 128 stores the sprites data in the appropri-
ate sprite storage area. The displayed sprite in the upper right corner of the
screen is turned off and control is returned to the SPRITE NUMBER
prompt. If you want to create another sprite enter another sprite number and
edit the new sprite just as you did with the first one. If you want to display
the original sprite in the work area again, enter the original sprite number. If
you want to exit SPRite DEFinition mode, simply press RETURN at the
SPRITE NUMBER prompt.
8. You can copy one sprite into another with the C1 key.
9. If you do not want to SAVE your sprite, press the STOP key. The Commo-
dore 128 turns off the displayed sprite and any changes you made are
cancelled. You are returned to the SPRITE NUMBER prompt.
10. To EXIT SPRite DEFinition mode, press the RETURN key while the
SPRITE NUMBER prompt is displayed on the screen without a sprite
number following it. You can exit under either of the following conditions:
Once you have created a sprite and have exited SPRite DEFinition mode, your
sprite data is stored in the appropriate sprite storage area in the Commodore 128's
memory. Since you are now back in the control of the BASIC language, you have to
turn on your sprite in order to see it on the screen. To turn it on, use the SPRITE
command you learned. For example, you created sprite 1 in SPRDEF mode. To turn it
on in BASIC, color it blue and expand it in both the X and Y directions and enter this
command:
SPRITE 1,1,7,0,1,1,0
Now use the MOVSPR command to move it at a 90-degree angle at a speed of 5,
as follows:
MOVSPR 1, 90 # 5
Now you know all about SPRDEF mode. First, create the sprite, save the sprite
data and exit from SPRDEF mode to BASIC. Next, turn on your sprite with the SPRITE
command. Move it with the MOVSPR command. When you're finished programming,
SAVE your sprite data in a binary file with the BSAVE command as follows:
BSAVE "filename", BO, P3584 TO P4096 (This saves all 8 sprites.)
SPRITE
Turn on and off, color, expand and set screen priorities for a sprite
SPRITE number> [,on/off][,fngd][,priority] [,x-exp] [,y-exp] [,mode]
The SPRITE statement controls most of the characteristics of a sprite. The
brackets signify optional parameters. If you omit a parameter, you still must include a
comma in its place.
PARAMETER DESCRIPTION
EXAMPLES:
SPRITE 1,1,3 Turn on sprite number 1 and color it red.
SPRITES 273
SPRITE 2,1,7,1,1,1 Turn on sprite number 2, color it blue, make it pass behind
objects on the screen and expand it in the vertical and
horizontal directions.
SPRITE 6,1,1,0,0,1,1 Turn on SPRITE number 6, color it black. The first 0
tells the computer to display the sprites in front of objects
on the screen. The second 0 and the 1 following it tell the
C128 to expand the sprite vertically only. The last 1
specifies multi-color mode. Use the SPRCOLOR com-
mand to select the sprite's multi-colors.
SPRSAV
Store sprite data from a text string variable into a sprite storage area or vice versa.
SPRSAV origin >, destination >
This command copies a sprite image from a string variable to a sprite storage area.
It also copies the data from the sprite storage area into a string variable. Either the origin
or the destination can be a sprite number or a string variable but both cannot be string
variables. If you are copying a string into a sprite, only the first 63 bytes of data are
used. The rest are ignored since a sprite can only hold 63 data bytes.
EXAMPLES:
SPRSAV 1,A$ Copies the bit pattern from sprite 1 to the string variable A$.
SPRSAV B$,2 Copies the data from string variable B$ into sprite 2.
SPRSAV 2,3 Copies the data from sprite 2 to sprite 3.
SSHAPE
Save/retrieve shapes to/from string variables
SSHAPE and GSHAPE are used to save and load rectangular areas of multi-color
or bit-mapped screens to/from BASIC string variables. The command to save an area of
the screen into a string variable is:
SSHAPE string variable, XI, Yl [,X2,Y2]
where:
Also see the LOCATE command described in Chapter 3 for information on the
pixel cursor.
EXAMPLES:
SSHAPE A$,10,10 Saves a rectangular area from the coordinates 10,10 to
the location of the pixel cursor, into string variable A$.
Saves a rectangular area from top left coordinate
SSHAPEB$,20,30,47,51
(20,30) through bottom right coordinate (47,51) into
string variable B$.
Saves a rectangular area 10 pixels to the right and 10
SSHAPE D$,+ 10.+ 10
pixels down from the current position of the pixel cursor.
ADJOINING SPRITES
The following program is an example of adjoining sprites. The program creates an outer
space environment. It draws stars, a planet and a spacecraft similar to Apollo. The spacecraft
is drawn, then stored into two data strings, A$ and B$. The front of the spaceship, the cap-
sule, is stored in sprite 1. The back half of the spaceship, the retro rocket, is stored in
sprite 2. The spacecraft flies slowly across the screen twice. Since it is traveling so slowly
and is very far from Earth, it needs to be launched earthward with the retro rockets. After the
second trip across the screen, the retro rockets fire and propel the capsule safely toward Earth.
Here's the program listing:
5 COLOR 4,1:COLOR 0,1:COLOR 1,2:REM SELECT BLACK BORDER & BKGRND, WHITE FRGRD
10 GRAPHIC 1,1:REM SET HI RES MODE
17 FOR I=lTO40
18 X=INT(RND(l)*320)+l:REM DRAW STARS
19 Y=INT(RND(l)*200)+l:REM DRAW STARS
21 DRAW 1,X,Y:NEXT : REM DRAW STARS
22 BOX 0,0,5,70,40,,1:REM CLEAR BOX
23 BOX 1,1,5,70,40:REM BOX-IN SPACESHIP
24 COLOR 1,8:CIRCLE 1,190,90,35,25:PAINT 1,190,95:REM DRAW & PAINT PLANET
25 CIRCLE 1,190,90,65,10:CIRCLE 1,190,93,65,10:CIRCLE 1,190,95,65,10:COLOR 0,1
2 6 DRAW 1,10,17 TO 16,17 TO 32,10 TO 33,20 TO 32,30 TO 16,23 TO 10,23 TO 10,17
28 DRAW 1,19,24 TO 20,21 TO 27,25 TO 26,28:REM BOTTOM WINDOW
35 DRAW 1,20,19 TO 20,17 TO 29,13 TO 30,18 TO 28,23 TO 20,19:REM TOP WINDOW
38 PAINT l,13,20:REM PAINT SPACESHIP
40 DRAW 1,34,10 TO 36,20 TO 34,30 TO 45,30 TO 46,20 TO 45,10 TO 34,10:REM SP1
42 DRAW 1,45,10 TO 51,12 TO 57,10 TO 57,17 TO 51,15 TO 46,17:REM ENG1
43 DRAW 1,46,22 TO 51,24 TO 57,22 TO 57,29 TO 51,27 TO 45,29:REM ENG2
44 PAINT 1,40,15:PAINT 1,47,12:PAINT 1,47,26:DRAW 0,45,30 TO 46,20 TO 45,10
45 DRAW 0,34,14 TO 44,14 :DRAW 0,34,21 TO 44,21:DRAW 0,34,28 TO 44,28
47 SSHAPE A$,10,10,33,32:REM SAVE SPRITE IN A$
48 SSHAPE B$,34,10,57,32:REM SAVE SPRITE IN B$
50 SPRSAV A$,1:REM SPR1 DATA
55 SPRSAV B$,2:REM SPR2 DATA
60 SPRITE 1,1,3,0,0,0,0:REM SET SPRl ATTRIBUTES
65 SPRITE 2, 1,7,0,0,0,0:REM SET SPR2 ATTRIBUTES
82 MOVSPR 1,150 ,150:REM ORIGINAL POSITION OF SPRl
83 MOVSPR 2 172 ,150:REM ORIGINAL POSITION OF SPR2
8 5 MOVSPR 1 270 # :REM MOVE SPRl ACROSS SCREEN
87 MOVSPR 2 270 # :REM MOVE SPR2 ACROSS SCREEN
90 FOR I=1TO 5950:NEXT:REM DELAY
92 MOVSPR 1 150,150:REM POSITION SPRl FOR RETRO ROCKET LAUNCH
9 3 MOVSPR 2 174,150:REM POSITION SPR2 FOR RETRO ROCKET LAUNCH
9 5 MOVSPR 1 270 # 10 :REM SPLIT ROCKET
96 MOVSPR 2 90 # 5 :REM SPLIT ROCKET
97 FOR 1 = 1 TO 1200:NEXT:REM DELAY
98 SPRITE 2,0:REM TURN OFF RETRO ROCKET (SPR2)
99 FOR I=1TO 20500:NEXT:REM DELAY
100 GRAPHIC 0,l:REM RETURN TO TEXT MODE
SPRITES 275
Lines 20 through 40 place all eight sprites at sprite coordinate location 100,100.
At this point, the sprites are not yet enabled, but when they are, all eight are on top of
one another.
Lines 50 and 60 turn on each of the eight sprites in eight different colors. The first
" I " is the sprite number parameter. The first " 1 " in line 60 signifies the enabling of
each sprite. The second " I " specifies the color code for each sprite. The second " 1 "
(the fourth parameter) sets the display priority for all the sprites. A display priority of
one tells the C128 to display the sprites behind objects on the screen. A zero display
priority enables sprites to pass in front of objects on the text or bit-map screen. The fifth
and sixth parameters, both of which are ones (1), expand the sprites' size in both the
vertical and horizontal directions to twice their original size. The final parameter in the
SPRITE statement selects the graphics display mode for the sprites; either standard
bit-map sprites (0) or multi-color bit-map sprites (1). In this example, the sprites are
displayed as standard bit-map sprites.
Line 70 moves the sprites on the screen. The first parameter, I, represents the
sprite number. The second parameter, "1*30", defines the angle at which the sprites
travel on the screen. The pound sign (#) notation signifies that the sprites move
according to a particular angle and speed. The final parameter " I " specifies the speed at
which the sprites travel on the screen. In this example, sprite 1 moves at the slowest rate
of 1, sprite 2 moves at the next highest speed of 2, while sprite 8 moves the fastest of
the eight sprites at speed 8. The highest speed a sprite can move is 15.
Finally, line 80 completes the FOR . . . NEXT structure of the loop.
SPRITES 277
Notice that the sprites move continuously even after the program has stopped
RUNning. The reason for this is that sprites are wedged into the interrupt processing of
the C128. To turn off and stop the sprites on the screen, either issue a SPRITE
command that turns them off, or press RUN/STOP and RESTORE,
The second sprite program example provides a simplified adjoining sprite algo-
rithm. It moves two adjoined sprites across the screen at a ninety-degree angle,
assuming that your sprites already reside in the sprite storage range between 3584
($0E00) and 4095 ($0FFF). For simplicity, if you don't have any actual sprite images
stored in the sprite data area, fill the sprite data area with 255 ($FF) from within the
Machine Language Monitor with this command:
F 0E00 OFFF FF
For now, this command turns on all pixels within each sprite. Now you can see
how the adjoining algorithm places and moves sprites 7 and 8 side by side.
Here's the listing:
10 REM ADJOINING SPRITE ALGORITHM
20 REM THIS PROGRAM ASSUMES YOUR SPRITES ALREADY EXIST IN SPRITE STORAGE
30 1=1 :REM INITIALIZE DISTANCE I
35 SCNCLR
40 MOVSPR 8,50,100:REM SET ORIG POSITION OF SPRITE 8
5 0 MOVSPR 73,100:REM SET ORIG POSITION OF SPRITE 7 TO ADJOIN SPR
60 DO
70 SPRITE 1,3:REM ENABLE SPR 8
80 SPRITE 1,4:REM ENABLE SPR 7
90 MOVSPR I ;90:REM MOVE SPR 8 I UNITS AT A 90 DEGREE ANGLE
100 MOVSPR 7,1 ;90:REM MOVE SPR 8 I UNITS AT A 90 DEGREE ANGLE
110 1=1+1 :REM INCREMENT LOOP
120 LOOP
Although these program examples are written in BASIC, the algorithms are the
same whether you are programming in BASIC or machine language. The next section
discusses sprite operations independent of the BASIC language. Since this section
explained sprites according to BASIC, the next section elaborates on the inner workings
of sprites from a machine level (language) perspective.
SPRITES 279
These registers control most sprite characteristics. Once you learn these programming
steps, you will be able to exercise full control over the display and movement of sprites.
Keep in mind that sprites are referred to as 1 through 8 in BASIC, but 0 through 7
in machine language.
SPRITE POINTERS
The VIC chip needs to know where to look for the bit patterns (data) that make up the
sprite image in memory. The sprite pointers are used explicitly for this purpose.
Unlike the Commodore 64, the C128 has automatically filled the sprite data
pointers with values that direct the VIC chip to point to the data stored in the sprite data
range 3584 ($0E00) through 4095 ($0FFF). These sprite data pointers are located at
2040 ($O7F8) through 2047 ($07FF) for sprites 0 and 7 respectively. They are also located
in the address range 8184 (S1FF8) through 8191 ($1FFF), once the bit map screen is
cleared with the GRAPHIC 1,1 command. The default contents of these locations are:
Hexadecimal 38 39 3A 3B 3C 3D 3E 3F
Decimal 56 57 58 59 60 61 62 63
To find the actual location where the sprite data pointers are looking for data in
memory, multiply the contents of the sprite data pointer by 64 (decimal). By multiplying
these values, you'll see that the pointers look for data in the default sprite storage
locations in Figure 9-3. See Figure 9-4 for an illustration.
The way the Commodore 128 automatically points to the correct sprite data is conven-
ient for programming, since it eliminates a step (provided the original values of the sprite
pointers have not been modified). If you want to store sprite data somewhere else in
memory, however, you'll have to change the original value of the sprite pointer (from
location 2040 through 2047, or 6184 through 8191) to a value that is equal to:
The start of sprite data is divided by 64 because the data area is allocated in 64-byte
sections. For example, you want to place your sprite 0 data in the new location 6144
($1800). Divide 6144 by 64 to get 96. Place'the value 96 ($60) in address 2040 ($078F).
ENABLING A SPRITE
Once the sprite image has been defined, and the data pointer is pointing to the correct
data, you can turn on the sprite. You do this by placing a value in the Sprite Enable
Register, location 53269 ($D015). The value placed in this register depends on which
sprite(s) you want to turn on. Bits 0 through 7 correspond to sprites 0 through 7. To
enable sprite 0, set bit 0. To enable sprite 1, set bit 1 and so on. The value you
place in the sprite enable register is equal to two raised to the bit position in decimal.
If you are programming in machine language and want to enable more than one
sprite at a time, add the values of two raised to the bit positions together and store the
result in the sprite enable register. For example, to enable sprite 5, raise two to the fifth
power (32 ($20)) and store it as follows:
LDA #$20
STA $D015
To enable sprites 5 and 7, raise two to the fifth (32 ($20)) and add it to two to the
seventh (128($80)) to obtain the result 160 (SAO):
LDA $A0
STA $D015
An easier way of perceiving the idea is through binary notation in the Machine
Language Monitor as follows:
LDA # % 10100000
STA $D015
To disable the sprite display, clear the bits in the sprite enable register.
SPRITES 283
ADDRESS DESCRIPTION
Figure 9-6 lists the color codes that are placed in the standard bit-map sprite color
registers:
0 Black 8 Orange
1 White 9 Brown
2 Red 10 Light Red
3 Cyan 11 Dark Gray
4 Purple 12 Medium Gray
5 Green 13 Light Green
6 Blue 14 Light Blue
7 Yellow 15 Light Gray
In standard bit-map sprites, the data in the sprite block determine how the colors
are assigned to the pixels on the screen within the visible sprite. If the bit in the
sprite storage block is equal to 1, the corresponding pixel on the screen is assigned
the color from the standard sprite color register. If the bit in the sprite data block
is equal to zero, those pixels on the sprite are transparent and the background data
from the screen passes through the sprite.
MULTI-COLOR SPRITES
Multi-color sprites offer a degree of freedom in the use of color, but you trade the
higher resolution of standard sprites for the added color. Multi-color sprites are displayed
in three colors plus a background color. Multi-color bit-map sprites are assigned colors
similar to the way the other multi-color modes work. Before you can assign a sprite
multiple colors, you must first enable the multi-color sprite. The sprite multi-color
register in location 53276 ($D01C) operates in the same manner as the sprite enable
register. Bits 0 through 7 pertain to sprites 0 through 7. To select a multi-color sprite,
set the bit number that corresponds to the sprite number. This requires that you raise
two to the bit position of the sprite that you want displayed in multi-color. For example,
to select sprite 4 as a multi-color sprite, raise two to the fourth power (16) and place
it in the multi-color sprite register. In machine language, perform the following
instructions:
LDA #$10
STA $D01C
To select more than one multi-color sprite, add the values of two raised to the bit
positions together and store the value in the multi-color sprite register.
The VIC chip provides two multi-color registers (0 and 1), in which to place color
codes. These are the locations of the sprite multi-color registers;
ADDRESS
Like multi-color character mode, the pixels in the multi-color sprites are assigned
color according to the bit patterns in the sprite storage block. In this mode, the bits in
the sprite block are grouped in pairs. The bit pair determines how the pixels are assigned
their individual colors, as follows:
If the bit pair is equal to 00, the pixels are transparent and the background from
the screen passes through the sprite. If the bit pattern equals 10 (binary), the color is
taken from the sprite color register (locations 53287-53294) of the sprite being defined.
Otherwise, the other two bit pair possibilities (01 and 11) are taken from sprite
multi-color registers 0 and 1 respectively.
LOCATION
DECIMAL HEX DESCRIPTION
The sprite position registers together plot the sprite on a vertical and horizontal
coordinate. The position of reference for the calculated vertical and horizontal coordi-
nate is taken from the upper-left corner pixel within the sprite. Whenever you want to
place the sprite on a particular screen position, calculate the position using the upper left
corner pixel within the sprite. The sprite coordinate plane is not the same as the bit-map
coordinate plane. The bit-map coordinate plane starts in the upper-left corner of the
screen at coordinate 0,0. The lower right corner of the bit map coordinate plane is point
319,199. The sprite coordinate plane starts at point 24,50 in the top-left corner of the
visible screen. The final visible point on the sprite coordinate plane at the bottom-right
corner of the screen is 343,249. Figure 9-8 shows how the sprite coordinate plane
relates to the visible screen.
0 ($00) 24 ($18 296 (S128)
8 ($08)
29 (S1D) \ '
50 ($32) - - 50 (J32|
NTSC*
40 COLUMNS
208 (SDO)- 25 ROWS
250 (SFA)-
r i
--
2 2 9 (SE5)
250 ($FA)
After seeing the sprite coordinate plane, you may have noticed something unusual.
The vertical coordinate positions have a range of 200. The horizontal coordinate
positions have a range of 320 coordinates. Since the C128 is an 8-bit computer, the
highest value any register can represent is 255.
How do you position a sprite past the 255th horizontal screen position? The
answer is, you have to borrow a bit from another register in order to represent a value
greater than 255.
An extra bit is already set aside in the Commodore 128 memory in case you want
to move a sprite past the 255th horizontal coordinate. Location 53264 controls sprite
movement past position 255. Each of the 8 bits in 53264 controls a sprite. Bit 0 controls
sprite 0, bit 1 controls sprite 1 and so on. For example, if bit 7 is set, sprite 7 can move
past the 255th horizontal position.
Each time you want a sprite to move across the entire screen, turn on the borrowed
bit in location 53264 when the sprite reaches horizontal position 255. Once the sprite
moves off the right edge of the screen, turn off the borrowed bit so the sprite can move
back onto the left edge of the screen. The following commands allow sprite seven to
move past the 255th horizontal position:
SPRITES 287
LDA $D010
ORA #$80
STA $D010
The number 128 is the resulting decimal value from setting bit 7. You arrive at this
value by raising two to the seventh power. If you want to enable bit 5, raise two to the
fifth power, which, of course, is 32. The general rule is to raise two to the power of the
sprite number that you want to move past the 255th horizontal screen position. Now you
can borrow the extra bit you need to move a sprite all the way across the screen. To
allow the sprite to reappear on the left side of the screen, turn off bit seven again, as
follows:
LDA $D010
AND #$7F
STA $D010
Not all of the horizontal (X) and vertical (Y) positions are visible on the screen.
Only vertical positions 50 through 249 and horizontal positions 24 through 343 are
visible. Location 0,0 is off the screen as is any horizontal location less than 24 and
greater than 343. Any vertical location less than 50 and greater than 249 is also off the
screen. The off-screen locations are set aside so that an animated image can move
smoothly on and off the screen.
ADDRESS
These registers operate in the same manner as the sprite enable register.
Bits 0 through 7 pertain to sprites 0 through 7. To expand the sprite size in either
direction, raise two to the bit position and place it in the expansion register(s). For
example, to expand sprite 7 in both directions, perform these machine language
instructions:
LDA #$80 (% 10000000 = binary notation in the Monitor)
STA $D017
STA $D01D
To expand more than one sprite, add two raised to the bit position for the sprite
numbers you want to expand, and store the result in the expansion registers.
To return the sprites to their original size, clear the bits in the expansion
registers.
1. Sprite-to-sprite
2. Sprite-to-data
Screen
Background
Plane
Sprite plane 7
Sprite plane 6
Sprite plane 5
Sprite plane 4
Sprite plane 3
Sprite plane 2
Sprite plane 1
Sprite plane 0
Figure 9-9. Relationship of Sprite Planes
The display priority of each sprite plane depends on the sprite number. The
sprite-to-sprite display priorities are predefined according to the sprite number. This
SPRITES 289
feature is preset by the C128 hardware, and is not controlled through a software
register. The lower the sprite number, the higher the priority. The higher priority sprite
passes in front of the lower priority sprite. Sprite 0 has the highest priority; therefore, it
passes in front of any other sprites that may be on the screen should they meet at a
particular screen location. For example, sprites 1 and 5 are moving toward a common
location on the screen. When the sprites reach the common location, sprite 1 passes in
front of sprite 5, since the lower sprite number has the higher display priority. Keep this
in mind when you want sprites to intersect paths and pass behind or in front of one
another. This is important when overlaying sprites. Assign the sprite you want to pass in
front of other sprites to the lower sprite number.
Portions of sprites (pixels) that are not assigned color (the bits in the sprite storage
block corresponding to those pixels are equal to zero) are transparent. Holes in these
sprites allow background data to pass through the transparent area and create a "win-
dow" effect. The same window effect occurs when a higher priority sprite with "holes"
passes in front of a lower priority sprite. Even though one sprite has a higher priority,
if portions of that higher priority sprite are transparent, the lower priority sprite or
the background display data is allowed to pass through the higher priority sprite.
SPRITE-TO-DATA COLLISIONS
A sprite-to-data collision occurs when an enabled pixel in the foreground of a sprite
overlaps a pixel from the foreground of an object on the screen. Location 53279
($D01F) flags whether a sprite-to-data collision has occurred. This register has a bit
which detects a collision for each sprite. Bits 0 through 7 pertain to sprites 0 through 7.
If a sprite is involved in a sprite-to-data collision, the bit corresponding to the sprite
involved in the collision is set. These bits remain set until they are read at which time
the VIC chip clears the entire register. A recommended programming practice is to store
the value of this register in a variable until the collision or conditional code depending
on the collision is fully processed.
Once a sprite-to-data collision is detected, the sprite-to-data collision IRQ flag in
bit 1 of location 53273 ($D019) is set and an interrupt occurs if enabled in the IRQ
Mask Register at 53274 (SD01A). When this occurs, you can incorporate an interrupt
routine to be activated upon the collision of two sprites. Therefore, your sprite-to-data
collision interrupt routine is only executed upon the condition that a sprite has collided
with an object on the screen foreground. Again, this gives you a way to conditionally
wedge an IRQ routine into your application program depending on the behavior of your
animated graphic objects on the screen.
Note that sprite-to-data collisions do not occur with multi-color bit pair 01
(binary). This permits those bits to be interpreted as background display data, without
interfering with sprite-to-data collisions.
10
PROGRAMMING
THE 80-COLUMN
(8563) CHIP
The Commodore 128 computer offers two types of video output: 40-column, composite
video through the VIC chip and 80-column, RGBI through the 8563 chip. The 80-column
display adds an important feature to the Commodore family of home and business
computers: The C128 can be regarded as a business machine. The 8563 chip enables the
C128 to display spreadsheets, wordprocessors, database managers and existing CP/M
applications in 80 columns. Now, the latest in the family of inexpensive Commodore
computers runs the Perfect series of business applications, and many other business
applications in C128 mode. In CP/M mode, the C128 runs Wordstar, and many other
popular business applications. In addition, the C128 supports all the hardware and
software available for the Commodore 64. The Commodore 128 is truly the complete
personal computer.
PROGRAMMING THE
80-COLUMN (8563) CHIP
Programming the 8563 video chip is a quite different from programming the VIC chip.
As you know, the registers of the VIC chip are located in the range 53248 ($D000)
through 53296 ($D030) in bank 15. Unlike the VIC chip, the 8563 has only two
memory locations in Commodore 128 I/O memory. $D600 and $D601. This means that
only two memory locations in the Commodore 128 I/O memory pertain to the 8563
video chip. Internally, the 8563 has thirty-seven internal registers, though they are not
addressable in C128 I/O memory. In addition, the 8563 has 16K of RAM of its own that
PROGRAMMING THE 80-COLUMN (8563) CHIP 293
is independent of the Commodore 128 RAM, You must address locations $D600 and
$D601 as the gateways through which you indirectly address the thirty-seven internal
registers and 16K of 8563 RAM. You cannot directly access any of the thirty-seven
internal registers or the 16K of 8563 RAM.
Location $D600 is the Address Register, and $D601 is the Data Register.
Generally, you place an 8563 register number in the address register ($D600) then either
write to or read from the data register in location $D601. This is a simplified explanation—
the more-detailed information given in the following sections is needed to program the
8563 successfully.
8563 NOTES:
1. You cannot use BASIC PEEK, POKE, or WAIT instructions to access
the 8563, because these commands are implemented using indirect
operations. Any indirect machine instructions (such as LDA ( ),Y or
STA( ),Y) must be avoided because they result in 'false' bus states
which are sensed by the 8563 and subsequently acted upon as though
they were valid instructions.
2. You should not, directly or indirectly, access the 8563 during inter-
rupts, because there is no way to save and restore the 8563 registers
without disrupting any I/O that might have been in progress at the
time of the interrupt.
Figure 10-1 is a summary of the 8563 registers, in the form of a register map:
BITS
REG 7 6 5 4 3 l l 0
0 HT7 HT6 HT5 HT4 HT3 HT2 HT1 HTO Horizontal Total
1 HD7 HD6 HD5 HD4 HD3 HD2 HD1 HDO Horizontal Displayed
2 HP7 HP6 HP5 HP4 HP3 HP2 HP1 HPO Horizontal Sync Position
3 VW3 VW2 VW1 VWO HW3 HW2 HW1 HWO Vert/Horiz Sync Width
4 VT7 VT6 VT5 VT4 VT3 VT2 VT1 VTO Vertical Total
5 VA4 VA3 VA2 VA1 VAO Vertical Total Adjust
6 VD7 VD6 VD5 VD4 VD3 VD2 VD1 VDO Vertical Displayed
7 VP7 VP6 VP5 VP4 VP3 VP2 VP1 VPO Vertical Sync Position
8 IM1 IMO Interlace Mode
9 CTV4 CTV3 CTV2 CTV1 CTVO Character Total Vertical
10 CM1 CMO CS4 CS3 CS2 CS1 cso Cursor Mode, Start Scan
11 — — CE4 CE3 CE2 CE1 CEO Cursor End Scan Line
12 DS15 DS14 DS13 DS12 DS11 DS10 DS9 DS8 Display Start Address hi
13 DS7 DS6 DS5 DS4 DS3 DS2 DS1 DSO Display Start Address lo
14 CP15 CP14 CP13 CP12 CPU CP10 CP9 CP8 Cursor Position hi
15 CP7 CP6 CP5 CP4 CP3 CP2 CP1 CPO Cursor Position lo
16 LPV7 LPV6 LPV5 LPV4 LPV3 LPV2 LPV1 LPVO Light Pen Vertical
17 LPH7 LPH6 LPH5 LPH4 LPH3 LPH2 LPH1 LPHO Light Pen Horizontal
18 UA15 UA14 UA13 UA12 UAH UA10 UA9 UA8 Update Address hi
19 UA7 UA6 UA5 UA4 UA3 UA2 UA1 UAO Update Address lo
20 AA15 AA14 AA13 AA12 AA11 AA10 AA9 AA8 Attribute Start Adr hi
21 AA7 AA6 AA5 AA4 AA3 AA2 AA1 AAO Attribute Start Adr lo
22 CTH3 CTH2 CTH1 CTHO CDH3 CDH2 CDH1CDHO Character Tot(h), Dsp(V)
23 _ — CDV4 CDV3 CDV2 CDV1 CDVO Character Dsp(v)
24 COPY RVS CBRATE VSS4 VSS3 VSS2 VSS1 vsso Vertical smooth scroll
25 TEXT ATR SEMI DBL HSS3 HSS2 HSS1 HSSO Horizontal smooth scroll
26 FG3 FG2 FG1 FGO BG3 BG2 BG1 BGO Foregnd/Bgnd Color
27 AI7 AI6 AI5 AI4 AI3 AI2 All AIO Address Increment / Row
28 CB15 CB14 CB13 RAM — — — — Character Base Address
29 — — — UL4 UL3 UL2 UL1 ULO Underline scan line
30 WC7 WC6 WC5 WC4 WC3 WC2 WC1 WCO Word Count
31 DA7 DA6 DA5 DA4 DA3 DA2 DAI DAO Data
32 BA15 BA14 BA13 BA12 BAH BA10 BA9 BA8 Block Start Address hi
33 BA7 BA6 BA5 BA4 BA3 BA2 BA1 BAO Block Start Address lo
34 DEB7 DEB6 DEB5 DEB4 DEB3 DEB2 DEB1 DEBO Display Enable Begin
35 DEE7 DEE6 DEE5 DEE4 DEE3 DEE2 DEE1 DEEO Display Enable End
36 — — — — DRR3 DRR2 DRR1 DRRO DRAM Refresh rate
37 HSyNCVSyNC — — — — — Horiz, Vert Sync Polarity
The numbers in the left column are the register numbers. When programming the
8563, the registers are referenced by number only, since they have no actual address in
the C128 memory map. Within the register map, columns 7 through 0 apply to the bits
within the registers. To the right are the register names, by function. Many of the
registers control more than one operation of the chip, so the names only reference the
primary purpose of the register. These registers are discussed individually at the end of
this chapter. Certain key registers are discussed in the next section. For an explanation
of each register, see the register-by-register description in the back of this chapter.
PROGRAMMING THE 80-COLUMN (8S63) CHIP 295
The 16K of 8563 RAM is organized by the Kernal in the following default
structure:
The layout can be changed by your application program. Registers 12 and 13 (high
byte/low byte) specify the start of the character display area, which is comparable to
screen RAM in the VIC chip. Registers 20 and 21 (high byte/low byte) specify the
character attribute base address. These registers determine the starting address of display
characteristics of a character such as reverse video, underlining, flashing and color.
Register 28 determines the character set base address, the start of the character defini-
tions in 8563 RAM.
As you can see, the 8563 display has the same three components as the
VIC display: screen memory, color memory, and character definitions. All three lie
in the 16K of 8563 RAM and do not show up in the C128 memory map. These
components of the 8563 video display are discussed in greater detail in the next
section.
The third element of 8563 programming is the address and data registers that
are located in locations $D600 and $D601. These locations are the transitions, the
doorways in and out of the 8563 chip. You cannot directly reference an 8563
register or RAM location. You must indirectly read or write to $D600 and $D601 in
order to communicate between the 8563 chip and the rest of the Commodore 128.
Figure 10-2 gives description of each of the mapped registers and the bits within
them:
In location $D600, bit 7 acts as a status bit. When you require a read or write
operation to the 8563 RAM or a register, you must check the value of bit 7 of
$D600. While it is 0, no read or write operations may take place.
This is the sequence of steps to perform a read or write operation:
Later in this chapter, you'll see example programs that illustrate the behavior of
these registers.
The rest of the bits in $D600 except bit 6, which involves a light pen are used to
represent a register number for read or write access. Six bits are necessary since the
8563 has 37 registers; therefore, enough bits are needed to represent numbers up to 37.
Location $D601 is strictly a data register that passes values between the 8563
and the 8502 during read and write operations respectively. Each bit in this register
is a data bit. All data that passes between 8563 and the 8502 must pass through this
register.
FUNDAMENTAL BACKGROUND
ABOUT THE 8S63 CHIP
CHARACTERS
As you know, the 8563 chip is primarily designed for displaying characters within an 80
by 25 character matrix. The visible character is an 8 by 8 pixel matrix. The character
can be defined by 16 or 32 bytes and can be displayed less than 8 by 8 pixels.
PROGRAMMING THE 80-COLUMN (8563) CHIP 297
The horizontal unit of measure within a character is a pixel. The vertical unit of
measure within a character is called a scan line. A scan line is a single horizontal row of
scanned pixels referred to as one raster. The pixel and the scan line are the smallest units
of measurement by the 8563 chip in the horizontal and the vertical directions, respec-
tively. The size of the displayed character image in both pixels and scan lines is
programmable and determined by four registers within the 8563: the Character Total
(R9) (vertical), Character Total (R22) (horizontal), Character Displayed (R23) (vertical)
and Character Displayed (R22) (horizontal) Registers. These registers are described in
the register by register description at the end of this chapter.
FRAMES
A. frame is a two-dimensional array (matrix) of characters, also referred to as simply the
screen. The default frame is the 80-column by 25-line screen in which characters are
displayed. Each character on the frame has a character pointer (a Display RAM byte)
that tells the 8563 which character to display in each character position within the frame.
Think of a frame as a framed picture on a wall containing a two-dimensional array
(matrix) of characters. For example, a frame specified to be 16 by 12 characters is filled
with characters as in Figure 10-4.
The frame also contains the vertical retrace and all other nonvisible portions of the
screen. The frame is programmable in size, similar to a window. The screen frame
determines the size of the viewed image, like the frame surrounding a window.
\_
HASADKHADKSFDKHA
HASADKHADKSFDKHA
HASADKHADKSFDKHA
HASADKHADKSFDKHA
HASADKHADKSFDKHA
HASADKHADKSFDKHA
HASADKHADKSFDKHA
HASADKHADKSFDKHA
HASADKHADKSFDKHA
HASADKHADKSFDKHA
HASADKHADKSFDKHA
HASADKHADKSFDKHA
Figure 10-4.
The default frame size is 80 columns by 25 lines. However, the frame size and
characteristics are programmable, so you can change them. The 8563 has several
registers that determine the size and characteristics of the frame. These registers are as
follows:
These registers are covered in the register-by-register description at the end of the
chapter.
PROGRAMMING THE 80-COLUMN (8563) CHIP 299
All of the 8563 video display memory resides in the 16K section of independent
RAM. The 8563 character definitions in RAM require up to 32 bytes per character. If 32
bytes per character are used, the 8563 character definitions use 8K of memory per
character set, or a total of 16K. Otherwise, each character set occupies 4K of indepen-
dent 8563 RAM, or a total of 8K for both character sets. The VIC chip requires a total
of 4K of character ROM to represent all the characters, since the VIC chip only requires
8 bytes to represent a character.
The rest of the section describes how the character display area, the character
attributes and the character definitions are addressed and interpreted.
UNDERSTANDING
DISPLAY MEMORY
The frame, which was introduced earlier in this chapter, pertains to display memory, the
portion of memory you can see on the screen. Display memory resides in the range
S0000^$07FF in the 16K independent 8563 RAM. Think of the screen as a frame of 25
rows of 80 characters each. A frame may have different proportions, but for the
purposes of this discussion, assume that the frame is 80 by 25.
Each character position (display memory location) within a frame contains a
code that acts as a pointer into the character definitions that tells the 8563 which
character to display in that particular character position within the frame. For the
defined screen of frame size 25 rows by 80 columns, the first 80 pointers define the
character codes for the 80-character positions in the top row of the screen (frame).
Locations 81 through 160 define which characters are displayed in the second row of
the screen (frame), and so on. For the defined screen frame of 80 by 25, 2000
display memory locations are necessary to display the 2000 possible character positions
of the screen.
In text mode, the contents of display RAM are screen display codes like the
ones the VIC chip uses. These are not ASCII CHR$ codes. Screen codes are actually
indexes into the 8563 character RAM definitions, like the screen codes used as indexes
into the VIC character ROM. Since the first character in 8563 character RAM is
the at-sign character, it is assigned screen code 0. The A is the second character,
so it is assigned the screen code 1, and so on. For a complete list of screen codes,
see Appendix D.
ADDRESSING
DISPLAY MEMORY
The contents of registers 12 (high-byte) and 13 (low-byte) define the 16-bit start address
of the first (top-left) character in the frame (display memory). The default start address
of display memory is $0000. The address of the second character position on the
frame, that is, the character in column two, row one, is defined by the contents of
registers 12 and 13 plus 1. Add an index to the contents of registers 12 and 13 to arrive
at the address of subsequent character positions on the frame. For example, to find the
address of the character position in the first column of the second row of an 80 by 25
frame, add an offset of 80 to the contents of registers 12 and 13. To find the address of
the character position in column 1, row 3, add 160 to the contents of registers 12
and 13.
PROGRAMMING THE 80-COLUMN (8S63) CHIP 301
In general, add an offset of 1 for each character position to the right of the
upper-left corner of the frame. To reach the same column in the row below the current
character position, add an offset of 80. Although the screen (frame) appears as a
two-dimensional matrix of characters, the address references in memory are accessed
linearly in sequence. For example, although the character in the top-left corner of the
screen is only 24 character rows away from the character in the lower-left corner of the
screen, in memory, the locations of those characters are really 1920 (24 x 80) memory
locations apart. So a frame, the size of the default screen (80 x 25) requires 2000
memory locations to store the contents of the 2000 character positions on the
frame. The contents of each display RAM location (acting as an indexed pointer into the
character definitions) tells the 8563 which character, out of the 256 available characters
in either character set, to place at any particular position on the 80 by 25 character
frame.
CHARACTER ATTRIBUTES
The character attributes are a set of 8563 RAM locations that assign video enhance-
ment qualities to the characters in the frame. Each character position in the frame
is assigned its own attribute byte, so a frame (screen) of 80 columns by 25 lines
requires 2000 attribute bytes. The default location of the attribute bytes for the 80
by 25 frame is stored in the range $0800 through $0FCF in the 16K of independent
8563 RAM.
The attributes (and the corresponding bits) that enhance the video qualities of the
characters in the frame are as follows:
BIT ATTRIBUTE
The ALTERNATE CHARACTER SET (bit 7), when high (1), enables an
additional 256 characters to be displayed within the frame.
The REVERSE VIDEO ATTRIBUTE (bit 6), when high (1), reverses the
foreground and background colors for the corresponding character in display memory.
See also the register-by-register description of the 8563 chip for all the details about
register 24, the Reverse Screen Register.
The UNDERLINE ATTRIBUTE (bit 5), when high (1), enables the UNDER-
LINE SCAN LINE (as defined by bits 0 through 4 of register 29) in the foreground
color for that character within the frame. The underline scan line may be any scan line
within the character as determined by the lower four bits of register 29.
When the BLINK ATTRIBUTE (bit 4) is equal to 1, the character associated
with this attribute byte blinks. The blinking is achieved by repeatedly switching back
and forth between the foreground and background colors. The blink rate is determined
by bit 5 of register 24.
Attribute bits 3 through 0 determine the foreground color for the R, G, B and I
respectively. The character within the associated display memory appears in the fore-
ground color determined by the R, G, B and I bits. The foreground color of each
character cell can be one of 16 colors. The actual colors on the screen can be more than
red, green and blue. The RGBI signals coming from each input and the combination of
these signals determine the actual screen color. Here are the available colors and
associated color codes. The characters' background color is determined by bits 0
through 3 of register 26. These bits in register 26 specify the background color for all
the characters on the screen. Note, however, that in machine language these codes are
one less than the BASIC codes.
20 and 21 for each character attribute to the right of the HOME position. To address the
character attribute directly below the HOME position (row 2, column 1), add an offset
of 80 to the contents of registers 20 and 21. To address the character attribute of the
character in the lower-left corner of the 80 by 25 frame, add a decimal offset of 1920
(24 x 80).
CHARACTER DEFINITIONS
The character definitions residing in 8563 RAM specify the character patterns you see
on the 80-column screen. The character patterns in memory define the pixel formation
of each member of the character set visually represented on the screen. The character
definitions can be redefined by your application program.
The default memory range for the character definitions is locations $2000 through
$3FFF in 8563 RAM. This range is a total of 8K (8192 bytes). This is enough memory
to represent two character sets of 256 characters each. The attribute bit 7 of each
attribute byte selects either of the character sets for each character position within a
frame.
The 8563 characters are represented by either 16 or 32 bytes, depending on the
value of the lower five bits (4-0) of register 9. If the value of the lower five bits of
register 9 is less than 16, each character is defined by 16 bytes in character storage.
Therefore, each character set requires a total of 4096 bytes of 8563 RAM. If the value
of the lower five bits of register 9 is greater than or equal to 16, each character is
defined by 32 bytes of 8563 character RAM. In this case, each character set occupies
8192 bytes (8K) of 8563 character RAM memory and the defined characters are
displayed using more than 16 scan lines each. This occupies the full 16K of 8563 RAM
and leaves no space for attributes. These taller characters are rarely used, however,
because the characters are twice as tall as they are wide and seem out of proportion.
The first byte of each character definition in memory represents the top horizontal
scan line of the character displayed on the screen. Depending on the value of the lower
five bits of register 9, a character will have either 16 or 32 scan lines, each being 8 bits
(pixels) wide.
Although the character definitions in 8563 character RAM are defined by either 16
or 32 8-bit bytes stacked one on top of another, the Display Data Bus is only 8 bits
wide, which limits the actual image of the character to 8 horizontal pixels. The total
width of the character including the horizontal intercharacter spacing may exceed 8
pixels. See the definition of a character in the beginning of the chapter and the
register-by-register description at the end of this chapter for details.
ADDRESSING THE
CHARACTER SET PATTERNS
The default location of the character definition start at address $2000 in 8563 RAM, and
since the starting location is programmable, you may change it. The starting location of
the character set definitions is determined by bits 5 through 7 of register 28. These are
the most significant three bits of the 16-bit address that points to the start of the
character definitions in 8563 RAM. Bits 4 through 0 of register 9 make up the five least
significant bits for the address that points to the start of the 8563 character definitions.
However, if the value of bits 4 through 0 in register 9 is greater than or equal to 16, only
bits 7 through 5 are significant, since the characters are made up of 32 bytes each and
the full 16K of 8563 RAM memory is allocated for the two character sets, 8K for each
set.
READING 8563
(RAM AND) REGISTERS
As you know, the 8563 chip has its own 16K of RAM and its own set of registers.
Neither of these appear in the standard Commodore 128 memory map. The only
memory locations that apply to the 8563 chip in Commodore 128 memory are the locations
PROGRAMMING THE 80-COLUMN (8563) CHIP 305
D600 and $D601. These are the 8563 address and data registers, respectively. In order
to read or write to 8563 RAM or registers, you must pass data through the address and
data registers. This section explains how to read the 8563 registers. The next section
illustrates how to write to the 8563 registers and RAM.
1. Load (immediate) the X register with the register number that you want to
read.
2. Store the contents of the X register (the 8563 register number) into the 8563
address register ($D600).
3. Check the status bit, bit 7 of address register $D600, until it is high (1).
4. If the status bit is low (0), go back and check it again.
5. Otherwise, load the accumulator with the contents of the 8563 data register
$D601. Store the contents of the data register into a C128 RAM location (a
variable) for future use and print the variable value.
Since many of the 8563 registers are pointers to a 16-bit address, a register pair is
required, one register for the high byte and one for the low byte. In this case, simply
increment the X register and repeat the five-step process to read the register contents of
the low byte. The high-byte register comes first in the register order, therefore the first
read is the high byte of a register pair, increment the X register and repeat the
process for the low byte. When the 8502 uses a register pair to point to a 16-bit
address, the high byte is the low byte plus 1.
Here's a program that reads the high- (R20) and low- (R21) byte register pair that
acts as a pointer to the start of the attribute storage in the 8563 RAM. The value stored
in locations $FB and $FC return the default start (high/low byte) of the attribute storage.
This pointer can be relocated to point to a section of 8563 RAM in which you define, as
is the case for display RAM and the character patterns.
EXAMPLE:
Reading a register (attribute base address)
10 SYS DEC("1800")
20 A$=HEX$(PEEK(251)}
30 B$=HEX$(PEEK(252))
40 C$=RIGHT$(A$,2)
50 D$=RIGHT$(B$,2)
60 E$=C$+D$
70 FS="S"
80 G$=F$+E$
90 PRINT "START ADDRESS = ";G$
READY.
MONITOR
PC SR AC XR YR SP
; FB0O0 00 00 00 00 F8
The behavior of the 8563 chip and the way data is transferred between the 8563
registers and the address and data registers suggests the use of the BIT instruction. The
nature of the 8502 BIT instruction is tailor-made for checking the Update Ready bit
status of location SD600. When the BIT instruction is encountered by the microproces-
sor, the value of bit 7 is transferred into the negative flag bit of the 8502 status register.
If the value is equal to 0, the negative condition does not exist. If the value is equal to 1,
a negative condition does exist. Depending upon the value of this bit, you can condition-
ally branch to instructions that carry out an operation according to the value of this flag.
That's where the third instruction in the above subroutine ($1815) comes into play.
PROGRAMMING THE 80-COLUMN (8563) CHIP 307
The BASIC portion of the program prints the high and low bytes of the 16-bit
address that defines the start of attribute storage.
To find the actual address in 8563 RAM of the start of attribute storage, put the
high byte and low byte together, and the four-digit hexadecimal number defines the start
of attribute storage. Within the monitor, issue this memory command:
M FB
The contents of $FB and $FC (high/low bytes) mark the start of attribute storage.
WRITING TO AN
8563 REGISTER
The five-step algorithm to read data from an 8563 register is similar to writing to an
8563 register. In the last section, Step 5 in the read algorithm loaded the accumulator
with the value contained in the 8563 data register (SD601). When writing, perform the
opposite operation. Instead of loading the accumulator as in a read operation, store the
accumulator value into the data register.
Here's an algorithm to write to an 8563 register:
1. Load the X register with the register number in which you want to write.
2. Load the accumulator with a value that you are writing to the 8563 register.
3. Store the contents of the X register into the 8563 address register at $D600.
4. Check bit 7, the status bit, of the Address Register until it is high (1).
5. If the status is low (0), loop back and check it again until it is high.
6. When the status bit (7) is high, store the value contained in the accumulator
into the 8563 data register ($D601).
Here's a sample program that writes to register pair R18 and R19, the Update RAM
location. Register pair R18 and R19 is the gateway into the independent 8563 RAM. For
now we'll illustrate how to write to an 8563 register. Later in this chapter, we'll take
it a step farther to explain how to read and write to the 16K of independent 8563 RAM.
READY.
MONITOR
PC SR AC XR YR SP
: FB000 00 00 00 00 F8
• The first instruction (at $1800) loads the X register with the register number
18 ($12).
• The next instruction loads the accumulator with the high byte of the value you
are placing in register 18 ($20).
• Instruction 3 calls the subroutine at location $181E, which is essentially the
same routine as in the read register example in the last section, with one
exception. The instruction in the subroutine immediately before the RTS is a
store instruction to the 8563 data register at $D601. The two instructions before
it form a loop that continually checks the Update Ready status bit pending the
write operation, just as the read program did. The write operation (STA
$D601) is not performed until the status bit 7 in the address register becomes
high (1). Once the status bit becomes equal to a 1, the high byte of the address
in register 18 is written to the data register ($D601). The subroutine returns
control to the main body of the program with the RTS instruction.
• The program resumes with the fourth instruction INX. This increments the
register number.
• The fifth instruction (LDA #00) loads the value of the low byte of the address
to be written to register 19 ($13) into the accumulator.
• The subroutine at $181E is called again, and the same process is repeated.
• Upon return of the subroutine, the same read routine example from the last
section is performed (the subroutine between S182C—$1837) to ensure that the
values that were written to registers 18 and 19 are valid. These values are
printed by the BASIC routine. To see those values, use the memory command
within the monitor as follows:
M FB
The first two bytes displayed are:
20 00
This shows that the address in the update location register pair (R18, R19) has
been written to successfully and is valid.
To execute this program, issue the Go (G) command within the Machine Lan-
guage Monitor. In order for this program to operate, I/O memory must be in context in
the currently selected monitor configuration. I/O memory is always in context within
configuration 15 ($F), so issue this command to execute the program:
G F1800
The first five instructions (memory $1800-$ 1808) and the subroutine stored in
memory locations $1821 through $182C are the same instructions contained in the program
that wrote to registers 18 and 19 in the last section. However, instead of placing the address
$2000 in register pair 18 and 19 as in the last section, the address $0000 is placed
there to mark the default starting location of display memory in 8563 RAM. This is where
the program begins to place screen code 102 in display RAM. The full 2000 bytes (8 pages
of memory minus 48 bytes) of display RAM are filled with this character screen code.
Here's how the rest of the program works. The instruction stored at location
$180B, LDY #$00, initializes the Y register to 0. The next instruction, LDA #$08
loads the accumulator with the value 8. Then, STA $FA, stores the contents of the
accumulator, which initializes this location to 8. Location $FA is used later in the
program as a counter for the number of pages to fill with screen code 102. The
instruction stored at $1811, LDA #$66, loads the accumulator with the hexadecimal
value ($66) of decimal screen code 102.
The instruction starting in location $1813, JSR $181F, calls the subroutine located
at address $18IF. This subroutine is the crux of the program and actually writes the data
to the display memory (screen). This is essentially the same routine as the subroutine
located between $181E and $1829, the one from the last section. However, there is one
key difference. The first instruction of the subroutine stored starting at $18 IF, LDX
#$1F, loads the X register with the register number 31 ($1F). When writing to 8563
PROGRAMMING THE 80-COLUMN (8563) CHIP 311
RAM, you must address register 31 because it acts as the internal data register of the
8563 chip. All data that will be written to the 8563 RAM must pass through register 31.
The next three instructions:
STX $D600
BIT SD600
BPL SI824
check the status bit (7) of the address register until the value becomes equal to 1
(high). These are the same three instructions used in the last two sections when reading
or writing to a register and in the first subroutine of this program.
Once the status bit of the 8563 address register becomes high, the data residing in
the accumulator (in this case) is written to the external 8563 data register at address
$D601, as in the instruction stored at location $1829. In addition, the data in the
accumulator is written to the address contained in the update register pair (R18, R19).
This occurs since you addressed the internal data register 31 by placing the value 31 in
the 8563 address register at $D600. Upon the status bit becoming high, all data in
register 31 is placed in the current address of 8563 RAM specified by the update register
pair (R18. R19). You placed this address in the update register pair in the very-
beginning of the program.
At this point, the 8563 hardware takes over. It automatically increments the
address contained in the update register pair (R18, R19). You as the programmer do not
increment the update register pair's contents; the 8563 chip does this for you automati-
cally. You can say that the update register pair is auto-incrementing. In addition, the
8563 reads the data from the incremented address within 8563 RAM, and places the
contents in the internal 8563 register 31. This also saves programming effort. Remem-
ber, both of these tasks are performed by the 8563 hardware, not the programmer.
Since the update register pair automatically increments the 8563 RAM addresses,
all you have to do is continually call the subroutine that writes the data to each
successive display RAM location. That's what the instructions between addresses $1813
and S181B do in the program. These instructions call the subroutine for eight pages of
display RAM, or a total of 2048 times. The write subroutine writes only one character to
the screen per call, so to fill the entire screen, it must be called 2000 (80 x 25) times.
This sample BASIC program shows how to properly read and write the 8563
registers, and read, modify, write any location in 8563 RAM. The two ML subroutines
are the key- and they can be used from either BASIC as shown here, or from your ML
program.
100 VI=DEC("1800"):VO=DEC("180C"):BANK15
110 READ A$
115 DO UNTIL A$="END"
116 : POKE VI+I,DEC(A$) (install ML routines)
117 : 1=1+1
118 : READ A$
119 : LOOP
120 : DATA 8E,00,D6,2C,00,D6,10,FB,AD,01,D6,60
130 : DATA 8E,00,D6,2C,00,D6,10,FB,8D,01,D6,60,END
140 DO (update location HIGH)
150 : PRINT
160 : INPUT"ADDRESS (0-16383)";AD (update location LOW)
170 : SYS VO, AD/256, 18
180 : SYS VO, ADAND255,19 (READ memory data)
190 : SYS VI,,31
200 : RREG A
210 : PRINT"THE 8563 MEMORY AT";AD;" IS",-A (update location HIGH)
220 : INPUT"NEW DATA (0-255) ";A (update location LOW)
230 : SYS VO, AD/256, 18
240 : SYS VO, ADAND255,19 (WRITE memory data)
250 : SYS VO, A ,31
260 : LOOP
The following disassembly shows the two ML routines used in the previous BASIC
program and in the Read register, Write register and Write to RAM examples in the
preceding sections. They are relocatable.
1. Place the initial address, where writing in RAM begins, into registers 18
(high byte) and 19 (low byte).
2. Next, load the accumulator with the data you want to place in successive 8563
RAM locations.
3. Load the X register with the number 31 which specifies the data register
within the 8563.
4. Wait for the Update Status Ready bit to become high (1). So far this is the
same procedure as writing to 8563 RAM which was described in the Writing
to 8563 RAM section.
5. To select the Block Write feature, clear (0) bit 7 of register 24, using the
same procedure you use to write to a register.
P R O G R A M M I N G T H E 8 0 - C O L U M N (8563) C H I P 313
6. Finally, place the number of successive memory locations you want to write
to 8563 RAM in register 30.
At this point, the 8563 writes the data in register 31 starting from the location deter-
mined by registers 18 and 19 through the number of successive memoiy locations specified
by register 30. The contents of registers 18 and 19 are automatically incremented to access
the next location to be written. Upon completion of the Block Write, registers 18 and 19
contain the last address plus one of the 8563 RAM locations in which it was written.
Note that one write cycle follows the initial write operation to register 31;
therefore, the quantity written to register 30 should be one less than the number of 8563
memory locations in which you want to write.
BLOCK COPY
The Block Copy feature copies (reads and writes) data from one section of 8563 RAM
to another. To copy a block of 8563 RAM:
1. Place the destination address, where copying in RAM begins, into registers
18 (high byte) and 19 (low byte).
2. Wait for the Update Status Ready bit to become high (1).
3. Set (1) bit 7 of register 24, which selects the Block Copy feature. At this
point, the 8502 writes the initial source address for the block copy to registers
32 (high byte) and 33 (low byte).
4. Place the number of successive memory locations to copy into register 30.
The 8563 reads the contents of the first source address and writes the data to the
first destination address. The 8563 RAM addresses are automatically incremented and
copying continues until the number of memory locations specified by register 30 are copied.
CURSOR POSITIONING
Register 14 (high byte) and 15 (low byte) determine the position of the cursor within the
displayed frame (screen). This register pair indicates the address of the cursor within
8563 display memory. The address of the cursor can be one that is not in the display
area of the current frame. If this address is within the address range of the current frame
(screen), the character position where the cursor is displayed appears in flashing reverse
video, as do most cursors.
The interrupt driven screen editor also has an indirect location that controls the
cursor column and row positioning. Location $0A35 in C128 RAM is the shadow
register for the 8563 cursor column and row selection.
BIT-MAPPING THE
80-COLUMN DISPLAY
The 8563 chip supports a bit-map mode. The resolution of the 80-column bit-map screen
is 640 by 400 pixels. The 8563 addresses the bytes that make up the bit map across the
width of the screen, instead of in 8 by 8 character cells as with the VIC chip.
Bit-map mode is selected by setting bit 7 of register 25. The Kernal initializes
bit 7 to 0 to select text mode.
The three main components of an 8563 bit-map display, bit-map data, display
memory and color, are similar to the VIC chip in some ways but differ in others. For
example, the VIC has an 8000-byte RAM bit map, in which each bit is assigned an
individual pixel on the visual screen. Since the 8563 bit map is twice the resolution of the
VIC screen, it uses twice the memory: 16,000 bytes (a little less than 16K). The
one-to-one correspondence between bits in memory and pixels on the screen is similar,
but they are addressed differently. The addresses to access those bits are laid out
differently in memory.
Figure 8-25 in chapter 8 illustrates how the VIC bit map is stored in memory. The
VIC screen stores 8 bytes of the bit-map in the 8 bytes that would normally make up a
character in character mode. For instance, the first 8 bytes of the visual bit map are
stored in the first (HOME) character position, which defaults to 8192 ($2000) to 8199
($2007). or the first eight pixels of the first eight raster rows. The character to the
immediate right of the HOME position stores the second eight pixels of the first eight
visual raster rows. The 200 visible VIC screen raster rows are 320 pixels wide. The 200
PROGRAMMING THE 80-COLUMN (8S63) CHIP 315
visible 8563 raster rows are 640 pixels wide. Both the VIC and 8563 screens have
raster rows which are not visible on the screen. This portion is known as the vertical retrace.
The 8563 screen is stored byte by byte across a raster row. The first eight pixels of
the first raster row are stored in the first byte of the 8563 bit-map byte, address $0000 in
8563 RAM. The second eight pixels of the first row are stored in the second byte of the
bit map ($0001 in 8563 RAM). The third eight pixels are stored in location $0002 and
so on. The first raster row is stored in the first eighty memory locations in 8563 RAM,
the second raster row is stored in the second eighty (80-159) 8563 RAM addresses and
so on. See Figure 10-5 below for an illustration.
RASTER
ROW 1 2 3 4 5 6 7 8 9 10 1 1 8 0
1 $0000 $0001 $0003 $40004 $0005 $0006 $0007 $0009 $000A$000B$000C . . . S004F
2 $0050 $0051 $0052 $0053 $0054 $0055 $0056 $0057 $009F
3 $00A0
4 $00F0
25 $3E30 $3E7F
Figure 10-5. The Relationship Between 8563 Bit Map Data and Screen Pixels
The collection of the 640 by 200 pixels on the screen form the image in this way: bits
that are set (1) enable screen pixels in the foreground color and clear (0) bits take on the
background color.
COLOR ASSIGNMENTS
The pixel color assignments for the 8563 bit map are based on the value of the bit in
memory which corresponds to the pixel on the screen. If the value of the bit in memory
is equal to zero, the pixel is colored in the background color according to the value of
bits 0 through 3 in 8563 register 26. If the value of the bit in memory corresponding to
the screen pixel is equal to one, the pixel is assigned the foreground color determined by
bits 4 through 7 in register 26.
The full-sized 640-by-200 pixel bit map bit takes up almost the full 16K of 8563 RAM.
You may wonder how you can use the attributes for the corresponding screen locations.
You have two choices: either disable the attributes or reduce the size of your bit
map by 2000 bytes, then define and enable the attributes. With a full-size bit map, you
cannot implement the attributes, because there is simply not enough independent 8563 RAM
to do both. If attributes are disabled, the 8563 bit-map screen uses only two colors, as
specified by the background and foreground color codes in register 26.
If you decide to reduce the size of the 8563 bit map and you want to implement
the attributes, set bit 6 of register 25 to enable attributes. Then place the high-byte
and low-byte addresses in registers 20 and 21, respectively, to define the start of
attribute storage. See the Character Attributes section for more information on attributes.
The instructions in this explanation are referenced by the memory addresses that
appear in the left column of the machine language monitor output as in the other
machine language program explanations.
The first instruction (JSR $18B3) jumps to a subroutine to clear the bit map (8563)
screen.
The next sequence of instructions ($1803-$ 1809) set bit 7 of 8563 register 25 to
select bit map mode. This bit defaults to 0 for text display. The subroutine starting at
$1877 is the familiar register write routine you have seen earlier in the chapter. Notice
that if the subroutine had started at location $1875, it would have written to 8563 RAM
instead of an 8563 register. This routine is called to do so later in the program.
The trick to the success of this program is addressing both the VIC screen and the
8563 screen correctly. The second sequence of instructions (S180A—$ 1816) define the
high byte of the 16-bit address for the start of both the VIC and 8563 screens. First the
X register is loaded with the value 18 ($12) which selects 8563 register 18, the 8563
RAM address high pointer. The accumulator is loaded with the value $20, which is
stored in location $FB, the VIC bit map pointer (high byte). Now the accumulator is
cleared to zero and the write register subroutine places the value zero into the 8563 bit
map (high byte) pointer.
The instructions $1817 through $181A perform the same operation for the low
byte of both the VIC and 8563 bit map pointers.
The instructions between $1820 and $1827 initialize the variables $FC, $FD, $B1
and $9C to zero. The variables $FC and $FD are the low and high byte pointers for the
8563 bit map RAM addresses. The variable $B1 is the column counter for the VIC
screen. The variable $9C is the counter that keeps track of how many addresses to skip
in 8563 RAM. This is explained later in the program.
PROGRAMMING THE 80-COLUMN (8563) CHIP S.
Here's where a major difference between the two video chips becomes important—
the way the bit map corresponds to the image on the screen. As you know, the VIC
screen stores eight rows of 8 pixels each to make up one character cell. Each row of the
eight pixels in a character on the screen are stored consecutively in memory. For
example, the HOME character position is stored in default locations $2000 through
$2007 for the bit map. The next character position (as if the display was standard text)
to the right of the HOME Position is stored between $2008 and $2015. So the first
character row is stored between $2000 and $2A00 ($2000 plus (8*8) * 40 = 2560). This
is represented graphically in the preceding section (Figure 10-5).
On the other hand, the 8563 stores a bit map across raster rows on the screen.
Each set of eight pixels of a raster row is stored in a memory location in 8563 RAM
starting at $0000. For example, the first raster row is stored in locations $0000 through
$0050, one location for each group of eight pixels. The 8563 screen is 640 pixels across;
therefore each row needs 80 bytes of storage in 8563 RAM.
Now you see how the two bit maps are addressed differently. To fully understand
how this program gets data from the VIC bit map and places it in the correct spot on the
8563 bit map, this algorithm is provided. The actual instructions to perform these steps
are added later. Here's the general scheme you need to follow:
1. Start at the beginning of both the VIC and 8563 bit map locations.
2. Get a VIC bit map byte.
3. Store it in the 8563 bit map.
4. Increment the VIC bit map pointer 8 times (the 8563 pointer increments itself
after a write).
5. Do steps 2, 3 and 4 thirty-nine times.
At this point, you have just transferred the first raster row of the VIC bit map onto
the 8563 bit map.
6. After each raster row is transferred, subtract 311 from the VIC bit map pointer.
This is done 7 times. On the eighth time, the VIC bit map pointer is
incremented by 1 to get the to the start of the next VIC character cell.
7. Perform 40 blank write operations (write zeros to the 40 blank columns) to
get to the beginning of an 8563 raster row. Remember, the 8563 bit map
pointer must be relative to the VIC screen bit map pointer.
If the VIC column counter equals 39, increment the 8563 bit map pointer 41
times to place its relative position at the start of a new character row according to the
VIC bit map.
8. Now repeat the process 25 times, once for each character row.
In the program, as discussed, the instructions in $180A through $181A start the
VIC and 8563 bit maps at locations $2000 and $0000 respectively. All these instructions
encompass step 1 of the algorithm.
The instructions that perform step 2 of the algorithm are stored at locations
$182D-$1830.
Step 3 stores the VIC bit map byte at the 8563 bit map position and is performed
by the instruction $1831 and the subroutine stored between $1875 and $1882. This
subroutine writes the value stored in the accumulator into the appropriate address in
8563 RAM as specified by the contents of 8563 registers 18 ($12) and 19 ($13).
The instructions stored at $183A through $183D perform the fourth step of the
algorithm.
The stored in $1883 through $188E update the VIC bit map pointer by 8.
Steps 2, 3 and 4 are performed while the pixel row counter in $9C is less than
seven. If it is less than seven, the next byte of the VIC bit map is loaded and stored into
the 8563 bit map.
Step 6 is contained in the subroutine starting at ($189B). This decrements the VIC
bit map pointer by 311 locations.
Step 7 of the algorithm is contained in the subroutine stored in locations $188F
through $1899.
Finally, step 8 of the algorithm is performed by the instructions $186F through
$1872.
This program allows you to transfer one bit map to the other, but leaves the VIC
bit map as 40 columns. Expand on the algorithm in this section and center the bit map
on the 80-column screen. Write a routine that proportionally spaces the 40-column bit
map and places it on the entire 80-column screen. Also add a routine that clears the
other half of the 80-column bit map. Add these routines to any business application, and
you'll have a valuable business tool which you can use completely within the 8563 chip
that display your character and bit map data.
VERTICAL SCROLLING
Scrolling in the vertical direction is easier than scrolling horizontally. The general
algorithm to scroll vertically is as follows:
1. Set the default start of the character RAM storage to $2000 in 8563 RAM.
This is done through writing to (or using the default contents of) registers
12 ($0C) and 13 ($0D). Now location $2000 in 8563 RAM marks the start
of the first character in the upper left corner of display memory (the HOME
position).
At this point, the size of the screen is 80-by-25 and the screen RAM
locations are from $2000 through $27CF in 8563 RAM. Therefore, the first
80 bytes store the first 80 characters in the top row of the 8563 screen.
2. Now add 80 ($50) to the low byte of the display RAM Pointer, register 13.
Now the second 80 bytes of the display RAM memory are displayed as the
first character row. The screen is now defined by locations $2050 through
$28IF in 8563 memory. This moves the characters up one character row. The
"old" first character row has moved off the top of the screen and the "new"
character row has moved onto the last character row of the screen from a
previously non-visible range in display area. The new character row should be
defined in 8563 RAM before it is moved onto the screen as the last character
row.
3. Though this moves an entire character row of display RAM up by one row,
the movement is sudden, abrupt and not smooth. The 8563 allows smooth
scrolling to occur vertically, through the lower four bits of register 24 ($18) in
the 8563.
To scroll smoothly one scan line at a time, write the value 1 to register
24. This moves the entire screen up by one scan line. The first previously
visible scan line is now off screen at the top and a new scan line is scrolled
from an off screen location from the bottom onto the last visible scan line of
the screen.
4. To scroll subsequent scan lines, increment the value of the lower four bits of
register 24. By incrementing this value to 2, the entire screen is smoothly scrolled
an additional scan line.
5. Continue to increment the value in register 24 until the value equals the value
stored in the lower four bits of register 9, the total number of vertical scan
lines of a character. Once these values are equal, only the bottom scan line of
the first character row is visible at the top of the screen, and all but the
last scan line of the newly scrolled data is visible at the bottom of the screen.
6. To continue to scroll, reset the value in the lower four bits of register 24 to
zero and add 80 more locations to the contents of the display RAM pointer as
you did in step 2.
If you plan to use attributes, you must increase the value of the attribute
start pointer also to keep up with the display RAM pointer.
018 0 0 A2 OC LDX #soc
01802 A9 20 LDA #$20
01804 85 FB STA SFB
01806 20 60 18 JSR $1860
01809 E8 INX
0180A A9 00 LDA #$00
0180C 85 FA STA $ FA
0180E 20 60 18 JSR $1860
01811 EA NOP
01812 A2 18 LDX #$18
01814 A9 01 LDA #$01
01816 A8 TAY
01817 20 60 18 JSR $1860
0 1 81A EA NOP
0181B C8 I NY
0181C 98 TYA
0181D CO 08 CPY #$08
0181F DO F6 BNE $ 18 1 7
01821 EA NOP
01822 EA NOP
01823 A9 00 LDA #?00
01825 20 60 18 JSR $1860
01828 AO 00 LDY #$00
0182A E6 FA INC $FA
0182C DO 02 BNE $1830
0182E E6 FB INC SFB
01830 C8 I NY
01831 CO 50 CPY #$50
01833 DO F5 BNE S182A
01835 A2 OC LDX #$0C
01837 A5 FB LDA $FB
01839 20 60 18 JSR $ 186 0
0183C E8 INX
0183D A5 FA LDA $FA
0183F 20 60 18 JSR $1860
01842 A9 00 LDA #$00
01844 85 FD STA $FD
01846 A9 00 LDA #$00
01848 85 FC STA $FC
0184A E6 FC INC $FC
0184C DO FC BNE $184A
0184E E6 FD INC $FD
018 5 0 A5 FD LDA $FD
01852 C9 AO CMP #$A0
01854 DO FO BNE $1846
01856 4C 12 18 JMP $1812
01859 EA NOP
0185A EA NOP
0185B EA NOP
0185C EA NOP
0185D EA NOP
0185E EA NOP
0185F NOP
01860 8E 00 D6 STX SD600
01863 2C 00 D6 BIT $D600
018 6 6 10 FB BPL $1863
01868 8D 01 D6 STA $D601
0186B 60 RTS
HORIZONTAL SCROLLING
Horizontal scrolling is more complex than vertical scrolling. First, the Display RAM
memory must be set up to match the "virtual" screen size. If the "virtual" screen is
132 characters wide, then the Display RAM memory must be organized as if 132
characters were to be displayed, even if only 80 horizontal characters will be displayed
PROGRAMMING THE 80-COtUMN (8S63) CHIP 323
R0 HORIZONTAL TOTAL
The number of characters, minus 1, between successive horizontal sync pulses. This
number includes the displayed part of a character row, the horizontal border and the
blanking interval during horizontal sync pulses.
R! HORIZONTAL DISPLAYED
The number of characters displayed on each character row. This number sets the width
of the displayed part of the character row.
R4 VERTICAL TOTAL
The number of character rows, minus 1, between successive vertical sync pulses. This
number includes the displayed rows, vertical border and the blanking interval during the
vertical sync pulse and determines the vertical sync rate.
R6 VERTICAL DISPLAYED
The number of character rows displayed in a frame. This number sets the height of the
displayed part of the frame.
R 10(4-0) and Rl 1(4-0). These registers allow the 8563 to be programmed for a
reverse-video "block" cursor, or for an "underline" cursor. The location of the cursor
can be changed by changing the contents of registers R14 and R15.
The number in R24(4-0) can be increased, increasing the number of scan lines
scrolled, until R24(4—0) equals R9(4—0). This is the maximum amount of smooth scroll
allowed. At this point, only one (the bottom) scan line will exist for the first character
row and the last character row will have scrolled onto the frame with only the last scan
line not visible. To scroll further, the CPU must change R24(4-0) back to 0, and
increase R12/R13 (display start address) and R20/R21 (attribute start address) to scroll
vertically by one character row. This sequence will have smooth scrolled by one
character row.
NOTE: One write cycle will follow the initial write of data to R31, so
the quantity written to R30 should be one less than the total number of
memory locations desired to be written.
Unscrolled 7 7 4
Scroll 1 7 6 3
Scroll 2 7 5 2
Scroll 3 7 4 1
Scroll 4 7 3 0
Scroll 5 7 2 7
Scroll 6 7 1 6
Scroll 7 7 0 5
There are two different versions of the 8563 chip (80-column RGBI) in produc-
tion, requiring slightly different register initialization values.
The difference between the 8563-R7A and subsequent revisions (8563-R8 and
8563-R9) is in the horizontal smooth scroll feature, represented by bits 0-3 of register
25. Even if this feature is not utilized, the correct value must be placed into this register
for a normal 80-column display. Software designed specifically for 8563-R7As will
exhibit a problem with the leftmost side of the display when run on a system with R8s or
R9s, and software designed specifically for 8563-R8s and R9s will exhibit a problem
with the rightmost side of the display when run on a system with R7A. To run correctly
on any system, the software must initialize register 25 with the correct data for the
PROGRAMMING THE 80-COLUMN (8563) CHIP 331
particular 8563 version in the system. The 8563 version can be easily ascertained
through software by reading the 8563 status register, located at SD600 in I/O memory.
Bits 0-2 contain the version number. Refer to the table below for the actual data to be
used.
7A 0 $40
8 1 $47
9 1 $47
This situation does not directly affect software which utilizes the resident C128
operating system (Kernal). The Kernal correctly determines which version of the 8563 is
present and initializes it accordingly. Software which relies on the Kernal IOINIT
routine to accomplish this initialization will not have any problems. Software which
performs the initialization itself, or alters the contents of the affected register, may
exhibit the 80-column display anomalies described above, but will otherwise function
normally.
R26(3-0) BACKGROUND R, G, B, I
In all cases, the background color is determined by R26(3-0). The borders surrounding
the screen and the vertical and horizontal intercharacter spaces are displayed at the
background color.
R26(7-4) FOREGROUND R, G, B, I
When attributes are disabled, the foreground color for all characters is determined by
R26(7-4).
be configured to be compatible with 4164 8563 RAMs (64K by 1) or with 4416 8563
RAMs (16K x 4). Register 28, bit 4 should be initialized to a 0 for operation with
4416s a 1 for operation with 4164s.
4416: Row/Col = A7/A15, A6/A13, A5/A12, A4/A11, A3/A10, A2/A9, A1/A8,
A0/A8
4164: Row/Col = A7/A15, A6/A14, A5/A13, A4/A12, A3/A11, A2/A10, A1/A9,
A0/A8
SOUND
ENVELOPE
VOL
TEMPO
PLAY
FILTER
ENVELOPE
Define a musical instrument envelope
ENVELOPE n,[,atk] [,dec] [,sus] [rel][,wf] [,pw]
where:
A parameter that is not specified will retain its predefined or currently redefined
value. Pulse width applies to the width of the variable pulse waveform (wf = 2) only.
The Commodore 128 has initialized the following ten envelopes:
N AD S R wf pw instrument
FILTER
Define sound (SID chip) filter parameters
FILTER [freq], [,lp] [,bp] [,hp] [,res]
where:
PLAY
Defines and plays musical notes and elements
PLAY "Vn,On,Tn,Un,Xn,elements"
Vn Voice (n = 1-3)
On Octave (n = 0-6)
TN Tune Envelope Defaults (n = 0-9)
0 = piano
1 = accordion
2 = calliope
3 = drum
4 = flute
5 = guitar
6 = harpsichord
7 = organ
8 = trumpet
9 = xylophone
Un Volume (n = 0-15)
Xn Filter on (n = 1), off (n = 0)
Notes: A R r ,D,E,F,G
Elements: # Sharp
$ Flat
w Whole note
H Half note
Q Quarter note
I Eighth note
s Sixteenth note
Dotted
R Rest
M Wait for all voices currently playing to
end current measure
The PLAY statement gives you the power to select voice, octave and tune
envelope (including ten predefined musical instrument envelopes), the volume and the
notes you want to PLAY. All these controls are enclosed in quotes.
All elements except R and M precede the musical notes in a PLAY string.
SOUND AND MUSIC ON THE COMMODORE 128 339
EXAMPLES:
PLAY "V1O4T0U5X0CDEFGAB" Play the notes C,D,E,F,G,A and
B in voice 1, octave 4, tune enve-
lope 0 (piano), at volume 5, with
the filter off.
PLAY "V3O5T6U7X1#B$AW.CHDQEIF" Play the notes B-sharp, A-flat,
a whole dotted-C note, a half
D-note, a quarter E-note and an
eighth F-note.
SOUND
Create sound effects and musical notes
SOUND v,f,d[,dir][,m][,s][,w][,p]
where:
v voice (1-3)
f frequency value (0-65535)
d duration (0-32767)
dir step direction (0(up), l(down) or 2(oscillate)) default = 0
m minimum frequency (if sweep is used) (0-65535) default = 0
s step value for sweep (0-32767) default = 0
w waveform (0 = triangle, 1 = sawtooth, 2 = variable, 3 = noise) default = 2
p pulse width (0-4095) default = 2048
The SOUND command is a fast and easy way to create sound effects and
musical tones. The three required parameters v,f and d select the voice, frequency
and duration of the sound. The duration is in units called jiffies. Sixty jiffies equals
1 second.
The SOUND command can sweep through a series of frequencies which allows
sound effects to pass through a range of notes. Specify the direction of the sweep with
the DIR parameter. Set the minimum frequency of the sweep with M and the step value
of the sweep with S. Select the appropriate waveform with W and specify P as the width
of the variable pulse waveform if selected in W.
EXAMPLES:
SOUND 1,40960,60 Play a SOUND at frequency 40960 in voice 1
for 1 second.
SOUND 2,20000,50,0,2000,100 Output a sound by sweeping through frequen-
cies starting at 2000 and incrementing upward
in units of 100. Each frequency is played for
50 jiffies.
SOUND 3,5000,90,2,3000,500,1 This example outputs a range of sounds start-
ing at a minimum frequency of 3000, through
5000, in increments of 500, The direction of
the sweep is back and forth (oscillating). The
selected waveform is sawtooth and the voice
selected is 3.
EXAMPLES:
SOUND 1, 49152, 240, 1, 0, 100, 1, 0
Voice
Frequency
Duration
Sweep Direction
Minimum Sweep Frequency
Step Value for Sweep
Waveform
Pulse Width for Variable Width Waveform
10 DO
20 PRINT"VC FREQ DIF MIN SV PW ":PRINT
30 V=INT(RNDi1)*3)+l REM VOICE
40 F=INT(RND(I)*65535) RE FREQ
50 D=INT(RND(1 '32767) REK DURATION
60 DIR=INT(RND(1)*3) RE* STEP DIR
7 0 M=INT(RND( 1 )*65535) REM MIN FREQ
80 S=INT(RND(1)*32767) REK STEP VAL
90 W=INT(RND(1}*4) REK WAVEFORM
100 P = INT(RND( 1)*4095 ) REM PULSE W
110 PRINT V; F;DIR;M;S;W P:PRINT:PRINT
120 SOUND V, F, D, DIR, M, S, W, P
130 SLEEP 4
140 SOUND V, 0, 0, DIR, 0, 0, W, P
150 LOOP
TEMPO
Define the speed of the song being played
TEMPO n
where n is a relative duration between (0 and 255)
The actual duration for a whole note is determined by using the formula given
below:
whole note duration = 19.22/n seconds
EXAMPLES:
TEMPO 16 Defines the TEMPO at 16.
TEMPO 1 Defines the TEMPO at the slowest speed.
TEMPO 250 Defines the TEMPO at 250.
VOL
Define output level of sound
VOL volume level
This statement sets the volume for SOUND and PLAY statements. VOLUME
level can be set from 0 to 15, where 15 is the maximum volume, and 0 is off. VOL
affects all voices.
EXAMPLES:
VOL 0 Sets volume to its lowest level.
VOL 15 Sets volume for SOUND and PLAY statements to its highest output.
CODING A SONG
FROM SHEET MUSIC
This section provides a sample piece of sheet music and illustrates how to decode notes
from a musical staff and translate them into a form the Commodore 128 can understand.
This exercise is substantially faster and easier if you know how to read music. However,
you don't have to be a musician to be able to play the tune on your Commodore 128.
For those of you who cannot read music, Figure 11-1 shows how a typical musical staff
is arranged and how the notes on the staff are related to the keys on a piano.
rnirnrnn
G A B C D E F 0 AIB C D E F Q A B C D E
jj r r rrrr
Middle
C
Inventio 13
The best way to start coding a song on your Commodore 128 is to break the notes
down into an intermediate code. Write down the upper staff notes on a piece of paper.
Now write down the notes for the lower staff. Precede the note values with a duration
code. For instance, precede an eighth note with an 8, precede a sixteenth note with a 16,
and so on. Next, separate the notes so the notes on the upper staff for one measure are
proportional in time with the notes for one measure on the lower staff.
If the musical composition had a third staff, you would separate it so the duration
would be proportional to the two other upper staffs. Once the notes for all the staffs are
separated into equal durations, a separate and dedicated voice plays each note for a
particular staff. For example, voice 1 plays the upper staff, voice 2 plays the second
staff and voice 3 plays the lowest staff.
Let's say the upper staff begins with a string of four eighth notes. In addition, say
the lower staff begins with a string of eight sixteenth notes. Since an eighth note is
proportional in time to two sixteenth notes, separate the notes as shown in Figure 11-3.
VI = 8A 8B 8C 8D
V2 = 16D 16E 16F 16G 16A 16B 16C 16D
The synchronization and timing in a musical composition are critical so you must
make sure the notes in the upper staff for voice 1, for example, are in time agreement
with the notes in the lower staff for voice 2. The first note in the upper staff in Figure
11-3 is an A eighth note. The first two notes for voice 2 are D and E sixteenth notes. In
this case, you must enter the voice 1 eighth note in the PLAY string first, then follow
the voice 2 sixteenth notes immediately after it. To continue the example, the second
note in Figure 11-3 for voice 1 (the upper staff) is a B eighth note. The B eighth note is
equal in time to the two sixteenth notes, F and G, which appear in the bottom staff for
voice 2. In order to coordinate the time, enter the B eighth note in the string for voice 1
and follow it with the two sixteenth notes, F and G, for voice 2.
As a rule, always start with the note with the longer duration. For example, if a
bar starts with a series of two sixteenth notes on the lower staff for voice 2 and the upper
staff starts with an eighth note for voice 1, enter the eighth note in the string first since it
must play for the duration while the two sixteenth notes are being fetched by the
Commodore 128. You must give the computer time to play the longer note first, and
then PLAY the notes of shorter duration, or else the composition will not be synchronized.
Here's the program that plays Invention 13. Spaces are omitted in the PLAY string
to conserve space. For readability in your programs, add space between elements in the
string. Enter it into your C128 and SAVE it for future use. Now RUN it and sit back
and enjoy the music!
The sound wave moves (oscillates) at a particular rate (frequency) which deter-
mines the overall pitch (the highness or lowness of the sound).
The sound is also made up of harmonics, which are accompanying multiples of the
overall frequency of the sound or note. The combination of these harmonic sound waves
give the note its qualities, called timbre. Figures 11-5 shows the relationship of basic
sound frequencies and harmonics.
-RESULTANT WAVE
The timbre of a musical tone (i.e., the way a tone sounds) is determined by the
tone's waveform. The Commodore 128 can generate four types of waveforms: triangle,
sawtooth, variable pulse and noise. See Figure 11-6 for a graphic representation of these
four waveforms.
••—PULSE W i D T H -
The volume of a sound changes throughout the duration of the note, from when
you first hear it until it is no longer audible. These volume qualities are referred to as
Attack, Decay, Sustain and Release (ADSR). Attack is the rate at which a musical note
reaches its peak volume. Decay is the rate at which a musical note decreases from its
peak volume to its midranged (sustain) level. Sustain is the level at which a musical note
is played at its midrange volume. Release is the rate at which a musical note decreases
from its sustain level to zero volume. The ENVELOPE generator controls the ADSR
parameters of sound. See Figure 11-7 for a graphical representation of ADSR. The
Commodore 128 can change each ADSR parameter to sixteen different levels. This
gives you absolute flexibility over the ENVELOPE generator and the resulting proper-
ties of the volume of the sound.
SUSTAIN LEVEL / 1 -
One of the most powerful Commodore 128 sound statements—the one that
controls the ADSR and waveform—is the ENVELOPE statement. The ENVELOPE
statement sets the different controls in the synthesizer which make each sound unique.
The ENVELOPE gives you the power to manipulate the SID synthesizer.
Here are the definitions of the parameters within the Envelope statement:
Envelope The properties of a musical note specified by the waveform and the attack,
decay, sustain and release settings of the note. For example, the envelope for a
guitar note has a different ADSR and waveform than that for a flute.
Waveform The type of sound wave created by the combination of accompanying
musical harmonics of a tone. The accompanying harmonic sound waves are
multiples of, and are based on the overall frequency of the tone. The qualities of
the tone generated by each waveform are recognizably different from one another
and are represented graphically in Figure 11-6.
Pulse Width The length of time between notes, generated by the pulse waveform.
The Commodore 128 has ten predefined envelopes for ten different musical
instruments. In using the predefined envelopes you do not have to specify the ADSR
parameters, waveform and pulse width settings—this is already done for you. All you
have to do is specify the envelope number. The rest of the parameters are chosen
automatically by the Commodore 128. Here are the preselected envelopes for different
types of musical instruments:
ENVELOPE
NUMBER INSTRUMENT ATTACK DECAY SUSTAIN RELEASE WAVEFORM WIDTH
0 Piano 0 9 0 0 2 1536
1 Accordion 12 0 12 0 1
2 Calliope 0 0 15 0 0
3 Drum 0 5 5 0 3
4 Flute 9 4 4 0 0
5 Guitar 0 9 2 1 1
6 Harpsichord 0 9 0 0 2 512
7 Organ 0 9 9 0 2 2048
Trumpet 8 9 4 1 2 512
Xylophone 0 9 0 0 0
FREQUENCY
Conversely, the high-pass filter allows all the frequencies above the cutoff fre-
quency to pass through the chip. All the ones below it are filtered out. See Figure 11-10.
The high-pass filter produces tinny, hollow sounds.
FREQUENCY
The band-pass filter allows a range of frequencies partially above and below the
cutoff frequency to pass through the SID chip. All other frequencies above and below
the band surrounding the cutoff frequency are filtered out. See Figure 11-11.
FREQUENCY
ADVANCED FILTERING
Each of the previous FILTERing examples used only one type of filtering at a time. You
can combine the SID chip's three methods of filtering with each other to achieve
different filtering effects. For example, you can enable the low-pass and high-pass filters
at the same time to form a notch reject filter. A notch reject filter allows the frequencies
below and above the cutoff to pass through the SID chip, while the frequencies close to
the cutoff frequency are filtered out. See Figure 11-12 for a graphic representation of a
notch reject filter.
CUTOFF
FREQUENCY
You can also add either the low-pass or high-pass filter to the band-pass filter to
obtain interesting effects. By mixing the band-pass filter with the low-pass filter, you
can select the band of frequencies beneath the cutoff frequency and below. The rest are
filtered out.
By mixing the band-pass and the high-pass filters, you can select the band of
frequencies above the cutoff frequency and higher. All the frequencies below the cutoff
are filtered out.
SOUND AND MUSIC ON THE COMMODORE 128 351
Experiment with the different combinations of filters to see all the different types
of accents you can place on your musical notes and sound effects. The filters are
designed to perfect the sounds created by the other components of the SID chip. Once
you have created the musical notes or sound effects with the SID chip, go back and add
the FILTERing to your programs to make them as crisp and clean as possible.
Now you have all the information you need to write your own musical programs in
Commodore 128 BASIC. Experiment with the different waveforms, ADSR settings,
TEMPOs and FILTERing. Look in a book of sheet music and enter the notes from a
musical scale in sequence within a play string. Accent the notes in the string with the
SID control characters. You can combine your Commodore 128 music synthesizer with
C128 mode graphics to make your own videos or "movies" complete with sound
tracks.
Run the three connecting wires inside the cable to attach to the audio in, audio out
and ground on the end of your component.
You can connect the C128 to your stereo system or VCR and channel sound
through your speakers. Be careful, however, not to exceed the standard electrical
restrictions. See the SID chip specs in Chapter 16 under the description EXT IN
(Pin 26).
Using the C128 in these ways opens your eyes to how flexible a personal computer
can be and how it can communicate with a wide range of devices in your home,
including your telephone (with an additional modem), VCR, stereo, TV—and don't
forget the electric guitar!
21 1 0 1 0 1 15 - - - - - FC 2 FC, FC 0
Filter
WRITE-ONLY
n
FC LO
22 1 0 1 1 0 16 FC,0 FC 9 FC 8 FC, FC 6 FC 5 FC4 FC 3 FC HI WRITE-ONLY
O
23 1 0 1 1 1 17 RES 3 RES 2 RES, RES 0 FILTEX FILT 3 FILT 2 FILT 1 RES/FILT WRITE-ONLY z
24 1 1 0 0 0 18 3 OFF HP BP IP VOL3 VOL 2 VOL, VOLo MODE/VOL WRITE-ONLY
H
Misc.
25 1 1 0 0 1 19 PX, PX6 PX5 PX4 PX3 PX2 PX, PX0 POT X READ-ONLY m
26 1 1 0 1 0 1A PY, P^6 PYA P^3 PY2 PY, P*o POT Y READ-ONLY n
27 1 1 0 1 1 1B o? °6
P*S
o5 °4 O3 O2 °1 o0 OSC 3 /RANDOM READ-ONLY o
28 1 1 1 0 0 1C E6 E5 E4 E3 E2 E, ENVT READ-ONLY 2
O
o
o
30
Figure 11—13. SID Memory Map
m
Here's the general algorithm to output sound from the SID chip in voice 1.
7. Place the high byte in Frequency Control Register (in $D401) for the
appropriate voice.
8. Place the low byte in the (low byte) frequency control register for the
appropriate voice ($D400).
9. Initiate (GATE) the note or tone. Gating means to start the ATTACK,
DECAY and SUSTAIN cycle of the tone. Set bit 0 of $D404 (VI), $D40B(V2)
and $D412(V3), respectively.
10. Leave bit 0 set for the duration you wish to play the note or tone.
11. Clear the GATE bit.
Vie 128
V» 256
DOTTED >/s 384
Vi 512
V* + Vlb 640
DOTTED 'A 768
Vi 1024
Vi + '/l6 1152
Vi + Vs 1280
DOTTED Vi 1536
WHOLE 2048
SOUND AND MUSIC ON THE COMMODORE 128 35S
To synchronize three voices, divide each measure into sixteen equal parts. Play
(Gate) the notes with longer duration first, then gate the values of smaller duration, but
of equal proportion, next. For example, one staff has an eighth note. The staff below it
has two sixteenth notes. Play the note of longer duration so they can be gated while the
other faster notes are being fetched.
The following machine language program plays musical notes in one voice. The
musical note data begins at location $1890. The data for each note is stored in the four
byte format starting at $1890 as follows:
For example, the data for the second note starts at location $1894, data for the
third note begins at location $1898 and so on.
For now, sample data has been supplied. Eventually, place your own data beginning
at location $1890. See Figure 11-15 at the end of this chapter for the low- and high-byte
frequency values to place in the SID frequency control registers. Refer to the duration
table on page 354 for the byte values for the note duration.
The NOP instructions are added between instruction sequences for readability.
Here's the program listing as it appears in the Machine Language Monitor:
READY.
f«NITOR
PC SF: AC XR YR SP
; FB000 ()0 00 00 00 F8
>01890 IE 19 80 00 1C 41 80 00
> 01 8 9 8 IE 19 80 00 1C 41 80 00
>018A0 IE 19 80 00 1C 41 00 00
>018A8 IE 19 80 00 1C 41 80 00
>018B0 IE 19 80 00 IE 19 80 00
>018B8 IE 19 80 01 IE 19 80 01
>018C0 IE 19 80 04 1C 19 80 04
>018C8 IE 19 80 04 1C 41 80 00
>018D0 IE 19 80 00 1C 41 00 00
>018D8 21 21 00 00 00 00 00 00
>018E0 OD 54 08 DO D7 AD 7B 08
>018E8 8D 6C: 0 8 AD 7C 08 8D 6D
Enter the program in memory with the Machine Language Monitor and save it.
Run the program with the following command:
GF1800
SOUND AND MUSIC ON THE COMMODORE 128 357
The program plays a series of notes in a single voice (voice 1). Here's a line by
line description of the instructions in the program.
The instructions stored in locations $1800 through $180A clear the SID registers
($D400-$D418) to zero. This is a recommended programming practice, so you can
assume that all the SID registers are initialized to zero.
The instructions stored in locations S180E through S1814 assign the attack/decay
values in the SID envelope generator. In this program, attack is set at (15:$0F) and the
decay is set at 5. This attack setting makes the sounds seem as if they are far away and
traveling closer, similar to the way a train sounds as it approaches from far away.
The instructions stored in locations $1818 through $18IE select the sustain/release
values for the voice 1 envelope generator. In this case the sustain duration is set on 10
($0A) and the release rate is set to 3. For more information on the ADSR settings, see
the beginning of the chapter.
The next sequence of instructions ($1823-$ 1829) sets the volume to maximum
output (15:$0F). Notice that the last three instruction sequences loaded the X register
with the register number, loaded the accumulator with the appropriate value and stored
the value in the location of the start of the SID plus an offset in the X register. This
programming style is easy to follow and is standardized throughout the program.
The instructions stored in locations $182D through $183E get the low- and
high-byte frequency values for the musical note data, and place them into the low- and
high-byte frequency control registers for voice 1. First the X and Y registers are cleared
to zero. The Y register is used as an index to the musical note data in memory starting at
location $1890. To access successive bytes for frequency and duration, the Y index
register is incremented. The X register is used as an index to access the low- and
high-byte frequency control registers at locations $D400 and SD401. In this program
segment, the X register can only have one of two values; 0 to access location $D400 and
1 to access location $D401.
The first time through the loop, the instruction starting at location $1831 (LDA
$1890,Y) loads the musical data value (low byte frequency) into the accumulator. The
next instruction (BEQ $1875) checks to see if this value is equal to zero. If it is, control
passes to location $1875, the volume is cleared to zero, and the program ends. This
suggests that to end the program, place a zero in the low byte data element. This
mechanism acts as a data terminator, since no additional data is read if the low-byte
value of a musical note equals zero. If the data value does not equal zero, it is stored in
the low byte frequency control register for voice 1.
Both the X and Y registers are incremented, and the next musical data value, this
time at $1891, is loaded into the accumulator with the instruction beginning at location
$183B. The next instruction (STA SD400.X) stores the data value in the high-byte
frequency control register ($D401) for voice 1.
The instruction at location $1844 increments the Y register. The next load
instruction starting at location $1845 loads the accumulator with the next data element in
memory, this time the low byte for the duration of the note. The duration note table is
found on page 252. The low-byte duration is stored in zero page location SFA. The Y
register is incremented again and the high byte duration is loaded into the accumulator
and stored in zero page location $FB. These two locations are decremented in the
instructions stored in location $185B through $1862.
The instructions stored in locations $1850 through $1857 GATE the note, in other
words play the note. To output audible notes, each voice has a gate bit which initiates the
sound from the envelope generator for a particular voice. Bit 0 of location $D404 is the
gate bit for voice 1. To gate a bit, set bit 0 and also set the bit for the desired wave-
form at the same time. In this case, the sawtooth waveform is gated on (32+ 1 = $21).
At this point, the sawtooth waveform is gated on and is playing in the voice 1
envelope generator. The selected frequency is output until you turn off the gate bit.
Here's where the duration of the note comes into play. The instructions stored in
locations $185B through $1862 decrement the low and high byte duration value stored
in zero page locations $FA and $FB respectively. These instructions act as a time delay
which count through the loops using the duration values from page 354 that are stored in
the musical data region starting at $1890 in memory. When both $FA and $FB are equal
to zero, program control drops through to the instructions stored at $1864 through
$186A. These instructions clear the voice 1 gate bit and stop the envelope generator
from outputting sound.
At this point, the Y register is incremented ($186E) and the program jumps to
$182F where the X register is cleared to zero. Since the Y register was already
incremented before the JMP instruction in location $ 186F—71, the low byte frequency
value for the second note is already pointed to by the Y register plus the base address of
$1890. The program then loads that low-byte value and stores it in the location $D400
plus the offset of the X register, in this case 0. That gives the appropriate address $D400
for the voice 1 (low byte) frequency control register. These instructions are executed
repetitively until a low-byte frequency of zero is encountered. When the low-byte
frequency equals zero, control is passed to location $1875, the volume is cleared to
zero, and the program breaks.
This program plays 19 notes, and on the 20th a zero is detected as the low-byte
frequency value (in location $18DC), so volume is set to zero and the program ends.
This data is entered as an example. Place your data there instead according to the note
table in Figure 11-15 at the end of the chapter and the duration table on page 354.
Expand on this example. Add multiple voices using different waveforms. Utilize
the filter to perfect the quality of the musical notes. Use this program as a basis for your
own full-featured musical program.
SYNCHRONIZATION AND
RING MODULATION
The 6581 SID chip lets you create more complex harmonic structures through synchro-
nization or ring modulation of two voices.
The process of synchronization is basically a logical ANDing of two wave forms.
When either is zero, the output is zero.
Here's a synchronization algorithm:
SOUND AND MUSIC ON THE COMMODORE 128 359
The synchronization feature is enabled (turned on) in step 6, where bits 0, 1, and 4
of register $D404 are set. Bit 1 enables the syncing function between voice 1 and voice
3. Bits 0 and 4 have their usual functions of gating voice 1 and setting the triangular
waveform.
Ring modulation (accomplished for voice 1 by setting bit 2 of register $D404 in
step 6 of the algorithm) replaces the triangular output of oscillator 1 with a "ring
modulated" combination of oscillators 1 and 3. This produces non-harmonic overtone
structures for use in mimicking bell or gong sounds.
VOICE I
FREQ LO/FREQ HI (Registers 00,01)
Together these registers form a 16-bit number which linearly controls the frequency of
Oscillator 1. The frequency is determined by the following equation:
Fou. = (Fn x Fclk/16777216) Hz
Where Fn is the 16-bit number in the Frequency registers and F d k is the system clock
applied to the 02 input (pin 6). For a standard 1.0-MHz clock, the frequency is given
by:
Fout = (Fn x 0.06097) Hz
A complete table of values for generating eight octaves of the equally tempered
musical scale with concert A (440 Hz) tuning is provided in Figure 11-15. It should be
noted that the frequency resolution of SID is sufficient for any tuning scale and allows
sweeping from note to note (portamento) with no discernable frequency steps.
GATE (Bit 0): The GATE bit controls the Envelope Generator for Voice 1. When this
bit is set to a one, the Envelope Generator is Gated (triggered) and the ATTACK/
DECAY/SUSTAIN cycle is initiated. When the bit is reset to a zero, the RE-
LEASE cycle begins. The Envelope Generator controls the amplitude of Oscillator
1 appearing at the audio output, therefore, the GATE bit must be set (along with
suitable envelope parameters) for the selected output of Oscillator 1 to be audible.
A detailed discussion of the Envelope Generator can be found in this book in the
chapter on Hardware Overview.
SYNC (Bit 1): The SYNC bit, when set to a one, synchronizes the fundamental
frequency of Oscillator 1 with the fundamental frequency of Oscillator 3, produc-
ing "Hard Sync" effects.
Varying the frequency of Oscillator 1 with respect to Oscillator 3 produces a
wide range of complex harmonic structures from Voice 1 at the frequency of
Oscillator 3. In order for sync to occur, Oscillator 3 must be set to some
frequency other than zero but preferably lower than the frequency of Oscillator 1.
No other parameters of Voice 3 have any effect on sync.
RING MOD (Bit 2): The RING MOD bit, when set to a one, replaces the Triangle
waveform output of Oscillator 1 with a "Ring Modulated" combination of
Oscillators 1 and 3. Varying the frequency of Oscillator 1 with respect to
Oscillator 3 produces a wide range of non-harmonic overtone structures for
creating bell or gong sounds and for special effects. In order for ring modulation
to be audible, the Triangle waveform of Oscillator 1 must be selected and
Oscillator 3 must be set to some frequency other than zero. No other parameters of
Voice 3 have any effect on ring modulation.
TEST (Bit 3): The TEST bit, when set to a one, resets and locks Oscillator 1 at zero until
the TEST bit is cleared. The Noise waveform output of Oscillator 1 is also reset and
the Pulse waveform output is held at a DC level. Normally this bit is used for testing
purposes, however, it can be used to synchronize Oscillator 1 to external events, allow-
ing the generation of highly complex waveforms under real-time software control.
(Bit 4): When set to a one, the Triangle waveform output of Oscillator 1 is selected.
The Triangle waveform is low in harmonics and has a mellow, flute-like quality.
(Bit 5): When set to a one, the Sawtooth waveform output of Oscillator 1 is selected.
The Sawtooth waveform is rich in even and odd harmonics and has a bright,
brassy quality.
SOUND AND MUSIC ON THE COMMODORE 128 361
(Bit 6): When set to a one, the Pulse waveform output of Oscillator 1 is selected. The
harmonic content of this waveform can be adjusted by the Pulse Width registers,
producing tone qualities ranging from a bright, hollow square wave to a nasal,
reedy pulse. Sweeping the pulse width in real-time produces a dynamic "phas-
ing" effect which adds a sense of motion to the sound. Rapidly jumping between
different pulse widths can produce interesting harmonic sequences.
NOISE (Bit 7): When set to a one, the Noise output waveform of Oscillator 1 is
selected. This output is a random signal which changes at the frequency of
Oscillator 1. The sound quality can be varied from a low rumbling to hissing
white noise via the Oscillator 1 Frequency registers. Noise is useful in creating
explosions, gunshots, jet engines, wind, surf and other unpitched sounds, as well
as snare drums and cymbals. Sweeping the oscillator frequency with Noise
selected produces a dramatic rushing effect.
One of the output waveforms must be selected for Oscillator 1 to be audible,
however, it is NOT necessary to de-select waveforms to silence the output of
Voice 1. The amplitude of Voice 1 at the final output is a function of the Envelope
Generator only.
NOTE: The oscillator output waveforms are NOT additive. If more than
one output waveform is selected simultaneously, the result will be a
logical ANDing of the waveforms. Although this technique can be used
to generate additional waveforms beyond the four listed above, it must be
used with care. If any other waveform is selected while Noise is on, the
Noise output can "lock up." If this occurs, the Noise output will remain
silent until reset by the TEST bit or by bringing RES (pin 5) low.
0 (0) 2 ms 6 ms
1 (1) 8 ms 24 ins
2 (2) 16 ms 48 ms
3 (3) 24 ms 72 ms
4 (4) 38 ms 114 ms
5 (5) 56 ms 168 ms
6 (6) 68 ms 204 ms
7 (7) 80 ms 240 ms
8 (8) 100 ms 300 ms
9 (9) 250 ms 750 ms
10 (A) 500 ms 1.5 s
11 (B) 800 ms 2.4 s
12 (C) 1s 3s
13 (D) 3s 9s
14 (E) 5s 15 s
15 (F) 8s 24 s
VOICE 2
Registers $07-$0D control Voice 2 and are functionally identical to registers $00-406
with these exceptions:
VOICE 3
Registers $0E-$14 control Voice 3 and are functionally identical to registers $00-$06
with these exceptions:
FILTER
FC LO/FC HI (REGISTERS $15,$ 16)
Together these registers form an 11-bit number (bits 3-7 of FC LO are not used) which
literally controls the Cutoff (or Center) Frequency of the programmable Filter. The
approximate Cutoff Frequency ranges from 30 Hz to 12 KHz.
FILT I (Bit 0): When set to a zero, Voice 1 appears directly at the audio output and the
Filter has no effect on it. When set to a one, Voice 1 will be processed through
the Filter and the harmonic content of Voice 1 will be altered according to the
selected Filter parameters.
FiLT 2 (Bit I): Same as bit 0 for Voice 2.
FILT 3 (Bit 2): Same as bit 0 for Voice 3.
FILTEX (Bit 3): Same as bit 0 for External audio input (pin 26).
LP (Bit 4): When set to a one, the Low-Pass output of the Filter is selected and sent to
the audio output. For a given Filter input signal, all frequency components below
the Filter Cutoff Frequency are passed unaltered, while all frequency components
above the Cutoff are attenuated at a rate of 12 dB/Octave. The Low-Pass mode
produces full-bodied sounds.
BP (Bit 5): Same as bit 4 for the Bandpass output. All frequency components above
and below the Cutoff are attenuated at a rate of 6 dB/Octave. The Bandpass mode
produces thin, open sounds.
HP (Bit 6): Same as bit 4 for the High-Pass output. All frequency components above
the Cutoff are passed unaltered, while all frequency components below the Cutoff
are attenuated at a rate of 12 dB/Octave. The High-Pass mode produces tinny,
buzzy sounds.
3 OFF (Bit 7): When set to a one, the output of Voice 3 is disconnected from the direct
audio path. Setting Voice 3 to bypass the Filter (FILT 3 = 0) and setting 3 OFF
to a one prevents Voice 3 from reaching the audio output. This allows Voice 3 to
be used for modulation purposes without any undesirable output.
NOTE: The Filter output modes ARE additive and multiple Filter modes
may be selected simultaneously. For example, both LP and HP modes
can be selected to produce a Notch (or Band Reject) Filter response. In
order for the Filter to have any audible effect, at least one Filter output
must be selected and at least one Voice must be routed through the Filter.
The Filter is, perhaps, the most important element in SID as it allows the
generation of complex tone colors via subtractive synthesis (the Filter is
used to eliminate specific frequency components from a harmonically rich
input signal). The best results are achieved by varying the Cutoff Fre-
quency in real-time.
Bits 0-3 (VOL0-VOL3) select 1 of 16 overall Volume levels for the final composite
audio output. The output volume levels range from no output (0) to maximum
volume (15 or $F) in sixteen linear steps. This control can be used as a static
volume control for balancing levels in multi-chip systems or for creating dynamic
volume effects, such as Tremolo. Some Volume level other than zero must be
selected in order for SID to produce any sound.
SOUND A N D MUSIC ON THE COMMODORE 128 365
MISCELLANEOUS
POTX (REGISTER $19)
This register allows the microprocessor to read the position of the potentiometer tied to
POTX (pin 24), with values ranging from 0 at minimum resistance, to 255 ($FF) at
maximum resistance. The value is always valid and is updated every 512 02 clock
cycles. See the Pin Description section for information on pot and capacitor values.
FILTER SETTIiNGS
LOCATION CONTENTS
INPUT/OUTPUT PORTS
Most of the connections are considered as input and output because information is
transmitted in both directions. These connections include the Commodore Serial Port for
the disk drive(s) and printer(s), the User Port for external communication with modems,
an expansion port for additional memory, a Datassette connector for a tape storage
device, two monitor ports for both the composite video and the RGBI monitors, a TV
connector, and game ports for various control devices such as joysticks, paddles and
graphics tablets. The port pinout details begin on page 394.
DISK DRIVE
The disk drive is the most popular information storage device today. It stores programs
and data as magnetic signals on a floppy disk of flexible plastic coated with iron oxide.
Information (characters, letters and numbers) represented by a series of binary digits is
magnetically impressed upon the disk in one of thirty-five concentric ring tracks. Each
ring is divided into 17 to 21 sectors each. Each ring can store about 5000 bytes per
track. A 1541 disk drive has a capacity of about 170K. The 1571 disk drive is
double-sided, so a disk formatted on the 1571 holds twice as much data, about 340K.
FORMATTING A DISK
Blank disks from the factory are not assigned tracks or sectors. A disk must be
formatted by your computer/disk drive according to the disk operating system. You
cannot store anything on a brand-new disk until this process, called Formatting or
newing, is completed. The Commodore disk drive has built-in microprocessors that
properly organize a blank disk when instructed to do so by the computer. The eighteenth
track is used as a directory for the disk drive. All the addresses for all the blocks (over
600) are stored on track 18 as the Block Allocation Map, or more simply the directory.
Prior to formatting a disk, decide on an identification name and a two-digit code.
Select a name of up to 16 characters that will help identify your disk. For example, the
disk name could be your name, or a topic such as games. The two-digit code can be almost
any letter-number combination. This code immediately alerts the disk drive whenever
INPUT/OUTPUT GUIDE 373
you change disks—so, for your own protection, try to assign each disk a unique code.
The format command for C128 mode is as follows:
HEADER "disk name", Ixy,D0,ON U8
For C64 or C128 modes, use:
OPEN 15,8,15, "NO:diskname, xy"
Note that xy is any two-digit code you select, such as 01, 45, W3, 40, or WD.
The 0 after the D or N represents the default drive number for a single disk drive or the
first drive of a dual drive unit where both share a common device number. The 8 in each
statement represents the device number. A second drive would be set to number 9, a
third drive to 10, etc. With a single drive, the HEADER command can simply be:
HEADER"disk name",Ixy
The formatting process typically takes about 80 seconds on the 1541 disk drive,
and considerably less on the 1571 drive. Once this operation is completed, this disk can
be used for storing programs and data. Do not format it again—otherwise everything
saved on it will be erased. To simply "wipe" an already formatted disk, use the above
instructions but do not include the comma followed by an identification number. This
process will maintain the original format, use the new name and wipe the directory
clean—a process considerably faster than total formatting.
The OPEN command establishes a communication link between the computer and
a specific device number. Disk drives are factory set as device number 8 and can be
converted to device 9, 10, 11 or 12. See your disk drive manual for details.
To verify you have properly formatted the disk, see the section below on reading
the directory.
SAVING PROGRAMS
The saving process for storing programs on a disk does not remove the program from
the computer. It simply "copies" the program or file from the computer onto the disk in
the disk drive. Nothing is lost in the process. BASIC programs are saved to a formatted
disk with the following commands:
C128 or C64 SAVE"program name",8
C128 only DSAVE"program name"
DSAVE"program name",DO,U9
(if the drive is device number 9).
In C128 mode, machine language programs or binary files can be saved through
these BASIC commands:
BSAVE"filename",Bb,Ps TO Pe
or BSAVE"filename",D0,U9,Bb,Ps TO Pe
(if the drive is device number 9).
In these formats:
" b " is the memory bank number (0 through 15)
" s " is the starting address
" e " is the ending address
EXAMPLE:
BSAVE"filename",B2,P3584 TO P4096
This saves the binary file named "filename" from memory bank 2, in the range of
memory' between 3584 to 4096 decimal.
The following command saves a BASIC program in either C128 or C64 modes:
SAVE "filename",8
where 8 represents the device number.
(to verify the program from the memory location from which it was SAVEd, primarily
machine language programs).
After your program has been saved and verified, it is stored on your disk for future
use.
THE DIRECTORY
Once a disk is formatted, it has a directory, or catalog listing of the files stored on the
disk. Prior to loading a program, you may want to view the directory to find out exactly
what is stored on the disk. When you call for the directory, the screen displays the disk
name and identification number followed by a list of programs or files presently stored.
Of course, a newly formatted disk will display only its name and number. To see the
directory, use the commands listed below.
In BASIC 7.0, use the following:
DIRECTORY
or CATALOG
or CATALOG D0,U9
or DIRECTORY D0,U9 (for a dual disk drive, device number 9)
The program in memory is not affected by this command.
In BASIC 2.0, use the following command:
LOAD"$0",8:LIST
This command erases the resident program. The 0 is optional with a single-drive
unit.
To print a hard copy of a directory, you must use the BASIC 2.0 method. You
must first open a channel to the printer. This is covered below in the section Output to a
Printer.
RETRIEVING PROGRAMS OR
FILES FROM DISKS
Once you have files or programs stored on a disk, you retrieve them with an appropriate
version of the LOAD command.
In BASIC 7.0, use the following command:
DLOAD"filename"
or DLOAD"filename",D0,U9
(for disk drive unit 9, drive 0)
To retrieve a program or binary file saved by the BSAVE command or by the
machine language monitor, use the following BASIC 7.0 command:
BLOAD"filename",Bb,Ps
or BLOAD"filename",D0,U9,Bb,Ps
(for disk drive unit 9, drive 0)
where b is the bank number and s is the starting address.
In BASIC 2.0, use the following command formats:
a File number: 0 through 255; 15 is reserved for special commands and error
checking.
• Device number: default is 8 for a disk drive; 4 for a printer (4-30 are available
for serial bus devices).
• Channel number: 0 through 255; the line of communication established between
devices (also known as secondary address)
opens file number 111 on device number 8, using channel 12. The file is opened to
default drive 0, with the filename "NAME," as a sequential file. The W specifies that a
write operation will take place. To store data, it is "written" on the disk. Data is
retrieved by "reading" the disk.
Enter, save and run the following programs as sample routines to create, save and
read a sequential file. See your disk drive manual for more information.
10 REM STORE DATA
11 REM NOTE PROGRAM STOPS WHEN YOU RESPOND WITH "END".
20 OPEN 5,8,5,"EXAMPLE,S,W"
25 DO
30 INPUT "NAME OF A FRIEND";N$
40 PRINT#5,N$
50 IF N$ = "END'THEN CLOSE 5:END
60 LOOP
NOTE: In C128 mode, the Commodore 128 has a set of disk input/
output commands. These include the DLOAD and DSAVE commands
already described, as well as the DOPEN, DCLOSE and other com-
mands. See the BASIC 7.0 Encyclopedia in Chapter 2 or your disk drive
manual for details on any of these commands.
Line 20 tells the disk drive to open a sequential file for writing data. Line 30
obtains the information from the keyboard by requesting it on the screen. The PRINT#
statement in line 40 specifies the file number where the information is to be written.
Line 40 is the statement that actually writes the data to the channel and creates the
contents of the file. Line 50 also puts a recognizable end-of-file marker—the word
"end" at the end of the file. Line 50 closes the file after all data has been written.
Here's a program that reads the data from the sequential file you just created:
10 REM RETRIEVE FILES
20 OPEN 6,8,6,"EXAMPLE,S,R"
25 DO
30 INPUT#6,L$
40 IF L$ = "END'THEN CLOSE6:END
50 PRINT L$
60 LOOP
Line 20 opens a channel to the sequential file called EXAMPLE for reading. Once
the end item is found, the file is properly closed. As each item is retrieved using the
INPUT# statement, it is printed to the screen with a simple PRINT statement. Any
sequential file in which all writing has been completed and which is already closed can
be opened only as a read file; it cannot be written to unless an APPEND operation is
specified or the @ prefix is used.
Files can be expanded in size with the BASIC 7.0 APPEND command as follows:
APPEND#7,' 'EXAMPLE''
This command opens the file called "EXAMPLE." Any data sent to it in a PRINT#7
statement will be appended. Any file number may be specified as long as the PRINT file
number matches the APPEND file number.
Once all the data is sent, the channel is closed with
DCLOSE#7
In BASIC 2.0, use this command:
OPEN7,8,7, "0:EXAMPLE,A"
The letter A allows subsequent PRINT# statements to enter data at the end of the
file "Example." This BASIC 2.0 technique also requires a CLOSE statement: CLOSE7.
OTHER FILES
C128 BASIC includes several direct disk drive housekeeping commands including
SCRATCH, RENAME, CONCAT, COPY and COLLECT as well as a relative file
command RECORD. Note that these operations are also available in the C64 mode if
combined with an OPEN statement on channel 15. See your C128 System Guide
Encyclopedia or disk drive manual for details.
In addition, see your disk drive manual for details on relative files, random files
and direct program access to the disk drive microprocessor via channel 15.
OUTPUT TO A PRINTER
Your Commodore 128 computer transmits data over the serial port to many different
styles of printers. The most popular Commodore printers today are the daisy wheel and
dot matrix types. The daisy wheel system uses metal or plastic molded letters similar to
those on a typewriter and produces the finest impressions. The fingers that hold these
characters are mounted on a center post, and the wheel resembles a daisy flower. The
printer head spins the wheel until the correct letter is in position behind a hammer,
which presses it against a ribbon onto the paper.
The more versatile system is the dot matrix. Using a column of metal pins, a
INPUT/OUTPUT GUIDE 379
series of dots is impressed on paper through an inked ribbon as the printer head moves
across the page. The pattern of dots is based upon the binary code of each character.
The infinite number of potential dot patterns makes it possible to print any style
character imaginable from italics to Japanese depending only upon the printer's internal
software (firmware).
Although many printer manufacturers claim their system is compatible with the
Commodore 128 computer, if Commodore does not authorize the use, a special printer
interface may be required. Printers cited as Centronics parallel or Serial do not directly
match any of the Commodore computer ports. Commodore does not support any third-
party printers or printer interfaces. The Commodore Serial Port is unique and not the
same as the RS232 Serial Port, which many printer manufacturers specify.
The Commodore computer can display 512 characters. The second set of 256
includes both upper and lower case letters; the first includes upper case only with
graphics. This is possible by using identical codes accessed separately. Consequently,
only Commodore dot matrix printers are preprogrammed to print all the available
Commodore characters. Owing to these differences, Commodore's ASCII codes are not
identical to the true ASCII standard. Therefore, special modifications are required when
interfacing with non-Commodore equipment.
In order to operate a printer, a line of communication with the computer must be
opened using the OPEN statement. The printer is usually device number 4, though often
switch selectable to 5. The command:
OPEN 3,4
establishes a link to the printer as device number 4. The first number can be any
number between 1 and 255. Numbers beyond 128 force a line feed after a carriage return.
NOTE: To print a listing with double spacing, a line feed can be forced
using a file number greater than 127 such as:
OPEN131,4:CMD131:LIST:PRINT#131:CLOSE131
PRINTING A TYPED LINE
A PRINT# command to an opened print file number outputs the associated data to the
printer. The following commands output whatever is typed:
OPEN3,4:PRINT#3,'TYPE ANYTHING"
After R E T U R N is depressed, the line is sent to the printer and anything
under quotes is printed on paper.
10 OPEN 3,4,7
20 DO UNTIL L = 5
25 IFL = 0THEN30 :ELSE INPUTA$:GOTO40
30 INPUT'PLEASE TYPE ";A$
40 PRINT#3,A$
50 L = L+1
60 LOOP
70 CLOSE3
This is the beginning of a simple word processor and could be expanded into a
complex system through printer control.
Many word processors can accommodate special printer controls with at least one
of these methods. Refer to your printer and word processing manuals for the technique
of sending control characters to your printer.
The alternate method of sending control codes to a printer is via the secondary
address in the OPEN statement. An OPEN statement without a secondary address
defaults to 0. Hence OPEN3,4 is the same as OPEN3,4,0. Generally a secondary
address of 7 will cause the printer to print with upper case and lower case characters:
OPEN3,4,7
Other secondary addresses are often available and will perform various duties in
accordance with your printer's design. See your manual for specifics. Most word
processors allow the use of secondary addresses as embedded codes.
The following program will open a channel to a sequential file on disk, read data
and output to a printer:
10 OPEN 3,8,3,"EXAMPLE,S,R"
20 OPEN 4,4,0
25 DO
30 INPUT#3,L$
40 IF L$ = ' 'END' 'THEN8OELSE5O
50 PRINT#4,L$
60 PRINT L$
70 LOOP
80 CLOSE4:DCLOSE3:END
OUTPUT TO A MODEM
A modem is a device used to transmit and receive data across telephone lines.
Generally, a computer uses an RS232 port to communicate with the external
world. Commodore's RS232C Port (also known as the User Port) is a variation of the
RS232 standard port. The RS232 has 0 to 5 TTL voltage levels rather than the standard
plus/minus 12 volts.
The OPEN statement for the modem (device 2) sets up the parameters to match the
speed (baud rate) and format (number of data and stop bits) of the host computer by
sending a Control Register code. A second required code, the Command Register code,
defines the parity, duplex and handshake. For example:
OPEN3,2,0,CHR$(6)CHR$(112)
opens a channel to the User Port (device #2) and establishes a 300-baud rate, 8-bit
word, single stop bit (Control Register (6)), even parity and half duplex (Command
Register (112)). See Figure 12-1, the Control Register Map, and Figure 12-2, the
Command Register Map.
THE RS-232 CHANNEL
The RS-232 capabilities can be accessed from either BASIC or machine language.
The BASIC commands INPUT# and GET# are used to fetch data from the receiving
buffer while PRINT# and CMD place data into the transmitting buffer.
The RS-232 Kernal routines run under the control of the 6526 CIA # 2 device
timers and interrupts. The 6526 chip generates NMI (Non-Maskable Interrupt) requests
for RS-232 processing. This allows background RS-232 processing to take place during
BASIC and machine language programs. There are built-in hold-offs in the Kernal,
cassette and serial bus routines to prevent the disruption of data storage or transmission
by the NMIs that are generated by the RS-232 routines. During cassette or serial bus
activities, data can not be received from RS-232 devices. But because these hold-offs
are only local, (assuming you're careful about your programming) no interference
should result.
There are two buffers in the Commodore 128 memory to help prevent the
loss of data when transmitting or receiving RS-232 information.
The Commodore 128 RS-232 I/O buffers consist of two first-in/first-out (FIFO)
buffers, each 256 bytes long. In C128 mode, the RS-232 I/O buffers are permanently
allocated. The input buffer is located between 3072 and 3327 ($0C00-$0CFF). The
output buffer is located between 3328 and 3583 ($0D00-$0DFF). You cannot harm
program storage by opening and closing the RS-232 channel as can happen with the
Commodore 64. By permanently allocating the buffers in a fixed location, no "OUT OF
MEMORY" error can occur, and your program in memory will not get "stepped on."
BASIC SYNTAX
OPEN lfn,2,0"<control reg.> <command reg.> <opt baud low> <opt baud high>"
The logical file number (lfn) then can be any number from 1 through 255. But be
aware of the fact that if you choose a logical file number that is greater than 127, then a
line feed will follow all carriage returns.
options. Select the parameters you want from the Control Register Map (Figure 12-1)
by placing the proper bit value in binary form. A selection, for example, from left to
right of two stop bits, 7-bit word and 1200-baud rate yields:
1010 1000 (in binary), which is decimal 168 ($A8) and results in
OPEN 3,2,0,CHR$(168)
defining these parameters.
128 64 32 8 4 )
[71 lil fsl [] (c)\
I3AUD RATE
0 0 0 0 USER RATE
STOP BITS — • 0 0 0 1 50 BAUD
0-1 STOP BIT 0 0 1 0 75
1-2 STOP BITS
0 0 1 1 110
0 1 0 0 134.5
0 1 0 1 150
0 1 1 0 300
WORD LENGTH' 1
0 1 1 600
BIT DATA
6 5 WORD LENGTH 1 0 0 0 1200
DUPLEX•
0-FULL DUPLEX
1-HALF DUPLEX
UNUSED
UNUSED
UNUSED
EXAMPLE:
1000 Baud: Divide the system frequency by the baud rate:
1022727/1000=1022.727
Divide by 2 and subtract 100: 1022.727/2 - 100 = 411.3635 (or rounded up to 412)
Convert this into two byte values: Division by 256 results in 1 with a remainder of
156. The following statement therefore defines a 1000-baud, 7-bit, single stop bit, odd
parity, full duplex:
OPEN3,2,0,CHR$(32)CHR$(32)CHR$( 156)CHR$( 1)
where the Control Register value in binary is 00100000 and the Command Register in
binary is 00100000.
[7] [6] [5] [4] [3] [2] [1] [0] (Machine Lang. —RSSTAT)
:_PARITY ERROR BIT
FRAMING ERROR BIT
RECEIVER BUFFER OVERRUN BIT
RECEIVER BUFFER —EMPTY
(USE TO TEST AFTER A GET#)
-CTS SIGNAL MISSING BIT
UNUSED BIT
DSR SIGNAL MISSING BIT
BREAK DETECTED BIT
All the above zero-page locations are used locally and are given only as a guide to
understand the associated routines. These cannot be used directly by the BASIC or
Kernal-level programmer to do RS-232-type programming functions. The system RS-232
routines must be used.
OUTPUT TO A SCREEN
The most common form of computer output (called soft copy) is a display tube that
displays luminescent dots on a screen controlled by electrical signals. Although the
television is a specialized monitor and limited by the dot density prescribed by FCC
standards for proper reception, it is available in most homes and becomes a ready-to-use
output device for the home computer. The C128 computer sends radio frequency signals
through the TV port to the television's antenna and tuner.
Monitors for computers produce better-quality displays since they are direct-wired
INPUT/OUTPUT GUIDE 389
and involve no tuners. The C128 includes a port to accept the traditional monitors as
well as Commodore's 40-column 1702 color monitor. The C128 80-column color
capability is enhanced with the new 40/80-column color monitor Model 1902. In
this RGBI monitor, signals separately control each of the three color guns (red, green,
blue) for maximum clarity and detail.
The screen can be accessed as an input or output device through the OPEN
command as device 3.
OPEN 1,3
The screen is the default output device on the C128. Typing on the keyboard (device 0)
results in a screen character display output whenever the monitor is powered up. No
special commands are normally required. However, once control is sent to another
device, reversion to the screen may be desired.
Control of the screen display is available primarily with the PRINT command;
associated punctuation including the quote and the semicolon and common, BASIC
functions including the TAB(X), SPC(X), and CHR$(X) as well as the POKE com-
mand. In addition, there are color controls, sprite animation and graphics keys..
If using the dual 1902 monitor or two separate 40- and 80-column monitors, it is
possible to swap control between the two screens via the 4 0 / 8 0 switch or pressing
the E S C and X keys. If one is used for text and the other for graphics, use the
GRAPHIC command.
The following command will also swap the display output device:
PRINT CHR$(27)"X"
In addition to a screen display, sound commands can be used through a Commodore
monitor or the television speakers. See Chapter 11, Sound and Music.
NOTE: Do not connect the Datassette and the 1571 disk drive to the C128
at the same time. If they are used at the same time, the data transfers may
not be reliable.
JOYSTICKS
A digital joystick has five distinct switches. Four of the switches are used for direction
and one is used for the fire button. The joystick switches are arranged as shown in
Figure 12—4.
(Top)
FIRE
(Switch 4)
UP
(Switch 0)
LEFT ; RIGHT
(Switch 2) , (Switch 3)
DOWN
(Switch 1)
These switches correspond to the lower 5 bits of the data in location 56320 or
56321. Normally the bit is set to a 1 if a direction is not chosen or the fire button is not
pressed. When the fire button is pressed, the bit (bit 4 in this case) changes to a 0. To
read the joystick from C64 BASIC, the following subroutine should be used:
INPUT/OUTPUT GUIDE 391
The values for JV correspond to the joystick directions shown in Table 12-2.
JV EQUAL TO DIRECTION
0 NONE
1 UP
2 DOWN
3 —
4 LEFT
5 UP & LEFT
6 DOWN & LEFT
7 —
8 RIGHT
9 UP & RIGHT
10 DOWN & RIGHT
Table 12-2. Joystick Direction Values
A machine language routine that accomplishes the same task is given in the
section on shift and rotate instructions in Chapter 5, Machine Language on the
Commodore 128.
BASIC 7.0 includes special joystick functions. To determine the position of joystick
N, PRINT JOY(N) returns the position of the joystick. A number between 0 and 8
inclusive specifies the relative position where 0 is stationary and 1 through 8 represent
clockwise positions. Values between 128 and 136 signify the fire button is pressed as
well. Thus if JOY(2) returns 131, it means joystick number 2 fires to the right (position 3).
PADDLES
A paddle is connected to both CIA-1 and the SID chip (MOS 6581 Sound Interface Device)
through a controller port. The paddle value is read via the SID registers 54297 ($D419) and
54298 ($D41A). Paddles are not reliable when read from BASIC alone! The best way to
use paddles, from BASIC or machine code, is to use a machine language routine (SYS
to it from BASIC then PEEK the memory locations used by the subroutine).
The following BASIC program moves a sprite with paddles:
LIGHT PEN
The light pen input latches the current screen position into a pair of registers (LPX,
LPY) on a low-going edge. The X position register 53267 ($D013) will contain the 8 MSB
of the X position at the time of transition. Since the X position is defined by a 512-state
counter (9 bits), resolution to two horizontal dots is provided. Similarly, the Y position
is latched in its register 53268 ($D014), but here 8 bits provide single raster resolution
within the visible display. The light pen latch may be triggered only once per frame, and
subsequent triggers within the same frame will have no effect. Therefore, you must take
several samples before turning the pen to the screen (three or more samples average),
depending upon the characteristics of your light pen. The following program is a light
pen draw routine in C128 mode:
OUTPUT CONTROL TO
ALL DEVICES
Each peripheral device is identified by a device number, as listed in Table 12-3.
Keyboard 0
Datasette 1 0,1,2
Modem (RS232) 2 0
Screen 3 0,1
Printer 4 or 5 0,7,etc
Disk Drive 8,9,10,11 2-14,15
Serial devices can be numbered 4 through 30, but they usually conform to the
above conventions. All devices can be accessed in a single OPEN statement by using
an integer variable:
10 INPUT "SELECT DEVICE NUMBER";D%
20 INPUT "SELECT SECONDARY ADDRESS",-S%
30 INPUT "NAME OF FILE OR CONTROL REGISTER";A$
40 OPEN 9,D%,S%,AS
50 GOSUB 80
60 CLOSE 9
70 END
80 REM PLACE SUBROUTINE HERE
90 RETURN
THE INPUT/OUTPUT
PINOUTS
SERIAL I/O
PIN TYPE
1 SERIAL SRQIN
2 GND
3 SERIAL ATN IN/OUT
4 SERIAL CLK IN/OUT
5 SERIAL DATA IN/OUT
6 RESET
1 2 3 4 5 6 7 8 9 10 11 12
A B C D E F H J K L M N
PIN
TOP SIDE DESCRIPTION NOTES
1 GROUND
2 + 5V (100 mA MAX.)
3 RESET By grounding this pin, the Commodore 128 will do
a cold start, resetting completely. The pointers to
a BASIC program will be reset, but memory will
not be cleared. This is also a RESET output for
the external devices.
4 CNT1 Serial port counter from CIA-1 (see CIA specs).
5 SP1 Serial port from CIA-1 (see 6526 CIA specs).
6 CNT2 Serial port counter from CIA-2 (see CIA specs).
7 SP2 Serial port from CIA-1 (see 6526 CIA specs).
8 PC2 Handshaking line from CIA-2 (see CIA specs).
9 SERIAL This pin is connected to the ATN line of the serial
ATNIN bus.
10 9 VAC + phase Connected directly to the Commodore 128 trans-
11 9 VAC-phase former (100 mA Max.).
12 GROUND
BOTTOM SIDE
A GROUND The Commodore 128 gives you control over Port
B FLAG2 B on CIA chip 1. Eight lines for input or output
C PBO are available, as well as two lines for handshaking
D PB1 with an outside device. The 1/0 lines for Port B
E PB2 are controlled by two locations. One is the Port
F PB3 itself, and is located at 56577 ($DD01 HEX).
H PB4 Naturally you PEEK it to read an INPUT, or
J PB5 POKE it to set an OUTPUT. Each of the eight
K PB6 I/O lines can be set up as either an INPUT or an
L PB7 OUTPUT by setting the Data Direction Register
M PA2 properly.
N GROUND
Table 12-4. User Port Pin Descriptions
The Data Direction Register has its location at 56579 ($DD03 hex). Each of the
eight lines in the port has a bit in the 8-bit Data Direction Register (DDR) that controls
whether that line will be an input or an output. If a bit in the DDR is a 1, the
corresponding line of the port will be an output. If a bit in the DDR is a 0, the
corresponding line of the port will be an input. For example, if bit 3 of the DDR is set to 1,
then line 3 of the port will be an output. If the DDR is set like this:
BIT # : 7 6 5 4 3 2 10
VALUE: 0 0 1 1 10 0 0
lines 5, 4 and 3 will be outputs since those bits are l's. The rest of the lines will be
inputs, since those lines are 0's.
To PEEK or POKE the User Port, it is necessary to use both the DDR and the port
itself.
Remember that the PEEK and POKE statements need a number from 0 to 255.
The numbers given in the example must be translated into decimal before they can be
used. The value would be:
25 + 24 + 23 = 32 + 16 + 8 = 56
Notice that the bit number for the DDR is the same number that is equal to 2 raised to a
power to turn the bit value on.
(16 = 2 | 4 = 2 x 2 x 2 x 2 , 8 = 2 | 3 = 2 x 2 x 2 )
The two other lines, flagl and PA2, are different from the rest of the User Port.
These two lines are mainly for handshaking, and are programmed differently from
port B.
Handshaking is needed when two devices communicate. Since one device may run
at a different speed than another device, it is necessary to give each device some way of
knowing what the other device is doing. Even when the devices are operating at the
same speed, handshaking is necessary to communicate when data is to be sent, and if it
has been received. The flagl line has special characteristics that make it well suited for
handshaking.
Flagl is a negative-edge-sensitive input that can be used as a general-purpose
interrupt input. Any negative transition on the flag line will set the flag interrupt
bit. If the flag interrupt is enabled, this will cause an Interrupt Request. If the
flag bit is not enabled, it can be polled from the Interrupt Register under program control.
PA2 is bit 2 of port A of the CIA. It is controlled like any other bit in the port.
The port is located at 56576 ($DDO0). The Data Direction Register is located at 56578
($DD02).
For more information on the 6526, see the hardware chapter.
THE COMPOSITE
VIDEO CONNECTOR
This DIN connector supplies direct audio and composite video signals. These can
be connected to the Commodore monitor or used with separate components. This is the
40-column output connector. Figure 12-7 shows the pinouts for the composite video
connector. Table 12-5 describes the pinouts.
INPUT/OUTPUT GUIDE 397
THE RGBI
VIDEO CONNECTOR
The RGBI video connector is a 9-pin connector that supplies an RGBI (Red/Green/Blue/
Intensity) signal. This is the 80-column output. Figure 12-8 shows the RGBI pinouts.
Table 12-6 defines the RGBI pinouts.
1 Ground
2 Ground
3 Red
4 Green
5 Blue
6 Intensity
7 Monochrome
8 Horizontal Sync
9 Vertical Sync
1 2 3 4 5 6
A B C D E F
PIN TYPE
A-l GND
B-2 + 5V
C-3 CASSETTE MOTOR
D-4 CASSETTE READ
E-5 CASSETTE WRITE
F-6 CASSETTE SENSE
1 JOYA0 1 JOYB0
2 JOYA1 2 JOYB1
3 JOYA2 3 JOYB2
4 JOYA3 4 JOYB3
5 POT AY 5 POT BY
6 BUTTON A/LP 6 BUTTON B
7 + 5V MAX. 50mA 7 + 5V MAX. 50mA
8 GND 8 GND
9 POT AX 9 POTBX
222«2O19»8 I7IS15 14 13 12 11 10 B 8 7 6 5 4 3 2 1
Z r I W V U T S R P N M L K J H F E D C BA
(view of port from the back of the C128)
1 GND A GND
2 + 5V B ROMH
3 + 5V C RESET
4 IRQ D NMI
5 R/W E S02
6 Dot Clock F A15
7 I/Ol H A14
8 GAME J A13
9 EXROM K A12
10 I/O 2 L All
11 ROML M A10
12 BA N A9
13 DMA P A8
14 D7 R A7
15 D6 S A6
16 D5 T A5
17 D4 U A4
18 D3 V A3
19 D2 w A2
20 Dl X Al
21 DO Y A0
22 GND Z GND
For example, the starting address of the routine ACPTR is stored, starting
in location $FFA5. Actually, the operation code (opcode) for the JMP instruc-
tion is stored at location $FFA5 and the address of the entry point of the
routine is stored at locations $FFA6 and $FFA7. What really happens is that
the JSR instruction in your application program transfers control to the jump
table address ($FFA5, for example); then the JMP instruction at $FFA5 jumps
to the subroutine at the address specified in locations $FFA6 and $FFA7. In
other words, when you issue a JSR instruction to the Kernal Jump Table, you
actually perform two jumps: one (JSR) to the jump table, and then a second
jump (JMP) to the actual starting address of the routine.
The routine terminates with an RTS instruction that is already part of the
Kernal subroutine. Your application program resumes with the instruction
immediately following the JSR instruction.
4. Upon return from the subroutine, check the status register for any error conditions. If
an error condition is present, take precautions in your application
program to handle the error and act on the value of the status register.
Figure 13-1 is the C128 system vector and jump table that includes the
name, address and function description of the operating system Kernal routines.
CI28 SYSTEM VECTORS
1. $FFFB SYSTEM operating system vector (RAMl)
2. $FFFA NMI ;processor NMI vector
3. $FFFC RESET processor RESET vector
4. $FFFE IRQ ;processor IRQ/BRK vector
Figure 13-2 lists the conventions used in the description of each Kernal subrou-
tine. The figure is followed by descriptions of the C128 system vectors and Kernal
subroutines. Included in each description are the subroutine name, call address, prepara-
tory routines needed (if any), the registers affected, the error codes associated with each
routine, how to use them and an example of each kernal subroutine call.
USER CALLABLE
KERNAL ROUTINE CONVENTIONS
Call Address: This is the call address of the Kemal routine, given in hexadecimal.
Function Name: Name of the Kernal routine.
Register: Registers, memory and flags listed under this heading are used to pass
parameters to and from the Kernal routines.
Preparatory Routines: Certain Kernal routines require that data be set up by prepara-
tory routines before the target routine can be called. The necessary routines are
listed here.
Error Returns: A return from a Kernal routine with the carry set indicates an error
was encountered in processing. The accumulator will contain the number of the
error.
Error Codes: Below is a list of error messages that can occur when using the
Kernal routines. If an error occurs during a Kernal routine, the carry bit of the
accumulator is set, and the number of the error message is returned in the
accumulator.
NOTE: Some Kernal I/O routines do not use these codes for error
messages. Instead, errors are identified using the Kernal READST routine.
NUMBER MEANING
Registers Affected: All registers, memory and flags used by the Kernal routine are
listed here.
Examples: An example of each Kernal routine is listed.
Description: A short explanation of the function of the Kernal routine is given here.
Up to this point there is no provision for user code. The next two routines in the
initialization path actually look for installed user code:
7. SECURE: Check and initialize the SYSTEM vector,
8. POLL: Check for a ROM cartridge.
POLL first scans for any installed C64 cartridges. They are recognized by
either the GAME or EXROM signal being pulled low. If so, GO64 is executed
(see the Kernal jump entry for details). Polling for C64 cartridges is actually
redundant at this point since the Z80 processor, which powers up initially, did this
already. POLL then scans for installed C128 cartridges and function ROM's. They
are recognized by the existence of the O key in any of the four function ROM
slots (two internal, two external) and are polled in the order external low (16 or
32KB), external high (16KB), internal low (16 or 32KB), internal high (16KB).
The entire format is:
$x000 -» cold start entry
$x003 —> warm start entry (unused)
$x006 -» ID. ($01-$FF)
$x007 -> "CBM" key string
where x = $8— or $C—.
The ID of any C128 cartridge found is entered into the Physical Address Table
(PAT) located at SAC1-SAC4. ID's must be non-zero. Cartridges may recognize
each other by examining the PAT for particular ID's. An ID of 1 indicates an
auto-start cartridge, and its cold start entry will be called immediately. All others
will be called later (see PHOENIX jump), as will any auto-starters that RTS is to
POLL. A cartridge can determine where it is installed by examining CURBNK,
located at $ACO. Because it is possible for a cartridge to be called with interrupts
enabled, the following diversion from the above format is recommended (the warm
start entry is never called by the system):
$x000 SEI
$x001 JMP STARTUP
$x004 NOP
$x005 NOP
The balance of the C128 initialization is:
9. IOINIT: Initialize I/O devices.
10. Check for STOP AND O keys.
11. RAMTAS: Initialize system RAM.
12. RESTOR: Initialize system indirects.
13. CINT: Initialize video displays.
14. Enable IRQ's (except foreign systems).
15. Dispatch.
IOINIT is perhaps the major function of the Reset handler. It initializes both CIA's
(timers, keyboard, serial port, user port, cassette) and the 8502 port (keyboard,
cassette, VIC bank). It distinguishes a PAL system from an NTSC one and sets
PALCNT ($A03) if PAL. The VIC, SID and 8563 devices are initialized, including
the downloading of character definitions to 8563 display RAM (if necessary). The
system 60Hz IRQ source (the VIC raster) is started. IOINIT is callable by the user
via the jump table.
During initialization, the user may press certain keys as a means of selecting
an operating mode. One key checked is the Commodore key O , indicating C64
mode is desired. While this key was scanned much earlier by the Z80 to speed
the switchover to C64 mode, there is a redundant check for it here. The only other
key scanned at this time is the S T O P key, which signals a request by the user
to power up into the Monitor utility. Note that control does not pass from the
initialization process at this point; the Kernal needs to know if RAMTAS should be
skipped. Only if the S T O P key is depressed and this was a "warm" reset
(vs. "cold" power-up) can RAMTAS be skipped.
RAMTAS clears all page-zero RAM, allocates the cassette and RS-232
buffers, sets pointers to the top and bottom of system RAM (RAM-0), and
installs the SYSTEM_VECTOR (discussed earlier under NMI) that points to BA-
SIC cold start. Lastly it sets a flag, DEJAVU ($A02), to indicate to other routines
that system RAM has been initialized. This is the difference between a "cold"
and a "warm" system. If DEJAVU contains $A5, the system is "warm" and
SYSTEM__VECTOR is valid. Many programmers debugging code need to recover
from a system hang or crash via R E S E T but do not want RAM cleared. This
is why the S T O P key is scanned, RAMTAS is skipped, and the Monitor
(rather than BASIC) is selected. RAMTAS is callable by the user via the jump
table.
RESTOR initializes the Kernal indirect vectors. This must be done before
many system routines will function. Applications that complement the operating
system via "wedges" must install them after they are initialized. RESTOR is user
callable from the jump table (see also the VECTOR call).
CINT is the Editor's initialization routine. Both 40- and 80-column display
modes are prepared, editor indirect vectors installed, programmable key definitions
assigned, and the 40/80 key scnaned for default display determination. CINT is also
a jump table entry.
Finally, the IRQ's are enabled and control is passed to either BASIC
initialization, GO64 code, or the ML Monitor. BASIC will call the Kernal
PHOENIX routine upon the conclusion of its initialization, which will call any
installed C128 cartridges (any ID) and attempt to auto-boot an application from
disk.
An initialization status byte, INIT_STATUS ($A04), marks the progress of
the initialization process. It is cleared automatically at the beginning of the Reset
code, and as specific stages are completed, a particular bit is set. The layout is:
B7 —» 8563 characters installed
B6 -» CINT performed
BO -> BASIC initialized
THE COMMODORE 128 OPERATING SYSTEM 4i I
Any IOINIT calls, including Reset, will not result in 8563 character RAM initial-
ization if B7 is set. Similarly, CINT will not initialize the keyboard matrix lookup
tables and the programmable key definitions if B6 is set. This is how NMFs, for
example, can call IOINIT and CINT without destroying users' setups. Finally,
BASIC initialization must be complete before BO is set. This determines whether
the IRQ handler, for example, should call the BASIC IRQ routines. Note that the
following sequence of events should be performed for a BASIC programmer to
recover from a crash via R E S E T :
This sequence is necessary because INIT_STATUS was cleared by the reset, and
the BASIC initialization was skipped, leaving BO reset. If BO had not been set,
BASIC IRQ routines such as SOUND, PLAY, and SPRITE handlers would not
have functioned, usually resulting in an apparent "hang."
This hardware vector is taken whenever the IRQ pin of the processor is pulled low,
or the processor executes a BRK instruction. For proper operation an IRQ must
occur sixty times every second [NTSC (60Hz) presents no problems, but adjust-
ments have to be made for PAL (50Hz) systems]. The usual source of IRQ's in the
C128 is the VIC raster, which is unleashed during system initialization by IOINIT.
In the event of an IRQ or BRK, the operating system saves the registers and current
memory configuration on the stack and brings the system bank (ROM's, I/O,
RAMO) into context. The processor status at the time of interruption is then read
from the system stack to determine if the interrupt was an IRQ or a BRK. The C128
uses the following code to accomplish this;
If the BRK flag is set, control passes to the ML Monitor through the BRK
indirect vector at $316, which usually points to the Monitor BREAK entry. Here
the program counter (PC), processor status, registers, memory configuration and
stack pointer are retrieved and displayed.
If the BRK flag is 0, an IRQ is assumed and control passes through the IRQ
indirect vector at $314, normally to the system IRQ handler. The following processes
are then performed in the order shown:
1. IRQ's disabled.
2. Editor: split screen handler.
3. Editor: clear VIC raster IRQ.
4. IRQ's enabled.
5. Editor: keyboard scan.
6. Editor: VIC cursor blink.
7. Kernal: "j if fie" clock.
8. Kernal: cassette switches.
9. Kernal: clear CIA-1 ICR.
10. BASIC: sprites, sounds, etc.
11. Return from interrupt.
As indicated in the preceding description, the C128 operating system uses the
IRQ heavily. In particular, the Editor split screen handler has rather strict require-
ments that programmers must recognize and accommodate. An all-text screen or a
fully bit mapped screen presents no particular problem, but a split text and bit map
screen requires twice the IRQ frequency (two every sixtieth of a second). Thus, the
Editor (and consequently, IRQ-dependent applications) must distinguish between
the "main" 60Hz IRQ and the "middle" IRQ. Only during the main IRQ will all
the actions listed above be performed; the middle IRQ is only used by the Editor to
split the screen. The Editor IRQ routine sets the carry flag to designate a main IRQ.
Moreover, there is no margin in the timing requirements of a split screen. Program-
mers should note the way the Editor uses the VIC during IRQ's and avoid direct VIC
I/O if the Editor screen operations are enabled. There is a flag byte called GRAPHM,
located at $D8, which can be set to $FF to disable the Editor's use of the VIC.
The Editor is also responsible for scanning the C128 keyboard. Programmers
should note that SCNKEY has two indirect jumps, KEYLOG and KEYPUT, it
takes during its execution. The keyboard is controlled via CIA-1 PRA, PRB, VIC
register #47 (extended key matrix), and the 8502 port (bit 6 = CAPS LOCK). The
SCNKEY routine is callable from the jump table.
The balance of the IRQ routines up to calling BASIC are self-explanatory.
The Kernal software clock is maintained by UDTIM, which is in the jump table.
The IRQ processing makes one last call to BASIC-IRQ ($4006), but only if
INIT_STATUS bit 0 is set indicating BASIC is ready to handle IRQs (this was
discussed earlier in the RESET section). BASIC_IRQ is a heavy user of the VIC
and SID, and the same precautions should be taken regarding direct VIC and SID
I/O as with the Editor. BASIC-IRQ also utilizes a hold-off byte called IRQ-WRAP
—FLAG. It is normally used by the system to block IRQ-ed IRQ calls, but can be
set by the user with the effect of disabling the BASIC-IRQ handler. Alternatively
you could clear bit 0 of the INIT_STATUS byte as mentioned above and achieve
the same result.
The use of the IRQ indirect ($314) by an application usually requires more
care than most other wedges for several reasons. The likelihood of an IRQ occur-
ring while the wedge is being installed is greater, there exists the possibility that the
user or some other software has already wedged the vector, and usually it is
THE COMMODORE 128 OPERATING SYSTEM 413
desirable for the system IRQ functions to continue normally (e.g., keyscan) as
opposed to replacing them totally with our own (as we did with the NMI examples).
The following examples accomplish these objectives as well as masking out all but
the main IRQ. First we must install our IRQ handler. This example converts the
4 0 / 8 0 key into a SLOW/FAST key:
Now we need a small routine to actually wedge our code into the system IRQ. The
following code saves the current IRQ vector for our handler above to exit through
and substitutes a pointer to our code:
Enable the wedge by typing J 1400, that's all there is to it. Depressing the
Locking 4 0 / 8 0 key now puts you in FAST mode; releasing it SLOWS you
down, and the keyscan, etc., continues to function. Note, however, that on this
split screen our code throws off the timing, making for an unattractive display.
There are really only three things to watch out for when toying with the C128
system IRQ: First, be sure to keep the raster compare value on-screen to keep the
IRQ's happening (the best way is to keep RC8 zero as in example above); second,
never attempt to access the 8563 during an IRQ if there is any chance that it is in
use; finally, be sure the source of the IRQ is being cleared.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
,X used
.Y used
Memory: init Editor RAM
init Editor I/O
Flags: none
EXAMPLE:
SEI
JSR $FF81 initialize screen
CLI
CINT is the Editor's initialization routine. Both 40- and 80-column display
modes are prepared, editor indirect vectors installed, programmable key definitions
assigned, and the 4 0 / 8 0 key scanned for default display determination. CINT
sets the VIC bank and VIC nybble bank, enables the character ROM, resets SID
volume, places both 40- and 80-column screens and clears them. The only thing it
THE COMMODORE 128 OPERATING SYSTEM 415
does not do that pertains to the Editor is I/O initialization, which is needed for IRQ's
(keyscan, VIC cursor blink, split screen modes), key lines, screen background
colors, etc. (see IOINIT). Because CINT updates Editor indirect vectors that are
used during IRQ processing, you should disable IRQ's prior to calling it. CINT
utilizes the status byte INIT_STATUS ($A04) as follows:
$A04 bit 6 = 0 -»• Full initialization.
(set INIT_STATUS bit 6)
1 —* Partial initialization.
(not key matrix pointers)
(not program key definitions)
EXAMPLE:
SEI
JSR $FF84 ;initialize syi
CLI
IOINIT is perhaps the major function of the Reset handler. It initializes both
CIA's (timers, keyboard, serial port, user port, cassette) and the 8502 port (key-
board, cassette, VIC bank). It distinguishes a PAL system from an NTSC one and
sets PALCNT ($A03) if PAL. The VIC, SID and 8563 devices are initialized,
including the downloading of character definitions to 8563 display RAM (if neces-
sary). The system 60Hz IRQ source, the VIC raster, is started (pending IRQs are
cleared). IOINIT utilizes the status byte INIT_STATUS ($A04) as follows:
$A04 bit 7 = 0 —* Full initialization.
(set INIT_STATUS bit 7)
= 1 —» Partial initialization.
(not 8563 character definitions)
You should be sure IRQ's are disabled before calling IOINIT to avoid interrupts
while the various I/O devices are being initialized.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
.Y used
Memory: initializes RAM
Flags: none
EXAMPLE:
JSR $FF87 initialize svster
RAMTAS clears all page-zero RAM, allocates the cassette and RS-232
buffers, sets pointers to the top and bottom of system RAM (RAM 0) and points
the SYSTEM_VECTOR ($A00) to BASIC cold start ($4000). Finally, it sets a
flag, DEJAVU ($A02), to indicate to other routines that system RAM has been
initialized and that the SYSTEMLVECTOR is valid. It should be noted that the
C128 RAMTAS routine does not in any way test RAM.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
.Y used
Memory: Kernal indirects restored
Flaes: none
THE COMMODORE 128 OPERATING SYSTEM 417
EXAMPLE:
SEI
JSR $FF8A ;restore Kernal indirects
CLI
RESTOR restores the default values of all the Kernal indirect vectors from
the Kernal ROM list. It does not affect any other vectors, such as those used by the
Editor (see CINT) and BASIC. Because it is possible for an interrupt (IRQ or NMI)
to occur during the updating of the interrupt indirect vectors, you should disable
interrupts prior to calling RESTOR. See also the VECTOR call.
PREPARATION:
Registers: .X = adr (low) of user list
.Y = adr (high) of user list
Memory: system map
Flags: .C = 0 —» load Kernal vectors
.C = 1 —> copy Kernal vectors
Calls: none
RESULTS:
Registers: .A used
.Y used
Memory: as per call
Flags: none
EXAMPLE:
LDX #save_lo
LDY #save_hi
SEC
JSR $FF87 ;copv indirects to "save"
VECTOR reads or writes the Kernal RAM indirect vectors. Calling VEC-
TOR with the carry status set stores the current contents of the indirect vectors to
the RAM address passed in the .X and .Y registers (to the current RAM bank).
Calling VECTOR with the carry status clear updates the Kernal indirect vectors
from the user list passed in the .X and .Y registers (from the current RAM bank).
Interrupts (IRQ and NMI) should be disabled when updating the indirects. See also
the RESTOR call.
6. $FF90 SETMSG ;Kernal messages on/off
PREPARATION:
Registers: .A = message control
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: none
Memory: MSGFLG ($9D) updated
Flags: none
EXAMPLE:
LDA#0
JSR $FF90 :turn OFF all Kernal mes
SETMSG updates the Kemal message flag byte MSGFLG ($9D) that deter-
mines whether system error and/or control messages will be displayed. BASIC
normally disables error messages always and disables control messages in Run
mode. Note that the Kemal error messages are not the verbose ones printed by
BASIC, but simply the I/O ERROR # message that you see when in the Monitor,
for example. Examples of Kemal control messages are LOADING, FOUND, and
PRESS PLAY ON TAPE. The MSGFLG control bits are:
MSGFLG bit 7 = 1 -» enable CONTROL messages
bit 6 = 1 —> enable ERROR messages
PREPARATION:
Registers: .A = SA (secondary address)
Memory: system map
Flags: none
Calls: LISTN
RESULTS:
Registers: .A used
Memory: STATUS ($90)
Flags: none
EXAMPLE:
LDA#8
JSR $FF81 ;LISTN device 8
LDA #15
JSR $FF93 ;pass it SA #15
THE COMMODORE 128 OPERATING SYSTEM 419
PREPARATION:
Registers: .A = SA (secondary address)
Memory: system map
Flags: none
Calls: TALK
RESULTS:
Registers: .A used
Memory: STATUS ($90)
Flags: none
EXAMPLE:
LDA # 8
JSR $FFB4 ;TALK device 8
LDA #15
JSR $FF93 ;pass it SA #15
PREPARATION:
Registers: .X = lsb of MEMSIZ
.Y = msb of MEMSIZ
Memory: system map
Flags: .C = 0 —* set top of memory
.C = 1 —* read top of memory
Calls: none
RESULTS:
Registers: .X = lsb of MEMSIZ
,Y = msb of MEMSIZ
Memory: MEMSIZ ($A07)
Flags: none
EXAMPLE:
SEC
JSR $FF99 ;get top of user RAMO
DEY
CLC
JSR $FF99 ;lower it 1 block
PREPARATION:
Registers: .X = lsb of MEMSTR
.Y = msb of MEMSTR
Memory: system map
Flags: .C = 0 —* set bot of memory
.C = 1 -* read bot of memory
Calls: none
RESULTS:
Registers: .X = lsb of MEMSTR
.Y = msb of MEMSTR
Memory: MEMSTR ($A05)
Flags: none
EXAMPLE:
SEC
JSR $FF9C ;get bottom of user RAMO
INY
CLC
JSR $FF9C ;raise it 1 block
THE COMMODORE 128 OPERATING SYSTEM 421
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: none
Memory: keyboard buffer
keyboard flags
Flags: none
EXAMPLE:
JSR $FF9F ;scan the keyboard
KEY is an Editor routine that scans the entire C128 keyboard (except the
4 0 / 8 0 key). It distinguishes between ASCII keys, control keys, and program-
mable keys, setting keyboard status bytes and managing the keyboard buffer. After
decoding the key, KEY will manage such features as toggling cases, pauses or
delays, and key repeats. It is normally called by the operating system during the
60Hz IRQ processing. Upon conclusion, KEY leaves the keyboard hardware driv-
ing the keyline on which the S T O P key is located.
There are two indirect RAM jumps encountered during a keyscan: KEYVEC
($33A) and KEYCHK ($33C). KEYVEC (alias KEYLOG) is taken whenever a key
depression is discovered, before the key in .A has been decoded. KEYCHK is taken
after the key has been decoded, just before putting it into the key buffer. KEYCHK
carries the ASCII character in .A, the keycode in .Y, and the shiftkey status in .X.
The keyboard decode matrices are addressed via indirect RAM vectors as
well, located at DECODE ($33E). The following table describes them:
$33E Mode 1 -> normal keys
$340 Mode 2 -> S H I F T keys
$342 Mode 3 -» O keys
$344 Mode 4 -> C O N T R O L keys
$346 Mode 5 -* C A P S LOG K keys
$348 Mode 6 -> ALT keys
The following list briefly describes some of the more vital variables utilized
or maintained by KEY:
ROWS $DC01 > I/O port outputting keys
COLM $DC00 * I/O port driving C64 keys
VIC #47 $D02F * I/O port driving new keys
8502 P6 $0001 » I/O port sensing CAPS key
NDX $D0 * keyboard buffer index
KEYD $34A > keyboard buffer
XMAX $A20 * keyboard buffer size
SHFLAG $D3 * shift key status
RPTFLG $A22 > repeat key enables
LOCKS $F7 > pause, mode disables
KEY is also found in the Editor jump table as SCNKEY at $C012.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: none
Memory: TIMOUT ($A0E)
Flags: none
EXAMPLE:
LDA #value
JSR $FFA2 :uodate TIMOUT
SETTMO is not used in the C128 but is included for compatibility and
completeness. It is used in the C64 by the IEEE communication cartridge to disable
I/O timeouts.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: TALK
TKSA (if necessary)
THE COMMODORE 128 OPERATING SYSTEM 423
RESULTS:
Registers: .A = data byte
Memory: STATUS ($90)
Flags: none
EXAMPLE:
JSR $FFA5 ;input a byte from serial bus
STA data
ACPTR is a low-level serial I/O utility to accept a single byte from the
current serial bus TALKer using full handshaking. To prepare for this routine,
a device must first have been established as a TALKer (see TALK) and passed
a secondary address if necessary (see TKSA). The byte is returned in .A.
(Most applications should use the higher-level I/O routines; see BASIN and
GETIN).
PREPARATION:
Registers: .A = data byte
Memory: system map
Flags: none
Calls: LISTN
SECND (if necessary)
RESULTS:
Registers: .A used
Memory: STATUS ($90)
Flags: none
EXAMPLE:
LDA data
JSR $FFA8 ;send a bvte via serial
CIOUT is a low-level serial I/O utility to transmit a single byte to the current
serial bus LISTNer using full handshaking. To prepare for this routine, a device
must first have been established as a LISTNer (see LISTN) and passed a secondary
address if necessary (see SECND). The byte is passed in .A. Serial output data is
buffered by one character, with the last character being transmitted with EOI after a
call to UNLSN. (Most applications should use the higher level I/O routines; see
BSOUT.)
15. $FFAB UNTLK ;serial: send untalk
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
Memory: STATUS ($90)
Flags: none
EXAMPLE:
JSR $FFAB :UNTALK seri
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
Memory: STATUS ($90)
Flags: none
EXAMPLE:
JSR SFFAE ;UNLISTEN se
PREPARATION:
Registers: .A = device (0-31)
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
Memory: STATUS ($90)
Flags: none
EXAMPLE:
PREPARATION:
Registers: .A = device (0-31)
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
Memory: STATUS ($90)
Flags: none
EXAMPLE:
JSR $FFB4 xommand device to
TALK is a low-level Kernal serial bus routine that sends a TALK command
to the serial bus device in .A. It commands the device to start sending data. (Most
applications should use the higher-level I/O routines; see ICHKIN.)
19. $FFB7 READSS ;read I/O status byte
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A = STATUS ($90 or $A14)
Memory: STATUS cleared if RS-232
Flags: none
EXAMPLE:
JSR $FFB7 ;STATUS for last I/O
READSS (alias READST) returns the status byte associated with the last I/O
operation (serial, cassette or RS-232) performed. Serial and cassette tape operations
update STATUS ($90) and RS-232 I/O updates RSSTAT ($A14). Note that to
simulate an ACIA, RSSTAT is cleared after it is read via READSS. The last I/O
operation is determined by the contents of FA ($BA); thus applications that drive
I/O devices using the lower-level Kernal calls should not use READSS.
PREPARATION:
Registers: .A = LA (logical #)
.X = FA (device #)
.Y = SA (secondary adr)
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: none
Memory: LA, FA, SA updated
Flags: none
EXAMPLE:
See OPEN
SETLFS sets the logical file number (LA, $B8), device number (FA, $BA)
and secondary address (SA, $B9) for the higher-level Kernal I/O routines. The LA
must be unique among OPENed files and is used to identify specific files for I/O
THE COMMODORE 128 OPERATING SYSTEM 427
operations. The device number range is 0 to 31 and is used to target I/O. The SA is
a command to be sent to the indicated device, usually to place it in a particular
mode. If the SA is not needed, the .Y register should pass $FF. SETLFS is often
used along with SETNAM and SETBNK calls prior to OPENs. See the Kernal
OPEN, LOAD and SAVE calls for examples.
PREPARATION:
Registers: .A = string length
.X = string adr low
.Y = string adr high
Memory: system map
Flags: none
Calls: SETBNK
RESULTS:
Registers: none
Memory: FNLEN, FNADR updated
Flags: none
EXAMPLE:
See OPEN
SETNAM sets up the filename or command string for higher-level Kernal I/O
calls such as OPEN, LOAD and SAVE. The string (filename or command) length is
passed in .A and updates FNLEN ($B7). The address of the string is passed in ,X
(low) and .Y (high). See the companion call, SETBNK, which specifies in which
RAM bank the string is found. If there is no string, SETNAM should still be called
and a null ($00) length specified (the address does not matter). SETNAM is often
used along with SETBNK and SETLFS calls prior to OPENs. See the Kernal
OPEN, LOAD and SAVE calls for examples.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: SETLFS, SETNAM, SETBNK
RESULTS:
Registers: .A = error code (if any)
.X used
.Y used
Memory: setup for I/O
STATUS, RSSTAT updated
Flags: .C = 1 —> error
OPEN prepares a logical file for I/O operations. It creates a unique entry in
the Kernal logical file tables LAT ($362), FAT ($36C) and SAT ($376) using its
index LDTND ($98) and data supplied by the user via SETLFS. There can be up to
ten logical files OPENed simultaneously. OPEN performs device-specific opening
tasks for serial, cassette and RS-232 devices, including clearing the previous status and
transmitting any given filename or command string supplied by the user via SETNAM
and SETBNK. The I/O status is updated appropriately and can be read via READSS.
The path to OPEN is through an indirect RAM vector at $31 A. Applications
may therefore provide their own OPEN procedures or supplement the system's by
redirecting this vector to their own routine.
PREPARATION:
Registers: .A = LA (logical #)
Memory: system map
Flags: .C (see text below)
Calls: none
THE COMMODORE 128 OPERATING SYSTEM 429
RESULTS:
Registers: .A = error code (if any)
.X used
.Y used
Memory: logical tables updated
STATUS, RSSTAT updated
Flags: .C = 1 —* error
EXAMPLE:
LDA #1 ;la
JSR $FFC3 ;CLOSE
BCS error ;(tape files only)
CLOSE removes the logical file (LA) passed in .A from the logical file tables
and performs device-specific closing tasks. Keyboard, screen and any unOPENed
files pass through. Cassette files opened for output are closed by writing the last
buffer and (optionally) an EOT mark. RS-232 I/O devices are reset, losing any
buffered data. Serial files are closed by transmitting a CLOSE command (if an SA
was given when it was opened), sending any buffered character, and UNLSTNing
the bus.
There is a special provision incorporated into the CLOSE routine of systems
featuring a BASIC DOS command. If the following conditions are all true, a full
CLOSE is not performed; the table entry is removed but a CLOSE command is not
transmitted to the device. This allows the disk command channel to be properly
OPENed and CLOSEd without the disk operating system closing all files on its
end:
C = 1 -» indicates special CLOSE
FA > = 8 —> device is a disk
SA = 15 —• command channel
The path to CLOSE is through an indirect RAM vector at $31C. Applications
may therefore provide their own CLOSE procedures or supplement the system's by
redirecting this vector to their own routine.
PREPARATION:
Registers: .X = LA (logical #)
Memory: system map
Flags: none
Calls: OPEN
RESULTS:
Registers: .A = error code (if any)
.X used
.Y used
Memory: LA, FA, SA, DFLTN
STATUS, RSSTAT updated
Flags: .C = 1 —> error
EXAMPLE:
LDX #1 ;la
JSR $FFC6 ;CHKIN
BCS error
CHKIN establishes an input channel to the device associated with the logical
address (LA) passed in .X, in preparation for a call to BASIN or GETIN. The
Kernal variable DFLTN ($99) is updated to indicate the current input device and the
variables LA, FA and SA are updated with the file's parameters from its entry in
the logical file tables (put there by OPEN). CHKIN performs certain device specific
tasks: screen and keyboard channels pass through, cassette files are confirmed for
input, and serial channels are sent a TALK command and the SA transmitted (if
necessary). Call CLRCH to restore normal I/O channels.
CHKIN is required for all input except the keyboard. If keyboard input is
desired and no other input channel is established, you do not need to call CHKIN or
OPEN. The keyboard is the default input device for BASIN and GETIN.
The path to CHKIN is through an indirect RAM vector at $3IE. Applications
may therefore provide their own CHKIN procedures or supplement the system's by
redirecting this vector to their own routine.
PREPARATION:
Registers: .X = LA (logical #)
Memory: system map
Flags: none
Calls: OPEN
RESULTS:
Registers: .A = error code (if any)
.X used
,Y used
Memory: LA, FA, SA, DFLTO
STATUS, RSSTAT updated
Flags: ,C = 1 —» error
THE COMMODORE 128 OPERATING SYSTEM 431
EXAMPLE:
LDX #1 ;la
JSR $FFC9 ;CKOUT
BCS error
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
Memory: DFLTI, DFLTO updated
Flags: none
EXAMPLE:
JSR $FFCC ;restore default I/O
CLRCH (alias CLRCHN) is used to clear all open channels and restore the
system default I/O channels after other channels have been established via CHKIN
and/or CHKOUT. The keyboard is the default input device and the screen is the
default output device. If the input channel was to a serial device, CLRCH first
UNTLKs it. If the output channel was to a serial device, it is UNLSNed first.
The path to CLRCH is through an indirect RAM vector at $322. Applications
may therefore provide their own CLRCH procedures or supplement the system's by
redirecting this vector to their own routine.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: CHKIN (if necessary)
RESULTS:
Registers: .A = character (or error code)
Memory: STATUS, RSSTAT updated
Flags: ,C = 1 if error
EXAMPLE:
LDY # 0 ;index
MORE JSR $FFCF ;input a character
STA data,Y ;buffer it
INY
CMP #$0D ;carriage return?
BNE MORE
BASIN (alias CHRIN) reads a character from the current input device (DFLTN
$99) and returns it in .A. Input from devices other than the keyboard (the default
input device) must be OPENed and CHKINed. The character is read from the input
buffer associated with the current input channel:
a. Cassette data is returned a character at a time from the cassette buffer at $B00,
with additional tape blocks being read when necessary.
b. RS-232 data is returned a character at a time from the RS-232 input buffer at $C00,
waiting until a character is received if necessary. If RSSTAT ($A14) is bad from
a prior operation, input is skipped and null input (carriage return) is substituted.
c. Serial data is returned a character at a time directly from the serial bus, waiting
until a character is sent if necessary. If STATUS ($90) is bad from a prior
operation, input is skipped and null input (carriage return) is substituted.
d. Screen data is read from screen RAM starting at the current cursor position and
ending with a pseudo carriage return at the end of the logical screen line. The
way the BASIN routine is written, the end of line (EOL) is not recog-
nized. Users must therefore count characters themselves or otherwise detect
when the logical EOL has been reached.
THE COMMODORE 128 OPERATING SYSTEM 433
e. Keyboard data is input by turning on the cursor, reading characters from the
keyboard buffer, and echoing them on the screen until a carriage return is
encountered. Characters are then returned one at a time from the screen until
all characters input have been passed, including the carriage return. Any calls
after the EOL will start the process over again.
PREPARATION:
Registers: .A = character
Memory: system map
Flags: none
Calls: CKOUT (if necessary)
RESULTS:
Registers: .A = error code (if any)
Memory: STATUS, RSSTAT updated
Flags: .C = 1 if error
EXAMPLE:
LDA #character
JSR $FFD2 ;output a character
a. Cassette data is put a character at a time into the cassette buffer at $B00, with
tape blocks being written when necessary.
b. RS-232 data is put a character at a time into the RS-232 output buffer at $D00,
waiting until there is room if necessary.
c. Serial data is passed to CIOUT, which buffers one character and sends the
previous character.
d. Screen data is put into screen RAM at the current cursor position.
e. Keyboard output is illegal.
PREPARATION:
Registers: .A = 0 -» LOAD
.A > 0 -* VERIFY
.X = loadadrlo(if SA = 0)
.Y = load adrhi(if SA = 0)
Memory: system map
Flags: none
Calls: SETLFS, SETNAM, SETI
RESULTS:
Registers: .A = error code (if any)
.X = ending adr lo
.Y = ending adr hi
Memory: per command
STATUS updated
Flags: .C = 1 —> error
This routine LOADs data from an input device into C128 memory. It can also
be used to VERIFY that data in memory matches that in a file. LOAD performs
THE COMMODORE 128 OPERATING SYSTEM 43S
device-specific tasks for serial and cassette LOADs. You cannot LOAD from
RS-232 devices, the screen or the keyboard. While LOAD performs all the tasks of
an OPEN, it does not create any logical files as an OPEN does. Also note that LOAD
cannot "wrap" memory banks. As with any I/O, the I/O status is updated appropriately
and can be read via READSS. LOAD has two options that the user must select:
a. LOAD vs. VERIFY: The contents of .A passed at the call to LOAD deter-
mines which mode is in effect. If .A is zero, a LOAD operation will be
performed and memory will be overwritten. If .A is nonzero, a VERIFY
operation will be performed and the result passed via the error mechanism.
b. LOAD ADDRESS: the secondary address (SA) setup by the call to SETLFS
determines where the LOAD starting address comes from. If the SA is zero,
the user wants the address in .X and . Y at the time of the call to be used. If the
SA is nonzero, the LOAD starting address is read from the file header itself
and the file is loaded into the same place from which it was SAVEd.
The C128 serial LOAD routine automatically attempts to BURST load a file,
and resorts to the normal load mechanism (but still using the FAST serial routines)
if the BURST handshake is not returned.
The path to LOAD is through an indirect RAM vector at $330. Applications
may therefore provide their own LOAD procedures or supplement the system
procedures by redirecting this vector to their own routine.
PREPARATION:
Registers: .A = pointer to start adr
.X = end adr lo
,Y = end adr hi
Memory: system map
Flags: none
Calls: SETLFS, SETNAM, SETBNK
RESULTS:
Registers: .A = error code (if any)
.X = used
.Y = used
Memory: STATUS updated
Flags: .C = 1 —» error
This routine SAVEs data from C128 memory to an output device. SAVE per-
forms device-specific tasks for serial and cassette SAVEs. You cannot SAVE from
RS-232 devices, the screen or the keyboard. While SAVE performs all the tasks of an
OPEN, it does not create any logical files as an OPEN does. The starting address of
the area to be SAVEd must be placed in a zero-page vector and the address of this
vector passed to SAVE in .A at the time of the call. The address of the last byte
to be SAVEd PLUS ONE is passed in .X and .Y at the same time. Cassette SAVEs
utilize the secondary address (SA) to specify the type of tape header(s) to be generated:
SA (bit 0) = 0 -» relocatable (blf) file
= 1 —> absolute (plf) file
SA (bit 1) = 0 —» normal end
= 1 —» write EOT header at end
There is no BURST save; the normal FAST serial routines are used. As with
any I/O, the I/O status will be updated appropriately and can be read via READSS.
The path to SAVE is through an indirect RAM vector at $332. Applications
may therefore provide their own SAVE procedures or supplement the system's by
redirecting this vector to their own routine.
PREPARATION:
Registers: .A = low byte
.X = middle byte
.Y = high byte
Memory: system map
Flags: none
Calls: none
THE COMMODORE 128 OPERATING SYSTEM 437
RESULTS:
Registers: none
Memory: TIME (SAO) updated
Flags: none
EXAMPLE:
LDA # 0 ;reset clock
TAX
TAY
JSR $FFDB :SETTIM
SETTIM sets the system software (jiffie) clock, which counts sixtieths (1/60)
of a second. The timer is incremented during system IRQ processing (see UDTIM),
and reset at the 24-hour point. SETTIM disables IRQ's, updates the three-byte timer
with the contents of .A, .X and .Y, and re-enables IRQ's.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A = low byte
.X = middle byte
.Y = high byte
Memory: none
Flags: none
EXAMPLE:
JSR SFFDE ;RDTIM
RDTIM reads the system software (jiffie) clock, which counts sixtieths (1/60)
of a second. The timer is incremented during system IRQ processing (see UDTIM),
and reset at the 24-hour point. RDTIM disables IRQ's, loads .A, .X and . Y with the
contents of the 3-byte timer, and re-enables IRQ's.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A = last keyboard row
.X = used (if STOP key)
Memory: none
Flags: status valid
EXAMPLE:
JSR $FFE1 ;scan STOP key
BEQ stop ;branch if down
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: CHKIN (if necessary)
RESULTS:
Registers: .A = character (or error code)
.X used
.Y used
Memory: STATUS, RSSTAT updated
Flags: .C = 1 if error
EXAMPLE:
wait JSR $FFE4 ;get any key
BEQ wait
STA character
GETIN reads a character from the current input device (DFLTN ($99)) buffer
and returns it in .A. Input from devices other than the keyboard (the default input
device) must be OPENed and CHKINed. The character is read from the input buffer
associated with the current input channel:
THE COMMODORE 128 OPERATING SYSTEM 439
a. Keyboard input: A character is removed from the keyboard buffer and passed
in .A. If the buffer is empty, a null ($00) is returned.
b. RS-232 input: A character is removed from the RS-232 input buffer at $C00
and passed in .A. If the buffer is empty, a null ($00) is returned (use READSS
to check validity).
c. Serial input: GETIN automatically jumps to BASIN. See BASIN serial I/O.
d. Cassette input: GETIN automatically jumps to BASIN. See BASIN cassette
I/O.
e. Screen input: GETIN automatically jumps to BASIN. See BASIN serial I/O.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
Memory: LDTND, DFLTN, DFLTO updated
Flags: none
EXAMPLE:
JSR $FFE7 xlose files
CLALL deletes all logical file table entries by resetting the table index,
LDTND ($98). It clears current serial channels (if any) and restores the default I/O
channels via CLRCH.
The path to CLALL is through an indirect RAM vector at $32C. Applications
may therefore provide their own CLALL procedures or supplement the system's by
redirecting this vector to their own routine.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
Memory: TIME, TIMER, STKEY updated
Flags: none
EXAMPLE:
SEI
JSR $FFEA ;UDTIM
CLI
UDTIM increments the system software (jiffie) clock, which counts sixtieths
(1/60) of a second when called by the system 60Hz IRQ. TIME, a 3-byte counter
located at $A0, is reset at the 24-hour point. UDTIM also decrements TIMER, also
a 3-byte counter, located at $A1D (BASIC uses this for the SLEEP command, for
example). You should be sure IRQ's are disabled before calling UDTIM to prevent
system calls to UDTIM while you are modifying TIME and TIMER.
UDTIM also scans key line C7, on which the STOP key lies, and stores the
result in STKEY ($91). The Keraal routine STOP utilizes this variable.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A = screen width
.X = window width
.Y = window height
Memory: none
Flags: none
EXAMPLE:
JSR $FFED ;SCRORG
SCRORG is an Editor routine that has been slightly changed from previous
CBM systems. Instead of returning the maximum SCREEN dimensions in .X and
.Y, the C128 SCRORG returns the current WINDOW dimensions. It does return
the maximum SCREEN width in .A. These changes make it possible for applica-
tions to "fit" themselves on the current screen window. SCRORG is also an Editor
jump table entry ($C00F).
THE COMMODORE 128 OPERATING SYSTEM 441
PREPARATION:
Registers: ,X = cursor line
.Y = cursor column
Memory: system map
Flags: .C = 0 —» set cursor position
.C = 1 —» get cursor position
Calls: none
RESULTS:
Registers: .X = cursor line
.Y = cursor column
Memory: TBLX, PNTR updated
Flags: .C = 1 —•» error
EXAMPLE:
SEC
JSR SFFFO ;read current position
INX ;move down one line
INY ;move right one space
CLC
JSR $FFF0 ;set cursor position
BCS error :new Dosition outside window
PLOT is an Editor routine that has been slightly changed from previous CBM
systems. Instead of using absolute coordinates when referencing the cursor position,
PLOT now uses relative coordinates, based upon the current screen window. The
following local Editor variables are useful:
When called with the carry status set, PLOT returns the current cursor
position relative to the current window origin (not screen origin). When called with
the carry status clear, PLOT attempts to move the cursor to the indicated line and
column relative to the current window origin (not screen origin). PLOT will return a
clear carry status if the cursor was moved, and a set carry status if the requested
position was outside the current window (no change has been made).
39. $FFF3 IOBASE ;read base address of I/O block
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .X = lsb of I/O block
.Y = msbof I/O block
Memory: none
Flags: none
EXAMPLE:
JSR $FFF3 ;find the I/O block
IOBASE is not used in the C128 but is included for compatibility and complete-
ness. It returns the address of the I/O block in .X and . Y.
PREPARATION:
Registers: none
Memory: system map
Flags: .C = 0 -> select SPINP
.C = 1 -» select SPOUT
Calls: none
RESULTS:
Registers: .A used
Memory: CIA-1, MMU
Flags: none
THE COMMODORE 128 OPERATING SYSTEM 443
EXAMPLE:
CLC
JSR $FF47 ;setup for fast serial input
The C128/1571 fast serial protocol utilizes CIA 1 (6526 at $DC00) and a
special driver circuit controlled in part by the MMU (at $D500). SPINP and
SPOUT are routines used by the system to set up the CIA and fast serial driver
circuit for input or output. SPINP sets up CRA (CIA 1 register 14) and clears the
FSDIR bit (MMU register 5) for input. SPOUT sets up CRA, ICR (CIA 1 register
13), timer A (CIA 1 registers 4 and 5), and sets the FSDIR bit for output. Note the
state of the TODIN bit of CRA is always preserved, but the state of the GAME,
EXROM and SENSE40 outputs of the MMU are not (reading these ports return the
state of the port and not the register values—consequently they cannot be pre-
served). These routines are required only by applications driving the fast serial bus
themselves from the lowest level.
PREPARATION:
Registers: .A -> device # (FA: 0-31)
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
.Y used
Memory: none
Flags: none
EXAMPLE:
LDA #$08
JSR $FF4A xlose all files on device 8
The FAT is searched for the given FA. A proper CLOSE is performed for all
matches. If one of the CLOSEd channels is the current I/O channel, then the default
channel is restored.
This call is utilized, for example, by the BASIC command DCLOSE. It is
also called by the Kernal BOOT routine.
3. $FF4D C64MODE reconfigure system as a C64
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: none
Memory: none
Flags: none
EXAMPLE:
JMP $FF4D :switch to C
There is no return from this routine. The 8502 DDR and port are initialized,
and the VIC is set to 1MHz (slow) mode. Control is passed to code in common
(shared) RAM, which sets the MMU mode register (#5) to C64 mode. From this
point on, the MMU and C128 ROMs are not accessible. The routine exits via an
indirect jump through the C64 RESET vector.
Since C64 operation does not allow for MMU access, all MMU registers must
be configured for proper operation before the C64 mode bit is set. Similarly,
because the start-up of the C64 operating system is not from a true hardware reset,
there is the possibility that unusual I/O states in effect prior to C64MODE calls can
cause unpredictable and presumably undesirable situations once in C64 mode.
There is no way to switch from C64 mode back to C128 mode; only a
hardware reset or power off/on will restore the C128 mode of operation. A reset
will always initiate C128 mode, although altering the SYSTEM vector beforehand
is one way to automatically "throw" a system back to C64 mode.
PREPARATION:
Registers: .X = bank (0-15)
.Y = DMA controller command
Memory: DMA registers set up system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
Memory: changed as per command
Flags: none
THE COMMODORE 128 OPERATING SYSTEM 445
EXAMPLE:
LDA #$00 ;setup C128 base address
STA $DF02 ;low
LDA #$20
STA $DF03 ;high
LDA #$00 ;setup expansion RAM address
STA $DF04 ;low
STA $DF05 ;high
STA $DF06 ;bank (0-n, where n = 3 if 256K)
LDA #$40 ;setup number of bytes
STA $DF07 ;low
LDA #$1F
STA $DF08 ;high
LDX #$00 ;C128 bank
LDY #$84 ;DMA command to "STASH"
JSR $FF50 ;execute DMA command
PREPARATION:
Registers: .A = drive number (ASCII)
.X = device number (0-31)
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
.Y used
Memory: changed as per command
Flags: .C -> 1 if I/O error
EXAMPLE:
LDA #$30 ;drive 0
LDX #$08 ;device 8
JSR $FF53 ;BOOT
BCS 10 ERROR
BCC NO BOOT SECTOR
BOOT attempts to load and execute the boot sector from an auto-boot disk in
the given drive and device. The BOOT protocol is as follows:
On any error, the BOOT operation is aborted and the UI command is issued
to the disk. A return may or may not be made to the caller depending upon the
completion status and the BOOTed code. The BOOT sector has the following
layout:
The following examples illustrate the flexibility of this layout. This loads and runs a
BASIC program:
This results in the message Booting NAME... being displayed and, utilizing a
C128 BASIC jump table entry that finds and executes a BASIC statement, loads
and runs the BASIC program named "PROGRAM." The same header can be used
to load and execute a binary (machine code) program by simply changing RUN to
BOOT. (While the file auto-load feature of the boot header could be used to load
binary files simply by furnishing a filename, to execute it you must know the
starting address and JMP to it. BASIC'S BOOT command does that, and allows a
more generic mechanism.) In the next example, a menu is displayed and you are
asked to select the operating mode. Nothing else is loaded in this "configure"-type
header:
PREPARATION:
Registers: none
Memory: cartridge map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
.Y used
Memory: changed as per command
Flags: none
EXAMPLE:
JSR $FF56 :PHOENIX
PREPARATION:
Registers: .A = LA (logical file number)
if LKUPLA
.Y = SA (secondary address)
if LKUPSA
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A = LA (only if found)
FA (only if found)
.Y = SA (only if found)
Memory: none
Flags: .C = 0 if found
1 if not found
THE COMMODORE 128 OPERATING SYSTEM 449
EXAMPLE:
LDY #$60 ;find an available SA
AGAIN INY
CPY #$6F
BCS TOO MANY ;too many files open
JSR SFF5C ;LKUPSA
BCC AGAIN ;get another if in use
LKUPLA and LKUPSA are Kernal routines used primarily by BASIC DOS
commands to work around a user's open disk channels. The Kernal requires unique
logical device numbers (LA's), and the disk requires unique secondary addresses
(SA's); therefore BASIC must find alternative unused values whenever it needs to
establish a disk channel.
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
.Y used
Memory: local variables swapped
Flags: none
EXAMPLE:
LDA $D7 ;check display mode
BMI is_80 ;branch if 80-column
JSR $FF5F ;switch from 40 to 80
PREPARATION:
Registers: none
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
.Y used
Memory: 8563 character RAM initialized
Flags: none
EXAMPLE:
JSR $FF62 unitialize 8563 char, defns.
PREPARATION:
Registers: .A = pointer to string adr
(lo/hi/bank)
.Y = string length
.X = key number (1-10)
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A used
.X used
.Y used
Memory: PKYBUF, PKYDEF tables updated
Flags: .C = 0 if successful
.C = 1 if no room available
THE COMMODORE 128 OPERATING SYSTEM 451
EXAMPLE:
LDA #$FA ;pointer to string address
LDY #$06 ;length
LDX #$0A ;key # (HELP key)
JSR $FF65 ;install new key def n
BCS NO ROOM
>000FA 00 13 00 :ptr to $1300 bank 0
>01300 53 54 52 49 4E 47 :"string"
PREPARATION:
Registers: .A = BA, memory bank (0-15)
.X = FNBANK, filename bank
Memory: system map
Flags: none
Calls: SETNAM
RESULTS:
Registers: none
Memory: BA, FNBANK updated
Flags: none
EXAMPLE:
See OPEN
SETBNK is a prerequisite for any memory I/O operations, and must be used
along with SETLFS and SETNAM prior to OPENing files, etc. BA ($C6) sets the
current 64KB memory bank for LOAD/SAVE/VERIFY operations. FNBANK ($C7)
indicates the bank in which the filename string is found. The Kernal routine
GETCFG is used to translate the given logical bank numbers (0-15). SETBNK is
often used along with SETNAM and SETLFS calls prior to OPEN's. See the Kernal
OPEN, LOAD and SAVE calls for examples.
13. SFF6B GETCFG ;lookup MMU data for given bank
PREPARATION:
Registers: .X = logical bank # (0-15)
Memory: system map
Flags: none
Calls: none
RESULTS:
Registers: .A = MMU configuration data
Memory: none
Flags: none
EXAMPLE:
LDX #$00 ;logical bank 0 (RAM 0)
JSR $FF6B ;GETCFG
STA $FF01 ;setup MMU pre-config # 1
PREPARATION:
Registers: none
Memory: system map, also:
$02-^ • bank (0-15)
$ 0 3 ^ • PC high
$ 0 4 ^ PC low
$ 0 5 - * • .S (status)
$06-*• .A
$07 -*• .X
$08-^ • . Y
Flags: none
Calls: none
RESULTS:
Registers: none
Memory: as per call, also:
$05 -»• .S (status)
$06-*• .A
$07-* .X
$08 -> .Y
Flags: none
The two routines, JSRFAR and JMPFAR, enable code executing in the
system bank of memory to call (or JMP to) a routine in any other bank. In the case
of JSRFAR, a return will be made to the caller's bank. It should be noted that
JSRFAR calls JMPFAR, which calls GETCFG. When calling a non-system bank,
the user should take necessary precautions to ensure that interrupts (IRQ's and NMI's)
will be handled properly (or disabled beforehand). Both JSRFAR and JMPFAR are
RAM-based routines located in common (shared) RAM at $2CD and $2E3
respectively.
The following code illustrates how to call a subroutine in the second RAM
bank from the system bank. Note that we need not worry about IRQ's and NMI's in
this case because the system will handle them properly in any configuration that has
the Kernal ROM or any valid RAM bank in context at the top page of memory.
PREPARATION:
Registers: .A = pointer to address
.X = bank (0-15)
.Y = index
Memory: setup indirect vector
Flags: none
Calls: none
RESULTS:
Registers: .A = data
.X used
Memory: none
Flags: status valid
EXAMPLE:
LDA #$00 ;setup to read $2000
STA $FA
LDA #$20
STA $FB
LDA #$FA
LDX #$01 ;in bank 1
LDY #$00
JSR $FF74 ;LDA ($FA,RAM 1),Y
BEQ etc
INDFET enables applications to read data from any other bank. It sets up
FETVEC ($2AA), calls GETCFG to convert the bank number, and JMPs to code in
THE COMMODORE 128 OPERATING SYSTEM 4S5
common (shared) RAM at $2A2 which switches banks, loads the data, restores the
user's bank, and returns. When calling a non-system bank, the user should take
necessary precautions to ensure that interrupts (IRQ's and NMI's) will be handled
properly (or disabled beforehand).
PREPARATION:
Registers: .A = data
.X = bank (0-15)
,Y = index
Memory: setup indirect vector
setup STAVEC ($2B9) pointer
Flags: none
Calls: none
RESULTS:
Registers: .X used
Memory: changed per call
Flags: status invalid
EXAMPLE:
LDA #$00 ;setup write to $2000
STA $FA
LDA #$20
STA $FB
LDA #$FA
STA $2B9
LDA data
LDX #$01 ;in bank 1
LDY #$00
JSR $FF77 ;STA ($FA,RAM 1),Y
INDSTA enables applications to write data to any other bank. After you set
up STAVEC ($2B9), it calls GETCFG to convert the bank number and JMPs to
code in common (shared) RAM at $2AF which switches banks, stores the data,
restores your bank, and returns. When calling a nonsystem bank, the user should
take necessary precautions to ensure that interrupts (IRQ's and NMI's) will be
handled properly (or disabled beforehand).
18. $FF7A INDCMP ;CMP (cmpvec),Y to any bank
PREPARATION:
Registers: .A = data
.X = bank (0-15)
.Y = index
Memory: setup indirect vector
setup CMPVEC ($2C8) pointer
Flags: none
Calls: none
RESULTS:
Registers: .X used
Memory: none
Flags: status valid
EXAMPLE:
LDA #$00 ;setup to verify $2000
STA $FA
LDA #$20
STA $FB
LDA #$FA
STA $2C3
LDA data
LDX #$01 ;in bank 1
LDY #$00
JSR $FF7A ;CMP ($FA,RAM 1),Y
BEQ same
CMPSTA enables applications to compare data to any other bank. After you
set up CMPVEC ($2C8), it calls GETCFG to convert the bank number and JMP's to
code in common (shared) RAM at $2BE which switches banks, compares the data,
restores your bank, and returns. When calling a nonsystem bank, the user should
take necessary precautions to ensure that interrupts (IRQ's and NMI's) will be
handled properly (or disabled beforehand).
PREPARATION:
Registers: none
Memory: none
Flags: none
Calls: none
THE COMMODORE 128 OPERATING SYSTEM 457
RESULTS:
Registers: none
Memory: none
Flags: none
EXAMPLE:
JSR $FF7D ;disp
;display following text
.BYTE "message"
.BYTE $00 ;terminator
JMP continue ;execution resumes here
PRIMM is a Kernal utility used to print (to the default output device) an
ASCII string which immediately follows the call. The string must be no longer than
255 characters and is terminated by a null ($00) character. It cannot contain any
embedded null characters. Because PRIMM uses the system stack to find the string
and a return address, you must not JMP to PRIMM. There must be a valid address
on the stack.
0 —» Keyboard
1 —» Cassette
2 -» RS-232
3 —* Screen (current)
4 —> Serial bus device:
4—7 usually printers
8-30 usually disks
Device number 31 should not be used. While it is specified to be a valid serial bus
address, when it is ORed with certain serial commands it results in a bad command,
hanging the bus and the serial drivers.
MEMORY MANAGEMENT IN
THE COMMODORE 128
BANK CONFIGURATION
0 RAM(O) only
1 RAM(l) only
2 RAM(2) only (same as 0)
3 RAM(3) only (same as 1)
4 Internal ROM,RAM(0),I/O
5 Internal ROM,RAM(1),I/O
6 Internal ROM,RAM(2),I/O (same as 4)
7 Internal ROM,RAM(3),I/O (same as 5)
8 External ROM,RAM(0),I/O
9 External ROM,RAM(1),I/O
10 External ROM,RAM(2),I/O (same as 8)
11 External ROM,RAM(3),I/O (same as 9)
12 Kernal and Internal ROM (LOW), RAM(0),I/O
13 Kernal and External ROM (LOW), RAM(0),I/O
14 Kernal and BASIC ROM, RAM (0), Character ROM
15 Kernal and BASIC ROM, RAM(O), I/O
When this occurs, some features of the MMU are no longer available to the
programmer. So before switching out I/O in the $D000-$DFFF range, make sure you
have made all the manipulations you need on the MMU (particularly, preselecting the
preconfiguration register values for the load configuration registers). See Figure 13-4 for
a graphic depiction of the way the MMU registers map into memory.
/ /
$FFQ4 LCRD - LORD C O N F I G U R R T I O N R E G D
$FF03 LCRC -/-- LOHD CONFIGURRTION R E G C
$FFQ2 LCRB -/-- LORD C O N F I G U R R T I O N R E G B
$FF01 LCRfl /-y L O R D C O N F I G U R R T I O N R E G R
~/-
$FFQQ CR •
/-- C O N F I G U R R T I O N
/ -
REGISTER
/ /
NOTE: Basic expects the LCR's and PCR's to be left alone. If you use
them to manage memory in your application, do not plan on using BASIC.
When I/O is switched out of (not present in) this range, the registers in the MMU
disappear from the memory map in the range $D500 through $D50B. The memory manage-
ment is then controlled through the MMU registers at locations $FF00 through $FF04. Any
write operation to an LCR ($FF01-$FF04) loads the corresponding PCR value (currently-
invisible to the 8502) into the CR. Reading an LCR returns the value stored in the
currently inaccessible PCR. The MMU registers ranging from $FF00 through $FF04 are
always present in the Commodore 128 memory, regardless of the memory configuration.
Bit 1 in the CR specifies how the microprocessor accesses the address range $4000
through $7FFF, called ROM LOW memory. If bit 1 is high, the microprocessor
accesses RAM in this range. If bit 1 is low (equal to 0), the microprocessor maps in the
BASIC LOW ROM in that range. Upon power-up or reset, this bit is set low, so
BASIC is available to the user as soon as the computer is turned on.
Bits 2 and 3 determine the type of memory that resides in the midrange of memory,
the address range $8000 through $BFFF. If both bits 2 and 3 are set high, RAM is
placed in this range. If bit 2 is high and 3 is low, INTERNAL FUNCTION ROM is
placed here. If bit 2 is low and 3 is high, EXTERNAL FUNCTION ROM appears. If
bits 2 and 3 are low, the BASIC HIGH ROM is placed here. Upon power-up or reset,
the MMU sets both bits 2 and 3 low, so BASIC is available to the user immediately.
Bits 4 and 5 work similarly to bits 2 and 3 and specify memory in the range $C000
through $FFFF, referred to as HIGH memory. If bits 4 and 5 are set high, RAM is
placed in this range. If bit 4 is high and 5 is low, INTERNAL FUNCTION ROM is
placed. If bit 4 is low and 5 is high, EXTERNAL FUNCTION ROM appears. If bits 4
and 5 are low, the Kernal and character ROMs are placed here. Upon power-up or reset,
bits 4 and 5 are set low, so the Kernal and character ROM are available to the user at once.
Note that bit 0 in the Configuration Register, the bit that switches in and out I/O in
address range $D000 through $DFFF, overrides the memory organization for bits 4 and 5.
If bit 0 is set high (1), the I/O Registers are not in place in the address range $D000
through $DFFF. Either the character ROM, internal or external function ROM or RAM
is located in this range, depending on the value of bits 4 and 5 of the configuration
register. If bit 0 in the Configuration Register is set low (0), the Input/Output registers
are present between $D000 through $DFFF, regardless of the value of bits 4 and 5 of the
configuration register. This means no matter what memory configuration is chosen
between $C000 and $FFFF with bits 4 and 5, if bit 0 is set low (0), the character ROM
(or whatever was originally in this address range) is overlaid by the I/O registers and
becomes unavailable to the microprocessor. This is why the character ROM and the I/O
registers are never available at the same time.
Finally, the last two bits of the MMU, 6 and 7, determine the RAM BANK
selection. For the base system of 128K, only bit 6 is significant; bit 7 is not imple-
mented. When bit 6 is high (1), RAM bank 1 is selected. When bit 6 is low (0), RAM
bank 0 is selected.
The 128K of RAM is organized into two 64K RAM banks. The microprocessor
only addresses 64K at a time, but since the two 64K RAM banks can be switched in and
out so quickly, the computer acts as though it addresses 128K at the same time. When
one RAM bank is being addressed by the microprocessor, the other bank stores
information to be processed once it is banked in. Portions of both banks can be shared in
memory at the same time. This is called Common RAM, and is discussed in the section
The RAM Configuration Register. RAM bank 0 is used typically for BASIC text area,
while RAM bank 1 is used for BASIC arrays and variable storage.
As indicated above, the MMU has a feature that allows a portion of RAM to be
common for the two RAM banks. The RAM Configuration Register controls the amount
of common RAM. This is discussed in detail later in this section under the description of
the RAM Configuration Register.
Figure 13-5 is a diagram of the Configuration Register, showing how the bits
control each memory organization.
corresponds to LCR B, and so on). The format for the Load Configuration and
Preconfiguration Registers is the same as for the Configuration Register. The four LCRs
and four PCRs are all initialized to zero.
$FFQU LCRD \/
$FF83 LCRC
$FF02 L£RB_
$FF01 LCRfl LORD C O N F I G U R H T I O N R E GR
$FF00 CR CONFIGURHTION REGISTER
$D50B VR
$D5QH PiH /
$D509 P1L
$D508 POH /
$D507 PGL /
$D5Q6 RCR /
$0505 MCR /
$0504 PCRD /
$D503 PCRC /
$D5Q2 PCRB /
$D501 / J
PCRR P R E C O N F I G U R R T I O N REGISTER
$0500 CR / CONFIGURRTION REGISTER
In this program segment, PART 1 initializes PCR A ($D501) with the value 14
($0E). which performs no immediate result. When PART 2 is encountered, the STA
instruction performs a write operation to location SFF01, which triggers the preconfiguration
mechanism and loads the value from PCR A into the Configuration Register. The store
instruction value is not significant; it must operate only on the address, and any store
instruction works. Once this instruction is executed, the memory management organiza-
tion is immediately changed according to the value in the appropriate PCR, in this case
PCR A ($D501).
The value 14 ($0E) loaded into PCR A selects the following memory organization:
set prior to switching out I/O in order for them to be of any service. Note that BASIC uses
the PCRs; if you alter them while BASIC is resident, you may obtain unpredictable results.
The MMU registers control the memory organization for RAM, BASIC, Kernal
and character ROM, internal and external function ROM, and I/O. The MMU has
additional registers that determine the mode (C128, C64 or CP/M) in which the
Commodore 128 operates, the common RAM configurations, and the location of pages
0 and 1. The registers in the MMU that control these operations are the Mode
Configuration Register (MCR), the RAM Configuration Register (RCR), and the
Page Pointers respectively. The following sections explain how these additional regis-
ters of the Memory Management Unit operate.
$D505 7 6 5 4 3 2 1 0
VALUE
BIT FUNCTION DESCRIPTION HIGH LOW
SOFFF
Hi Common
RAM Hi
$E000 - Common
RAM
scooo -
SOFFF -
Low
Common
$03FF RAM
Low Common
RAM
Bits 2 and 3 specify which portions of the two RAM banks are common, if at all. If
both bits are low (0), no RAM sharing occurs. If bit 2 is set high (1) and bit 3 is low (0),
THE COMMODORE 128 OPERATING SYSTEM 469
a section of the bottom of RAM bank 0 replaces the corresponding section of RAM bank
1 for all RAM address accesses. If bit 3 is set high (1) and bit 2 is set low (0), a section
of the top RAM bank 0 replaces the corresponding section of RAM bank 1 for all RAM
address accesses. If both bits 2 and 3 equal 1 (high), RAM is common to both the top
and bottom of the RAM banks. Upon power-up or reset, bits 2 and 3 are set to 0, and no
RAM is shared between banks. From a hardware standpoint, the 128K MMU selects the
common RAM by forcing the CASO enable line low and CASl enable line high for all
common memory accesses.
Bits 4 and 5 have no assigned function. They are reserved for future expansion.
Bits 6 and 7 in the RCR operate as a RAM bank pointer to tell the VIC chip which
portion of RAM to use. At the present time, bit 7 is ignored. It too is reserved for
future RAM expansion. When bit 6 is low (0) (driving CASO low), the VIC chip is told
to look in RAM bank 0. When bit 6 is set high (1) (driving CASl low), the VIC chip is
steered into RAM bank 1. Either setup allows the VIC chip RAM bank to be selected
from the microprocessor RAM bank independently.
When the microprocessor speed is increased to 2MHz, the VIC chip is disabled
and the 80-column (8563) chip takes over the video processing. The VIC chip is
affected by holding the AEC hardware line high. The disabling of the VIC chip is not
directly affected by the actions of the MMU.
Figure 13-9 summarizes the RAM Configuration Register activities.
$D506 -> 7 6 5 4 3 2 1 0
Bit 0 of the high byte page pointers corresponds to the RAM bank number
for any page 0 address access. Bit 0 controls the generation of the CASO hardware
control line if it is low and the CAS1 line if it is high, and bits 1 and 3 are
ignored.
To relocate page 0, perform a write operation on the high-byte 0 page pointer.
This is stored in the high-byte page pointer location and has no direct result until a write
operation is performed on the low-byte 0 page pointer. When this occurs, bits 0 through
7 of the low-byte page pointer correspond to the Translated Address lines TA8 through
TA15 for any 0 page address reference, which relocates the 0 page. Any subsequent 0
page address is relayed to the new page zero.
The page 1 pointer works the same way. Both pairs of pointers are initialized to 0
upon power-up, placing pages 0 and 1 in actual page 0 and page 1 locations.
It is important to note that memory addresses 0 and 1 are always available at those
absolute address references, regardless of whether pages zero or one are relocated.
The page zero low-byte pointer directly replaces the high-order address of zero
page (normally 00). When pages zero and one are directed to locations in RAM memory
above page one, the MMU translates the addresses back to the normal locations of pages
zero and one, effectively swapping those two pages of memory. This address translation
applies only to RAM; ROM and I/O registers are not back-translated. VIC chip
addresses are not translated back to their original memory locations, so you must ensure
that you do not place page zero or one in the address of the VIC chip. The ROM
appearing in these address ranges still overlays the RAM regardless of whether the RAM
is zero page, page one or any other page of RAM memory. If you need to use the
Kernal, the necessary variables required for the Kernal routine must be placed in
memory where the Kernal is in context, Machine Language Monitor bank 15 ($0F) for
example.
THE COMMODORE 128 OPERATING SYSTEM 471
Bit 0 of both high-byte page pointers (0 and 1) corresponds to the RAM bank
number for any address access in page zero or one. The page zero high byte (bit 0)
normally overrides the RAM bank set by the configuration register. However, if
common RAM (at the bottom of RAM bank 0) is specified, the high-byte pointer for
pages zero and one is ignored and pages zero and one appear in common RAM. Other-
wise, if common RAM is not allocated, pages zero and one appear where you specify
according to the contents of the page pointers. In other words, common RAM takes priority
over the page pointers, if common RAM is allocated by the RAM configuration register.
This feature of relocatable page zero and page one provides many benefits to the
programmer. This allows machine language programs to create several pages of zero
page variables or several different stacks. When you need to access the additional zero
page variables or extra 256 bytes of the stack, simply change the pointer to look at the
next page. This provides additional speed in your programs since you may use zero page
addressing for subsequent zero pages. You can even place zero page in screen memory
for extra fast writing to the screen. In addition, it gives you a way to implement deeper
levels of subroutines since you have a larger stack area. Remember, though, to leave
three bytes on the top of the stack for interrupt requests and servicing.
1. Log the cartridge I.D. into the Physical Address Table (PAT).
2. If the I.D. equals 1, call the cold start vector (which may RTS).
The first 9 bytes of the Commodore 128 auto start sequence are:
BYTE
where X is the hexadecimal digit " 8 " for $8000 or " C " for $C000.
There are four slots where cartridges (ROM's) may plug in (two internal, two
external). They must follow the sequence described above, whether they are internal or
external.
COMMODORE 64 MODE
The first 10 bytes of the Commodore 64 auto start sequence are:
BYTE
where X is the hexadecimal digit " 8 " for $8000 or " C " for $C000.
The recommended cartridge header for both operational modes is as follows:
SEI
JMP START
NOP
NOP
This header is recommended so that the interrupt disable status bit is set when
control is passed to the software in the cartridge ROM.
THE COMMODORE 128 OPERATING SYSTEM 473
The Commodore screen editor is among the easiest to use of all screen editors. As soon
as you turn on the computer, the screen editor is available to you. You don't have to call
any additional text editors. Using the keys for manipulating text, the screen editor gives
you more freedom than most other editors.
KEY FUNCTION
CHR$ KEYBOARD
VALUE CONTROL CHARACTER FUNCTION
Entries 17, 18, and 24 are table pointers, and are not callable routines. Entries 19-23
are considered indirect vectors, not true entry points.
This chapter has presented the Commodore 128 operating system. Chapter 16
provides information on CP/M on the Commodore 128 and Commodore 64 memory
maps.
14
CP/M 3.0
ON THE
COMMODORE 128
CP/M® is a microprocessor operating system produced by Digital Research, Inc. (DRI).
The version of CP/M used on the Commodore 128 is CP/M Plus® Version 3.0. In this
chapter, CP/M is generally referred to as CP/M 3.0, or simply CP/M.
This chapter summarizes the non-C128-dependent aspects of CP/M on the Commodore
128. For detailed information on C128-dependent CP/M 3.0, see Appendix K of this
guide. For detailed information on non-C128-dependent CP/M 3.0, see the Commodore-
produced volume that includes DRI's CP/M Plus User's Guide, Programmer's Guide,
and System Guide.
CP/M 3.0 on the Commodore 128 Personal Computer normally consists of the
following elements:
NOTE: CP/M can also be used with a 40-column monitor. To view all
80 columns of display, you must scroll the screen horizontally by press-
ing the C O N T R O L key and the appropriate C U R S O R key
(left or right).
CP/M 3.0 can also be used with the 1541 disk drive. In this case, only single-
sided GCR disks can be used, and the speed of operation will be approximately
one-tenth the speed achieved using the 1571 disk drive. (See the discussion of disk
formats later in this chapter for more details.)
CP/M 3.0 ON THE COMMODORE 128 479
COMMODORE ENHANCEMENTS
TO CP/M 3.0
Commodore has added a number of enhancements to CP/M 3.0. These enhancements
tailor the capabilities of the Commodore 128 to those of CP/M 3.0. They include such
things as a selectively displayed disk status line, a virtual disk drive, local/remote
handling of keyboard codes, programmable function keys (strings) and a number of
additional functions/characters that are assigned to various keys. These enhancements
are described at appropriate points in this chapter.
CP/M FILES
There are two types of CP/M files:
FILE SPECIFICATION
A CP/M file is identified by a file specification that can consist of up to four individual
elements, as follows:
EXAMPLE:
The following file specification contains all four possible elements, all separated by the
appropriate symbols:
A:DOCUMENT.LAW;FIREBIRD
USER NUMBER
CP/M 3.0 further identifies all files by assigning each one a user number, which can
range from 0 to 15. CP/M 3.0 assigns the user number to a file when the file is created.
User numbers allow you to separate your files into sixteen file groups.
Any user number other than 0 must precede the drive specifier. User 0, which is
the default user number, is not displayed in the prompt.
If a file resides in user 0 and is marked with a system file attributs, that file can
be accessed from any user number. Otherwise, a command can access only those files
that have the current user number.
CREATING A FILE
There are several ways to create a CP/M file, including:
RESERVED CHARACTERS
The characters in Table 14—1 are reserved characters in CP/M 3.0. Use only as indicated.
CHARACTER MEANING
< $ , »l> [] |
TAB, SPACE, \File specification delimiters
CARRIAGE RETURN]
: Drive delimiter in file specification
Filetype delimiter in file specification
; Password delimiter in file specification
; Comment delimiter at the beginning of a command line
*? Wildcard characters in an ambiguous file specification
< > & ! I \ H— Option list delimiters
[ ] Option list delimiters for global and local options
() Delimiters for multiple modifiers inside square
brackets for options that have modifiers
/$ Option delimiters in a command line
RESERVED FILETYPES
The filetypes defined in Table 14-2 are reserved for system use.
FILETYPE MEANING
CP/M COMMANDS
There are two types of commands in CP/M 3.0:
CP/M 3.0 has six built-in commands and over twenty transient utility commands.
Utilities can be added by purchasing CP/M 3.0-compatible application programs. In
addition, experienced programmers can write utilities that operate with CP/M 3.0.
BUILT-IN COMMANDS
Built-in commands are entered in the computer's memory when CP/M 3.0 is loaded,
and are always available for use, regardless of which disk is in which drive. Table 14—3
lists the Commodore 128 CP/M 3.0 built-in commands.
Some built-in commands have options that require support from a related transient
utility. The related transient utility command has the same name as the built-in com-
mand and has a filetype of COM.
COMMAND FUNCTION
DIR Displays filenames of all files in the directory except those marked with
the SYS attribute.
DIRSYS Displays filenames of files marked with the SYS (system) attribute in the
directory.
ERASE Erases a filename from the disk directory and releases the storage space
occupied by the file.
RENAME Renames a disk file.
TYPE Displays contents of an ASCII (TEXT) file at your screen.
USER Changes to a different user number.
To make backups of the CP/M system disks, use the FORMAT and PIP utility
programs. FORMAT formats the disk as either a C128 single-sided or C128 double-sided
diskette.
CP/M 3.0 O N THE COMMODORE 128 483
NAME FUNCTION
DEVICE Assigns logical CP/M devices to one or more physical devices, changes
device driver protocol and baud rates, or sets console screen size.
DIR Displays directory with files and their characteristics.
GET Temporarily gets console input from a disk file rather than the
keyboard.
FORMAT Initializes disk in GCR format for CP/M use.
HELP Displays information on how to use CP/M 3.0 commands.
INITDIR Initializes a disk directory to allow time and date stamping.
KEYFIG Allows redefinition of keys.
PATCH Displays or installs patches to CP/M system.
PIP Copies files and combines files.
PUT Temporarily directs printer or console output to a disk file.
RENAME Changes the name of a file, or a group of files, using wildcard characters.
SAVE Saves a program in memory to disk.
SET Sets file options including disk labels, file attributes, type of time and
TYPE Displays contents of text file (or group of files, if wildcard characters are
used) on screen (and printer if desired).
Table 14—4. Transient Utility Commands
CHARACTER MEANING
A>FORMAT
and follow the instructions given on the screen. When the copy disk is formatted,
type:
A>PIPE: = A:CPM + .SYS
A>PIPE:=A:CCP.COM
A>PIPB: =A:CPM+.SYS
When you have copied the CPM+ .SYS file, use the PIP command to copy the
CCP.COM file. This provides a copy of the operating system only. To copy all of
the files from the system disk, enter the following PIP command:
A>PIPB: = A:*.*
This PIP command copies all the files on the disk in drive A to the disk in drive B. PIP
displays the message COPYING, followed by each filename as the copy operation
proceeds. When PIP finishes copying, the system prompt (A>) is displayed.
GENERAL CP/M 3.0 SYSTEM LAYOUT
The Commodore 128 computer is a two-processor system, with the 8502 as the primary
processor and the Z80 as the secondary processor. The 8502 has the same instruction set
as the 6502. The Z80's primary function is to run CP/M 3.0. This section describes the
general requirements and methods for implementing CP/M 3.0 on the C128.
When CP/M is running, the normal functions of the C128 are not supported
(CP/M and BASIC cannot run at the same time). Also, CP/M does not directly support
all the display modes of the VIC chip. (An application could be written to run under
CP/M that could use additional graphics capabilities, but the application would have to
keep track of all the details, such as memory maps).
The BDOS contains a set of functions that the CCP and applications programs call
to perform disk and character input and output operations.
The BIOS contains a Jump Table with a set of thirty-three entry points that the
BDOS calls to perform hardware-dependent primitive functions, such as peripheral
device I/O. For example, CONIN is an entry point of the BIOS called by the BDOS to
read the next console input character.
Similarities exist between the BDOS functions and BIOS functions, particularly
for simple device I/O. For example, when a transient program makes a console output
function call to the BDOS, the BDOS makes a console output call to the BIOS. In the
case of disk I/O, however, this relationship is more complex. The BDOS file may make
many BIOS function calls to perform a single BDOS file I/O function. BDOS disk I/O is
in terms of 128-byte logical records. BIOS disk I/O is in terms of physical sectors and
tracks.
The System Control Block (SCB) is a 100-byte (decimal) CP/M 3.0 data structure
that resides in the BDOS system component. The BDOS and the BIOS communicate
through fields in the SCB. The SCB contains BDOS flags and data, CCP flags and data,
and other system information, such as console characteristics and the current date and
time. You can access some of the System Control Block fields from the BIOS.
Note that the SCB contains critical system parameters that reflect the current state
of the operating system. If a program modifies these parameters, the operating system
can crash. See Section 3 of the DRI CPIM Plus System Guide and the description of
BDOS Function 49 in the DRI CPIM Plus Programmer's Guide for more information on
the System Control Block.
Page zero is a region of memory that acts as an interface between transient
programs and the operating system. Page zero contains critical system parameters, includ-
ing the entry to the BDOS and entry to the BIOS Warm BOOT routine. At system
start-up, the BIOS initializes these two entry points in page zero. All linkage between
transient programs and the BDOS is restricted to the indirect linkage through page zero
All the entry points in the BIOS jump vector are included in the C128 CP/M 3.0
BIOS.
Each jump address in Table 14-6 corresponds to a particular subroutine that
performs a specific system operation. Note that two entry points are reserved for future
versions of CP/M, and one entry point is provided for the Commodore system functions.
Table 14-7 shows the five categories of system operations and the function calls
that accomplish these operations.
OPERATION FUNCTION
SYSTEM MEMORY
ORGANIZATION
Figure 14-1 shows the general memory organization of CP/M 3.0.
COMMON SYSTEM MEMORY
FOOO -
EOOO
DOOO -
COOO
AOOO -
9000
8000 -
T
7000 - P
A
6000
SOOO
4000
CCP BUFFER
3000
VIC SCREEN
8502 BIOS
2000 - 40-COLUMN -
1 LOGICAL SCREEN
1000 KEY TABLES
• ROM CODE
0000
The memory map is limited to 64K at any one point in time. However, the RAM
bank can be selected and then different ROM areas can overlay the RAM (with
bleed-through on write operations). The actual memory map is controlled by the MMU. The
MMU can be accessed in the I/O area (only when I/O is enabled in Z80 space) or
through the Load Configuration Register located at FF00 through FF04.
If the Load Configuration Registers are read, then the current value is read. A
write to FF00 changes the configuration after completing the current instruction. A
write to FF01 to FF04 updates the current configuration to the value stored in the
Preconfiguration Registers (the data written is not used). The MMU page pointers have
both a low (page) and a high (page) pointer. The high is written first and latched in the
MMU; the high value is updated from the latch when the low byte is written. The MMU
Control Registers are listed in Chapter 13.
DISK ORGANIZATION
CP/M 3.0 supports a number of different disk formats, including three Commodore
formats and a number of MFM formats. (MFM is the industry standard format.) The
first Commodore format is single-sided Commodore GCR, which is compatible with the
CP/M 2.2 that runs on the Commodore 64. With this format, the File Control Block
(FCB) is set up as 32 tracks of 17 sectors each and a track offset of 2. The BIOS routine
adds a 1 to tracks greater than 18 (this is the C64 directory track).
The second format, known as the C128 CP/M Plus disk format, is new and is also
single-sided. This format, which is also a GCR format, takes advantage of the full disk
capacity by setting up the FCB with 638 tracks of 1 sector each and a track offset of 0.
This has the effect of having CP/M set the track to the block number relative to
the beginning of the disk, with the sector always set to 0. The following algorithm is
used to convert the requested TRACK to a real track and sector number.
NOTE: This is not the usual way to handle a two-sided disk; however,
allocating the disk in this manner, the user with a 1541 may still be able
to read data written at the start of a two-sided disk.
The third Commodore format and all MFM formats require that the user have the
new 1571 disk drive. This disk drive supports both single- and double-sided diskettes
and both the Commodore GCR and industry standard MFM data coding formats.
The following table summarizes 1541/1571 disk drive capabilities with regard to
the various disk formats.
C64 GCR
v'
single-sided
C128 GCR
v'
single-sided
C128 GCR
V
double-sided
MFM
format
SECTOR
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
O B B B B B B B B B B B B B B B B B x x x x
1 B B B B B B B B B B B B B B B B B x x x x
2 x x x x
3 x x x x
4 x x x x
5 x x x x
6 x x x x
7 x x x x
8 x x x x
9 x x x x
10 x x x x
11 x x x x
12 x x x x
13 x x x x
14 x x x x
15 x x x x
16 x x x x
1 7 D D D D D D D D D D D D D D D D D D D
18 x x
19 x x
20 xx
21 xx
22 xx
23 xx
24 x
25 x
26 x
27 x
28 x
29 x
30
31
32
33
34
. Used by CP/M.
B Boot Sector (System).
D Directory Sector (Disk DOS).
x Not used by CP/M.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 B . . . . X
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 D
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
SKEW TABLE
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 00 17 13 09 05 01 18 14 10 06 02 19 15 11 07 03 20 16 12 08 04
2 00 04 08 12 16 01 05 09 13 17 02 06 10 14 18 03 07 11 15
3 00 11 04 15 08 01 12 05 16 09 02 13 06 17 10 03 14 07
4 00 07 14 04 11 01 08 15 05 12 02 09 16 06 13 03 10
When you insert one of these disks into the disk drive and try to access it, the system
senses the type of disk with respect to the number of bytes per sector and the number of
sectors per track. If the disk format is not unique, a box is displayed near the bottom-left
corner of the screen, showing which disk type you are accessing. The system requires
you to select the specific disk type by scrolling through the choices given in this
window.
NOTE: The choices are given one at a time; scroll through using the
right and left arrow keys. Press R E T U R N when the disk type that
you know is in the disk drive is displayed. Press C O N T R O L
R E T U R N to lock this disk format so that you will not need to
select the disk type each time you access the disk drive.
KEYBOARD SCANNING
The keyboard scan routine that is called to get a keyboard character returns the key code
of the pressed key, or a code indicating that no key is currently being pressed. The
keyboard scan code is also responsible for handling programmable keys, programmable
function keys, setting character and background colors, selecting MFM disk formats and
selecting current screen emulation type.
Any key on the keyboard can be defined to generate a code or function except the
following keys:
LEFT SHIFT
RIGHT SHIFT
SHIFT LOCK
G
CONTROL
RESTORE (8502 NMI)
40/80 DISPLAY
CAPS LOCK KEY
The keyboard recognizes the following special functions:
DEFINING A KEY
The KEYFIG utility program allows the user to define the code that a key can produce.
Each key has four modes of use for this function:
• Normal
• Alpha shift
• Shift
a Control
The alpha shift mode is toggled on/off by pressing the Commodore (O) key. When
this mode is turned on, a small white box appears on the bottom of the screen. The first
key that is pressed thereafter is the key to be defined. The current hex value assigned to
this key is displayed, and the user can then type the new hex code for the key, or abort
by typing a non-hex key. The following is a definition of the codes that can be assigned
to a key. See KEYFIG HELP for more information.
CP/M 3.0 ON THE COMMODORE 128 497
CODE FUNCTION
DEFINING A STRING
The DEFINE STRING function allows the user to assign more than one key code to a
single key. Any key that is typed in this mode is placed in the string. The user can see
the results of typing in a long box at the bottom of the screen. Note, however, that some
keys may not display what they are.
To allow the user control of entering data, five special edit functions are provided.
To access any of these functions, you first press the C O N T R O L and R I G H T
S H I F T keys. (This allows the user to enter any key into the buffer.)
The functions assigned to the five string edit keys are as follows:
KEY FUNCTION
ALT MODE
This function is a toggle (on/off) and is provided to allow the user to send 8-bit
codes to an application without the keyboard driver "eating" the code from 80h to
FFh.
UPDATING THE
40/80 COLUMN DISPLAY
As noted elsewhere in this book, there are two different display systems within
the C128. The first, which is controlled by the VIC chip, produces a 25-line by
40-column display, has many graphics modes of operation, and can be used with a
standard color (or black-and-white) television or color monitor. (See Chapters 8 and 9
for details.) The only VIC-controlled display mode used by CP/M is standard character
mode, with each character and screen background having up to sixteen colors.
The second display system available in C128 CP/M is controlled by the 8563
display controller. The display format of this controller is 25 lines by 80 columns, with
character color attributes. The VIC chip is a memory-mapped display, and the 8563 is
I/O-controlled. The two display subsystems are treated as two separate displays. CP/M
3.0 can assign one or both to the console output device.
Both displays are controlled by a common terminal emulation package, a Lear
Siegler ADM-31 (ADM-3A is a subset of this) driver. The terminal driver is divided
into two parts: terminal emulation and terminal functions. Terminal emulation is
handled by the Z80 BIOS, and the terminal function is handled primarily in the
Z80 ROM.
The following section shows the various terminal emulation protocols supported
by Commodore 128 CP/M.
NOTE: The following have been added to allow the system to emulate
the KayPro II display more closely.
CHARACTER
FUNCTION SEQUENCE
This concludes the summary explanation of the Commodore 128 CP/M system.
However, the Commodore 128 CP/M System includes many additional Commodore
128-dependent routines and functions that are performed by the Z80 microprocessor.
Since most of these routines, system calls and functions are tabular information, they are
covered in Appendix K. For information on any of the following topics, refer to
Appendix K.
See Appendix K for the Z80 memory map for CP/M on the Commodore 128.
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
KERNAL/EDITOR STORAGE
STATUS 0090 144 I/O OPERATION STATUS BYTE
STKEY 0091 145 STOP KEY FLAG
SVXT 0092 146 TAPE TEMPORARY
VERCK 0093 147 LOAD OR VERIFY FLAG
C3P0 0094 148 SERIAL BUFFERED CHAR FLAG
BSOUR 0095 149 CHAR BUFFER FOR SERIAL
SYNO 0096 150 CASSETTE SYNC #
XSAV 0097 151 TEMP FOR BASIN
LDTND 0098 152 INDEX TO LOGICAL FILE
DFLTN 0099 153 DEFAULT INPUT DEVICE #
DFLTO 009A 154 DEFAULT OUTPUT DEVICE #
PRTY 009B 155 CASSETTE PARITY
DPSW 009C 156 CASSETTE DIPOLE SWITCH
MSGFLG 009D 157 OS MESSAGE FLAG
PTR1 009E 158 CASSETTE ERROR PASS1
Tl TEMPORARY 1
PTR2 009F 159 CASSETTE ERROR PASS2
T2 TEMPORARY 2
TIME 00A0 160 24 HOUR CLOCK IN 1/60TH SECONDS
R2D2 00A3 163 SERIAL BUS USAGE
PCNTR CASSETTE
BSOUR1 00A4 164 TEMP USED BY SERIAL ROUTINE
FIRT
COUNT 00A5 165 TEMP USED BY SERIAL ROUTINE
CNTDN CASSETTE SYNC COUNTDOWN
BUFPT 00A6 166 CASSETTE BUFFER POINTER
THE COMMODORE 128 AND COMMODORE 64 MEMORY MAPS 507
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
KERNAL/EDITOR STORAGE
KERNAL/EDITOR STORAGE
BA 00C6 198 BANK FOR CURRENT LOAD/SAVE/
VERIFY OPERATION
FNBANK 00C7 199 BANK WHERE CURRENT FN IS
FOUND (AT 'FNADR')
RIBUF 00C8 200 RS-232 INPUT BUFFER POINTER
ROBUF 00CA 202 RS-232 OUTPUT BUFFER POINTER
GLOBAL SCREEN E
KEYTAB OOCC 204 KEYSCAN TABLE POINTER
IMPARM 00CE 206 PRIMM UTILITY STRING POINTER
NDX 00D0 208 INDEX TO KEYBOARD QUEUE
KYNDX 00D1 209 PENDING FUNCTION KEY FLAG
KEYIDX 00D2 210 INDEX INTO PENDING FUNCTION
KEY STRING
SHFLAG 00D3 211 KEYSCAN SHIFT KEY STATUS
SFDX 00D4 212 KEYSCAN CURRENT KEY INDEX
LSTX 00D5 213 KEYSCAN LAST KEY INDEX
CRSW 00D6 214 < C R > INPUT FLAG
MODE 00D7 215 40/80 COLUMN MODE FLAG
GRAPHM 00D8 216 TEXT/GRAPHIC MODE FLAG
CHAREN 00D9 217 RAM/ROM VIC CHARACTER FETCH
FLAG (BIT-2)
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
VECTORS
ESC_FN_VEC 02FC 764 VECTOR FOR ADDITIONAL
FUNCTION ROUTINES
BNKVEC 02FE 766 VECTOR FOR FUNCTION CART.
USERS
IERROR 0300 768 VECTOR FOR PRINT BASIC ERROR
(ERR IN .X)
IMAIN 0302 770 VECTOR TO MAIN (SYSTEM DIRECT
LOOP)
ICRNCH 0304 772 VECTOR TO CRUNCH
(TOKENIZATION ROUTINE)
IQPLOP 0306 774 VECTOR TO LIST BASIC TEXT
(CHAR LIST)
IGONE 0308 776 VECTOR TO GONE (BASIC CHAR
DISPATCH)
IEVAL 030A 778 VECTOR TO BASIC TOKEN
EVALUATION
IESCLK 030C 780 VECTOR TO ESCAPE-TOKEN
CRUNCH,
IESCPR 030E 782 ...LIST,
IESCEX 0310 784 ...AND EXECUTE.
HRQ 0314 788 RAM V E C T O R ^
CINV
IBRK 0316 790 BRK INSTR R A M VECTOR ?
CBINV
INMI 0318 792 NMI VECTOR
IOPEN 031A 794 KERNAL OPEN ROUTINE VECTOR
ICLOSE 031C 796 KERNAL CLOSE ROUTINE VECTOR
ICHKIN 031E 798 KERNAL CHKIN ROUTINE VECTOR
ICKOUT 0320 800 KERNAL CHKOUT ROUTINE
VECTOR
ICLRCH 0322 802 KERNAL CLRCHN ROUTINE
VECTOR
CI28 Memory Map (continued)
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
VECTORS
IBASIN 0324 804 KERNAL CHRIN ROUTINE VECTOR
IBSOUT 0326 806 KERNAL CHROUT ROUTINE
VECTOR
ISTOP 0328 808 KERNAL STOP ROUTINE VECTOR
IGETIN 032A 810 KERNAL GETIN ROUTINE VECTOR
ICLALL 032C 812 KERNAL CLALL ROUTINE VECTOR
EXMON 032E 814 MONITOR COMMAND VECTOR
ILOAD 0330 816 KERNAL LOAD ROUTINE VECTOR
ISAVE 0332 818 KERNAL SAVE ROUTINE VECTOR
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
DOS/VSP AREA
DOSSTR 1100 4352 DOS OUTPUT STR. BUF
48 BYTES TO BUILD DOS STRING
VWORK 1131 4401 GRAPHICS VARS
XYPOS 1131 4401
XPOS 1131 4401 CURRENT X POSITION
YPOS 1133 4403 CURRENT Y POSITION
XDEST 1135 4405 X-COORDINATE DESTINATION
YDEST 1137 4407 Y-COORDINATE DESTINATION
XYABS 1139 4409 LINE DRAWING VARIABLES
XABS 1139 4409
YABS 113B 4411
XYSGN 113D 4413
XSGN 113D 4413
YSGN 113F 4415
FCT 1141 4417
ERRVAL 1145 4421
LESSER 1147 4423
GREATR 1148 4424
ANGLE ROUTINE VARIABLES
ANGSGN 1149 4425 SIGN OF ANGLE
SINVAL 114A 4426 SINE OF VALUE OF ANGLE
THE COMMODORE 128 AND COMMODORE 64 MEMORY MAPS 517
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
DOS/VSP AREA
COSVAL 114C 4428 COSINE OF VALUE OF ANGLE
ANGCNT 114E 4430 TEMPS FOR ANGLE DISTANCE
ROUTINES
BASIC GENERAL I
XCENTR 1150 4432
YCENTR 1152 4434
XDIST1 1154 4436
YDIST1 1156 4438
XDIST2 1158 4440
YDIST2 115A 4442
DISEEND 115C 4444 PLACEHOLDER
COLCNT 115E 4446 CHAR'S COL. COUNTER
ROWCNT 115F 4447
STRCNT 1160 4448
BOX-DRAWING VARIABLES
XCORD1 1150 4432 POINT 1 X-COORD.
YCORD1 1152 4434 POINT 1 Y-COORD.
BOXANG 1154 4436 ROTATION ANGLE
XCOUNT 1156 4438
YCOUNT 1158 4440
BXLENG 115A 4442 LENGTH OF A SIDE
XCORD2 115C 4444
YCORD2 115E 4446
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
INTERRUPT VECTORS
INT_TRIP_FLAG 1276 4726
INT_ADR_LO 1279 4729
INT_ADR_HI 127C 4732
INTVAL 127F 4735
COLTYP 1280 4736
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
BASIC ENTRY
JMP HARD_RESET 4000 16384 COLD ENTRY
JMP SOFT_RESET 4003 16387 WARM ENTRY
JMP BASIC_IRQ 4006 16390 IRQ ENTRY
FORMAT CONVERSIONS
JMP AYINT AF00 44800 CONVERT F.P. TO INTEGER
JMP GIVAYF AF03 44803 CONVERT INTEGER TO F.P.
Basic Jump Table (continued)
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
FORMAT CONVERSIONS
JMP FOOT AF06 44806 CONVERT F.P. TO ASCII STRING
JMPVAL_1 AF09 44809 CONVERT ASCII STRING TO F.P.
JMP GETADR AFOC 44812 CONVERT F.P. TO AN ADDRESS
JMPFLOATC AFOF 44815 CONVERT ADDRESS TO F.P.
MATH FUNCTIONS
JMPFSUB AF12 44818 MEM - FACC
JMPFSUBT AF15 44821 ARG - FACC
JMP FADD AF18 44824 MEM + FACC
JMPFADDT AF1B 44827 ARG - FACC
JMP FMULT AF1E 44830 MEM * FACC
JMP FMULTT AF21 44833 ARG * FACC
JMPFDIV AF24 44836 MEM / FACC
JMPFDIVT AF27 44839 ARG / FACC
JMP LOG AF2A 44842 COMPUTE NATURAL LOG OF FACC
JMP INT AF2D 44845 PERFORM BASIC INT ON FACC
JMPSQR AF30 44848 COMPUTE SQUARE ROOT OF FACC
JMPNEGOP AF33 44851 NEGATE FACC
JMPFPWR AF36 44854 RAISE ARG TO THE MEM POWER
JMP FPWRT AF39 44857 RAISE ARG TO THE FACC POWER
JMPEXP AF3C 44860 COMPUTE EXP OF FACC
JMP COS AF3F 44863 COMPUTE COS OF FACC
JMP SIN AF42 44866 COMPUTE SIN OF FACC
JMP TAN AF45 44869 COMPUTE TAN OF FACC
JMPATN AF48 44872 COMPUTE ATN OF FACC
JMP ROUND AF4B 44875 ROUND FACC
JMPABS AF4E 44878 ABSOLUTE VALUE OF FACC
JMP SIGN AF51 44881 TEST SIGN OF FACC
JMP FCOMP AF54 44884 COMPARE FACC WITH MEM
JMP RND 0 AF57 44887 GENERATE RANDOM F.P. NUMBER
MOVEMENT
JMPCONUPK AF5A 44890 MOVE RAM MEM TO ARG
JMPROMUPK AF5D 44893 MOVE ROM MEM TO ARG
JMPMOVFRM AF60 44896 MOVE RAM MEM TO FACC
JMP MOVFM AF63 44899 MOVE ROM MEM TO FACC
JMP MOVMF AF66 44902 MOVE FACC TO MEM
JMPMOVFA AF69 44905 MOVE ARG TO FACC
JMP MOVAF AF6C 44908 MOVE FACC TO ARG
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
MONITOR ENTRY
JMP CALL B000 45056 MONITOR CALL ENTRY
JMP BREAK B003 45059 MONITOR BREAK ENTRY
JMP MONCMD B006 45062 MONITOR COMMAND PARSER
ENTRY
C000 49152 KERNAL (OR FUNCTION) ROM
$CO0O-$FFFF
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
7-6 UNUSED
5 RESET
4 MULTI-COLOR MODE
(1 = ENABLE)
3 SELECT 38/40 COLUMN
DISPLAY (1 =40 COLS)
2-0 SMOOTH SCROLL TO
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
SID REGISTERS
SIDREGO D400 54272 VOICE 1 FREQUENCY LO
SIDREG1 D401 54273 VOICE 1 FREQUENCY HI
SIDREG2 D402 54274 VOICE 1 PULSE WIDTH LO
SIDREG3 D403 54275 VOICE 1 PULSE WIDTH HI (0-15)
SIDREG4 D404 54276 VOICE 1 CONTROL REGISTER
7 NOISE (1 =
NOISE)
6 PULSE (1 =
PULSE)
5 SAW (1 =
SAWTOOTH)
4 TRI (1=
TRIANGLE)
3 TEST (1 =
DISABLE
OSCILLATOR)
2 RING (1 = RING MODULATE
OSC 1 WITH OSC
3 OUTPUT)
1 SYNC (1 = SYNCHRONIZE
OSC 1 WITH OSC
3 FREQ)
0 GATE (1 = START ATTACK/
DECAY/SUSTAIN
0 = START RELEASE)
SIDREG5 D405 54277 VOICE 1 ATTACK/DECAY
7-4 ATTACK (0-15)
3-0 DECAY (0-15)
CJ28 Memory Map (continued)
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
SID REGISTERS
SIDREG6 D406 54278 VOICE 1 SUSTAIN/RELEASE
7-4 SUSTAIN (0-15)
3-0 RELEASE (0-15)
SIDREG7 D407 54279 VOICE 2 FREQUENCY LO
SIDREG8 D408 54280 VOICE 2 FREQUENCY HI
SIDREG9 D409 54281 VOICE 2 PULSE WIDTH LO
SIDREG10 D40A 54282 VOICE 2 PULSE WIDTH HI (0-15)
SIDREG11 D40B 54283 VOICE 2 CONTROL REGISTER
7 NOISE(1 = NOISE)
6 PULSE(1 = PULSE)
5 SAW (1 = SAWTOOTH)
4 TRI (1 = TRIANGLE)
3 TEST (1 = DISABLE
OSCILLATOR)
2 RING (1 = RING MODULATE
OSC 2 WITH OSC
1 OUTPUT)
1 SYNC (1 = SYNCHRONIZE
OSC 2 WITH OSC
1FREQ)
0 GATE (1 = START ATTACK/
DECAY/SUSTAIN
0 = START RELEASE)
SIDREG12 D40C 54284 VOICE 2 ATTACK/DECAY
SUSTAIN (0-15)
3-0 RELEASE (0-15)
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
SID REGISTERS
SIDREG18 D412 54290 VOICE 3 CONTROL REGISTER
7 NOISE(1 = NOISE)
6 PULSE(1 = PULSE)
5 SAW (1 = SAWTOOTH)
4 TRI (1 = TRIANGLE)
3 TEST (1 = DISABLE
OSCILLATOR)
2 RING (1= RING MODULATE
OSC 3 WITH OSC
2 OUTPUT)
1 SYNC (1 = SYNCHRONIZE
OSC 3 WITH OSC
2 FREQ)
0 GATE (1 = START ATTACK/
DECAY/SUSTAIN
0 = START RELEASE)
SIDREG19 D413 54291 VOICE 3 ATTACK/DECAY
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
SID REGISTERS
SIDREG24 D418 54296 MODE/VOLUME
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
7-4
3-2 A19-A18 (USED IN 1MB
SYSTEM)
1-0 A17-A16 (256K SYSTEM)
7-0 A15-A8
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
0 PRAO VA14
1 PRA1 VA15
2 PRA2 RS232 DATA
OUTP1JT
3 PRA3 SERIAL ATN
OUTP!JT
4 PRA4 SERIAL CLK
OUTP1JT
5 PRA5 SERIAL DATA
OUTP1JT
6 PRA6 SERIAL CLK INPUT
7 PRA7 SERIAL DATA INPUT
C128 Memory Map (continued)
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
7 INTERRUPT
PENDING (1 = INT.
WAITING TO BE
SERVICED)
6 END OF BLOCK
(1= TRANSFER
COMPLETE)
5 FAULT (1 = BLOCK
VERIFY ERROR)
4 SIZE(0 = EXP.
MEMORY =
128K)
(1 = EXP.
MEMORY =
512K)
3-0 VERSION
7 EXECUTE
6 RESERVED
5 LOAD (1 = ENABLE
AUTO = LOAD)
4 $FF00 (1 = DISABLE $FF00
DECADES)
3 RESERVED
2 RESERVED
1-0 MODE (00 = TRANSFER
TKUiVl IN 1 CKfNAJL 1U
EXTERNAL,
01 = FROM EXT TO INT,
10 = SWAP, 11 = VERIFY)
DMA ADL DF02 57090 LSB OF INTERNAL (C128) ADDRESS
TO ACCESS
DMA ADH DF03 57091 MSB OF INTERNAL (C128) ADDRESS
TO ACCESS
DMA LO DF04 57092 LSB OF EXTERNAL EXPANSION
RAM TO ACCESS
DMA HI DF05 57093 MSB OF EXTERNAL EXPANSION
RAM TO ACCESS
DMA BNK DF06 57094 64K EXTERNAL RAM BANK
BITS ($DF06)
C128 Memory Map (continued)
MEMORY
ADDRESS HEXADECIMAL DECIMAL
LABEL ADDRESS ADDRESS DESCRIPTION
ADDRESS/NAME EXPLANATION
Init_Status. See also above. Lets system know what has been initialized and what
hasn't. Set to $00 by a reset but untouched by NMI.
System_Vector. Where the Kernal goes when it has to go somewhere. It's set to
BASIC cold at reset. BASIC itself sets it to BASIC warm after it has initialized.
The monitor respects it too.
System. Vector in RAM1 at SFFF8. Set at power-up to C128MODE, user may redirect
it to his code. Taken at reset always providing user with control (protection) from
reset.
HEX DECIMAL
LABEL ADDRESS LOCATION DESCRIPTION
HEX DECIMAL
LABEL ADDRESS LOCATION DESCRIPTION
HEX DECIMAL
LABEL ADDRESS LOCATION DESCRIPTION
HEX DECIMAL
LABEL ADDRESS LOCATION DESCRIPTION
1
HEX DECIMAL BITS DESCRIPTION
C64 compatibility
80-column display capability
Z80 coprocessor (CP/M version 3.0 (2 MHz))
2 MHz 8502 operation in 80-column mode
128K standard system RAM
48K standard system ROM
32K internal function ROM (optional)
32K external cartridge ROM
Fast serial disk drive interface
Full keyboard, ninety-two keys with C A P S LOCK key, HELP key
and separate cursor-control keys.
C128 HARDWARE SPECIFICATIONS 5S7
SYSTEM ARCHITECTURE
The C128 computer utilizes a shared bus structure similar to that of the C64. The shared
bus emulates dual-port RAM and ROM, which allows the character ROM, color RAM
and system RAM to be shared by both the microprocessor and the 8564 VIC video
controller, with no interference to each other. This requires that the RAM be fast enough
to supply valid data in half the time of a normal microprocessor machine cycle. Normal
sharing is controlled by a coprocessor that will enable or disable the processor during
alternate halves of the machine cycle.
The C128 system splits the address bus into shared and nonshared sections. All
normal 8502 I/O parts are on the nonshared address bus; the VIC chip and its associated
support chips are located on the shared bus. The VIC chip will gate processor addresses
onto the shared bus based upon its AEC control line. The data bus is common to both
sides of the address bus.
The processor interfaces with most of the system chips like a standard 6502 bus
cycle, where a machine cycle is equal to a clock cycle. This allows the use of 1 MHz
parts for a 1 MHz clock and eliminates the need to create valid address and data strobes,
as this information is now supplied by the edges of the master clock, $ 0 . Chip selects
for the I/O and system ROM are generated by the PLA that tracks the microprocessor
addresses during $ 1 .
For system RAM access, the row address is the address from the microproces-
sor, and the column address is the MMU output address (called the Translated Address).
The Translated Address outputs are calculated by considering the contents of the
MMU's Configuration Register and RAM Configuration Register. From these values,
the MMU generates either normal or translated addresses, a CAS selection. The
CAS-gating circuitry in the MMU enables either one of the two banks of 64K RAM in a
128K system. For VIC cycle access of RAM, the RAM bank is set independently of the
processor's bank. A write to ROM will result in the write "bleeding through" to RAM
underneath, while a read from ROM will always disable CAS in both banks. The MMU
allows custom arrangements of RAM for both banks 0 and 1.
Banking ROM is effected through the setting of bits in the Configuration Register
contained in the MMU and communicated to the PLA decoder. This allows Banking
Function ROM and any attached C128 cartridge to be included in the basic system
configuration.
The PLA generates chip selects for the color RAM, VIC control registers and
character ROM, which are used during processor and VIC cycles, as well as all chip
selects needed for the processor-only ROM and peripherals. To avoid bus contention,
the PLA must also generate CAS disable for any accesses to ROM or I/O devices.
The VIC chip generates the signals used to control Dynamic Memory and provides
macro-control functions such as RAM refresh. The VIC's primary purpose is to fetch
screen data from memory, using either cycle sharing or DMA, and create an NTSC- or
PAL-compatible video output that is applied to a monitor or modulated and applied to a
TV set. The C128 provides outputs for Composite, Chroma/Luminance and RF video
outputs from the VIC chip, as well as an edge-triggered light pen input latch going to
the VIC chip.
The output from the SID chip sound generator is buffered and applied directly to
an external amplifier, like that found in an external monitor, or modulated and repro-
duced in the user's television set. The SID chip also has an external input for mixing
another sound source.
The 8563 video control chip fetches screen data from a dedicated section of RAM
referred to as the display RAM and creates an RGBI (Red-Green-Blue-Intensity) output
for use with an external 80-column monitor. The 8563 also creates all needed signals for
dynamic refresh of its dedicated display RAM. The C128 provides RGBI and composite
monochrome outputs from the 8563 chip.
The cassette port is implemented using the zero page ports available on the 8502
and software control of hardware handshaking. The Commodore serial bus port is imple-
mented in a similar manner using a 6526 CIA for I/O. The serial bus works with
Commodore serial components, and in C64 mode is actually driven by the software
routines contained in the C64. The User Port is a multipurpose port comprising several
parallel port lines that support peripherals such as slow RS232, modem, etc. The
joystick ports are identical to those on the C64 and are implemented using a 6526 CIA
to read/write the port.
The video connector has composite video as well as separate chroma and lumi-
nance outputs for use with monitors. The 1701 and 1702 Commodore monitors interface
directly to this connector. The RF output jack supplies an RF signal compatible with the
regulations for TV interface devices and is switch selectable between channels 3 and 4.
Both NTSC and PAL television standards are supported. The RGBI connector and
signal are similar to the ones used by IBM, and are compatible with most monitors
supporting Type I RGBI. Additionally, a composite monochrome signal is available on
the RGBI connector and is generally compatible with NTSC (or PAL) composite. Audio
is available only from the 40-column video/audio connector.
SYSTEM SPECIFICATION
This section discusses various features and constraints of the C128 system. Included are
descriptions of the system and its configurations and limiting factors such as power,
loading and environment.
Figure 16-1 shows the C128 system.
Figure 16-1. The CI28 System
SYSTEM BUS ARCHITECTURE
The buses described include:
As mentioned above, the Z80 is not in direct communication with the processor
data bus, because of the need to adapt the Z80 to 8502 bus protocol. Note, however,
that every other device and every other bus (except two that will be explained later)
shares the processor data bus as a common data bus.
chip by driving the multiplexed address buses. It directly drives system ROM 4 address
line 12 to allow the Z80 ROM relocation. Finally, this bus becomes address lines 8
through 15 of the C64 compatible expansion port.
During a VIC cycle or a DMA, the MMU pulls TA12-TA15 high, while TA 8 -TA,,
are tri-stated. This allows the VIC chip to drive TA g -TA u as VIC addresses VA 8 -VA n .
During an external DMA cycle, the TA lines of the MMU are tri-stated, and the TA
bus, presumably driven by the DMA source, in turn drives the processor address bus
from A8 to A )5 . Thus allows the DMA source to access any peripheral chip except the
MMU. The action of the VIC during a VIC cycle is described below.
SYSTEM MEMORY
ORGANIZATION
This section describes the C128 memory system. Figure 16-2 is a detailed diagram of
the C128 Memory Map.
s, \
I/O and CHRRON
^ CD cc 5
CO t )
I 0 cc §
cj s:
s^*- CJ
s
1
CD c
a) 0
0 TS (I) XI
0 0
L c c.
a) 0
CJ -t-j CJ
X L ,
LU
I I
U_ O C3 CD CD CD CD CD CD CD CD OJ CD
U_ O CD CD O CD CD CD CD O CD O CD O
CD O CD CD CD CD CD 0 ^j* CD O
a c_) cr CO CO C\J —t
O CD CD
(ft Vt *& -W (A (ft (ft (ft
BK RflM
$800B_ $8O0B_ $BB0EL
$MBO0_ __ SHOOEL
This Mop i This Mop Used For This Mop Used For
Default M B Hop 60K of RRM and Full 614K RHM Bccea
1BK RfiM 1BK RflM I/O. Note that the 16K RHM
n
o
second setup removes
the character ROM.
3
$BBBB $0BB0
era
I
5 8K KERNHL ROM
LORRM
HIRHM
GRME
EXROM
=
=
-
=
0
1
1
X
8K KERNflL ROM
LORHM = 0
HIRBM = 1
GflME - 1
EXROM = 0
8K KERNRL ROM
HIRflM = 1
GflME - B
EXROM = B
$E80fL SEBOO SEBB0_ .
IK I/O UK I/O
$D0O6_ . $DQOB_ »OBO0_
UK RHM UK RRM (BUFFER) UK RRM (BUFFER)
$CBSB . JCOOtL...
BK ROM
(CARTRIDGE) 16K ROM
16K RfiM
(CRRTRIDGE)
*800EL 18 0 B 0.
1BK RRM
$1JBBB_ syoaa... _
This Mop Used For This Mop Used For This Mop Used For
Softlood Languages 8K ROM Plug-ins that 16K Plug-In ROMs
16K RRM do not require BRSiC thnt do not require
BBSIC
$800CL
CI28 RAM MEMORY ORGANIZATION
As shown in Figure 16-2, the RAM present in the system is actually composed of two
banks of 64K by 8 bytes of DRAM. The RAM is accessed by selecting one of the two 64K
banks, the maximum address range of the 8502 and Z80, according to the RAM banking
rules set in the RAM configuration register of the MMU. This area shown as RAM
represents what the processor would see if all ROM were disabled. Bank switching can
be accomplished in one of two ways.
The bank in use is a function of the value stored in the configuration register. A
store to this register will always take effect immediately. An indirect store to this
register, using programmed bank configuration values, can be accomplished by writing
to one of the indirect load registers known as LCRs, located in the $FF00 region of
memory. By writing to an LCR, the contents of its corresponding PCR (PreConfiguration
Register) will be latched into the configuration register. This allows the programmer to
set up four different preprogrammed configurations that allow each bank to be personal-
ized ahead of time; e.g., bank 1 as a data bank might be strictly a RAM bank with no
ROM or I/O enabled, while bank 0 as the system bank can have the system ROM and
I/O enabled by default. Additionally, reading any LCR will return the value of its
corresponding PCR.
When dealing with 64K banks of memory at once, it may be desirable to bank in
bank 1 but still retain the system RAM (stack, zero page, screen, etc.). The MMU has
provisions for what is referred to as common RAM. This RAM does not bank and is
programmable in size and position (top, bottom, or both) in the memory map. The size
is set by bits 0 and 1 in the RAM Configuration Register (RCR). If the value of the
bits is 0, IK will be common. Values of 1, 2 and 3 produce common areas of 4K, 8K
and 16K respectively. If bit 2 of the RCR is set, bottom memory is held common; if bit
3 is set, then top memory is common. In all cases, common RAM is physically located
in bank 0.
Zero page and page one can be located (or relocated) independently of the
RCR. When the processor accesses an address that falls within zero page or page
one, the MMU adds to the high-order processor address the contents of the P0
register pair or the PI register pair, respectively, and puts this new address on the
bus, including the extended addressing bit A16. RAM banking will occur as appropriate
to access the new address. Writes to the P0 and PI registers will be stored in pre-
latch until a write to the respective low byte page pointer occurs. This prevents a P xH
high byte page pointer from affecting the translated address until both high and low
bytes have been written. Common memory overrides the page pointers.
At the same time, the contents of the P0 and PI registers are applied to a digital
comparator, and a reverse substitution occurs if the address from the 8502 falls within
the page pointed to by the register. This results in a swapping of the zero page or page
one with the memory that it replaced. Swapping occurs only if the swapped area is
defined as RAM; i.e., system or function ROM must always be at its assigned addresses
and thus should not be back-substituted but of course will not cause contention of any
kind. Note that upon system reset, the pointers are set to true zero page and true page
one.
CI28 HARDWARE SPECIFICATIONS 567
NOTE: There are actually several memory modes that override parts of
the bank as selected here. These modes are mentioned below, and are
covered in detail in a later section.
For VIC-chip access, one bit in the MMU status register substitutes for extended
address line A 1 6 , selecting the proper CAS enable to make it possible to steer the VIC
to anywhere in the 128K range. Note that AEC is the mechanism the MMU uses to steer
a VIC space address; i.e., when AEC is low, a VIC access is assumed. This results in
the VIC bank being selected as well for an outside DMA, since this, too, will pull the
AEC line to the MMU low.
PERFORMANCE SPECIFICATIONS
POWER CONSUMPTION
Table 16-1 contains values for C128 power consumption, including various add-on
options.
PERIPHERALS
o o o o
Magic Desk 1 0.24 0.35 0 0 0 A
RS-232 1 0.07 0.10 0 0 0 A
Auto Modem 1 0 0 0.07 0.10 0 A
Cassette 1 0 0 0.28 0.40 0 A
PERIPHERAL TOTAL 4 0.31 0.45 0.35 0.50 0 0 A
C128 AND PERIPHERALS 2.94 4.28 0.38 0.55 0 0 A
5V 12V
Voltage 5.25 9.45 12.60 TOTAL
Power 22.47 5.20 0.00 27.67
BUS LOADING
Table 16-2 details AC and DC device loading for the C128 system. All capacitances
are in picofarads and currents are in microampheres.
Dev: DRAM ROM VIC 8563 4016 2332 LS MMU PLA 8502 Z80 4066 SID TOTAL
Signal TTL CIA LOADS
TA8-TA,5
# 1 1 1 1 2
I ... 10 2.5 ... 10 10 800 833
p 8 a A Q ^n ee
SA,,-SA7
# 1 1 1
I 10 10 400 420
c A S 1^ 27
Do-D7
# 2 5 1 1 1 1 — 1 1 3
I 20 50 2.5 2.5 400 2.5 — 2.5 — 0.1 7.5 488
c 40 8 8 15 8 — 8 8 24 129
R/W
# ... ... 1 1 ... ... 2 1 1 1 3
I 2.5 2.5 800 2.5 2.5 2.5 7.5 820
c 8 8 30 8 8 8 24 94
RES
# ... 1 ... 1 — 1 1 — 3
I ... ... 2.5 ... ... 2.5 — 2.5 2.5 — 7.5 18
c 8 8 — 8 8 — 24 56
1MHz
# 5 a
I 2000 7c 2008
c 75 99
ENVIRONHENTAL SPECIFICATIONS
The C128 is rated to operate at from 10 to 40 degrees Celsius (50 to 104 degrees
Fahrenheit) and at a noncondensing relative humidity of 5 to 95 percent.
CI28 HARDWARE SPECIFICATIONS 569
THE 8502
MICROPROCESSOR
GENERAL DESCRIPTION
The 8502 is an HMOSII Technology microprocessor, similar to the 6510/6502. It is the
normal operating processor used in C64 and C128 modes. Software-compatible with
the 6510, hence the 6502, the 8502 also features a zero page port used in memory
management and cassette implementation.
The 8502 is also specified for operation at 2 MHz. The 2 MHz operation is made
possible by removing the VIC from the system as a display chip. (The VIC chip is never
completely removed from the C128 system, as it continues to function as clock
generator and refresh controller.) What this refers to is that the VIC is removed as a display
chip and co-processor; thus the full clock cycle can be devoted to processor functioning
instead of sharing the cycle with the VIC.
The task of the video display processor is taken over by the 8563, which can
function without the need for bus sharing. Since the I/O devices, SID, etc., are rated at
1 MHz only, stretching of the 2 MHz clock is used to allow these parts to be accessed
directly by the 2 MHz processor and still keep throughput to a maximum.
The I/O devices are not affected by the 2 MHz operation, as they are still driven
by a 1 MHz source (as such, all timer operations remain unchanged), and clock
stretching is used only to synchronize the 2 MHz machine cycle to the 1 MHz <P0 high
time. The clock sources and clock-stretching capabilities are generated by the VIC chip.
ELECTRICAL SPECIFICATION
This section describes some of the electrical constraints and specifications of the system.
MAXIMUM RATINGS
Table 16-3 gives the absolute maximum ratings of the 8502 microprocessor.
ELECTRICAL CHARACTERISTICS
Table 16-4 gives the 8502's basic electrical specifications for minimum, typical and
worst-case operation, valid over the range of operation T.
CHARACTERISTIC SYMBOL MIN TYP MAX UNIT
SIGNAL DESCRIPTION
Below is a description of all the 8502 signals from a functional and electrical point of
view:
CLOCK (<I>0)—This is the dual speed system clock. Note that the input level required is
above worst-case TTL; thus, extra precautions must be taken when attempting to
drive this input from a standard TTL level input.
ADDRESS BUS (A o -A, 5 )—TTL output. Capable of driving 2 TTL loads at
130 pF.
DATA BUS (Do-D7)—Bidirectional bus for transferring data to and from the device
and the peripherals. The outputs are tri-state buffers capable of driving 2 standard
TTL loads at 130 pF.
CI28 HARDWARE SPECIFICATIONS 571
RESET—This input is used to reset or start the processor from a power down
condition. During the time that this line is held low, writing to or from the
processor is inhibited. When a positive edge is detected on the input, the
processor will immediately begin the reset sequence. After a system initialization
time of 6 cycles, the mask interrupt flag will be set and the processor will load the
program counter from the contents of memory locations $FFFC and $FFFD. This is
the start location for program control. After Vcc reaches 4.75 volts in a power up
routine, reset must be held low for at least 2 cycles. At this time the R/W line will
become valid.
INTERRUPT REQUEST (IRQ)—TTL input; requests that the processor initiate an
interrupt sequence. The processor will complete execution of the current instruc-
tion before recognizing the request. At that time, the interrupt mask in the Status
Code Register will be examined. If the interrupt mask is not set, the processor will
begin an interrupt sequence. The Program Counter and the Processor Status
Register will be stored on the stack and the interrupt disable flag is set so that no
other interrupts can occur. The processor will then load the program counter from
the memory locations $FFFE and $FFFF.
NON-MASKABLE INTERRUPT REQUEST (NMI)—TTL input, negative edge
sensitive request that the processor initiate an interrupt sequence. The processor
will complete execution of the current instruction before recognizing the request.
The Program Counter and the Processor Status Register will be stored on the
stack. The processor will then load the program counter from the memory
locations $FFFA and $FFFB. Since NMI is non-maskable, care must be taken to
insure that the NMI request will not result in system fatality.
ADDRESS ENABLE CONTROL (AEC)—The Address Bus is only valid when the
AEC line is high. When low, the address bus is in a high impedance state. This
allows DMA's for dual processor systems.
I/O PORT (P<r-P6)—Bidirectional port used for transferring data to and from the
processor directly. The Data Register is located at location $0001 and the Data
Direction Register is located at location $0000.
R/W—TTL level output from processor to control the direction of data transfer between
the processor and memory, peripherals, etc. This line is high for reading memory
and low for writing.
RDY—Ready. TTL level input, used to DMA the 8502. The processor operates
normally while RDY is high. When RDY makes a transition to the low state, the
processor will finish the operation it is on, and any subsequent operation if it
is a write cycle. On the next occurrence of read cycle the processor will halt,
making it possible to gain complete access to the system bus.
PROCESSOR TIMING
This section explores the timing considerations of the 8502 processor unit. Table 16-5 is
a processor timing chart. Figure 16-4 presents timing diagrams that show both general
timing and the particular method of clock stretching used in 2 MHz mode.
Electrical Characteristics Vcc = 5v ± 5%, Vss = Ov, T s = 0 °C to 70 °C
CLOCK STRETCHING
When running in 2 MHz mode, the processor clock sometimes must be stretched. This
is handled by the VIC chip, the processor and the PLA working together. When an I/O
operation is decoded during a 2 MHz cycle, the phase relationship between the 2 MHz
and 1 MHz clocks must be considered. If the 2 MHz access occurs during 1MHz $ 1 , the
access to a clocked I/O chip would be out of synchronization with the 1 MHz clock that
drives all I/O chips. Thus, during this phase relationship, /IOACC from the PLA signals
the VIC chip to extend the 2 MHz clock. Should the 2 MHz cycles take place during the
1 MHz <P2 cycle, no special attention is necessary.
C128 HARDWARE SPECIFICATIONS 573
1 MHz i - i
Clock
2 MH7
Clook 1
1 /U Hcc "^^m k ~-
V
>
r Ji i :
1 / !]
!
Proc _
Clncki
Note the speed implications of this. In 2 MHz mode, half the I/O access given will
occur at an effective speed of 1MHz.
Figure 16-5 is a diagram of the 8502 microprocessor pin configuration.
vuu
013119,
! Q
Rl it
n8
R3
Qf]\ /
vss
121
*
Z80 MICROPROCESSOR
HARDWARE SPECIFICATION
The Z80 microprocessor is used as a secondary processor in the C128 to run CP/M
based programs. Covered in this section is not only the operation of the Z80 as part of
CI28 HARDWARE SPECIFICATIONS S75
the C128 system, but some important electrical and timing specifications of the Z80. For
more information on Z80 bus interfacing, consult the Zilog Z80 Data Book.
SYSTEM DESCRIPTION
The Z80A, a 4MHz version of Zilog's standard Z80 processor, is included as an
alternate processor in the C128 system. This allows the C128 to run the CPM 3.0
operating system at an effective speed of 2 MHz. The Z80 is interfaced to the 8502 bus
interface and can access all the devices that the Z80 can access. The bus interface for the
Z80 (the most complex part of the Z80 implementation) is described in this section,
along with Z80's operation as a coprocessor in the C128 system.
NOTE: See the Signal Description section later in this chapter for
definitions of the signals mentioned in the following paragraphs.
BUS INTERFACE
Because a Z80 bus cycle is much different than a 65xx family bus cycle, a certain
amount of interfacing is required for a Z80 to control a 65xx-type bus. Since the Z80
has built-in bus arbitration control lines, it is possible to isolate the Z80 by tri-stating its
address lines. Thus, both the Z80 and the 8502 share common address lines.
The interfacing of the data lines is more complex. Because of the shared nature of
the bus during Z80 mode, the Z80 must be isolated from the bus during AEC low. Thus,
a tri-statable buffer must drive the processor bus during Z80 data writes. The reverse
situation occurs during a Z80 read—the Z80 must not read things that are going on
during AEC low; it must latch the data that was present during AEC high. Thus, a
transparent latch drives the data input to the Z80. It is gated by the Z80 read-enable
output, and latched when the 1 MHz clock is low. It will be seen that the Z80 actually
runs during AEC low, but that the data bus interfaces with it only during AEC high.
CONTROL INTERFACE
The Z80 control read-enable interfacing must provide useful clock pulses to the Z80,
and must tailor the Z80 and write-enable signals for the 8502-type bus protocol. The
Z80 clock is provided by the VIC chip, and is basically a 4MHz clock that occurs only
during AEC low, as seen in Figure 16-6. This ensures that the Z80 is clocked only when
it is actively on the bus. One additional consideration in clocking the Z80 is that while
all of the 8502 levels and most of the Z80 levels are TTL-compatible, the Z80 clock
input expects levels very close to 5 volts. For that reason, the output from the VIC chip
is processed by the 9-volt supply; thus, the 9-volt circuit must be operational for the
Z80, and the system, to function. The most common power-up failure for the C128 is a
blown 9-volt fuse.
)ys ie
PROCESSOR SWITCHING
It is important in normal operation for the Z80 and the 8502 to operate as coprocessors,
communicating with each other. Since only one processor may have the bus at any one
time, this is only serial coprocessing, not parallel coprocessing or multiprocessing. This
is important in several ways:
First, the C128 system must power-up with the Z80 as master processor. This is to
prevent the Z80 from accidentally accessing the bus when powering up. Thus, the Z80
is made master on power-up and can do anything it likes to the bus. Also, because the
Z80 can start-up certain C64 applications that would cause the 8502 to crash, the Z80 is
the logical choice as start-up processor. After some initializations, the Z80 starts-up the
8502 in either C128 or C64 mode, depending upon whether a cartridge is present, and
upon the type of cartridge, if one is present. The operating system also allows C64 mode
to be forced on power-up.
Second, processor switching allows the Z80 to access 8502 Kernal routines. For
standardized programs or for any I/O operation not supported in the Z80 BIOS, the Z80
can pass on the task of I/O to the 8502. Since the Z80 sees BIOS ROM where the 8502
sees its pages 0 through F, the Z80 can operate without fear of disrupting any 8502
pointers or the stack in RAM Bank 0. The Z80 ROM BIOS physically overlays that
critical section of RAM Bank 1.
The Z80 can receive a bus grant request from the MMU via /Z80EN, or from the
VIC chip via BA. Since the VIC control line is used for DMAs, the latter request is not
of immediate concern. The /Z80EN action, however, is important, since it is the
mechanism by which the two processors exchange control.
CI28 HARDWARE SPECIFICATIONS 577
When the /Z80EN line goes high, it triggers a Z80 /BUSRQ. The Z80 then relin-
quishes the bus by pulling /BUSACK low. This action drives the 8502 AEC high and
(providing VIC does not request a DMA) also drives the 8502 RDY line high, enabling
the 8502. To switch back, a low on the Z80 /BUSRQ will result in Z80 /BUSACK
going high, tri-stating and halting the 8502.
See Appendix K on CP/M for interchip communication details.
SIGNAL DESCRIPTION
The list below defines each Z80 signal. The Z80 pin configuration is shown in Figure 16-7.
Address Bus (Ao-A| 5 ): 16-bit tri-stating address bus. Used for 16-bit I/O cycles. This
allows up to 256 input or 256 output ports. During refresh time, the lower 7 bits
contain a valid refresh address. (This signal is not used in the C128 system.)
Data Bus (Do-D 7 ): Input/output bus capable of tri-stating; used for 8-bit exchanges
with memory and I/O devices.
Machine Cycle One (/M|): Output, active low. This signal indicates that the current
machine cycle is the operation code fetch of an instruction execution. During
execution of a two-byte opcode, /Mi is generated, as each byte is fetched. /Mi also
occurs with an input/output request (/IORQ) to indicate an interrupt acknowledge
cycle. The M) line is used to disable the I/O decoder during an interrupt acknowl-
edge cycle (See Input/Output Request).
Memory Request (/MREQ): Active low, tri-state output that indicates that the address
bus holds a valid address for a memory read or write operation.
Input/Output Request (/INRQ): Active low, tri-state output. The /INRQ signal
indicates that the lower half of the address bus holds a valid address for an I/O
read or write operation. An /INRQ signal is also generated with a /Mi signal when
an interrupt is being acknowledged to indicate that an interrupt response vector
can be placed on the data bus. An interrupt can acknowledge during /Mi; I/O
operations never occur during /Mj.
Memory Read (/RD): Active low, tri-state output. /RD indicates that the CPU wants
to read data from memory or from an I/O device. This signal is generally used to
gate-read data onto the data bus.
Memory Write (/WR): Active low tri-state output. /WR indicates that the data bus
holds valid data to be processed by memory or by an I/O device.
Refresh (/RFSH): Active low output used to indicate that the address bus holds a
refresh address in its lower 7 bits. Thus, the current /MREQ signal should be used
to do a refresh read to all dynamic memories not refreshed from an alternate source.
A7 is set to 0 and the upper 8 bits contain the I register at this time.
Halt State (/HALT): Active low output, indicating that the Z80 has executed a halt
instruction and is awaiting some kind of interrupt before execution can continue.
While in the halt state, the Z80 continuously executes NOPs to continue refresh
activity.
Wait (/WAIT): Active low input, used to drive the Z80 into wait states. As long as this
signal is low, the Z80 executes wait states; thus, this signal can be used to access
slow memory and I/O devices.
NOTE: While the Z80 is in either a wait state or a bus acknowledge
(/BUSAK) state, a dynamic memory refresh cannot be performed. See Bus
Acknowledge.
Interrupt Request (/INT): Active low input, driven by external devices. If the
interrupt flag IFF is enabled and the bus request (/BUSRQ) line is not active, the
processor honors the request interrupt at the end of the current instruction. When
the Z80 acknowledges an interrupt, it generates an interrupt acknowledge signal
(/INRQ during /MO at the beginning of the next instruction cycle. There are three
different modes of response to a given interrupt. See Bus Request.
Non-Maskable Interrupt (/NMI): Active low input. This interrupt is edge-triggered
and cannot be masked against. It is always recognized at the end of the current
instruction, forcing the Z80 to restart at location $0066. The program counter is
automatically saved in the stack to allow a return from the interrupt program. Note
that continuous cycles can delay an /NMI by preventing the end of the current
cycle, and that /BUSRQ will override /NMI.
Reset (/RESET): Active low input that forces the program counter to zero and
initializes the Z80, which will set interrupt mode 0, disable interrupts, and set
register I and R to 0. During /RESET, the address and data buses go tri-state and
all other signals go inactive.
Bus Request (/BUSRQ): Active low input that requests the CPU address, data and
tri-statable output control signals to go tri-state for sharing and DMA's. The lines
go tri-state upon termination of the current machine cycle.
Bus Acknowledge (/BUSAK): Active low output, used to indicate to any device
taking over the bus that the Z80 has gone into tri-state and the bus has been
granted.
Clock (4>): Single phase system clock.
C128 HARDWARE SPECIFICATIONS 579
/MEMREQ
/ H~ ^ -
ELECTRICAL SPECIFICATIONS
ABSOLUTE MAXIMUM RATINGS
Table 16-6 gives the absolute maximum temperature, voltage and power dissipation
ratings for the Z80. Permanent damage is likely to occur if these ratings are exceeded.
PARAMETER SYMBOL RANGE UNITS
DC OPERATING CHARACTERISTICS
Table 16-7 shows the maximum DC operating ratings for the Z80. Except as noted,
these ratings apply over the full rated temperature and voltage ranges.
CAPACITANCE
The line capacitance values for the Z80 are given in Table 16-8. All measurements are
at T = 25 degrees, F = 1 MHz.
Clock Capacitance C§ 35 pF
Input Capacitance C(n 5 pF
Output Capacitance Cout 10 pF
Table 16-8. Z80 Capacitance Values
CI28 HARDWARE SPECIFICATIONS 581
THE PROGRAMMED
LOGIC ARRAY (PLA)
The 8721 C128 PLA is a programmed version of the Commodore 48 Pin Programmable
Logic Array (Commodore Part #315011). It provides all the chip selects and other
decoded signals that are necessary for the C64, along with a number of such signals
new in the C128 system. Figure 16-8 shows the PLA chip.
The PLA does a number of things vital to the operation of the C128, including:
All ROM selects (Kernal, BASIC, function, external) in all operating modes.
VIC chip select.
Color RAM chip select.
Character RAM chip select.
Write enable to color RAM.
Latched write enable to DRAMs.
Z80 select decoding.
Z80 I/O decoding, for Z80 I/O cycle and Z80 memory mapping.
Data bus direction signal.
I/O group chip select (includes I/O-l, I/O-2, CIA-1, CIA-2, SID, 8563).
I/O access signal indicating an I/O operation is occurring.
CAS ENaBle for DRAM enable.
OTHER FUNCTIONS
The PLA performs a variety of functions other than chip selects. It creates the write
enable strobes for both DRAM and Color RAM. In C128 mode, the C64 control lines
(HIRAM, LORAM and CHAREN) are not needed, since the MMU controls the more
sophisticated C128 method of banking. Thus, these lines are used to extend the
functionality of the C128 at little or no additional cost in hardware. The CHAREN line is
used in C128 mode to turn the Character ROM on and off in the VIC bank selected; in
C128 mode the ROM can appear or disappear in any VIC bank.
The second of the new functions uses LORAM and HIRAM to select one of two
Color RAM banks. The level of LORAM selects the bank that will be seen during
processor time; the level of HIRAM selects the bank that will be seen during VIC time.
Thus, a program can swap between two full-color pictures very cleanly, or the processor
can modify one full-color picture while displaying another.
>2_JR1
>A_JR1
mi / 2 8Q TO
i GNC
THE MEMORY
MANAGEMENT UNIT (MMU)
The MMU is designed to allow complex control of the C128 system memory resources.
Because of the way it handles all the standard C64 modes of operation, it is completely
compatible with the C64. Additionally, it controls the management of particular C128
modes including the Z80 mode. The MMU's features include:
PHYSICAL DESCRIPTION
Many of the MMU input and output signals have been discussed informally so far.
This section contains descriptions of the MMU as a physial 48-pin device, includ-
ing a description of all pin requirements, input and output signals, and electrical
requirements.
PIN REQUIREMENTS
Table 16-9 lists the required MMU pins, indicating the number in each signal category
and the total number.
SIGNAL NAMES DESCRIPTION NUMBER OF PINS
PIN DESCRIPTION
The following comprises a signal-by-signal description of the MMU input and output
signals. Figure 16-9 shows the MMU pin configuration. Included here are any available
bond options.
The MMU input signals are:
bus and VAj 6 have the processor bus, and no pointer or BIOS translation takes
place. This signal occupies pin 16.
• MUX: The memory multiplex signal, used to clock various sections of the
MMU. It is located at pin 17.
m
Vdd: System + 5 Vdc supply, connected at pin 1.
• Vss: System Ground, connected at pin 34.
The following represents the MMU bidirectional lines. Some of the port bits
detailed here are left for future expansion in a one-directional sense.
The following list represents the MMU output signals, their physical locations on
the MMU and their logical levels if applicable.
• TAg~-TA15: Translated address outputs. Tri-stated for VIC cycles during AEC,
they provide translated physical addresses for use on the Multiplexed Address
Bus and the Shared Static Bus. TA12 to TA, 5 are each defined to have an
internal, depletion mode pull-up with an equivalent resistance of 3.3KJQ. TAg
to T A n each go tri-state during VIC time (AEC low). These are located on the
MMU at pins 10 to 3.
• MSo-MSp Also called ROMBANK0 and ROMBANK1, these outputs control
ROM banking for all ROM slots. They are located on pins 15 and 14. These
lines are used to decode ROM bank selection for any ROM access in C128
mode. If they are both low, a system ROM has been selected. If MSj alone is
high, then a built-in function ROM has been selected. If MS0 alone is high,
then an external function ROM has been selected. Finally, if both are high, the
RAM that occupies the particular slot has been selected. In C64 mode, the
PLA completely ignores these lines.
• I/O: This output is used to select memory mapped I/O in C128 mode. It is on
pin 13, and is also known as MS2. In C128 mode, this line always reflects the
polarity of the I/O bit. It is ignored by the PLA in C64 mode, and remains
high throughout C64 mode.
• C128: This output directs the system to act in either C128 or C64 mode. It is
located on pin 47, and is also known at MS3. It goes low to indicate C64
mode, high for C128 mode.
• /Z80EN: This output is used to enable the Z80 processor and disable the
normal operation of the 8502 processor. It can be found at pin 43. It goes low
to indicate Z80 mode, high for all other modes.
• / C A S Q - C A S , : CAS enables to control RAM banking. CAS 0 enables the first
bank of 64K; CAS] enables the second bank of 64K. These are pins 12 and
11, respectively.
VDD
M !V ' i 7
lu A i £
30 | p i Lj.
>dR13
^IEJ H i D /Z8GENUii
ssiqq
06/7
P U/ S
181
o ! RE
MM
0
42
1
H7
D6
D5
o 39 ] D 4
38! n^
15JD0
/CRS1
ly/EXROM RE5E~
FSDIRlii4
VSS
GENERAL DESCRIPTION
The 8564 VIC chip is similar to the 6567 VIC chip, yet it supports many new
features unique to the C128 system requirements. It will run on a single 5V DC supply,
and is packaged in a 48-pin dual-in-line package.
As these functions exist in the previous VIC, their description is purposely kept to
a minimum here, while the VIC programming information is contained in Chapter 8. The
new functions, however, are described in detail below.
retaining C64 keyboard compatibility in C64 mode. In this register (register 53295
($D02F)), bits 0-2 are directly reflected in output lines Ko to K2, while bits 3-7 are
unused, returning high when read.
2 MHz OPERATION
The VIC chip contains a register that allows the C128 system to operate at 2 MHz
instead of the standard 1 MHz speed of the C64. This operating speed, however,
disallows the use of the VIC chip as a display processor. This is bit 0 in 53296 ($D030),
and setting this bit enables 2 MHz mode. During 2 MHz operations, the VIC is disabled
as a video processor. The processor spends the full time cycle on the bus, while VIC is
responsible only for dynamic RAM refresh. Clearing this bit will bring back 1 MHz
operation and allow the use of the VIC as a video display chip. During refresh and I/O
access, the system clock is forced to 1 MHz regardless of the setting of this bit.
The 2MHz speed is available in C64 mode by setting bit 0 of location 53296
($D030). Prior to this, blank the screen by clearing bit 4 of location 53265 ($D011).
You can then process at 2MHz (to perform number crunching, for example); however,
you will have no visible VIC screen. To return, set bit 4 of 53265 ($D011) and clear bit
Oof 53296 ($D030).
Bit 1 of this register contains a chip-testing facility. For normal operation, this bit
must be clear. None of the other bits in this register is connected.
SIGNAL DESCRIPTION
The VIC chip is mounted in a 48-pin dual-in-line package. The following lists describe
the electrical signals that it generates.
The signals used in the system interface are:
• D 0 -D 7 : These are the bidirectional data bus signals. They are for communica-
tion between the VIC and the processor, and can be accessed only during AEC
high. They occupy pins 7 through 1 and 47, respectively.
• Dg-Dn: These are the extended data bus signals. They are used for VIC
communication with the color RAM. They occupy pins 47 to 43 in order.
• /CS: Chip select, used by the processor to select the VIC chip. Found at pin 13.
• R/W: Standard 8502 bus read/write for interface between the processor and
the various VIC registers. Pin 14.
•A 0 -A 6 : Multiplexed address lines, pins 32 through 38. During row address
time, Ao-Ag are driven on A o -A 5 . During column address time, A 8 -A 13 are
driven on A o - A5 and A6 is held at 1. During a processor read or write, A o -A 5
serve as address inputs that latch on the low edge or /RAS.
a A-A J0 : Static address lines, pins 39 through 42, These address lines are used
for non-multiplexed VIC memory accesses, such as to character ROM and
color RAM.
• 1MHz: The 1 MHz system clock, pin 18. All system bus activity is referenced
to this clock.
• 2MHz: This is the changing system clock, which will be either 1 MHz or 2
MHz. If the 2 MHz bit is clear, no VIC or external DMA is taking place, and
no I/O operation is occurring, the clock will be 2 MHz; otherwise it will be 1
MHz. Found at pin 23.
• Z80 Phi: The special 4 MHz Z80 clock, pin 25.
• /IOACC: From PLA, indicating an I/O chip access for clock stretching. Pin 22
of the VIC.
B /RAS: Row address strobe for DRAMs, pin 19.
• /CAS: Column address strobe for DRAMs, pin 20.
• MUX: Address multiplexing control for DRAMs, pin 21.
a /IRQ: Interrupt output, used to signal one of the various internal interrupt
sources has taken place. Requires a pull-up, found at pin 8 on the chip.
a AEC: Address Enable Control, high for processor enable on the shared bus,
low for VIC cycle and VIC or external DMA. Found at pin 12 of the VIC.
H BA: Bus Available signal, used to DMA processor. Pin 10.
• K0-K2: Extended keyboard strobe bits, pins 26 to 28.
• LP: Edge triggered latch for light pen input. Pin 9 of the VIC chip.
The signals comprised in the video interface, i.e., all the signals required to create
a color video image, are:
• PH IN: The fundamental shift rate clock, also called the dot clock. Used as the
reference for all system clocks. Located at pin 30.
• PH CL: The color clock, used to derive the chroma signal. Pin 29.
a SYNC: Output containing composite sync information, video data and lumi-
nance information. Requires a pull-up, pin 17.
• COLOR: Output containing all color-based video information. Open source
output, should be tied through a resistor to ground. Found at pin 16.
ELECTRICAL SPECIFICATION
Tables 16-12 and 16-13 specify the electrical operation of the VIC chip in its new form.
These specs include absolute maximum ratings and maximum operating conditions.
CI28 HARDWARE SPECIFICATIONS 591
Below is a list of the maximum operating specifications for the new VIC chip:
RASTER REGISTER
The Raster Register is a dual function register. A read of the raster register 53266 ($D012)
returns the lower 8 bits of the current raster position [the MSB-RC8 is located in register
53265 ($D011)]. A write to the raster bits (including RC8) is latched for use in an internal
raster compare. When the current raster matches the written value, the raster interrupt
latch is set. The raster register should be interrogated to prevent display flicker by
delaying display changes to occur outside the visible area. The visible area of the
display is from raster 51 to raster 251 ($033-$0FB).
INTERRUPT REGISTER
The Interrupt Register indicates the status of the four sources of interrupts. An interrupt
latch in register 53273 ($D019) is set to 1 when an interrupt source has generated an
interrupt request.
LATCH ENABLE
BIT BIT WHEN SET
To enable an interrupt request to set the IRQ/ output to 0, the corresponding interrupt
enable bit in register 53274 ($D01A) must be set to " 1 " . Once an interrupt latch has
been set, the latch may be cleared only by writing a " 1 " to the associated bit in the
interrupt register. This feature allows selective handling of video interrupts without
software storing the active interrupts.
SCREEN BLANKING
The display screen can be blanked by clearing the BLNK bit (bit 4) in register 53265
($D011) to zero (0). When the screen is blanked, the entire screen displays the exterior
color specified by register 53280 ($D020). When blanking is enabled, only transparent
(phase 1) memory accesses are required, permitting full processor utilization of the
system bus. However, sprite data will be accessed if the sprites are not also disabled.
0 24 rows 0 38 columns
1 25 rows 1 40 columns
The RSEL bit (bit 3) is in register 53265 ($D011), and the CSEL bit (bit 3) is in
register 53270 ($D016). For standard display, the larger display window is normally
used, while the smaller display window is normally used in conjunction with scrolling.
SCROLLING
The display data may be scrolled up to one character in both the horizontal and vertical
directions. When used in conjunction with the smaller display window (above), scrolling
can be used to create a smooth panning motion of display data while updating the
system memory only when a new character row (or column) is required. Scrolling is
also used for centering a display within the border. An example of horizontal smooth
scrolling is found in Chapter 8.
LIGHT PEN
The light pen input latches the current screen position into a pair of registers (LPX,
LPY) on a low-going edge. Since the X position is defined by a 9-bit counter (53267
($D013)), resolution to 2 horizontal dots is provided. Similarly, the Y position is latched
in register 53268 ($D014) with 8 bits providing unique raster resolution within the
visible display. The light pen latch may be triggered only once per frame, and subse-
quent triggers within the same frame will have no effect.
For more information on programming the VIC (8564) chip, see Chapter 8, The
Power Behind Commodore 128 Graphics.
Figure 16-10. The 8564 VIC Chip
CI28 HARDWARE SPECIFICATIONS 595
THE 8563
VIDEO CONTROLLER
The 8563 is a HMOSII technology custom 80-column, color video display controller.
The 8563 supplies all necessary signals to interface directly to 16K of DRAM, including
refresh, and generated RGBI for use with an external RGBI monitor. For more informa-
tion on the 8563 video controller, see Chapter 10, Programming the 80-Column (8563) Chip.
GENERAL DESCRIPTION
The 8563 is a text display chip designed to implement an 80-column display system with
a minimum of parts and cost. The chip contains the high-speed pixel frequency logic
necessary for 80-column RGBI video. It can drive loads directly, though some buffering
is desirable in most real-world applications. The chip can address up to 64K of DRAM
for character font, character pointer, and attribute information. The chip provides RAS,
CAS, write enable, address, data and refresh for its subordinate DRAMs. A program-
mable bit selects either two 4416 DRAMs (16K total) or eight 4164 DRAMs (64K total)
for the display RAM. The C128 system uses the 4416 DRAMs.
EXTERNAL REGISTERS
The 8563, which sits at $D600 in the C128, appears to the user as a device consisting of
only two registers. These two registers are indirect registers that must be programmed to
access the internal set of thirty-seven programming registers. The first register, located
at $D600, is called the Address Register. Bit 7 of $D600 is the Update Ready Status Bit.
When written to, the five least significant bits convey the address of an internal register
to access in some way. On a read of this register, a status byte is returned. Bit 7 of this
register is low while display memory is being updated, and goes high when ready for the
next operation. The sixth bit will return low for an invalid light pen register condition and
high for a valid light pen address. The final register indicates with a low that the scan is
not in vertical blanking, and with a high that it is in vertical blanking.
The other register is the Data Register. It can be read from and written to. Its
purpose is to write data to the internal register selected by the address register. All
internal registers can be read from and written to through this register, though not all of
them are a full 8 bits wide.
INTERNAL REGISTERS
There are thirty-seven internal registers in the 8563, used for a variety of operations.
They fall into two basic groups: setup registers and display registers. Setup registers are
used to define internal counts for proper video display. By varying these registers, the
user can configure the 8563 for NTSC, PAL or other video standards.
The display registers are used to define and manipulate characters on the screen.
Once a character set has been downloaded to this chip, it is possible to display
80-column text in 4-bit digital color. There are also block movement commands that
remove the time overhead needed to load large amounts of data to the chip through the
two levels of indirection. Figure 16-11 is a display of the 8563 internal register map.
Figure 16-11. 8S63 Register Map
SIGNAL DESCRIPTION
There are many different signals involved with the 8563 chip, but they can be divided
into three general categories. The CPU interface signals serve as an interface to the 8502
bus. The local bus management signals serve to maintain the local memory bus. Finally,
the video interface signals are the signals that are necessary to provide an RGBI image
on an RGBI monitor. The 8563 pin configuration is shown in Figure 16-12.
• /RS: Register Select input. A high allows reads and writes to the selected data
register. A low allows reads of the status register and writes to the address
register. In the system, this line is tied to AO. It is located at pin 8.
• R/W: This line controls the data direction for the data bus. This is a typical
8502 control signal. Found at pin 9.
• INIT: Active low input for clearing internal control latches, allowing the chip
to begin operation following initial power-on. Connect to /RES in the C128,
at pin 23.
• DISPEN: Display Enable output signal, unused in the C128. Found at pin 19.
• RES: This input initializes all internal scan counters, but not control registers.
It is not actively used in the C128 circuit, and is not found at pin 22.
• TST: Pin used for testing only, tied to ground in the C128. Located at pin 24
of the chip.
• DDo-DD7: Bidirectional local display DRAM data bus, comprising pins 35-36
and 38-42.
• DA0-DA7: Local display DRAM multiplexed address bus. Takes up pins
26-33.
• DR/W: Local display DRAM Read/Write, pin 21.
• /RAS: Row Address Strobe for local DRAM, pin 47.
• /CAS: Column Address Strobe for local DRAM, pin 48.
• DCLK: Video Dot Clock, determines the pixel width and is used internally as
the timing basis for all synchronized signals, such as character clock and
DRAM timing. Found at pin 2.
• CCLK: The character clock output, unused in the C128 system, and found at pin 1.
• LP2: Input for light pen; a positive going transition on this input latches the
vertical and horizontal position of the character being displayed at that time.
Found at pin 25.
• HSYNC: The horizontal sync signal, fully programmable via internal 8563
registers, and found at pin 20.
• R,G,B>I: The pixel data outputs. They form a 4-bit code associated with each
pixel, containing color/intensity information, allowing a total of sixteen colors
or gray shades to be displayed. Located at pins 46, 45, 44, 43, respectively.
37
DD7 VDD CS
DH7 33
32
DD6 DR6
,40 31
DD5 DH5
,39 30
004 DR4
,38 29
DD3 DR3
.36 28
DD2 DR2
,35 27
DD 1 Dfll
,34 26
DD0 DH0
148
07 /CflS
47
D6 /RRS
21
05 DR/W
oy
D3
02 UvJ 46
45
Dl
1414
DQ
H3
/RS
, 7 20
g
/cs V5YN
3
HSTN
.23
R/W
/RES
CCLK
DISPEN
.25
/LP2
24
TST
22
/DCLK INI T
vss
12
CONCEPT
The 6581 Sound Interface Device (SID) is a single-chip, three-voice electronic music
synthesizer/sound effects generator compatible with the 8502 and similar microprocessor
families. SID provides wide-range, high-resolution control of pitch (frequency), tone
color (harmonic content), and dynamics (volume). Specialized control circuitry mini-
mizes software overhead, facilitating use in arcade/home video games and low-cost
musical instruments.
FEATURES
• 3 TONE OSCILLATORS
Range: 0-4 kHz
• 4 WAVEFORMS PER OSCILLATOR
Triangle, Sawtooth,
Variable Pulse, Noise
• 3 AMPLITUDE MODULATORS
Range: 48 dB
• 3 ENVELOPE GENERATORS
Exponential response
Attack Rate: 2ms-8 s
Decay Rate: 6 ms-24 s
Sustain Level: 0-peak volume
Release Rate: 6 ms-24 s
• OSCILLATOR SYNCHRONIZATION
• RING MODULATION
• PROGRAMMABLE FILTER
Cutoff range: 30 Hz-12 kHz
12 dB/octave Rolloff
Low pass, Bandpass,
High pass, Notch outputs
Variable Resonance
• MASTER VOLUME CONTROL
• 2 A/D POT INTERFACES
• RANDOM NUMBER/MODULATION GENERATOR
• EXTERNAL AUDIO INPUT
CAP1A 1 28 VDD
CAP2A 3 26 EXT IN
CAP2B 4 25 Vcc
RES 5 24 POTX
°2 6 23 POT Y
R/W 7 6581 22 D7
SID
CS 8 21 D6
Ao 9 20 D5
A, 10 19 D4
A2 11 18 D3
12 17 D2
A3
A4 13 16 D,
GND 14 15 Do
o
HP
SYNC/RM
TONE
OSCILLATOR/ AUDIO OUT
WAVEFORM
GENERATOR 3 n
00
I
ENVELOPE
GENERATOR 3 39
o
V)
"D
m
n
n
5o
VI
DESCRIPTION
The 6581 consists of three synthesizer "voices" which can be used independently or in
conjunction with each other (or external audio sources) to create complex sounds. Each
voice consists of a Tone Oscillator/Waveform Generator, an Envelope Generator and an
Amplitude Modulator. The Tone Oscillator controls the pitch of the voice over a wide
range. The Oscillator produces four waveforms at the selected frequency, with the
unique harmonic content of each waveform providing simple control of tone color. The
volume dynamics of the oscillator are controlled by the Amplitude Modulator under the
direction of the Envelope Generator. When triggered, the Envelope Generator creates an
amplitude envelope with programmable rates of increasing and decreasing volume. In
addition to the three voices, a programmable Filter is provided for generating complex,
dynamic tone colors via subtractive synthesis.
SID allows the microprocessor to read the changing output of the third Oscillator
and third Envelope Generator. These outputs can be used as a source of modulation
information for creating vibrato, frequency/filter sweeps and similar effects. The third
oscillator can also act as a random number generator for games. Two A/D converters are
provided for interfacing SID with potentiometers. These can be used for "paddles" in a
game environment or as front panel controls in a music synthesizer. SID can process
external audio signals, allowing multiple SID chips to be daisy-chained or mixed in
complex polyphonic systems. For full register descriptions, see Chapter 11, Sound and
Music on the Commodore 128.
RES (PIN 5)
This TTL-level input is the reset control for SID. When brought low for at least ten 4>2
cycles, all internal registers are reset to 0 and the audio output is silenced. This pin is
normally connected to the reset line of the microprocessor or a power-on-clear circuit.
CI28 HARDWARE SPECIFICATIONS 603
cj>2 (PIN 6)
This TTL-level input is the master clock for SID. All oscillator frequencies and
envelope rates are referenced to this clock. cf>2 also controls data transfers between SID
and the microprocessor. Data can only be transferred when <j>2 is high. Essentially, cj>2 acts
as a high-active chip select as far as data transfers are concerned. This pin is normally
connected to the system clock, with a nominal operating frequency of 1.0 MHz.
R/W (PIN 7)
This TTL-level input controls the direction of data transfers between SID and the
microprocessor. If the chip select conditions have been met, a high on this line allows
the microprocessor to Read data from the selected SID register and a low allows the
microprocessor to Write data into the selected SID register. This pin is normally
connected to the system Read/Write line.
CS (PIN 8)
This TTL-level input is a low active chip select which controls data transfers between
SID and the microprocessor. CS must be low for any transfer. A Read from the selected
SID register can only occur if CS is low, <|>2 is high and R/W is high. A Write to the
selected SID register can only occur if CS is low, <J>2 is high and R/W is low. This pin is
normally connected to address decoding circuitry, allowing SID to reside in the memory
map of a system.
GND(PIN 14)
For best results, the ground line between SID and the power supply should be separate
from ground lines to other digital circuitry. This will minimize digital noise at the audio
output.
D0-D7(PINS 15-22)
These bidirectional lines are used to transfer data between SID and the microprocessor.
They are TTL compatible in the input mode and capable of driving two TTL loads in the
output mode. The data buffers are usually in the high-impedance off state. During a
Write operation, the data buffers remain in the off (input) state and the microprocessor
supplies data to SID over these lines. During a Read operation, the data buffers turn on
and SID supplies data to the microprocessor over these lines. The pins are normally
connected to the corresponding data lines of the microprocessor.
POTX,POTY (PINS 24,23)
These pins are inputs to the A/D converters used to digitize the position of potentiome-
ters. The conversion process is based on the time constant of a capacitor tied from the
POT pin to ground, charged by a potentiometer tied from the POT pin to + 5 volts. The
component values are determined by:
RC = 4.7E-4
V D D (PIN 28)
As with Vcc, a separate + 12 VDC line should be run to SID V DD and a bypass capacitor
should be used.
CI28 HARDWARE SPECIFICATIONS 60S
ELECTRICAL CHARACTERISTICS
(V DD = 12 VDC±5%, Vcc = 5 VDC±5%, T A = 0 to 70° C)
TB-
\\Y\Y\\
Do-D7 •
EQUAL-TEMPERED
MUSICAL SCALE VALUES
The table in Chapter 11 lists the numerical values which must be stored in the SID
Oscillator frequency control registers to produce the notes of the equal-tempered musical
scale. The equal-tempered scale consists of an octave containing twelve semitones
(notes): C,D,E,F,G,A,B and C # , D # , F # , G # , A # . The frequency of each semitone is
exactly the 12th root of 2 {^/~2) times the frequency of the previous semitone. The table
is based on a 4>2 clock of 1.02 MHz. Refer to the equation given in the Register
Description in Chapter 11 for use of other master clock frequencies. The scale selected
is concert pitch, in which A-A = 440 Hz. Transpositions of this scale and scales other
than the equal-tempered scale are also possible.
Although the table in Chapter 11 provides a simple and quick method for generat-
ing the equal-tempered scale, it is very memory inefficient as it requires 192 bytes for
the table alone. Memory efficiency can be improved by determining the note value
algorithmically. Using the fact that each note in an octave is exactly half the
frequency of that note in the next octave, the note look-up table can be reduced from
ninety-six entries to twelve entries, as there are twelve notes per octave. If the twelve
entries (24 bytes) consist of the 16-bit values for the eighth octave (C-7 through B-7),
then notes in lower octaves can be derived by choosing the appropriate note in the eighth
octave and dividing the 16-bit value by two for each octave of difference. As division by
two is nothing more than a right-shift of the value, the calculation can easily be
accomplished by a simple software routine. Although note B-7 is beyond the range of
the oscillators, this value should still be included in the table for calculation purposes
(the MSB of B-7 would require a special software case, such as generating this bit in the
CARRY before shifting). Each note must be specified in a form which indicates which
of the twelve semitones is desired, and which of the eight octaves the semitone is in.
Since 4 bits are necessary to select one of twelve semitones and 3 bits are necessary to
select one of eight octaves, the information can fit in one byte, with the lower nybble
selecting the semitone (by addressing the look-up table) and the upper nybble being used
by the division routine to determine how many times the table value must be right-shifted.
PEAK AMPLITUDE
ZERO AMPLITUDE
This volume envelope can be easily reproduced by the ADSR as shown below,
with typical envelope rates:
C128 HARDWARE SPECIFICATIONS 609
Note that the tone can be held at the intermediate SUSTAIN level for as long as
desired. The tone will not begin to die away until GATE is cleared. With minor
alterations, this basic envelope can be used for brass and woodwinds as well as strings.
An entirely different form of envelope is produced by percussion instruments such
as drums, cymbals and gongs, as well as certain keyboards such as pianos and
harpsichords. The percussion envelope is characterized by a nearly instantaneous attack,
immediately followed by a decay to zero volume. Percussion instruments cannot be
sustained at a constant amplitude. For example, the instant a drum is struck, the sound
reaches full volume and decays rapidly regardless of how it was struck. A typical
cymbal envelope is shown below:
ATTACK: 0 2 ms
DECAY: 9 750 ms
SUSTAIN: 0
RELEASE: 9 750 ms
Note that the tone immediately begins to decay to zero amplitude after the peak is
reached, regardless of when GATE is cleared. The amplitude envelope of pianos and
harpsichords is somewhat more complicated, but can be generated quite easily with the
ADSR. These instruments reach full volume when a key is first struck. The amplitude
immediately begins to die away slowly as long as the key remains depressed. If the key
is released before the sound has fully died away, the amplitude will immediately drop to
zero. This envelope is shown below:
ATTACK: 0 2 ms
DECAY: 9 750 ms
SUSTAIN: 0
RELEASE: 0 6 ms
Note that the tone decays slowly until GATE is cleared, at which point the
amplitude drops rapidly to zero.
The most simple envelope is that of the organ, When a key is pressed, the tone
immediately reaches full volume and remains there. When the key is released, the tone
drops immediately to zero volume. This envelope is shown below:
ATTACK: 0 2 ms
DECAY: 0 6 ms
SUSTAIN: 15 ($F)
RELEASE: 0 6 ms
The real power of SID lies in the ability to create original sounds rather than
simulations of acoustic instruments. The ADSR is capable of creating envelopes which
do not correspond to any "real" instruments. A good example would be the "back-
wards" envelope. This envelope is characterized by a slow attack and rapid decay
which sounds very much like an instrument that has been recorded on tape then played
backwards. This envelope is shown below:
Many unique sounds can be created by applying the amplitude envelope of one
instrument to the harmonic structure of another. This produces sounds similar to familiar
acoustic instruments, yet notably different. In general, sound is quite subjective and
experimentation with various envelope rates and harmonic contents will be necessary in
order to achieve the desired sound.
DESCRIPTION
The 6526 Complex Interface Adapter (CIA) is an 8502 bus compatible peripheral
interface device with extremely flexible timing and I/O capabilities. Figure 16-19 shows
the 6526 pin configuration. Figure 16-20 shows the 6526 block diagram.
FEATURES
ORDERING INFORMATION
MXS 6526 —
FREQUENCY RANGE
NO SUFFIX = 1 MHz
A = 2MHz
PACKAGE DESIGNATOR
C = CERAMIC
P = PLASTIC
Vss [_> 40 CNT
PA0 [T 39 SP
PA, FT 38 RS0
PA 2 FT 37| RS,
PA 3 FT 3e] RS2
34 RES
33j DB0
32 DB,
PBo HO
6526 31 DB 2
PB, hT 30 DB 3
PB2 12 29 DB 4
PB 3 [J3 28 DB 5
PB4 [i4 27 DB 6
PB 5 1^15 26 DB 7
PB 6 H6
PB7 h7 24 FLAG
PC FIB" 23 CS
TOD 19 22 R/W
21 iRQ
D0D7
0
DATA BUS BUFFERS
PAQ-PA7
SP SERIAL
BUFFER PORT
CNT CNT
BUFFED
PB 0 -PB 7
TOD TOD TOO/
BUFFER ALARM
L1 r
>—*1
TIMER B
— \
_ /
CRB
FLAG - FLAG
BUFFER
TIMER A
100 INT/ — \
IRQ
BUFFER MASK
CRA
1 1 1 1 1i A 1
R/W 02 CS RS3 RS2 RS1 RSO RES
COMMENT
Stresses above those listed under "Absolute Maximum Ratings" may cause permanent
damage to the device. These are stress ratings only. Functional operation of this device
at these or any other conditions above those indicated in the operational sections of this
specification is not implied and exposure to absolute maximum rating conditions for
extended periods may affect device reliability.
ELECTRICAL CHARACTERISTICS
(V c c ± 5%, V ss = 0 V, T A = 0-70°C)
02 INPUT
- Tpp •
PERIPHERAL
DATA OUT
CS "Y
RS3-RS0
T
RWH •
R/W
DATA IN
DB7-DB0
02 INPUT
PORT IN
CS
RS3-RS0
R/W
DATA OUT
DB 7-OBO
RS3-RS0—ADDRESS INPUTS
The address inputs select the internal registers as described by the Register Map.
RES—RESET INPUT
A low on the RES pin resets all internal registers. The port pins are set as inputs and
port registers to zero (although a read of the ports will return all highs because of
passive pullups). The timer control registers are set to 0 and the timer latches to all ones.
All other registers are reset to 0.
i>2 Clock
TCYC Cycle Time 1000 20,000 500 20,000 ns
TR, T F Rise and Fall Time — 25 — 25 ns
TCHW Clock Pulse Width (High) 420 10,000 200 10,000 ns
TCLW Clock Pulse Width (Low) 420 10,000 200 10,000 ns
Write Cycle
TpD Output Delay From 4>2 — 1000 — 500 ns
Twcs CS low while c|>2 high 420 — 200 — ns
TADS Address Setup Time 0 — 0 — ns
TADH Address Hold Time 10 — 5 — ns
TRWS R/W Setup Time g 0 _ ns
TRWH R/W Hold Time 0 — 0 — ns
TDS Data Bus Setup Time 150 — 75 — ns
TDH Data Bus Hold Time 0 — 0 — ns
C128 HARDWARE SPECIFICATIONS 617
Read Cycle
T PS Port Setup Time 300 — 150 — ns
Twcs(2) CS low while <f>2 high 420 — 20 — ns
TADS Address Setup Time 0 — 0 — ns
TAOH Address Hold Time 10 — 5 — ns
TRWS R/W Setup Time 0 — 0 — ns
TRWH R/W Hold Time 0 — 0 — ns
TACC Data Access from RS3-RS0 — 550 — 275 ns
IcoO) Data Access from CS — 320 — 150 ns
TDR Data Release Time 50 — 25 — ns
1. All timings are referenced from Vj L max and V ^ min on inputs and VOL max and
V DH min on outputs.
2- T w c s is measured from the later of 4>2 high or CS low. CS must be low at least
until the end of 4>2 high.
3. T c o is measured from the later of <|>2 high or CS low. Valid data is available only
after the later of T A C C or Tco-
REGISTER MAP
RS3 RS2 RSI RS0 REG NAME DESCRIPTION
HANDSHAKING
Handshaking on data transfers can be accomplished using the PC output pin and the
FLAG input pin. PC will go low for one cycle following a read or write of PORT B.
This signal can be used to indicate "data ready" at PORT B or "data accepted" from
PORT B. Handshaking on 16-bit data transfers (using both PORT A and PORT B) is
possible by always reading or writing PORT A first. FLAG is a negative edge sensitive
input which can be used for receiving the PC output from another 6526, or as a general
purpose interrupt input. Any negative transition of FLAG will set the FLAG interrupt
bit.
REG NAME D, D6 Ds D4 D, D2 D, Do
START/STOP
A control bit allows the timer to be started or stopped by the microprocessor at any
time.
C128 HARDWARE SPECIFICATIONS 619
PB ON/OFF
A control bit allows the timer output to appear on a PORT B output line (PB6 for
TIMER A and PB7 for TIMER B). This function overrides the DDRB control bit and
forces the appropriate PB line to an output.
TOGGLE/PULSE
A control bit selects the output applied to PORT B. On every timer underflow the output
can either toggle or generate a single positive pulse of one cycle duration. The toggle
output is set high whenever the timer is started and is set low by RES.
ONE-SHOT/CONTINUOUS
A control bit selects either timer mode. In one-shot mode, the timer will count down
from the latched value to 0, generate an interrupt, reload the latched value, then stop. In
continuous mode, the timer will count from the latched value to 0, generate an interrupt,
reload the latched value and repeat the procedure continuously.
FORCE LOAD
A strobe bit allows the timer latch to be loaded into the timer counter at any time,
whether the timer is running or not.
INPUT MODE
Control bits allow selection of the clock used to decrement the timer. TIMER A can
count 4>2 clock pulses or external pulses applied to the CNT pin. TIMER B can count 4>2
pulses, external CNT pulses, TIMER A underflow pulses or TIMER A underflow pulses
while the CNT pin is held high.
The timer latch is loaded into the timer on any timer underflow, on a force load or
following a write to the high byte of the prescaler while the timer is stopped. If the timer
is running, a write to the high byte will load the timer latch, but not reload the counter.
READ (TIMER)
REG NAME
WRITE (PRESCALER)
REG NAME
READ
REG NAME
8 TOD 10THS 0 0 0 0 T« T4 T2 T,
9 TOD SEC 0 SH4 SH2 SH, SL8 SL4 SL2 SLj
A TOD MIN 0 MH4 MH2 MH, ML8 ML4 ML 2 ML,
B TOD HR PM 0 0 HH HL8 HL4 HL 2 HL,
WRITE
CRB7 = 0TOD
CRB7 = 1 ALARM
(SAME FORMAT AS READ)
shifted out on the SP pin at one half the underflow rate of TIMER A. The maximum
baud rate possible is 4>2 divided by 4, but the maximum useable baud rate will be
determined by line loading and the speed at which the receiver responds to input data.
Transmission will start following a write to the Serial Data Register (provided TIMER A
is running and in continuous mode). The clock signal derived from TIMER A appears as
an output on the CNT pin. The data in the Serial Data Register will be loaded into the
shift register then shift out to the SP pin when a CNT pulse occurs. Data shifted out
becomes valid on the falling edge of CNT and remains valid until the next falling edge.
After eight CNT pulses, an interrupt is generated to indicate more data can be sent. If
the Serial Data Register was loaded with new information prior to this interrupt, the new
data will automatically be loaded into the shift register and transmission will continue. If
the microprocessor stays one byte ahead of the shift register, transmission will be
continuous. If no further data is to be transmitted, after the 8th CNT pulse, CNT will
return high and SP will remain at the level of the last data bit transmitted. SDR data is
shifted out MSB first and serial input data should also appear in this format.
The bidirectional capability of the Serial Port and CNT clock allows many 6526
devices to be connected to a common serial communication bus on which one 6526 acts
as a master, sourcing data and shift clock, while all other 6526 chips act as slaves. Both
CNT and SP outputs are open drain to allow such a common bus. Protocol for
master/slave selection can be transmitted over the serial bus, or via dedicated handshaking
lines.
REG NAME
CONTROL REGISTERS
There are two control registers in the 6526, CRA and CRB. CRA is associated
with TIMER A and CRB is associated with TIMER B. The register format is as
follows:
CRA:
CRB:
-TA-
RUN OLT
REG NAME ALARM IN MODE LOAD MODE MODE PS ON START
All unused register bits are unaffected by a write and are forced to zero on a
read.
DYNAMIC RANDOM ACCESS
MEMORY
This section discusses the characteristics of the C128 dynamic RAMs, which are
currently the 4164 64K-bit RAM. This RAM device is in the 64K by 1-bit configura-
tion. This section also contains information on the 4416 dynamic RAMs used by
the 8563 video controller. This type of RAM is a 64K RAM in the 16K by 4 bit
configuration.
PHYSICAL CHARACTERISTICS
This section covers some of the characteristics of the 64K by 1-bit RAM and 16K by
4-bit RAM that are used in the C128 system. A pinout table and a figure are given for
both the 4164 and the 4416 packages (See Tables 16-15 and 16-16 and Figures 16-23 and
16-24).
CI28 HARDWARE SPECIFICATIONS 625
1 NC No Connection
2 Din Data In
3 /WE Write Enable (Active Low)
4 /RAS Row Address Strobe (Active Low)
5 Ao Address Bit 0
6 A2 Address Bit 2
7 A, Address Bit 1
8 Vcc Power Supply + 5 Vdc
9 A7 Address Bit 7
10 As Address Bit 5
11 A4 Address Bit 4
12 A3 Address Bit 3
13 A6 Address Bit 6
14 D«, Data Out
15 /CAS Column Address Strobe (Active Low)
16 vss Power Supply Ground
PL
-O
\/
T
ROM BANKING
Refer back to the MMU register map, Figure 13—4 in Chapter 13. Note that the
Configuration Register (CR) controls the type of ROM or RAM seen in a given address
location. Dependent on the contents of the CR, ROM may be enabled and disabled to
attain the most useful configuration for the application at hand. ROM is enabled in three
memory areas in C128 mode, each consisting of 16K of address space. The lower ROM
may be defined as RAM or System ROM, the upper two ROMs may be System ROM,
Function ROM, Cartridge ROM or RAM. In C64 mode, the C64 memory mapping rules
apply, which are primitive compared to those used in C128 mode. C64 ROM is banked
as two 8K sections, BASIC and Kernal, according to the page zero port and the
cartridge in place at the time. No free banking can occur when a cartridge is in
place.
In the C128, if an address falls into the range of an enabled ROM, the MMU will
communicate the status of ROM to the PLA decoder via the memory status lines.
Essentially, the MMU looks up in the Configuration Register which ROM or RAM is
set. See Chapter 13. The way the banking scheme is implemented, it allows up to 32K
of internal, bankable ROM for use in such programs as Function Key Applications,
and will support 32K of internal bankable ROM. Various combinations of ROM are
possible, and can be noted by studying the configurations for the Configuration
Register. Type 23128 (16K by 8) and 23256 (32K by 8) ROMs are used by the
system.
TIMING SPECIFICATION
INTERNAL ROMs
This section specifies timing parameters for both the 23128 and the 27256 Read Only
Memories. This timing spec applies to internal ROMs and for external ROMs run at 1
MHz. For external ROMs run at 2 MHz, see Table 16-18.
RDORESS -
CHIP
ENRBLE
OUTPUT
ENRBLE
DRTfl
EXTERNAL ROMS
All C64 mode external ROMs and many C128 mode external ROMs can be of the type
mentioned above. Any external ROM that is to run at 2 MHz must be faster, as
specified in Table 16-18.
:
<>. : •
-o
A : !\ U
Figure 16-26. The 23128 ROM Chip (BASIC, Kernal, Editor and External Function
ROMs)
CI28 HARDWARE SPECIFICATIONS 631
1 vw Programming Voltage
2 A12 Address Bit 12
3 A7 Address Bit 7
4 A6 Address Bit 6
5 A5 Address Bit 5
6 A4 Address Bit 4
7 A3 Address Bit 3
8 A2 Address Bit 2
9 A, Address Bit 1
10 Ao Address Bit 0
11 Do Data Bit 0
12 D, Data Bit 1
13 D2 Data Bit 2
14 GND Power Supply Ground
15 D3 Data Bit 3
16 D4 Data Bit 4
17 D5 Data Bit 5
18 D6 Data Bit 6
19 D7 Data Bit 7
20 /CE-/PGM Chip Enable-Program Enable (Active Low)
21 Aio Address Bit 10
22 /OE Output Enable (Active Low)
23 An Address Bit 11
24 A9 Address Bit 9
25 A8 Address Bit 8
26 A, 3 Address Bit 13
27 A]4 Address Bit 14
28 Vcc Power Supply +5 Vdc
Table 16-20. 23256 ROM Pinout (Internal or External Function ROMs)
Figure 16-27. The 23256 ROM Chip
CI28 HARDWARE SPECIFICATIONS 633
BUS OPERATIONS
There are three basic bus operations that take place on the serial bus, in both fast and
slow modes. The first of these is called Control. The C128 is the controller in most
circumstances. The controller of the bus is always the device that initiates protocol on
the bus, requesting peripheral devices to do one of the two other serial operations, either
Talk or Listen.
All serial bus devices can listen. A listening device is a device that has been
ordered by the controller to receive data. Some devices, such as disk drives, can talk. A
talking device is sending data to the controller. Both hardware and software drive this
bus protocol.
BUS SIGNALS
The Commodore serial bus is composed of the following signals:
• SRQ (pin 1): This signal is called Service Request. The slow serial bus does
not use this line, the fast bidirectional clock line. (Not used in C64 Mode.)
• GND (pin 2): Chassis ground.
• ATN (pin 3): This signal is called Attention. It is used to address a device on
the bus. When requesting a device to talk to or listen, the controller brings this
signal low, creating some sort of interrupt on all serial bus devices. It then
sends out an address that will select one device on the bus. It is the controller's
responsibility to time out if a device on the bus does not respond within a
reasonable amount of time.
• CLK (pin 4): This is the slow serial clock. It is used by slow serial devices,
which are software-clocked, to clock data transmitted on the serial bus.
• DATA (pin 5): This is the serial data line. It is used by both slow and fast
serial devices to transmit data in sync with clock signal.
• RESET (pin 6): This is the reset line, used to reset all peripherals when the
host resets.
FAST SERIAL BUS
FAST PROTOCOL
To function as a fast talker, the system must be addressing a fast device, such as the
1571 disk drive. When addressing any device, the C128 sends a fast byte, toggling the
SQR line eight times, with the ATN line low. If the device is a fast device, it will record
the fact that a fast controller accessed it and respond with a fast acknowledge. If the
device is a slow device, no response is delivered and the C128 then assumes it is talking
with a slow device. The status of drive speed is retained until the device is requested to
untalk or unlisten, if an error occurs, or if a system reset occurs.
FAST HARDWARE
The fast serial bus, in order to achieve its speed increase, uses different hardware from
that of the slow serial bus. The slow serial bus uses several 6526 port lines to drive
ATN, CLK and DATA. Thus, clocking of the data transfers must be software-driven.
The fast serial method is to use the serial port line of a 6526 (CIA-1) to actually transfer
the serial data. This increases the transfer rate dramatically, to the point where the
transfer becomes limited more by software overhead than anything else. The actual
speed of transfer is set by the 6526 timer. Current 6526's have a minimum serial timer
value of 4, though in actual use this value is closer to 6, owing to loading. Any
advances in the 6526 would make a faster data transfer possible.
This scheme could interfere with slow serial transmissions, since the DATA line is
shared by both schemes. Thus, circuitry exists that will isolate the fast serial drivers
from the slow serial bus. Setting FSDIR to input mode is sufficient to remove any
possible fast serial interactions with the slow serial bus, other than the additional device
loading, which is not a problem at slow serial bus speeds.
In order to ensure compatibility with the C64, however, the slow serial bus cannot
interfere with the fast drivers, since these drivers are shared with the User Port and a
user port device could presumably make use of them. Once C64 mode is set, the input
direction of the interface circuitry is disabled. Thus, in C64 mode, the FSDIR bit must
be set to input to remove fast to slow interference, but slow to fast interference is
automatically removed by invoking C64 mode. There is no way to disable slow to fast
interference in C128 mode (at least not simultaneously with the elimination of fast to
slow interference).
C128 HARDWARE SPECIFICATIONS 635
CARTRIDGE ADDITION
The C128 can use larger and more sophisticated cartridges than the C64. One of the
main reasons for this is the new banking scheme used in the C128 for external
cartridges. The C64 uses two hardware control lines, /EXROM and /GAME, to control
banking out of internal facilities and banking in of cartridge facilities. The C128 uses a
software polling method, where upon power-up it polls the cartridge, according to a
defined protocol, to determine if such a cartridge exists, and if so, what its software
priority is. Since the C128 is always free to bank between cartridges and built-in ROM,
an external application can take advantage of internal routines and naturally become an
extended part of the C128, as opposed to becoming a replacement application. See
Chapter 13 for information on the Auto Start Cartridge ROM sequence.
The elimination of /EXROM and /GAME as hardware control lines for cartridge
identification (in C128 mode) has freed up both of these lines for extended functioning.
Both of the lines appear as bits in the MMU Mode Configuration Register, and are both
input and output ports. Neither has a dedicated function other than general cartridge
function expansion, and lend themselves to act as latched banking lines or input sense
lines. Of course, neither can be asserted on C128 power-up or C64 mode will automati-
cally be set.
DMA CAPABILITY
The C128 expansion bus supports DMAs in a fashion similar to that of the C64. A C64
DMA is achieved by pulling the /DMA pin on the expansion bus low. Immediately after
this happens, the RDY and AEC lines of the processor are brought low. This can neatly
shut down the processor, but it can also cause problems, depending on what the
processor is doing at the time. The RDY input of an 8502 series processor, when brought
low, will halt the processor of the next <f>l cycle, leaving the processor's address lines
reflecting the current address being fetched. However, if the processor is in a write cycle
when RDY is brought low, it will ignore RDY until the next read cycle. Thus, in the
C64, a /DMA input occurring during a write cycle will tri-state the processor's address
and data bus, but not stop it until up to three cycles later when the next read cycle
occurs. The write cycles following the /DMA input do not actually write, causing
memory corruption and often processor fatality when the /DMA line is released. Any
/DMA input during $ 2 is a potentially fatal DMA.
If a proper /DMA is asserted, the C64 tri-states and shuts down, allowing the
DMA source complete access to the processor bus. Such a DMA source must monitor
the <f>2 and BA outputs, as it must tri-state when the VIC is on the bus, and it must
completely DMA when a VIC DMA is called for. The VIC chip always has the highest
DMA priority. When on the bus, the DMA source has access to RAM, ROM and I/O
in the C64 scheme. A proper DMA shutdown is usually achieved via some C64 software
handshaking with the DMA source.
The C128 system uses a similar DMA scheme. When the /DMA input goes low,
the RDY input to the 8502, the AEC input to the 8502, and the /BUSRQST input to the
Z80 immediately go low. Additionally, the gated AEC signal, GAEC, goes low,
causing the MMU to go immediately to its VIC CYCLE MODE, and the Z80 Data Out
buffer to tri-state. The DMA causes the Address to the Shared Address buffer to reverse
direction, and the Translated Address to the Address buffer to be enabled, giving the
external DMA source complete access to the processor address bus. The PLA is still
looking at ungated AEC and as such will allow access to I/O devices, RAM and ROM.
There can be no access to the MMU; thus for C128 memory mapping the memory map
must be set up before being DMA'ed. For C64 mode, memory mapping is done by the
8502 processor port lines and by the external /EXROM and /GAME. Since the 8502
ports will be inaccessible by a DMA source, only the C64 map changes based upon
/EXROM and /GAME can be made during a DMA. This is the same as in a C64 unit.
All DMA sources, as with the C64, must yield to the VIC during 4>0 or BA low. The
C128 can perform a destructive DMA as easily as the C64. In order to use DMA's, the DMA
source will most likely have to cooperate with a C128 mode program, allowing it to
handshake with a DMA source to effect DMA's nondestructively.
C128 HARDWARE SPECIFICATIONS 637
MODULATOR SPECIFICATION
The modulator provides a broadcast-type RF signal carrying the VIC composite video
and audio signals. The NTSC modulator is switchable between channels 3 and 4 to help
minimize local broadcast interference. The signal generated by the RF modulator
complies with the FCC ruling concerning FCC Class B, TV interface devices. The RF
output is accessible via a standard RCA-type phono/video jack.
MONITOR OUTPUT
The VIC video output provides the signals shown in Table 16-22.
PIN SIGNAL
1 Luminance/Sync
2 Ground
3 Audio Out
4 Composite
5 Audio In
6 Chroma
7 N.C.
8 N.C.
MONITOR OUTPUT
Table 16-24 shows the signals provided by the 8563 output.
1 Ground
2 Ground
3 Red
4 Green
5 Blue
6 Intensity
7 Monochrome (non-standard)
8 Horizontal Sync
9 Vertical Sync
Table 16-25. 8563 Video Connector Pinout
THE KEYBOARD
The C128 Keyboard is an advance over the standard C64 keyboard, while still maintain-
ing full compatibility. It has several extra keys that are used in C128 mode, but not in
C64 mode. It features a numeric keypad, a H E L P key, extended function keys, a
true C A P S L O C K key, and a 4 0 / 8 0 column switch key, all of which are
strobed by the VIC chip or tied to dedicated 8502 or MMU I/O lines.
CONNECTOR PiNOUT
The C128 keyboard is designed to be connected by one 12- and one 13-pin internal
single-in-line connector for the unit with a built-in keyboard. Table 16-26 illustrates
both connections.
CI28 HARDWARE SPECIFICATIONS 641
D-TYPE SIGNAL
1 Ground
2 Key
3 Restore
4 + 5V
5 Row 3
6 Row 6
7 Row 5
8 Row 4
9 Row 7
10 Row 2
11 Row 1
12 RowO
13 Column 0
14 Column 6
15 Column 5
16 Column 4
17 Column 3
18 Column 2
19 Column 1
20 Column 7
21 Ko
22 Kj
23 K2
24 40/80
25 Alpha Lock
Rl RET W R Y I P * <- 8 + 0
PINll
R2 t A D G J L ] CTRL 5
PIN10 I ;
R6 F6 E T U O @ Q 7 9
PIN6 F5
/ (LOCKING)
SHIFT
LOCK
NMI RESTR
«
PIN3
/ (LOCKING)
40/80 40/80
PIN24 * DSPLY
/ (LOCKING)
P6510 CAPS
<
PIN25 LOCK
NOTE: Pins RO through R7 pertain to the keyboard row values for the keyboard SCAN.
These pins correspond to bits 0 through 7 of location 56321 (SDC01).
Pins CO through C7 are the keyboard's column values, which correspond to bits 0
through 7 of location 56320 ($DC00).
Pins K0 through K2 pertain to the C128 keyboard control register bit, 0 through 2 of
location 53295 ($D02F).
APPENDIXES
Appendix A - BASIC Language Error Messages 644
Equipment 652
Appendix K -
BASIC LANGUAGE
ERROR MESSAGES
The following error messages are displayed by BASIC. Error messages can also be
displayed with the use of the ERR$() function. The error numbers below refer only to
the number assigned to the error for use with the ERR$() function.
ERROR
NUMBER ERROR MESSAGE AND DESCRIPTION
ERROR
NUMBER ERROR MESSAGE AND DESCRIPTION
27 READ ERROR
This message is generated when a checksum error has been detected in the
header of the requested data block. The block has not been read into DOS
memory.
28 WRITE ERROR
This error message is generated when a data block is too long and
overwrites the sync mark of the next header.
29 DISK ID MISMATCH
This message is generated when the controller has been requested to access
a diskette that has not been initialized or improperly formatted. The
message can also occur if a diskette has a bad header.
30 SYNTAX ERROR (general syntax)
The DOS cannot interpret the command sent to the command channel.
Typically, this is caused by an illegal number of file names, or patterns
that are illegally used. For example, two file names appear on the left side
of the COPY command.
31 SYNTAX ERROR (invalid command)
The DOS does not recognize the command. The command must start in the
first position.
32 SYNTAX ERROR (invalid command)
The command sent is longer than 58 characters. Use abbreviated disk
commands.
33 SYNTAX ERROR (invalid file name)
Pattern matching is invalidly used in the OPEN or SAVE command. Spell
out the file name.
34 SYNTAX ERROR (no file given)
The file name was left out of the command or the DOS does not recognize
it as such. Typically, a colon(:) has been left out of the command.
39 SYNTAX ERROR (invalid command)
This error may result if the command sent to the command channel
(secondary address 15) is unrecognized by the DOS.
50 RECORD NOT PRESENT
Result of disk reading past the last record through INPUT# or GET#
commands. This message will also appear after positioning to a record
beyond end-of-file in a relative file. If the intent is to expand the file by
adding the new record (with a PRINT# command), the error message may
be ignored. INPUT# and GET# should not be attempted after this error is
detected without first repositioning.
ERROR
NUMBER ERROR MESSAGE AND DESCRIPTION
51 OVERFLOW IN RECORD
PRINT# statement exceeds record boundary. Information is truncated.
Since the carriage return that is sent as a record terminator is counted in the
record size, this message will occur if the total characters in the record
(including the final carriage return) exceed the defined size of the record.
52 FILE TOO LARGE
The record position within a relative file indicates that disk overflow will
result.
60 WRITE FILE OPEN
This message is generated when a write file that has not been closed is
being opened for reading.
61 FILE NOT OPEN
A file that has not been opened in the DOS is being accessed. Sometimes
in this situation, a message is not generated; the request is simply ignored.
62 FILE NOT FOUND
The requested file does not exist on the indicated drive.
63 FILE EXISTS
The file name of the file being created already exists on the diskette.
64 FILE TYPE MISMATCH
The requested file access is not possible using files of the type named.
Reread the chapter covering that file type.
65 NO BLOCK
Occurs in conjunction with block allocation. The sector you tried to allocate
is already allocated. The track and sector numbers returned are the next
higher track and sector available. If the track number returned is 0, all
remaining higher sectors are full. If the diskette is not full yet, try a
lower track and sector.
66 ILLEGAL TRACK AND SECTOR
The DOS has attempted to access a track or a block that does not exist in
the format being used. This may indicate a problem reading the pointer to
the next block.
67 ILLEGAL SYSTEM T OR S
This special error message indicates an illegal system track or sector.
70 NO CHANNEL (available)
The requested channel is not available, or all channels are in use. A
maximum of five buffers are available for use. A sequential file requires
two buffers; a relative file requires three buffers; and the error/command
channel requires one buffer. You may use any combination of those as
long as the combination does not exceed five buffers.
APPENDIXES 651
ERROR
NUMBER ERROR MESSAGE AND DESCRIPTION
71 DIRECTORY ERROR
The BAM (Block Availability Map) on the diskette does not match the
copy on disk memory. To correct this, initialize the disk drive.
72 DISK FULL
Either the blocks on the diskette are used, or the directory is at its entry
limit. DISK FULL is sent when two blocks are still available on the
diskette, in order to allow the current file to be closed.
73 DOS VERSION NUMBER (73, CBM DOS V30 1571, 00, 00)
DOS 1 and 2 are read compatible but not write compatible. Disks may be
interchangeably read with either DOS, but a disk formatted on one version
cannot be written upon with the other version because the format is
different. This error is displayed whenever an attempt is made to write
upon a disk that has been formatted in a noncompatible format. This
message will also appear after power-up or reset and is not an error in this
case.
74 DRIVE NOT READY
An attempt has been made to access the disk drive without a diskette
inserted; or the drive lever or door is open.
APPENDIX C
CONNECTORS/PORTS FOR
PERIPHERAL EQUIPMENT
1. Power Socket 7. Serial Port
2. Power Switch 8. Composite Video Connector
3. Reset Button 9. Channel Selector
4. Controller Ports 10, RF Connector
5. Expansion Port 11. RGBI Connector
6. Cassette Port 12. User Port
4 3 2 1
6 7 8 9 10 11
APPENDIXES 653
CONTROLLER PORT 1
PIN TYPE NOTE ( 1 2 3 4 5
\ O O O O O
1 JOYAO \
2 JOYA1
3 JOYA2
\ o o o o /
4 JOYA3 \^ 6 7 8 9 J
5 POT AY
6 BUTTON A/LP
7 + 5V MAX. 50mA
8 GND
9 POT AX
CONTROLLER PORT 2
PIN TYPE NOTE
1 JOYB0
2 JOYB1
3 JOYB2
4 JOYB3
5 POT BY
6 BUTTON B
7 + 5V MAX. 50mA
8 GND
9 POTBX
REAR CONNECTIONS
5. Expansion Port—This rectangular slot is a parallel port that accepts program or
game cartridges as well as special interfaces.
CARTRIDGE
EXPANSION PORT
PIN TYPE PIN TYPE
12 BA 1 GND
13 DMA 2 + 5V
14 D7 3 + 5V
15 D6 4 IR&
16 D5 5 R/W
17 D4 6 Dot Clock
18 D3 7 I/Ol
19 D2 8 GAME
20 Dl 9 EXROM
21 DO 10 I/O 2
22 GND 11 ROML
Z V X W V U T S B P N M L K J H F E O C 8 A
6. Cassette Port—A 1530 Datassette recorder can be attached here to store programs
and information.
CASSETTE PORT
PIN TYPE 12 3 4 5 6
A-l GND
B-2 + 5V
C-3 CASSETTE MOTOR A B C D E F
D-4 CASSETTE READ
E-5 CASSETTE WRITE
F-6 CASSETTE SENSE
APPENDIXES 655
7. Serial Port—A Commodore serial printer or disk drive can be attached directly to
the Commodore 128 through this port.
1 SERIAL SRQIN
2 GND
3 SERIAL ATN IN/OUT
4 SERIAL CLK IN/OUT
5 SERIAL DATA IN/OUT
6 RESET
Composite Video Connector—This DIN connector supplies direct audio and com-
posite video signals. These can be connected to the Commodore monitor or used
with separate components. This is the 40-column output connector.
RGBI CONNECTOR
PIN SIGNAL
1 Ground
2 Ground
3 Red
4 Green
5 Blue
6 Intensity
7 Monochrome
8 Horizontal Sync
9 Vertical Sync
12. User Port—Various interface devices can be attached here, including a Commo-
dore modem.
APPENDIXES 657
1 GND
2 + 5V MAX. 100mA
3 RESET
4 CNT1
5 SP1
6 CNT2
7 SP2
8 PC2
9 SER. ATN IN
10 9 VAC MAX. 100mA
11 9 VAC MAX. 100mA
12 GND
A GND
B FLAG2
C PBO
D PB1
E PB2
F PB3
H PB4
J PB5
K PB6
L PB7
M PA2
N GND
12 3 4 5 6 7 8 9 10 11 12
A B C D E F H J K L M N
APPENDIX D
@ 0 N n 14 E 28
A a 1 0 0 15 ] 29
B b 2 p P 16 t 30
C c 3 Q q 17 31
D d 4 R r 18 SPACE • 32
E e 5 S s 19 33
F f 6 T t 20 34
G 9 7 U u 21 # 35
H h 8 V V 22 $ 36
I i 9 W w 23 % 37
J j 10 X X 24 & 38
K k 11 Y y 25 •
39
I I 12 Z z 26 ( 40
M m 13 ( 27 ) 41
APPENDIXES 659
42 G 71 • 100
43 H 72 • 101
44 I 73 m 102
45 a J 74 a 103
46 a K 75 104
47 D I 76 105
0 48 M 77 106
1 49 0 N 78 CB 107
2 50 D O 79 a 108
3 51 P 80 Q 109
4 52 Q 81 H 110
5 53 • R 82
• 111
6 54 H S 83
H 112
7 55 D T 84
B 113
8
9
56 a U 85
86
114
115
57 V
58 w 87 D 116
59 X 88 c 117
60 DD Y 89 a 118
61 z 90 n 119
62
63
91
92
n 120
121
64
m 93 • 122
A 65 94 El 123
m B 66
a 95
a 124
B C 67 SPACE 96 H 125
B D 68 I 97 E 126
B E 69
H 98 S 127
F 70
n 99
0 23 46 E 69
1 24 47 F 70
2 25 0 48 G 71
3 26 1 49 H 72
4 27 2 50 I 73
5 28 3 51 J 74
6 29 4 52 K 75
16. 7 30 5 53 L 76
18 31 6 54 M 77
9 32 7 55 N 78
10 33 8 56 O 79
11 34 9 57 P 80
12 # 35 58 Q 81
13 $ 36 59 R 82
14 37 60 S 83
38 61 T 84
39 Z> 62 U 85
40 ? 63 V 86
41 @ 64 W 87
42 A 65 X 88
43 B 66 Y 89
44 C 67 z 90
45 D 68 91
APPENDIXES 661
e 92 ® 115 f4 138
D 161
175
eg 106 Orange 129 Gray 152
a 107 130 Lt. Green 153 H 176
112 f5 135
1i 158 C 181
APPENDIX F
55296-
55336
55376
55416
55456
55496
55536
55576
55616
55656
55696
55736
55776
55816
55856
55896
55936
55976
56016
56056
56096
56136
56176
56216
56256 httfnri
The Screen Map is POKEd with a Screen Display Code value (see Appendix D).
For example:
POKE 1024, 13 (from BANK 0 or 15)
will display the letter M in the upper-left corner of the screen.
VIC CHIP (40-COLUMN) COLOR MEMORY MAP
COLUMN
20
1063
1024- m
1064 ! -H—|—.—
: t 4: ! , ,
1104
1144 f —
1184
1224
1264
1304
1344 4- ,4
1384 1 i .
1424
1464
1504
4
1544 j'
1584 |
1624
1664
1704
4
1744
1784 1 1
1824 1 1
1864
1904
1944 j 1 1
1984 1 "T
2023
If the color map is POKEd with a color value, this changes the character color. For
example:
POKE 55296,1 (from BANK 15)
will change the letter M inserted above from light green to white.
0 Black 8 Orange
1 White 9 Brown
2 Red 10 Light Red
3 Cyan 11 Dark Gray
4 Purple 12 Medium Gray
5 Green 13 Light Green
6 Blue 14 Light Blue
7 Yellow 15 Light Gray
Border Control Memory 53280
Background Control Memory 53281
APPENDIXES 665
APPENDIX G
DERIVED TRIGONOMETRIC
FUNCTIONS
PRINT
CODES KEY CODES
EFFECTIVE
IN MODE:
(CHR$) KEY SEQUENCE FUNCTION C64 C128
CHR$(2) CTRLB Underline (80) y
CHR$(5) CTRL 2 or CTRL E Set character color to white y y
CHR$(7) CTRL G Produce bell tone y
CHR$(8) CTRLH Disable character set change y
CHR$(9) CTRL I Enable character set change y
Move cursor to next set tab
position y
CHR$(10) CTRL J Line feed y
CHR$(11) CTRLK Enable character set change y
CHR$(12) CTRLL Disable character mode change y
CHR$(13) CTRLM Send a carriage return and line
feed to the computer and enter a
line of BASIC y y
CHR$(14) CTRLN Set character set to upper/lower
case y <//
CHR$(15) CTRLO Turn flash on (80) y
CHR$(17) CRSR DOWN/CTRL Move the cursor down one
Q row y y
CHR$(18) CTRL 9 or CTRL R Cause characters to be printed in
reverse field y y
CHR$(19) HOME Move the cursor to the home po-
sition (top left) of the display (the
current window) y y
NOTE: (40) = 40-column screen only
(80) = 80-column screen only
APPENDIXES 667
PRINT
CODES KEY CODES
EFFECTIVE
IN MODE:
(CHR$) KEY SEQUENCE FUNCTION C64 C128
CHR$(20) DEL or CTRL T Delete last character typed and
move all characters to the right
of the deleted character one space
to the left
CHR$(24) CTRL X, CTRL TAB
or O TAB Tab set/clear
CHR$(27) ESC or CTRL[ Send an ESC character y
CHR$(28) CTRL 3 or CTRL £ Set character color to red (40)
and (80) •J v'
CHR$(29) CRSR or CTRL] Move cursor one column to the
right •j y
CHR$(30) CTRL 6 or CTRL Set character color to green (40)
and (80) V V
ESCAPE CODES
This table lists the key sequences for the ESCape functions available on the Commodore
128. ESCape sequences are entered by pressing and releasing the E S C key, fol-
lowed by pressing the key listed in the right column.
KEYWORD ABBREVIATION
ABS ASHIFT B
APPEND ASHIFT P
ASC ASHIFT S
ATN ASHIFT T
AUTO ASHIFT U
BACKUP BASHIFT c
BANK BSHIFT A
BEGIN BSHIFT E
BEND BESHIFT N
BLOAD BSHIFT L
BOOT BSHIFT O
BOX none
BSAVE B SHIFT
t/i
BUMP B SHIFT U
CATALOG C SHIFT A
CHAR CH SHIFT A
CHR$ C SHIFT H
CIRCLE C SHIFT I
CLOSE CL SHIFT O
CLR C SHIFT L
CMD C SHIFT M
COLLECT COLL SHIFT E
COLLISION COL SHIFT L
COLOR COL SHIFT 0
CONCAT C SHIFT O
CONT none
COPY CO SHIFT P
COS none
DATA D SHIFT A
DEC none
DCLEAR DCL SHIFT E
DCLOSE D SHIFT C
DEFFN none
DELETE DE SHIFT L
DIM D SHIFT I
APPENDIXES 671
KEYWORD ABBREVIATION
DIRECTORY DISHIFT R
DLOAD D SHIFT L
DO none
DOPEN D SHIFT O
DRAW D SHIFT R
DS none
DS$ none
DSAVE D SHIFT S
DVERIFY D SHIFT V
EL none
END none
ENVELOPE E SHIFT N
ER none
ERR$ E SHIFT R
EXIT EX SHIFT I
EXP E SHIFT X
FAST none
FETCH F SHIFT E
FILTER F SHIFT I
FOR F SHIFT O
FRE F SHIFT R
FNXX none
GET G SHIFT E
GETKEY GETK SHIFT E
GET# none
GOSUB GO SHIFT S
GO64 none
GOTO G SHIFT O
GRAPHIC G SHIFT R
GSHAPE G SHIFT S
HEADER HE SHIFT A
HELP X SHIFT X
HEX$ H SHIFT E
IF . . . GOTO none
IF . . . THEN . . ELSE none
INPUT none
INPUT# I SHIFT N
INSTR IN SHIFT S
INT none
JOY J SHIFT O
KEY K SHIFT E
LEFTS LE SHIFT F
LEN none
LET L SHIFT E
LIST L SHIFT I
LOAD L SHIFT O
LOCATE LO SHIFT C
LOG none
KEYWORD ABBREVIATION
LOOP LO SHIFT O
MID$ M SHIFT I
MONITOR MO SHIFT N
MOVSPR M SHIFT 0
NEW none
NEXT N SHIFT E
ON GOSUB ON GO SHIFT S
ON GOTO ONG SHIFT o
OPEN O SHIFT p
PAINT P SHIFT A
PEEK PE SHIFT E
PEN P SHIFT E
PI none
PLAY P SHIFT L
POINTER PO SHIFT I
POKE PO SHIFT K
POS none
POT P SHIFT O
PRINT none
PRINT# P SHIFT R
PRINT USING US SHIFT I
PUDEF p SHIFT U
RCLR R SHIFT c
RDOT R SHIFT D
READ RE SHIFT A
RECORD R SHIFT E
REM none
RENAME RE SHIFT N
RENUMBER REN SHIFT U
RESTORE RE SHIFT S
RESUME RES SHIFT u
RETURN RE SHIFT T
RGR R SHIFT G
RIGHTS R SHIFT I
RND R SHIFT N
RREG R SHIFT R
RSPCOLOR RSP SHIFT C
RSPPOS R SHIFT S
RSPR none
RSPRITE RSP SHIFT R
RUN R SHIFT U
RWINDOW R SHIFT w
SAVE S SHIFT A
SCALE sc SHIFT A
SCNCLR s SHIFT C
SCRATCH sc SHIFT R
SGN s SHIFT G
APPENDIXES 673
KEYWORD ABBREVIATION
SIN s SHIFT I
SLEEP s SHIFT L
SLOW none
SOUND s SHIFT O
SPC none
SPRCOLOR SPR SHIFT C
SPRDEF SPR SHIFT D
SPRITE s SHIFT P
SPRSAV SPR SHIFT S
SQR s SHIFT Q
SSHAPE s SHIFT S
STASH s SHIFT T
ST none
STEP ST SHIFT E
STOP ST SHIFT O
STR$ ST SHIFT R
SWAP S SHIFT W
SYS none
TAB( T SHIFT A
TAN none
TEMPO T SHIFT E
TI none
TI$ none
TO none
TRAP T SHIFT R
TROFF TRO SHIFT F
TRON TR SHIFT O
UNTIL U SHIFT N
USR U SHIFT S
VAL none
VERIFY V SHIFT E
VOL V SHIFT 0
WAIT w SHIFT A
WHILE w SHIFT H
WIDTH WI SHIFT D
WINDOW w SHIFT I
XOR X SHIFT 0
APPENDIX J
*Although there is no single equivalent command in BASIC 2.0, there is an equivalent multi-command
instruction. See your disk drive manual for these BASIC 2.0 conventions.
APPENDIX K
a) Function Name
b) Input Parameters
c) Output Parameters
d) Brief Description
e) Other required preparatory/post routines (or additional information)
The 8502 BIOS and User Function routines require certain values to be placed into
the Z80 microprocessor registers. In Chapter 5 you learned about the 8502 microproces-
sor registers: A, X, Y, Status (PSW), Stack Pointer (S) and Program Counter (PC). The
Z80 also has applicable registers. The Z80 registers are named as follows:
A (Accumulator)
BC
DE
HL
PSW (Status Word)
IX (X register)
IY (Y index register)
PC (program counter)'
SP (stack pointer)
6 AUXOUT
Bank: Oor 1
Input: C = ASCII Character to send to AUX device
Output: None
Function: Sends the character in C to ALL devices that are currently
assigned to the AUXOUT device. It waits for all assigned devices
to accept a character before exiting.
7 AUXIN
Bank: Oor 1
Input: None
Output: A = ASCII character from AUX device
Function: Reads a character from any ONE of the assigned AUXIN devices.
A scan of each assigned device is done until an input character
is found. The character is returned in the A register.
8 HOME
Bank: 0
Input: None
Output: None
Function: Homes the head on the currently selected disk drive. This
function sets the current track to 0 and does not move the head
of the disk.
9 SELDSK
Bank: 0
Input: C = Disk Drive (0-15) (A = 0)
E = Initial Select Flag (LSB)
Output: HL = Address of Disk Parameter Header (DPH) if drive exists.
HL = 000H if drive does not exist.
Function: Selects the disk drive whose address is in C as the current drive
for all further disk operations. If the LSB of the E register is a
zero, then this is the first logging of this disk. The disk type
(C64 CP/M, MFM or C128 CP/M) is checked and the DPB
parameters adjusted for the diskette currently in the drive.
10 SETTRK
Bank: 0
Input: BC = Track number
Output: None
Function: Register pair BC contains the track number to be used in the
subsequent disk access. This value is saved.
11 SETSEC
Bank: 0
Input: BC = Sector number
Output: None
Function: Register pair BC contains the sector number to be used in the
subsequent disk access. This value is saved. The value in BC
is the value returned by the sector translation routine (in HL).
12 SETDMA
Bank: 0
Input: BC = Direct memory access address
Output: None
Function: The value in BC is saved as the current DMA address. This is
the address where ALL disk reads or writes occur. The DMA
address that is set is used until it is changed by a future call to
this routine to change it.
13 READ
Bank: 0
Input: None
Output: A = 000H if no errors
A = 001H if nonrecoverable error
A = OFFH if media has changed
Function: Reads the sector addressed by the current disk, track and
sector to the current DMA address. If the data is read with no
errors then A = 0 on return. If an error occurs, the operation is
tried several more times, and if a successful read does not
occur then A is set to 001H. A test for media change is
performed each time this routine is called and A is set to -1 if
the media has been changed.
14 WRITE
Bank: 0
Input: C = Deblocking code (not used)
Output: A = 000H if no errors
A = 001H if nonrecoverable error
A = 002H if disk is read only
A = OFFH if media has changed
Function: Writes the sector addressed by the current disk track and
sector from the current DMA address. If the data is written with
no errors, then A is set to 0 on return. If an error occurs, the
operation is tried several more times, and if a successful write
does not occur, then A is set to 001H. A test for media change
is performed each time this routine is called and A is set to
-1 if the media has been changed. Also, if an attempt is made
to write to a read-only disk, then the A register is set to 002H.
15 LISTST
Bank: Oor 1
Input: None
Output: A = 00H if list device is not ready to accept a character.
A = OFFH if list device is ready to accept a character.
Function: This routine scans the currently assigned list devices and returns
with A set to OFFH if ALL assigned devices are ready to accept a
character. If any assigned device is not ready then A is set
to 00H.
APPENDIXES 681
16 SECTRN
Bank: 0
Input: BC = Logical sector number (0-n)
DE = Translation table address (from DPB)
Output: HL = Physical sector number
Function: This routine converts the physical sector number to a logical
sector number. If no translation is needed then it moves the
BC register to HL and returns.
17 CONOST
Bank: Oor 1
Input: None
Output: A = OFFH if Ready
A = 000H if not Ready
Function: This routine scans the currently assigned console devices and
returns with A set to OFFH if ALL assigned devices are ready
to accept a character. If any assigned device is not ready then
A is set to 000H.
18 AUXIST
Bank: Oor 1
Input: None
Output: A = OFFH if console character present
A = 000H if no console character
Function: Checks the status of the current AUXIN device. If any of the
devices have a character available, OFFH is returned, otherwise
000H is returned.
19 AUXOST
Bank: Oor 1
Input: None
Output: A = OFFH if ready
A = 000H if not ready
Function: This routine scans the currently assigned AUXOUT devices and
returns with A set to OFFH if ALL devices are ready to accept a
character. If any assigned device is not ready then A is set
toOOH.
20 DEVTBL
Bank: Oor 1
Input: None
Output: HL = address of character I/O table
Function: This routine returns the address of the Character I/O table.
This table is used to name each of the driver modules and
set/control the baud rate and XON/XOFF logic for each driver.
Note: the device drive mechanism is used to replace the IOBYTE
used with CP/M 2.2.
21 DEVINI
Bank: Oor 1
Input: C = device number
Output: None
Function: Initializes the physical character device specified in the C
register to the BAUD rate in the DEVTBL.
22 DRVTBL
Bank: 0
Input: None
Output: HL = address of the drive table
Function: Returns the address of the drive table in HL (NOTE: first
instruction MUST be LXI H, DRVTBL). The drive table is a
list of 16 word pointers that point to the DPH for that drive. If
a drive is not present in the system, then the pointer for that
drive is set to zero.
23 MULTIO
Bank: 0
Input: C = multisector count
Output: None
Function: The multisector count is set before the track, sector, and DMA
address and the read/write of the sectors occur. A maximum
of 16K can be transferred by each multisector count.
24 FLUSH
Bank: 0
Input: None
Output: A = 000H if no errors
A = 001H if nonrecoverable error
A = 002H if disk is read-only
A = OFFH if media has changed
Function: This routine is used only if blocking/deblocking is done in the
BIOS. This code ALWAYS returns with A =000H.
25 MOVE
Bank: Oor 1
Input: HL = destination address
DE = source address
BC = count
Output: HL = HL(in) + BC(in)
DE = DE(in) + BC(in)
Function: Moves a block of data. Data to be moved is to/from the current
memory bank (or common) unless the XMOVE routine is
called first, then the move is an interbank data movement.
26 TIME
Bank: Oor 1
Input: C = 000H (Time Get) / OFFH (Set Time)
Output: None
APPENDIXES 683
Function: This function is called with C = 000H if the system time in the
SCB needs to be updated by the clock. If C = 0FFH, then the
time in the SCB has just been updated and the clock is
set to the SCB time. NOTE: HL and DE MUST be preserved.
27 SELMEM
Bank: Oor 1
Input: A = memory bank
Output: None
Function: Changes the current memory bank. This code MUST be in
common memory.
28 SETBNK
Bank: 0
Input: A = DMA memory bank
Output: None
Function: Sets the DMA bank for the next READ/WRITE operation.
29 XMOVE
Bank: 0
Input: B = destination bank
C = source bank
Output: None
Function: Provides the system with the ability to perform memory-to-
memory DMA through the entire system space.
30 USERF
Banks Oor 1
Input: A = function number, L = subfunction number
Output: Outputs depend on the called function or subfunction.
Function: This calls the user functions and 8502 BIOS routines, which
are defined in the Commodore 128 System Dependent User
Function section.
31 RESERV1
Bank: N/A
Input: N/A
Output: N/A
Function: Not available to the user.
32 RESERV2
Bank: N/A
Input: N/A
Output: N/A
Function: Not available to the user.
DATA STRUCTURES
WRT Contains the address of the sector write routine for this drive.
READ Contains the address of the sector read routine for this drive.
LOGIN Contains the address of the login routine for this drive.
INIT Contains the address of the first time initialization routine for this drive.
TYPE This byte is used by the BIOS to keep track of density and media type.
UNIT Contains the drive number relative to the disk controller.
XLT Contains the address of the sector translation table or zero if none.
-0- BDOS scratch area (9 bytes).
MF Media flag cleared to zero if disk logged in. BIOS sets to OFFH if media
has changed.
DPB Contains a pointer to the current DPB that describes the current media type.
CSV Contains a pointer to directory checksum area (one per disk drive).
ALV Contains a pointer to allocation vector area (one per disk drive).
DIRBCB Contains a pointer to a single directory Buffer Control Block (BCB).
DTSBCB Contains a pointer to a single data Buffer Control Block (BCB).
HASH Contains a pointer to an optional directory hashing table (FFFFH is
not used).
HBANK Contains a bank number of the directory hashing table.
APPENDIXES 685
SPT BSH BLM EXM DSM DRM ALO ALl CKS OFF PSH PHM
DRV Drive associated with this record. Set to OFFH when not used.
REC# Contains the absolute sector number of the buffer.
WFLG Set to OFFH when buffer contains data that must be written to disk.
00 Scratch byte used by BDOS
TRACK Physical track address of buffer.
SECTOR Physical sector address of buffer.
BUFFAD Address of the buffer associated with this BCB.
BANK Bank number of buffer associated with this BCB.
LINK Contains the address of the next BCB in this linked list. Set to zero if last.
a) Function Name
b) Input Parameters
c) Output Parameters
d) Brief Description
e) Additional Information
0 a) User Function 0: Read any Byte in RAM Bank 00
b) A = 0 (function number)
DE = 16 bit address to be read
c) C = Value read from address in RAM Bank 0
A = 0 on RETurn from routine
d) This reads a value from RAM BANK 0 ($0-$0FFF, $1000-$FFFF RAM)
and places it in register C.
I. a) User Function 1: Write Function in RAM Bank 0
b) A = 1 (function number)
DE = 16-bit address where write operation occurs
C = Value to be written to the address in Bank 0
c) A = 0 on RETurn from routine if write is successful
A = -1 ($FF) on RETurn from routine if write is unsuccessful
d) This function writes the value in register C to RAM in bank 0 specified
by the address in register pair DE. An error is flagged if a write to ROM
($0-$DFFFH) or the top page of memory ($FF00-$FFFF) is attempted.
II. a) User Function 2: Keyscan Function
b) A = 2 (function number)
c) B = -1 ($FF) if no key is pressed
B = Matrix position in the keyboard matrix table (if pressed)
A = Contents (character value) of matrix position whether A is lower- or
uppercase or containing the C O N T R O L key.
HL = Address (pointer) where A (contents of matrix position) is found
in memory
Address = Tablestart + (4 * B) + C (bits 1 and 0)
C = Returns control code information, where each bit has a specific
meaning as follows:
Bits 1 & 0
0 0 = lower case
0 1 = upper case
1 0 = shifted
1 1 = control key
APPENDIXES 687
d) The keyscan function allows the user to bypass the normal I/O BIOS
keyboard processing and check for a particular key or key sequence
being pressed.
e) Additional Information—Important Addresses:
$FD09 = Pointer to Tablestart (low byte first)
Each ASCII character has four coded definitions. Each key has a defined code for
the following:
a) lower case
b) upper case
c) shifted key and character
d) control key and character
ASCII$TBL: A B C D
ASCIISTBL: A B C D
NOTE: Subfunctions 122 and 124 and 126 must be direct Z80 calls. The
example routines provided in this section for subfunctions 122, 124 and 126
will not work. They are usually not user-accessible, and must run in BANK 0.
e) Additional Information: This subfunction assumes that both the data and
command channels have been opened previously. Data is written from
the buffer at $FE00H.
IV. 3.a) Subfunction 3: 1571 Read Set Up (MFM or GCR formats)
b) A = 4
L = 3
* VICTRACK = (1-35)—Variable for track number on disk
* VICSECTOR = (0-21)—Variable for sector number on disk
* VICDRV = —Variable for disk drive device number (See VICDRV
table above.)
* = Ranges apply to GCR format only. The ranges are different for
MFM disks depending on the manufacturer.
VIC$COUNT = Number of sectors to read (on the track)
c) VICDATA = 11 ($0B) if disk in drive has been changed
VICDATA = 12 ($0C) if drive is not a fast (1571) disk drive
VICDATA = 13 ($0D) if channel error occurs
VICDATA = 15 ($0F) if device is not present
If FAST ANDed with VICDRV = 0 meaning drive is a 1541
If FAST ANDed with VICDRV = 1 meaning drive is a 1571
d) This subfunction sets up the 1571 disk drive for a read operation.
However, the data transfer is not performed by the 8502 BIOS. The
data is transferred by the Z80.
e) Additional Information: To access the back side of an MFM disk set bit
7 ($80) of VICSECTOR. For MFM formats, a dash between the track and
sector on the display window means that the drive accesses the back
side of the disk. This is usually performed by the BIOS.
IV. 4.a) Subfunction 4: 1571 Write Set Up (MFM or GCR formats)
b) A = 4
L = 4
* VICTRACK = (1-35)—Variable for track number on disk
* VICSECTOR = (0-21)—Variable for sector number on disk
VICDRV = —Variable for disk drive device number. See VICDRV
table on previous page.
VICSCOUNT = Number of sectors to read
* = Ranges apply to GCR format only. The ranges are different for
MFM disks depending on the manufacturer.
c) VICDATA = 11 ($0B) if disk in drive has been changed
VICDATA = 12 ($0C) if drive is not a fast (1571) disk drive
VICDATA = 13 ($0D) if channel error occurs
VICDATA = 15 ($0F) if device is not present
If FAST ANDed with VICDRV = 0 meaning drive is a 1541
If FAST ANDed with VICDRV = 1 meaning drive is a 1571
d) This subfunction sets up the 1571 disk drive for a write operation.
However, the data is not performed by the 8502 BIOS. The data is
transferred by the Z80.
e) Additional Information. This is how the user should select between a
1541 and 1571 Drive. To access the back side of an MFM disk set bit 7
of VICSECTOR. To perform a write operation, the user will have to do
so in their application.
IV. 5.a) Subfunction 5: Interrogate 1541 or 1571 Disk Drive
b) A = 4
L = 5
VICDRV = (8-11)—Disk drive device number variable
c) VICDATA = lower four bits returns status for FAST read/write
(same as previous VICDATA Disk error codes, which
are listed in the Disk Error Status table on the next page).
= upper four bits return sector size for MFM disks
d) This subfunction interrogates the disk drive for the disk sector size
(MFM or GCR) and the drive status. In addition, this subfunction
initializes the FAST variable, closes and reopens the channel for the
corresponding drive, and clears the drive status.
IV. 6.a) Subfunction 6: Query to Disk
b) A = 4
L = 6
VICTRACK = (1-35)—Variable for track number on disk
VICSECTOR = (0-21)—Variable for sector number on disk
VICDRV = —Variable for disk drive device number
c) If error-free
VICDATA = lower four bits returns status for FAST read/write
= upper four bits return sector size for MFM disks and the
subfunction inputs 6 bytes into a memory buffer starting at
location $FE00 (and ending at $FEFF). These 6 bytes are
defined as :
1) $FE00-TRACK STATUS (on track below)
2) $FE01 -Number of Sectors
3) $FE02-Logical Track
4) $FE03-Minimum Sector Number (on this track)
5) $FE04-Maximum Sector Number (on this track)
6) $FE05-Physical Interleave
If an error occurs:
VICDATA = 11 ($0B) if disk in drive has been changed
VICDATA = 12 ($0C) if drive is not a fast (1571) disk drive
VICDATA = 13 (SOD) if channel error occurs
VICDATA = 15 ($0F) if device is not present
d) This subfunction queries the disk, and returns the disk status and sector
size (if MFM format). In addition, the buffer located between $FE00
and $FEFF receives 6 data items as described above.
APPENDIXES 699
GCR
OOOx = Ok.
0010 = Sector not found.
0011 = No Sync.
0100 = Data block not found.
0101 = Data block checksum.
0110 = Format error.
0111 = Verify error.
1000 = Write protect error.
1001 = Header block checksum.
1010 = Data extends into next block.
1011 = Disk ID mismatch/Disk change.
1100 = Drive is not fast (1571).
1101 = Channel Error.
1110 = Syntax.
1111 = No Drive present.
MFM
OOOx = Ok.
0010 = Sector not found.
0011 = No address mark.
0100 = Unused.
0101 = Data CRC error.
0110 = Format error.
0111 = Verify error.
1000 = Write protect error.
1001 = Header CRC error.
1010 = Unused.
1011 = Disk change.
1100 = Drive is not fast (1571).
1101 = Channel Error.
1110 = Syntax.
1111 = No Drive present.
Disk Error Status Table
IV. 7.a) Subfunction 7: Print characters to a serial bus printer
b) A = 4
L = 7
VICDRV = Printer number (either 4 or 5)
VICTRACK = Secondary address in which device is opened as
VICDATA = Character to be printed to the serial bus printer (if
VICCOUNT = 0)
c) VICDATA = -1 ($FF) if device is not present
d) This subfunction outputs characters to the previously opened serial bus
printer.
e) Additional Information: If the secondary address (which is normally 7)
is changed, the device is closed and reopened with the new secondary
address. If a serial bus error besides device not present occurs, the
channel is closed, reopened and the original operation is executed
again.
If VICCOUNT is not equal to zero, the data is printed from the buffer
pointed to by $FE0O. The number of bytes printed is supplied in VICCOUNT.
IV. 8.a) Subfunction 8: Format a 1541 or 1571 Diskette
b) A = 4
L = 8
DRIVE#
FAST
c) VICDATA
d) This subfunction formats a 1541 or 1571 diskette in the appropriate
drive. If FAST is enabled, (FAST ANDed with DRIVE# (not equal to
0)), the length of a disk command is fetched from memory buffer
location $FE00. The command starting at location $FE01 and ending at
the location specified by the length of the command in $FE00 is sent to
the drive. For example, if $FE00 = $06, the command in the memory
buffer between $FE01 and $FE06 is sent to the drive. All commands
have a " U 0 " preceding them, so only the command from the memory
buffer must be supplied.
IV. 9.a) Subfunction 9: User Call to 8502 Code Routine
b) A = 4
L = 9
VICOUNT = ($FD05) low byte address of 8502 routine (pointer to the
start of execution of the user routine)
VICDATA = ($FD06) high-byte address of 8502 routine
c) User defined outputs only
d) This is the routine that allows you to call an 8502 machine language
subroutine from Z80 mode. The 8502 coded routine is usually user
defined. It must execute in RAM bank 0 with the input/output registers
enabled. The MMU value = $3E. Control is transferred to the 8502
processor with the KERNAL disabled. If you want to call a C128
APPENDIXES 701
KERNAL routine, you must enable the KERNAL after you have trans-
ferred control to the 8502. Before you return to the Z80, you must
disable the KERNAL again.
When control passes from the Z80 to the 8502 processor, the Z80
is idle. To return control to the Z80 processor, place the customary
8502 RTS instruction at the end of your 8502 coded routine and control
is passed back to the Z80.
e) Additional Information: Once control is passed from the Z80 to the
8502, the 8502 is running at the speed of 1 Mhz. You can increase the
speed to 2 Mhz to speed up processing on the 8502 side of the
computer. However, YOU MUST RETURN TO 1 Mhz SPEED BEFORE
RETURNING TO THE Z80 OR A SYSTEM CRASH WILL OCCUR.
The nature of the timing of the two processors dictates this. If you
don't return to 1 Mhz, the clock cycle timing is thrown off and the
system crashes.
IV. lO.a) Subfunction 10: RAM Disk Read
b) A = 4
L = 10
c) Data is transferred to expansion RAM from RAM (BANK 0)
d) All expansion RAM registers must be set up prior to calling this routine.
IV. 11.a) Subfunction 11: RAM Disk Write
b) A = 4
L = 11
c) Data is transferred to expansion RAM from RAM (BANK 0)
d) All expansion RAM registers must be set up prior to calling this routine.
V. a) User Function 5: Read 40/80 Column Key
b) A = 5 (function number)
c) A = Value stored in $D505 (C128 Mode Configuration register)
If bit 7 is high (1), 40/80 key is up, otherwise 40/80 is down.
d) This function returns the value of location $D505, the mode configura-
tion register. Only bit 7 is significant as noted above. The 40/80 key is
not in the keyboard matrix table, so this function is dedicated to reading
its position.
VI. a) Functions 6 through 254 are not implemented.
b) none
c) HL = number of days (in binary) since 1/1/78
VII. a) User Function 255: System Date
b) A = -1 ($FF)
c) HL = number of days (in binary) since 1/1/78
d) By specifying A = - 1 , the system date is returned.
APPENDIX K
PART II
CALLING CP/M BIOS, 8502 BIOS AND
CP/M USER FUNCTIONS IN
Z80 MACHINE LANGUAGE
The Commodore 128 CP/M system allows you to call the CP/M BIOS, 8502 BIOS and
CP/M user functions in your own Z80 assembly language programs. However, in order
to program in Z80 assembly language, you need either an assembler or machine
language monitor. Many Z80 assemblers and monitors are available on the market;
however, the full featured Digital Research CP/M Plus (3.0) system now available on
the Commodore 128 comes with two Z80 assemblers, MAC and RMAC and CP/M plus
documentation. These programs or documentation are not included in the Commodore
128 Personal Computer package; refer to the Commodore 128 System Guide for infor-
mation on obtaining them.
Assuming you have the MAC and RMAC assemblers, you can now enter and
assemble Z80 assembly language programs. At this point, this reference guide must
make a substantially large assumption about its readers and their knowledge of Z80
assembly language programming. As you probably agree, this reference guide could not
possibly introduce Z80 machine language and thoroughly cover it. That is simply
beyond the scope of this book, considering how voluminous it is already. Your trusty
local bookstore undoubtedly offers several excellent books on Z80 programming. See
"Suggestions for Further Reading" for a few Z80 book titles.
Now that all the assumptions are out of the way, here's how to call a Z80 user or
BIOS function. First, the user function call.
recalling the CP/M jump vector on page 677 of Appendix K. The first 30 jumps (0-29)
are direct calls to CP/M BIOS routines. Jump number 30 is the call to the user functions, of
which user function 4 is the 8502 BIOS. The 8502 BIOS is a subset of the CP/M user
functions. The user function call is 1 of 31 system routine calls within the CP/M BIOS
jump table.
The following example calls user function 2 the keyscan function. The calling
routine starts at "waitkey" and the subroutine starts at "user$fun".
MVI useroffset,30
waitkey:
MVI A,2 ; load A reg. with function no. 2
CALL user$fun ;calls subroutine user$fun
INRB ;increment B—test for -1 if no key is pressed
JZ waitkey ;jump to wait key if none
DCRB ;decrement B if B not equal to 0
;this restores original matrix value
Rest of Program
user$fun
PUSHH ;place HL reg. pair on stack
LHLD 1 ;load address of jump vector 1 (WBOOT) into HL
MVI L, useroffset * 3 ;get offset of 90 (30*3) to L
XTHL ;exchange HL with top of stack
RET ;jump to new HL pointer location of routine
First, the main program loads the user function number (2) into the A register. To
call a user function, place the required input parameter, the user function number, in the
A register. If a subfunction is going to be called, like in user function 4 (8502 BIOS), the
input parameter for the subfunction number must be placed in L.
The second instruction in the main routine is a CALL to the subroutine user$fun.
However, in this example of the keyscan user function, the returned value B is -1 if
no key is pressed. If this is the case, B is incremented to zero and the main program
jumps to waitkey and scans the keyboard again. Otherwise, the rest of the program
continues processing.
When the subroutine is called, the first instruction saves the HL register pair, the
address pointer, on top of the stack. The next instruction loads memory location 1 (low)
and 2 (high) into register pair HL. The high byte points to the page number that the
jump vectors are on and the low byte is always 3 (Jump #1 the warm boot vector). Next
the jump number times 3 is loaded into the low byte (L) of register pair HL. This adds the
offset of 90 memory locations to base address of the CP/M BIOS jump table, which now
points to jump number 30, USERF.
The XTHL instruction exchanges the HL register pair with the top of the stack.
This places the computed address on the top of the stack and the entry values of HL
back in HL, When the RETurn instruction is reached by the Z80, program control is
therefore passed to the USERF vector, entry 30 in the CP/M BIOS jump table. When
the function has completed, control returns to the instruction immediately following the
CALL User$Fun instruction (INR B).
In order for the routines to be called successfully, the proper required input
parameters must be placed in the appropriate registers. The user function number must
be placed in the A register, the subfunction number is placed in L, if any. Additional
inputs must be placed in the correct register or variable prior to calling the user function.
The above example calls user function 2, the keyscan function. To call any other
user function, load the subfunction number into the A register. To call a subfunction,
load the L register with a subfunction number on the beginning of the main (calling)
program as follows:
MVI L, subfun
The way this program is written, the value in L, which you will load at the beginning
of the program with the above instruction, is placed back in L from the stack when the
XTHL is reached at the end of the subroutine. Use this example as a template when
calling other subfunctions. Make sure the proper inputs are present in the correct
locations prior to calling the user function.
Rest of Program
RET
bios$pb: ;BIOS variable table
db FUNNUM ;BIOS function no. variable
db AREG temporary A reg. storage
dw BCREG ;temp BC reg. pair storage
dw DEREG ;temp DE reg. pair storage
dw HLREG ;temp HL reg. pair storage
The first instruction in the main routine stores the function number 50 in the C
register. The system expects the input parameter C to be the BIOS function number. The
next instruction loads the address of the BIOS variable table bios$pb into register pair
DE. The third instruction calls BDOS function 50 through the call BDOS vector, the
standard BIOS vector through which all direct BIOS functions are called. BDOS
function 50 manipulates the banking in and out of RAM banks 0 and 1. This is the
recommended way of directly calling a CP/M BIOS function over that of the first
example which is designed primarily for calling user functions.
The variable table "bios$pb" contains the necessary input parameters required for
BDOS function 50. The " d b " 's stand for a byte of storage (like .byte in 8502) while the
" d w " 's stand for a 16 bit word (like .word in 8502).
This appendix is the only section of the book that crosses the Z80 programming
barrier. It at least points you in the right direction and gives you the "hooks" into the
machine level routines of the CP/M system. For more detailed Z80 programming
information see the "Suggestions for Further Reading" at the back of the book. For
more detailed CP/M information, refer to the Digital Research CP/M Plus documentation.
Ma nufacture rs
a b c d e al bl
Disk Type DSDD SSDD DSDD SSDD SSDD DSDD DSDD
Starting pos. (t/s) 2/1 1/1 0/10 1/0 3/1 2/1 1/1
Sector size (bytes) 256 512 512 512 1024 512 512
Vumber of sec/trk 32 8 10 10 5 20 8
Xumber of tracks 40 40 80 40 40 40 80
Block alloc size 2048 1024 2048 1024 1024 2048 2048
# of dir entries 128 64 128 64 64 128 64
# of resvd tracks 2 1 1 1 3 2 1
SS = single sided
DS = double sided
DD = double density
NOTE: Epson (a) labels sector numbers 1 through 16. The other Epson
QX10 format (al) labels sectors from 1 to 10. Both the top and bottom of
the disk are labeled the same way.
IBM (b) labels sector numbers 1 through 8. Both the top and
bottom of the disk are labeled the same way.
KayPro IV and KayPro II (c and d) label sector numbers 0 through
9 on top and 10 through 19 on the bottom.
These values are taken from the MFM table. The vector at $FD46 holds the
pointer to the start of the table labeled MFM$table. In the current system, these are the
formats that are read and write compatible on the Commodore 128 CP/M Plus system.
The following is a listing of the MFM format table:
APPENDIXES 707
db 8
db ' IBM-8 SS'
db 10
db 'KayPro II'
MFM Format Table
db S1024*2 + (5*2-8) +1 ; 1024 byte sect, 5 sect/trk
db MFM + S1024 + Type0 + C0 + Sl ; SSDD
dw 0 ; start on track 3 sector 1 (2 ale)
dpb 1024,5,40,1024,64,3 ; sect# 1 to 5
db 5 ;
db 'Osborne DD' ;7
MFM Format Table (continued)
APPENDIXES 709
APPENDIX K
PART III
THE CP/M SYSTEM MEMORY MAP
The following pages contain the Z80 CP/M memory map for the Commodore 128.
The memory map includes all the key CP/M locations, vectors and variable tables.
Use it as a guide through the Z80 CP/M system within the Commodore 128.
The CP/M memory map is available as a disk file "CXEQU.LIB" on the disk
that comes with the computer.
$*MACRO
false equ 0
true equ not false
banked equ true
EXTSYS equ false ; use external system as disk and char I/O
preSrelease equ false
date macro
db '6 Dec 85'
endm
The following equates are used by the interrupt driven keyboard handler
int$rate equ recv$data+1
RxD$buf$size equ 64
RxD$buf$count equ key$buffer+keySbuf$size
RxD$buf$put equ RxDSbufScount+1
RxD$buf$get equ RxD$bufSput+l
RxDSbuffer equ RxD$buf$get+l
tick$\'ol equ RxD$buffer+RxD$buf$size
equ tick5vol+l
buff$large equ 25
buffSsmall equ 7
buffSpos equ 7
ROM functions
macro x
rst 2 ! db x
endm
TCALL macro x
mvi l,x ! rst 4
endm
macro x
rst 3 ! db x
endm
RCALL macro x
mvi 1,x ! rst 5
endm
FRS40 equ offset to 40 column ROM functions
FR$trkS40 equ 6 Oh
FR$setScur$40 equ 62h
FR$line$paint equ 64h
FRSscreenSpaint equ 66h
FR$prt$msg$both equ 68h
FRSprtSdeSboth equ 6Ah
FR$update$it equ 6Ch
equ 6Eh
FRSASCII$to$pet equ 7 Oh
FR$cur$adr54O equ 72h
FR$curSadrS80 equ 74h
ER$look$color equ 76h
equ 78h
FR$blk$fill equ 7Ah HL passed on the stack
FR$blk$move equ 7Ch
FR$char$inst equ 7Eh
if bit 7 is 1 (MFM)
6 C0=0, Cl=l (side 2 #, 0 to (n/2)-l or n/2 to n-1)
5,4 00=128, 01=256, 10=512, 11=1024 byte/sector
3,2,1 disk type (MFM)
0 starting sector # ( 0 or 1}
if bit 7 is 0 (GCR)
6 unused (set to 0)
5,4 always 01 (256 byte sectors)
3,2,1 disk type (GCR)
TypeO = none, set track and sector as passed
Typel = C64 type disk
Type2 = C128 type disk
unused (set to 0)
SI 28 equ 0*16
S256 equ 1*16
S512 equ 2*16
S1024 equ 3*16
; 6510 conmands
control charactors
719
Variables
OOOD INTCTRL FD27 INTHL FD52 INTRATE FD3D INTSTACK FDFD INTVECTOR
FF03 IO FF03 IOO FF04 IO1 2471 KEYBUF FD63 KEYBUFFER
0010 KEYBUFSIZE DC01 KEYCOL 2472 KEYDOWNTBL FD4C KEYFXFUNCTION
FD5F KEYGETPTR FD61 KEYPUTPTR DC00 KEYROW FD53 KEYSCANTBL FD09 KEYTBL
3C02 LDBLKPTR 000A LF 0055 LF ARROW 0080 LFSHIFTKEY 3C00 LOADCOUNT
OOOE LTBLUE OOOD LTGREEN 000F LTGREY 000A LTRED OOOC MEDGRAY
0080 MFM FD46 MFMTBLPTR D500 MMU D500 MMUSTART D50B MMUVERSION
DS05 MODEREG 2489 MSGPTR 248B OFFSET 2404 OLDOFFSET 0008 ORANGE
0000 PAGEO D508 PAGE0H D507 PAGE0L 0001 PAGE1 D50A PAGE1H
D509 PAGE1L 2408 PAINTSIZE 241D PARMAREA40 241A PARMAREA80 2418 PARMBASE
FDOO PARMBLOCK FD48 PRTCONV1 FD4A PRTCONV2 2405 PRTFLG 0004 PURPLE
DFOO RAMDSKBASE D506 RAMREG OOFA RCMPHLDE OFOA RCOLORCONVERTTBL
FD51 RECVDATA 0002 RED DE01 RESET6551 3C36 RETRY FFEE RETURN6502
FFDC RETURNZ80 2410 REV40 DF02 RM128LOW DF03 RM128MID DF01 RMCOMMAND
DFOA RMCONTROL DF08 RMCOUNTHI DF07 RMCOUNTLOW DF06 RMEXTHI DF04 RMEXTLOW
DF05 RMEXTMID DF09 RMINTRMASK DFOO RMSTATUS 0000 ROM
0183 RREADMEMORY FD4F RS232STATUS
0186 RSETUPDATEADR OEFA RSTATUSCOLORTBL 0056 RTARROW
0010 RTSHIFTKEY 0189 RWAIT 0180 RWRITEMEMORY DE00 RXD6551
FD73 RXDBUFCOUNT FD76 RXDBUFFER FD75 RXDBUFGET FD74 RXDBUFPUT
003C RXDBUFS1ZE 0008 RXRDY 0000 SO 0001 SI 0030 S1024
0000 S128 0010 S256 0020 S512 1400 SCREEN40 002B SFDELETE
0001 SFEXIT 0028 SFINSERT 0055 SFLEFT 0056 SFRIGHT D400 SID
FD10 SOUND1 FD12 SOUND2 FD14 SOUND3 FD44 SOURCEBNK 0017 SPECIAL
FD22 STATENABLE DE01 STATUS6551 248D STRINGINDEX OOOC SYNCDATA
248E SYSFREQ 1000 SYSKEYAREA 2400 TEMPI 0005 TIMERAHIGH 0004 TIMERALOW
0007 TIMERBHIGH 0006 TIMERBLOW OOOB TODHRS 000A TODMIN 0009 TODSEC
0008 TODSEC60 FFFF TRUE DE00 TXD6551 0010 TXRDY 0000 TYPE0
0002 TYPE1 0004 TYPE2 OOOE TYPE7 0003 TYPECNTRL 0003 TYPEFIELD
0000 TYPELOWER 0002 TYPESHIFT 0001 TYPEUPPER OOOE TYPEX DE00 USART
FD25 USARTADR FD3D USERHLTEMP D000 VIC D800 VICCH 1000 VICCL
FD01 VICCMD 1000 VICCOLOR FD05 VICCOUNT FD06 VICDATA FD02 VICDRV
0008 VICFRMT 0000 VICINIT D02F VICKEYROW 0007 VICPRT 0006 VICQUERY
0001 VICRD 0003 VICRDF FFFF VICRESET 000A VICRMRD OOOB VICRMWR
2C00 VICSCREEN FD04 VICSECT 0005 VICTEST FD03 VICTRK 0009 VICUSERFUN
0002 V1CWR 0004 VICWRF 0001 WHITE FD50 XMITDATA FD4E XXDCONFIG
0007 YELLOW 00B1 Z80OFF 0(114(1 Z80ON FD1F OADRV FEOO (ffiBUFFER
FD1D (SCBNK FD1C (ffiCNT FD1E (ffiDBNK FD18 (©DMA 2402 (SOFF40
FD20 (5RDRV FD1A (ci'SECT FD16 (S'TRK
Variables
APPENDIXES 721
APPENDIX L
m cc <
SI I JEW ^fy^_^%_l
o— tMI(i9 IOOPF
cc PT^ ^- ^M
APPENDIXES 727
•»SNS!
I/O CONNECTOR
VIC TOUSA
, 74LS74A
PLAT &4C
MA® - M A I
APPENDIXES 729
RAM, ROM
SCHEMATIC 310378
GLOSSARY
Program: A series of instructions that direct the computer to perform a specific task.
Programs can be stored on diskette or cassette, reside in the computer's memory,
or be listed on a printer.
Program Line: A statement or series of statements preceded by a line number in a
program. The maximum length of a program line on the Commodore 128 is 160
characters.
Programmable: Capable of being processed with computer instructions.
PROM: The acronym for Programmable Read Only Memory. A semiconductor memory
chip whose contents can be changed.
Protocol: The rules under which computers exchange information, including the
organization of the units of data to be transferred.
Random Access Memory (RAM): The programmable area of the computer's memory
that can be read from and written to (changed). All RAM locations are equally
accessible at any time in any order. The contents of RAM are erased when the
computer is turned off.
Random Number: A nine-digit decimal number from 0.000000001 to 0.999999999
generated by the RaNDom (RND) function.
Read Only Memory (ROM): The permanent portion of the computer's memory. The
contents of ROM locations can be read, but not changed. The ROM in the
Commodore 128 contains the BASIC language interpreter, character-image pat-
terns and the operating system.
Register: Internal storage compartments with the microprocessor that communicate
between system ROM, RAM, and themselves.
Release: The rate at which the volume of a musical note decreases from the sustain
level to 0.
Remark: Comments used to document a program. Remarks are not executed by the
computer, but are displayed in the program listing.
Resolution: The fineness of detail of a displayed image, determined by the density of
pixels on the screen.
RGBI Monitor: A high-resolution display device necessary to produce the C128 80-
column screen format. RGBI stands for Red/Green/Blue/Intensity.
Ribbon Cable: A group of attached parallel wires, usually made up of 25 lines for
RS-232 communication.
Ring Network: A system in which all stations are linked to form a continuous loop or
circle.
RS-232: A recommended standard for electronic and electromechanical specifications for
serial communication. The Commodore 128 parallel user port can be treated as a
serial port if accessed through software, sometimes with the addition of an
interface device.
Screen: A video display unit, which can be either a television or a video monitor.
Screen Code: The number assigned to represent a character in screen memory. When
you type a key on the keyboard, the screen code for that character is entered into
screen memory automatically. You can also display a character by storing its
screen code directly into screen memory with the POKE command.
Screen Memory: The area of the Commodore 128's memory that contains the infor-
mation displayed on the video screen.
Serial Port: A port used for serial transmission of data; bits are transmitted one bit
after the other over a single wire.
Serial Transmission: The sending of sequentially ordered data bits.
Software: Computer programs (set of instructions) stored on disk, tape or cartridge that
can be loaded into random access memory. Software, in essence, tells the com-
puter what to do.
Sound Interface Device (SID): The MOS 6581 sound synthesizer chip responsible
for all the audio features of the Commodore 128.
Source Code: A nonexecutable program written in a higher-level language than
machine code. A compiler or an assembler must translate the source code into an
object code (machine language) that the computer can understand.
Sprite: A programmable, movable, high-resolution graphic image. Also called a Mov-
able Object Block (MOB).
Standard Character Mode: The mode the Commodore 128 operates in when you
tum it on and when you write programs.
Start Bit: A bit or group of bits that identifies the beginning of a data word.
Statement: A BASIC instruction contained in a program line.
Stop Bit: A bit or group of bits that identifies the end of a data word and defines the
space between data words.
String: An alphanumeric character or series of characters surrounded by quotation
marks.
Subroutine: An independent program segment separate from the main program that
performs a specific task. Subroutines are called from the main program with the
GOSUB statement and must end with a RETURN statement.
Subscript: A variable or constant that refers to a specific element in an array by its
position within the array.
Sustain: The midranged volume of a musical note.
Synchronous Transmission: Data communications using a synchronizing, or clock-
ing, signal between sending and receiving devices.
Syntax: The grammatical rules of a programming language.
Tone: An audible sound of specific pitch and waveform.
Transparent: Describes a computer operation that does not require user intervention.
Variable: A unit of storage representing a changing string or numeric value. Variable
names can be any length, but only the first two characters are stored by the
Commodore 128. The first character must be a letter.
Video Interface Controller (VIC): The MOS chip (8564) responsible for the 40-column
graphics features of the Commodore 128.
Voice: A sound-producing component inside the SID chip. There are three voices
within the SID chip so the Commodore 128 can produce three different sounds
simultaneously. Each voice consists of a tone oscillator/waveform generator, an
envelope generator and an amplitude modulator.
Waveform: A graphic representation of the shape of a sound wave. The waveform
determines some of the physical characteristics of the sound.
Word: Number of bits treated as a single unit by the CPU. In an 8-bit machine, the
word length is 8 bits; in a 16-bit machine, the word length is 16 bits.
INDEX
BASIN, 423-433 C128 BASIC, 219-220
Abbreviations, 670-673 BCC, 163 C64 BASIC, 222
ABS, 73 BCS, 163 multi-color. 233-237
Accumulator, 127-129 BEGIN/BEND, 28-29 programmable characters, 230-233
addressing, 138 BEQ, 164 screen location, 224, 234
loading, 147-148 BIOS (Basic Input Output System), screen memory data, 224-225
ACPTR, 422-423 486-489, 500, 677-683, 704- standard, 223-233
ADC, 162 705 CHKIN, 429-430
Addition, 19 BIT, 153-154, 164 CHRS, 74, 660-662
Addressing Bit map mode 112, 221, 222 CIA (6526) chip, 611-623
absolute, 138-139, 143 data, 241-243 control registers 622-623
accumulator, 138 80-column (8563) chip, 314-320 description, 611, 618-622
immediate, 138 multi-color, 243-245 electrical characteristics, 613-615
implied, 139 standard, 239-243 interface signals, 615-616
indexed, 141-143, 144-145 standard sprites, 283-284 interrupt control, 621-622
indirect, 143-145 video matrix, 240-241, 244 serial port, 620-621
modes, 137, 141-142 Bits timing, 616-617, 618-620
relative, 140-141 masking, 97-98 CINT, 410, 414
16-bit, 133-135 16-bit addressing, 133-135 CIOUT, 423
table, 161-179 values in a byte, 98-99 CIRCLE, 32-33, 115-116
zero-age. 139, 142 BLOAD, 29 CKOUT 430-431
ALT Mode. 497 BMI, 164 CLALL, 439
AND, 152, 162 BNE, 164 CLC, 166
APPEND, 27 BOOT, 29-30, 446-447 CLD, 166
Arithmetic BOX, 30, 113-114 CLI, 166
instructions, 151-152 BPL, 165 CLOSE, 33, 428^*29
operations. 18-20 BRK, 165 CLOSE ALL, 443
Arrays, 13, 16-18 BSAVE. 31 CLR. 33
ASC, 73. 660-662 BSOUT, 433 CLRCH, 431-432
ASL, 163 Buffer CLV, 166
Assembler, 126-127 control block, 685 CMD, 33
ATN, 73 routine. 93 CMP, 167
AUTO, 27 BUMP, 73-74 CMPSTA, 456
Bus COLLECT, 34
B architecture, 560-562 COLLISION, 34, 267
BACKUP 27-28 color data, 562 COLOR, 34-35, 116-117
BANK, 28 display, 562 Color mode
BASIC expansion, 635-637 extended background, 237-239
advanced programming techniques, loading, 567-568 memory map, 664
103-107 multiplexed address, 561 sprites, 283-285
color RAM in C128, 218 processor, 560 See also Memory, color RAM
color RAM in C64, 218-219 serial, 633-634 Commands. 12
C128 bit map mode, 221 shared address, 561-562 basic, 27-72
crunching of programs, 95 translated address, 560-561 CP/M, 481-482, 483
C64 bit map mode, 222 BVC, 165 format, 25-27
C64 character modes, 222 BVS, 165 graphics, 113-122
entering machine language subrou- machine language monitor, 186-194
tines through, 198-202 sprites, 267-270
error messages, 644-647 Cassette connector, 398 summary, 674-675
intelligent use of, 97 CATALOG, 31 See also specific commands
mixed with machine language, CHAR, 31-32, 115 Commodore 128. See C128 Mode
198-205 Character mode Commodore 64. See C64 Mode
placement of machine language accessing character ROM, 229 Complex Interface Adapter. See CIA
routines with, 203-205 character memory. 226-229, (6526) chip
relocating, 106 234-235 CONCAT, 35-36
screen memory in C128, 215-217 color data, 225-226, 235-237 C128 Mode. 2-3, 5
screen memory in C64, 217 color memory, 226 BASIC bit map mode. 221
C128 Mode (continued) DEY, 168 FETCH. 43
character memory, 219-220 DIM, 38 Files
character set availability. 222 DIRECTORY, 38-39 CP/M, 479-481
color RAM in BASIC, 218 Directory, 375 creating and storing, 376-378
CP/M disk format, 493^t94 Disk drive disk drive, 374-376
memory map, 502-540 copies. 482, 485 merging, 106-107
ROM cartridge, 471-472 device number, 378 FILTER, 43, 337-338, 348-351
screen memory in BASIC, 215-217 directory. 375 FNxx, 74
switching from mode to mode, 6 formatting, 372-373 FOR/TO/STEP/NEXT, 44
using C64 function key values, 95 replacing files or programs, 374 FRE, 75
Configuration Register. See Memory retrieving files or programs, 375-376 Function keys
Connectors, 652-657 saving programs, 373-374 changing, 95
Constants, 12-15 verifying files or programs, programming, 94
floating-point, 13 374-375 using C64 values, 95
integer. 13 Disk Parameter Block, 685 Functions, 72-86
string, 14-15 Division, 19-20 errors, 101
CONT. 36 DLCHR, 450 user, 685-704
Control codes, 666-668 DLOAD, 39 See also specific functions
COPY, 36 DMA CALL. 444-445
COS, 74 DO/LOOP/WHILE/UNTIL/EXiT. 39-40 G
CP/M, 676 DOPEN. 40 GET, 44-45
BIOS routines, 677-683, 704-705 DOS errors, 101, 648-651 GET#, 45
calling user function, 702-704 Dot matrix printer, 378-379 GETCFG, 452
commands, 481-482. 483 DRAW, 41, 117-118 GETIN, 438-439
control characters for line editing, Drive Table, 684-685 GETKEY, 45
482, 484 DSAVE, 41 GO64, 45
copies of disks and files, 482, 485 DVERIFY, 42 GOSUB, 45-46
disk organization, 491-495 GOTO/GO TO, 46
enhancements, 479 GRAPHIC, 46, 119
files, 479-481, 482,485 Editor. See Screen editor Graphics
keyboard scanning, 496-497 80-column (8563) chip, 292-334 commands, 113-122
memory map, 709-720 bit map mode, 314—320 power behind, 208-263
mode, 4 Block Write and Block Copy, programming, 110-122
requirements for system, 478 312-313, 333 system, 215-223
switching from mode to mode, 7 characters, 296-297, 301-304, 325, GSHAPE, 46, 119-120
system layout, 486-487 328, 333
system memory organization, cursor, 313-314, 326 H
489-491 display, 299-301, 326, 327-334 Hardware
system operations, 500 frames, 297-299 components, 4-5
system release, 8 RAM, 304-305, 309-313, 327-334 specifications, 556-641
CPX, 167 registers, 304-309. 324-334 system architecture, 557-558
CPY, 167 scrolling of screen. 320-323. See also specific components
C64 Mode, 3, 5, 444 328-331 HEADER. 47
BASIC bit map mode, 222 8502 microprocessor, 569-574 HELP, 47
BASIC character modes, 222 description. 569 HEXS, 75
color RAM in BASIC, 218-219 electrical specification, 569-571 Hexadecimal notation, 136-137
CP/M disk format, 492-493 processor timing, 571-574
input/output assignments, 546-554 END, 42 I
memory map, 540-554 ENVELOPE. 42, 336-337, 347-348 IF/THEN/ELSE. 47-48
ROM cartridge, 472 Environmental specifications, 568 INC, 169
screen memory in BASIC, 217 EOR, 152, 168 INDFET, 454-455
switching from mode to mode, 7 Errors INDSTA, 455
using function key values. 95 BASIC messages, 644-647 INPUT. 48
Cursor. 313-314, 326 DOS, 101, 648-651 INPUT*, 49
functions, 101 Input/output, 5, 372-400, 727
logic, 99 BIOS (Basic Input Output System),
Daisy wheel printer, 378 syntax, 99 486-489, 500, 667-683, 704-
DATA, 36 tracing of, 101 705
Datassette, 389-390 trapping of, 100 controller ports input, 390-393
Data structures, 684-685 See also Programming, debugging C64 assignments, 546-554
DCLEAR. 37 Escape codes, 669 Datassette output, 389-390
DCLOSE, 37 Exponentiation. 20 disk drive, 372-376
Debugging. See Programming Expressions, 18 files, 376-378
DEC, 168 arithmetic, 18 modem output, 381
DEF FN, 37 string. 24 output control. 393-394
DELETE. 38 pinouts, 394-400
Device numbers. 457 F printer output, 378-381
DEX, 168 FAST, 43 RS-232 channel, 382-388
INDEX 741
Half-Duplex Mode: In this mode, data can be transmitted in only one direction at a
time; if one device is sending, the other must simply receive data until it's time for
it to transmit.
Hardware: Physical components in a computer system, such as the keyboard, disk
drives and printer.
Hexadecimal: Refers to the base-16 number system. Machine language programs are
often written in hexadecimal notation.
Home: The upper-left corner of the screen.
IC: The abbreviation for Integrated Circuit. A silicon chip containing an electrical
circuit made up of components such as transistors, diodes, resistors and capaci-
tors. Integrated circuits are smaller, faster and more efficient than the individual
circuits used in older computers.
Increment: To increase an index variable or counter with a specified value.
Index: The variable counter within a programming loop.
Input: Data fed into the computer to be processed. Input sources include the keyboard,
disk drive, Datassette or modem.
Integer: A whole number (i.e., a number containing no fractional part), such as 0, 1,
2, etc.
Interface: The point of meeting between a computer and an external entity, whether an
operator, a peripheral device or a communications medium. An interface may be
physical, involving a connector, or logical, involving software.
I/O: The abbreviation for Input/Output. Refers to the process of entering data into the
computer, or transferring data from the computer to a disk drive, printer or storage
medium.
Keyboard: Input component of a computer system.
Kilobyte (K): 1024 bytes.
Local Network: One of several short-distance data communications schemes typified
by common use of a transmission medium by many devices at high-data speeds.
Also called a Local Area Network, or LAN.
Loop: A program segment executed repetitively a specified number of times.
Machine Language: The lowest-level language the computer understands. The com-
puter converts all high-level languages, such as BASIC, into machine language
before executing any statements. Machine language is written in binary form, which
a computer can execute directly. Also called machine code or object code.
Matrix: A two-dimensional rectangle with row and column values.
Memory: Storage locations inside the computer. ROM and RAM are two different
types of memory.
Memory Location: A specific storage address in the computer. There are 131,072
memory locations (0-131,071) in the Commodore 128.
MFM: The abbreviation for Modified Frequency Modulation, a method of storing
information on disks. The 1571 disk drives can read and write to MFM disks.
Microprocessor: A CPU that is contained on a single integrated circuit (IC). Micropro-
cessors used in Commodore personal computers include the 6510, the 8502 and
the Z80.
Mode: A state of operation.
Modem: The acronym for MOdulator/DEModulator. A device that transforms digital
signals from the computer into analog electrical impulses for transmission over
telephone lines, and does the reverse for reception.
Monitor: A display device resembling a television set but with a higher-resolution
(sharper) image on the video screen.
Motherboard: In a bus-oriented system, the board that contains the bus lines and edge
connectors to accommodate the other boards in the system.
Multi-Color Bit Map Mode: A graphic mode that allows you to display one of four
colors for each pixel within an 8 by 8 character grid. See Pixel.
Multi-Color Character Mode: A graphic mode that allows you to display four
different colors within an 8 by 8 character grid.
Multiple-Access Network: A flexible system by which every station can have access
to the network at all times; provisions are made for times when two computers
decide to transmit at the same time.
Null String: An empty character ( " " ) . A character that is not yet assigned a character
string code. Produces an illegal quantity error if used in a GET statement.
Octave: One full series of eight notes on the musical scale.
Operating System: A built-in program that controls everything a computer does.
Operator: A symbol that tells the computer to perform a mathematical, logical or
relational operation on the specified variables, constants or array elements in the
expression. The mathematical operators are + , - , *, / and | • The relational
operators are < , = , > , < = , > = and < > . The logical operators are AND,
OR NOT and XOR.
Order of Operations: Sequence in which computations are performed in a mathemat-
ical expression. Also called Hierarchy of Operations.
Parallel Port: A port used for transmission of data 1 byte at a time using 8 data lines,
one for each bit.
Parity Bit: A 1 or 0 added to a group of bits that identifies the sum of the bits as odd or
even, for error checking purposes.
Peripheral: Any accessory device attached to the computer such as a disk drive, printer,
modem or joystick.
Pitch: The highness or lowness of a tone that is determined by the frequency of the
sound wave. See Frequency.
Pixel: Computer term for picture element. Each dot that makes up an image on
the screen is called a pixel. Each character on the screen is displaced within
an 8 by 8 grid of pixels. The entire screen is composed of a 320 by 200 pixel
grid. In bit-map mode, each pixel corresponds to a bit in the computer's
memory.
Pointer: A register used to indicate the address of a location in memory.
Polling: A communications control method used by some computer/terminal systems
whereby a "master" station asks many devices attached to a common transmis-
sion medium, in turn, whether they have information to send.
Port: A channel through which data is transferred to and from the CPU.
Printer: Peripheral device that outputs the contents of the computer's memory onto a
sheet of paper. This paper is referred to as a hard copy.