0% found this document useful (0 votes)
45 views

Mappingthe Commodore 128

Uploaded by

Joe Pep
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views

Mappingthe Commodore 128

Uploaded by

Joe Pep
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 347

MAPPING

THE
COMMODORE
128
Ottis R. Cowper

COMPUTE! Publications,Inc
Part or ABC Consumer Magazines. Inc.
One of the ABC Publishing Companies

Greensboro, North Carolina


I

Copyright 1986^ COMPUTE! Publications, Inc. All rights reserved.

Reproduction or translation of any part of this work beyond that permitted by


Sections 107 and 108 of the United States Copyright Act without the permission of
the copyright owner is unlawful.

Printed in the United States of America

10 9 8 7 6 5 4 3 2 1

ISBN 0-87455-060-2

The author and publisher have made every effort in the preparation of this book to insure the ac-
curacy of the programs and information However, the information and programs in this book are
sold without warranty, either express or implied. Neither the author nor COMPUTE! Publications,
Inc. will be liable for any damages caused or alleged to be caused direct!)', indirectly, incidentally,
or consequentially by the programs or information in this book.

The opinions expressed in this book are solely those of the author and are not necessarily those of
COMPUTE! Publications, Inc.

COMPUTE! Publications, Inc., Post Office Boy 5406, Greensboro, NC 27403, (919)
275-9809, is part of ABC Consumer Magazines, Inc., one of the ABC Publishing Com-
panies, and is not associated with any manufacturer of personal computers. Commo-
dore 64 and Commodore 128 are trademarks of Commodore Electronics Limited,
Contents
Preface v
Introduction vii

1. Memory Organization 1
2. Common Working Storage Area 13
3. Bank 0 Working Storage Area 115
4. RAM Usage 181
5. BASIC ROM 195
6. Machine Language Monitor ROM 241
7. Screen Editor ROM 267
8. I/O Chip Registers, Color RAM, and Character ROM 331
9. Kernal ROM 509

Appendices 617
A. Interrupts/Todrf Heimarck 619
B. Bugs and Quirks in 128 ROM 625
C. Character, Screen, and Keyboard Codes 629
D. Musical Note Frequencies 645
E. 64/128 Memory Map Cross Reference 649
P. BASIC Keyword Index 657
G. Index of Locations and Routines 663
Preface
The random access memory (RAM), read-only memory (ROM),
and interface hardware chips in your Commodore 128 are like
postal stations with hundreds of thousands of mailboxes, each
of which can hold a single character, or byte of information.
This book is a map of all of those memory locations, but it's
more than just a list of addresses. It's also a thorough discus-
sion of how the locations are used by the computer, and, more
importantly, how you can take advantage of this information
to write more powerful programs.
Why a mapping book? The 128's BASIC is the most
powerful version yet in a Commodore computer. It could be
argued that there's little need to get "under the hood" of the
128, since most of the functions that required lots of PEEKs
and POKEs and an intimate understanding of internal hard-
ware functioning in earlier models like the Commodore 64 can
now be handled by simple BASIC statements on the 128.
While it may be true that the 128's advanced BASIC makes
programming easier, complete control over all the computer's
features belongs only to those who understand the secrets of
how the system operates. The purpose of this book is to un-
lock those secrets. The information is valuable for both begin-
ning BASIC and advanced machine language programmers.
The standard features provided by the 128 are often plain
vanilla, giving only the barest hint of the full capabilities of
the computer. Would you like to set up a Dvorak keyboard
that will work with almost any program? See the discussion of
the keyboard table pointers in Chapter 2. How about an 80-
column X 50-line screen display on your RGB monitor? The
explanation of the VDC chip registers in Chapter 8 explains
the necessary steps. Do you want to learn how the computer
sends data over the serial bus? The process is described in
Chapter 9. In fact, you'll find here the answers to most of your
questions about the 128. And these answers are written in un-
derstandable, clear prose.
This book is the result of painstaking disassembly and de-
ciphering of the Commodore 128 ROMs—a task that required
gallons of midnight oil. Commodore's BASIC and operating
system are now nearly ten years old. The ROM routines have
many twists and turns where various Commodore program-
mers have made additions and enhancements along the way.
Although the 128 is internally quite different from the Com-
modore 64, there are similarities. As a result, several previous
COMPUTE! books for the 64 provided invaluable assistance in
attempts to understand some of the intricacies. I'm particularly
indebted to Sheldon Leemon for Mapping the Commodore 64,
and to Dan Heeb for his two volumes of Commodore 64 and
V1C-20 Tool Kit: BASIC and Kernal.
Every effort has been made to insure that the information
provided here is accurate, but in a project of this size and
scope it is inevitable that some errors will creep in. Please
send any corrections you may discover to the attention of the
Book Editor at COMPUTE! Publications in Greensboro. You
can also send electronic mail messages concerning this book to
CompuServe user ID 73317,1143 or to BIX (Byte Information
Exchange) user name ottis.
I'd like to salute my wife Gail for moral and logistical
support far above and beyond the call of duty. I'd also like to
thank the COMPUTE! staff for patience shown when this
project dragged on months longer than anticipated. Finally, I'd
like to dedicate this book to George and George, departing
and arriving as the work took shape.

VI
Introduction
This memory map is a guide to the way a Commodore 128 in
128 mode uses and manipulates its RAM and ROM. No at-
tempt is made here to provide detailed coverage of the 128's
64 mode. A Commodore 128 in 64 mode doesn't just emulate
a Commodore 64; for all practical purposes it is a 64, with
completely separate Kernal and BASIC ROM. The memory
map of the Commodore 64 mode (and its BASIC 2.0) is cov-
ered in complete detail in COMPUTERS Mapping the Commo-
dore 64. However, Appendix E discusses those 128 features
available in 64 mode, and provides a cross reference of impor-
tant memory locations for 64 and 128 modes—information
that will be useful in translating Commodore 64 machine lan-
guage routines for use in 128 mode.
Nor does this book make any attempt to map the way the
128's CP/M mode uses memory. CP/M is a large and com-
plex operating system, and a CP/M mode memory map would
easily fill another entire volume. Moreover, the major portion
of CP/M is loaded from disk instead of being permanently
stored in ROM. As a result, CP/M is subject to more frequent
modification; so far, in the short life of the 128, there have
been at least three major revisions. Detailed technical infor-
mation on Commodore 128 CP/M is available in the book
CP/M Plus User's Guide /Programmer's Guide/System Guide,
available directly from Commodore.
Because this book is intended as a reference for intermedi-
ate to advanced BASIC and machine language programmers,
no attempt is made to provide simple explanations of all the
concepts discussed. The discussions assume familiarity with
elementary computer concepts such as bits and bytes, and
with memory quantity units such as a page (256 bytes) or a K
(kilobyte, 1024 bytes). The book also assumes familiarity with
the binary and hexadecimal numbering systems, although dec-
imal equivalents are usually provided.
Hexadecimal numbers in the text are always preceded by
a dollar sign ($), the standard 8502 nomenclature for hex.
Decimal numbers appear without any prefix. When you see a
pair of numbers separated by a slash (/), the first number is

vu
decimal and the second is hexadecimal, unless otherwise indi- data is to be retrieved or in which data is to be stored,
cated. This book uses the machine language monitor's conven- whereas a vector points to the address of a routine to be
tion of preceding binary numbers with a percent (%) sign. For executed.
example, %11 indicates the binary value equivalent to decimal A flag is a memory location in which individual bits are
3, not decimal 11. used to signal particular conditions. A binary bit can have one
When you see numbers mentioned in this book, it should of two conditions, %0 or %1 (also referred to as clear and set,
be obvious from the context whether the number refers to an respectively). The term comes from the analogy of flags, like
address or a value. Where there could have been confusion, the those on rural mailboxes, that can be either lowered or raised
terms value and location or address specify what is meant. In (there's no half-mast in binary). An example is the active
keeping with common practice, only two hexadecimal digits are screen flag, location 215/$D7. Bit 7 of the location is clear
generally used when discussing addresses in the first page of (%0) when the 40-column display is active, or set (%1) when
memory (zero page). That is, addresses 0-255 are usually writ- the 80-column display is active. (You'll find that flag locations
ten as $00-$FF. Four hexadecimal digits are used for all other often use bit 7 because that bit can be tested very easily in
addresses. For example, location 256 will be written as $0100, machine language with the BMI and BPL instructions.)
By nature, the computer prefers to deal with whole num- Chapter 1 provides a brief introduction to the way the
bers and doesn't handle fractions easily. Floating point is the 128 arranges and manages its memory resources. That chapter
method used to manipulate whole and fractional decimal and Chapter 4 are the only chapters in the book intended to
numbers in 128 BASIC. Floating point also enables very large be read from beginning to end. The remaining chapters de-
numbers to be handled in only a few bytes. All mathematical scribe the use or function of various areas of memory and
operations in BASIC are performed in floating point. (When should be used as an encyclopedic reference. The chapters
you specify integer variables in a mathematical operation, the generally cover memory in ascending address order, starting
integer value is converted to floating point for the operation; with zero page in Chapter 2 and ending with the Kernal jump
then the result is reconverted to integer format.) However, be- table at the very top of memory in Chapter 9. Each entry in
cause floating point is a rather complex subject, it is not ex- Chapters 2-9 consists of the decimal and hexadecimal address
plained in detail in this book even though it is mentioned of the location or routine; a label, if one is commonly used; a
extensively in Chapter 5. If you are interested in the inner short statement of the function of the location or routine; and
workings of floating point, refer to the excellent discussion of a short description of how the location or routine is used.
the topic in COMPUTED VIC-20 and Commodore 64 Tool Kit:
BASIC, by Dan Heeb. Although not written specifically for the
128, all the information about floating point applies to BASIC
7.0 as well.
Several terms used freely in this book need clarification.
Most locations discussed in Chapters 2 and 3 are either point-
ers, vectors, or flags. Pointers and vectors refer to a pair of
memory locations that hold an address. Two-byte address val-
ues in pointers and vectors are stored in low-byte/high-byte
order. That is, the least significant byte of the address should
be stored in the first byte of the pointer or vector, and the
most significant byte of the address in the second pointer or
vector byte.
The difference between pointers and vectors is that a
pointer (as the name implies) points to an address from which
IX
vm
Memory
Organization
The memory arrangement of a Commodore 128 in 128 mode
is much different and more complex than that of any of its
Commodore predecessors. As a result, it's necessary to under-
stand how the 128 organizes and manages its memory resources
before beginning a detailed examination of how those re-
sources are used. Of the computer's three possible personal-
ities, 128 mode is the default. Unless you take some other
action—holding down the Commodore key, inserting a Com-
modore 64 cartridge, placing a CP/M boot disk in the drive—
the computer comes up in 128 mode when you turn it on. As
the native mode of the system, 128 mode makes the most
complete use of the available memory resources.
You might be interested to learn that, while 128 mode is
the default operating mode, the computer always starts out in
CP/M mode. When you first turn on power, the Z80 micro-
processor has control before the 8502 is allowed to take over.
There are only a few signs of this: two short routines are cop-
ied into bank 0 RAM. One, at 65488/$FFD0, is an 8502 ML
routine that surrenders control to the Z80; the other, at
65504/$FFEO, is a Z80 ML routine that surrenders control to
the 8502. There are no routines in any of the 128 mode ROMs
to perform this initialization. However, once the Z80 com-
pletes its initialization sequence, it turns the system over to
the 8502 and 128 mode, and does not go back to CP/M mode
unless a CP/M disk is booted.

128 Mode
The 128 mode configuration includes 128K of random access
memory (RAM) in two 64K blocks, a 28K BASIC interpreter in
read only memory (ROM), a 4K machine language monitor in
ROM, 4K of screen editor routines in ROM, 8K of Kernal op-
erating system routines in ROM, a 4K character pattern ROM,
and 4K of address space for hardware chip registers (with two
separate IK banks of color RAM). The design also provides for
up to 32K of additional ROM internally and up to 32K of
ROM on cartridge. The operating system can support two ad-
ditional 64K banks of RAM, although the 128's design makes
no provision for adding memory chips. In sum, that's 373K of
address space, as illustrated in Figure 1-1.
This entire 373K address space must be manipulated by
the 8502 microprocessor that is the brains of the 128, but an
8502 can directly access only 64K of memory at a time. So
how is 128 mode even possible?

Memory Management Unit


The key is the MMU (Memory Management Unit), a special
chip designed by Commodore's engineers to control the mem-
ory elements that are visible to the processor. The MMU is as-
sisted by a companion device, the PLA (Programmable Logic
Array). The PLA accepts a variety of system timing and con-
trol signals and combines them in various ways to create new
control signals, taking the place of many separate discrete
logic gates. Together, these chips assemble a 64K assortment
of RAM, ROM, and I/O chips for the microprocessor to
manipulate. The MMU is described in detail in Chapter 8, but
the central feature of its memory control system is the configu-
ration register. The value stored in this register, or in a related
preconfiguration register, determines what elements the pro-
cessor sees where. Only the 64K of memory elements defined
by the MMU is available to the processor at any given time.
Figure 1-2 illustrates the defined function of each bit in the
register.
Since the configuration register is a standard eight-bit lo-
cation, it can hold 256 different values (0-255/$00-$FF); thus,
there are theoretically 256 possible configurations of memory
resources in a Commodore 128. Fortunately, not all of the pos-
sibilities are equally useful, so you don't have to concern your-
self with learning them all. The designers of the 128 operating
system selected 16 of the most useful arrangements and de-
fined them as banks.
Banks are a central feature of the 128, Banks are not fixed
physical arrangements of RAM and ROM. Instead, the 128's
banks are illusions created by the MMU to allow the micro-
processor to manipulate much more memory than would oth-
erwise be possible. There's nothing particularly sacred about
the defined banks—you are free to create your own custom
configurations (see the discussion of the MMU in Chapter 8 Table 1-1. Standard Bank Configurations
for details)—but it is usually more convenient to work in one
of the predefined banks. Table 1-1 shows the bank configura- Configuration
tions defined by the 128's operating system. Register
Bank Setting Addresses Contents
0/$00 63/$3F $0000-$FFFF RAM from block 0
Figure 1-2. MMU Configuration Register i/$oi 127/$7F $0000-$03FF RAM from block 0
$0400-$FFFF RAM from block 1
2/$02 191/$BF $0000-$03FF RAM from block 0
$0400-$FFFF RAM from block 2
3/$03 255/SFF $0000-$03FF RAM from block 0
$0400-$FFFF RAM from block 3
4/$04 22/$16 $0000-$7FFF RAM from block 0
$8000-$CFFF Internal function ROM
$D000-$DFFF I/O block
$E000-$FFFF Internal function ROM
86/$56 $0000-$03FF RAM from block 0
5/$05 RAM from block 1
$0400-$7FFF
$8000-$CFFF Internal function ROM
$D000-$DFFF I/O block
$E000-$FFFF Internal function ROM
150/$96 $0000-$03FF RAM from block 0
6/$ 06
$0400-$7FFF RAM from block 2
$8000-$CFFF Internal function ROM
$D00O-$DFFF I/O block
$EO00-$FFFF Internal function ROM
7/$07 214/$D6 $0000-$03FF RAM from block 0
$0400-$7FFF RAM from block 3
$8000-$CFFF Internal function ROM
$D0O0-$DFFF I/O block
$E000-$FFFF Internal function ROM
8/$08 42/$2A $0000-$7FFF RAM from block 0
$8000-$CFFF External function ROM
$D000-$DFFF I/O block
$E000-$FFFF External function ROM
9/$09 106/$6A $0000~$03FF RAM from block 0
$0400-$7FFF RAM from block 1
$8000-$CFFF External function ROM
$D000-$DFFF I/O block
$EO00-$FFFF External function ROM
Configuration This banking system would be too unwieldy to be usable
Register were it not for another capability of the MMU. Notice in the
Bank Setting Addresses Contents table that the contents of addresses 2-1023/$0002-$03FF are
10/$0A 170/$AA $0000-$03FF RAM from block 0 the same in all banks—RAM from block 0. (This particular
$0400-$7FFF RAM from block 2 feature is controlled by the MMU's RAM configuration register
$8000-$CFFF External function ROM rather than by the configuration register.) The common area of
$D0O0-$DFFF I/O block RAM is another key to the operation of the 128. Since the area
$EO00-$FFFF External function ROM
is visible to all banks, a collection of machine language sub-
11/$OB 234/$EA $0000-$03FF RAM from block 0 routines is copied here from Kernal ROM when the system is
$0400-$7FFF RAM from block 3 initialized. These common subroutines, along with the fact that
$8000-$CFFF External function ROM the MMU makes itself visible in every bank, allow routines in
$D00O-$DFFF I/O block one bank to retrieve, store, and compare data in any other bank;
$E000-$FFFF External function ROM
12/$0C 6/$06 $0000-$7FFF RAM from block 0
to call subroutines in another bank; or to jump directly to
routines in other banks. See the INDFET, INDSTA, INDCMP,
$8000-$BFFF Internal function ROM JSRFAR, and JMPFAR entries in Chapter 2.
$C00O-$CFFF System ROM (screen
editor) Actually, the operating system's banking scheme promises
$DO00~$DFFF I/O block more than the 128 is able to deliver at this time. Of the four
$E00O-$FFFF System ROM (Kernal) 64K blocks of RAM in the general operating system specifica-
13/$0D 10/$0A $0000-$7FFF RAM from block 0 tion, only two (blocks 0 and 1) are present in the current ver-
$8000-$BFFF External function ROM sion of the 128. The operating system was designed to leave
$CO00-$CFFF System ROM {screen open a gateway to future enhanced versions (perhaps a Com-
editor} modore 256). The circuit board doesn't provide for the addi-
$D0O0-$DFFF I/O block tion of RAM chips to populate blocks 2 and 3, nor does the
$EO00-$FFFF System ROM (Kernal) current version of the MMU actually support them (bit 7 of
14/$0E l/$01 $0000-$3FFF RAM from block 0 the configuration register has no effect). Thus, banks 2, 3, 6, 7,
$4000-$CFFF System ROM (BASIC 10, and 11 can be dismissed outright. If you try to access block
7.0, ML monitor, screen 2 RAM (banks 2, 6, or 10), what you'll see is block 0 RAM, so
editor) banks 0 and 2, 4 and 6, and 8 and 10 are identical. An at-
$D000-$DFFF Character ROM tempt to access block 3 will show block 1, so banks 1 and 3, 5
$E0O0-$FFFF System ROM (Kernal) and 7, and 9 and 11 are also identical.
15/$0F 0/$00 $0000-$3FFF RAM from block 0 You should be aware that connecting one of the Commo-
$4000-$CFFF System ROM (BASIC dore memory expansion modules (the 1700 for 128K or the
7.0, ML monitor, screen 1750 for 512K) won't fill in these missing blocks of RAM.
editor) Memory in the expansion modules isn't connected directly to
$D00O-$DFFF I/O block the computer's address lines. Instead, it must be accessed indi-
$E00O-$FFFF System ROM (Kernal) rectly via the RAM Expansion Controller (REC) chip in the
Exceptions: In all banks, locations $0000 and $0001 are the 8502 processor's on-chip
I/O port direction and data registers, and locations $FFOO-$FF04 are MMU configura- module. See Chapter 8 for more information about the REC
tion and load configuration registers. and memory expansion modules. Memory in the expansion
modules is also arranged in banks, but you shouldn't confuse
these with the internal RAM blocks.
Banks 4, 5, and 12 are useful only if you have a function
ROM chip installed in the free socket on the circuit board. Banks
8, 9, and 13 are useful only if you have a 128 ROM cartridge Figure 1-3. Normal Bank Configurations
(called an external function ROM) plugged into the expansion
port. If you attempt to access one of these ROM areas with no
ROM chip installed, you'll get only random, unpredictable
data. Since both internal and external function ROMs for the
128 are relatively rare, you can ignore those banks as well,
unless you are writing a program specifically to put into ROM.
That leaves only four standard bank configurations which
are generally useful: 0, 1, 14, and 15. Figure 1-3 shows the
contents of these banks. All the memory areas mapped in this
book appear in one or more of these banks. The lower IK of
block 0 RAM is the heavily used common area of RAM which
appears in every block. It's covered in Chapter 2. The next 7K
of block 0 (1024-7167/$0400-$lBFF) is used as working stor-
age by a variety of Kernal and BASIC routines. This area, visi-
ble in banks 0, 14, and 15, is covered in Chapter 3. Other
RAM usage (banks 0 and 1} is discussed in Chapter 4. Chapter
5 covers BASIC ROM, visible in banks 14 and 15. Chapters 6
and 7 cover the machine language monitor and screen editor,
respectively—both also visible in banks 14 and 15. Chapter 8
covers two of the possibilities for addresses 53248-57343/
$D000-$DFFF: the I/O block (including VIC-II chip color
RAM) and character pattern ROM. Chapter 9 covers the
Kernal ROM seen in banks 14 and 15.
There is one memory selection function not controlled by
the MMU. The 128 has two separate IK banks of color RAM,
both seen at the same addresses, 55296-56319/$D800-$DBFF
in the I/O block. Bits 0 and 1 in the 8502 processor's on-chip
data I/O port (location l/$01) determine which block will be
seen by the processor and by the VIC chip. See the entry for
location l/$01 in Chapter 2 for more information.

11
10
Common Working
Storage Area
The 128's memory management hardware has the ability to
create common areas of memory—areas where the same
memory will be seen regardless of the bank configuration. The
system allows up to 16K at both the top and bottom of the
processor's address space to be made common. However, the
operating system uses only part of this capability, setting up a
IK common area at the bottom of memory, locations 0-1023/
$0000-$03FF. No matter what bank configuration you choose,
the same block 0 RAM will be seen at these locations. It is this
common area, and especially the common routines in page 2,
that makes the 128's bank-switching operating system possible.

Zero Page: BASIC and Kernal Working


Storage
0-255/$00-$FF
The first 256 memory locations—collectively known as zero
page—are special in any computer based on a 6502-family
microprocessor like the 128's 8502. The processor has several
special addressing modes which use this area. The zero-page
addressing modes not only require less memory (two bytes per
instruction instead of three); they also execute faster. As a re-
sult, system ROM routines make extensive use of these modes.
Nearly every address in this page of memory is used by one
or more system ROM routines. In fact, you'll notice in the en-
tries for this page that a number of locations have multiple
functions, and some have multiple entries.
One of the biggest challenges for machine language pro-
grammers is finding sufficient free space in zero page for their
programs. Only four locations in the entire page (251-254/
$FB-$FE) are completely unused by any system routine. Most
of the locations in the range 10-143/$OA-$8F are used only
by BASIC, not by the Kernal. Thus, many of those locations
are free for machine language programs that do not require

15
$00 $01

BASIC. You should be aware that any value stored in zero 1 $01 R85O2
page will be wiped out during a reset. The RAMTAS routine Data register for processor's on-chip I/O port
[$E093], part of the reset sequence, clears locations 2-255/ Each of the seven I/O lines on the 8502 microprocessor has a
$02-$FF to zero. (You can prevent this by holding down the corresponding bit in this location (bit 7 is unused). The direc-
RUN/STOP key during the reset which will cause the RAMTAS tion of data flow on the lines is controlled by location $00. If
step of the reset sequence to be skipped. In this case, the sys- an I/O port line is set for input, the corresponding bit here
tem will be left in the machine language monitor after the re- will reflect the state of the input line: %0 if the line is low (0
set rather than in BASIC.) volts), or %1 if the line is high ( + 5 volts). While a line is set
Unlike other Commodore computers, the 128 has the abil- for input, values written to the corresponding bit have no ef-
ity to make the 8502 see zero page anywhere in memory. The fect. If an I/O port line is set for output, its state will be con-
MMU (memory management unit) chip has a feature which al- trolled by the corresponding bit in this location. Storing a %0
lows the processor to exchange zero page with another page in the bit forces the output line to a low (0 volts) state, while
so that references to zero page are directed to the alternate storing a %1 in the bit sets the line to a high ( + 5v state).
page, and references to addresses in the alternate page are di- The I/O lines are connected as follows:
rected to zero page. See the discussion of the MMU in Chapter Bits 0-1: The lines connected to these bits control which of the
8 for details. The 128 does not normally make use of this fea- two IK blocks of color memory will be visible at 55296-56319/
ture; the default position for zero page is at the true zero-page
$D800-$DBFF when the I/O block is selected. For this pur-
locations.
pose, the lines should always be configured as outputs. Unlike
The first two addresses in this page have a special func- in the Commodore 64, these bits have no effect on whether
tion. The 8502 processor has a built-in I/O port, and it sees RAM or ROM is selected at a given address. In the 128, mem-
the registers for that port at locations 0-l/$00-$01. References ory management is the domain of the MMU chip. See Chapter
to those addresses always affect the port; the processor will 8 for more information.
never see the first two bytes of RAM. These locations are not Bit 0 controls which block the processor sees, while bit 1
affected by the page-swapping feature. Regardless of where controls which block the VIC chip sees. Setting either bit to
the remainder of zero page is currently seen, locations 0-1 are %0 selects block 0, while a setting of %1 selects block 1. The
used exclusively to control the internal port.
setting of these bits is established during the screen-setup por-
tion of the screen IRQ routine [$C194], That routine sets both
0 $00 D8502 bits to %1 for text mode (GRAPHIC 0), or for the text portion
Data direction register for processor's on-chip I/O port of the split-screen modes (GRAPHIC 2 or GRAPHIC 4). For
Bits 0-6 in this location control the direction of data flow for the bitmapped modes (GRAPHIC 1 or GRAPHIC 3) or for the
the seven I/O (input/output) lines on the 8502 microprocessor bitmapped portion of the split-screen modes, bit 1 is set to
chip, labeled P0-P6. Setting a bit to %0 makes the correspond- %0. Thus, the VIC sees different blocks of memory for the
ing line an input, and its state can be read at the correspond- modes, and drawing on the bitmapped screen will not disturb
ing bit position in location $01. Setting a bit to %1 makes the colors on the text screen. To manipulate these bits in other
corresponding line an output, and its state will be controlled ways, the screen-setup portion of the IRQ routine must be dis-
by the setting of the corresponding bit position in location abled. Refer to the discussion of the color memory area in
$01. The value here is initialized to 47/$2F by the IOINIT Chapter 8 for details on switching color blocks.
routine [$E109], part of both the reset and RUN/STOP-
Bit 2: The line for this bit, known as the CHAREN line, deter-
RESTORE sequences. This sets lines 0-3 and 5 for output and
mines whether the VIC chip will see character ROM in its cur-
lines 4 and 6 for input. Since only seven lines are provided,
rent video bank. For proper functioning, the line should be
bit 7 is not used. That bit will retain whatever value is written
configured as an output. While this bit is %0, the VIC chip
to it, but its setting has no effect.
16 17
$01 $02

will see character ROM beginning at an offset of 4096/$1000 MTR line, is turned off. Setting this bit to %0 turns on the 9-
from the start of the bank. The uppercase/graphics set will volt power supply to the motor. The setting of this bit is con-
appear to occupy locations with offsets of 4096-6143/ trolled by a shadow location, the cassette motor interlock at
$1000-$17FF, and the lowercase/uppercase set will appear at 192/SCO.
offsets of 6144-8191/$1800-$lFFF. The character sets will be Bit 6: The line for this bit is connected to the CAPS LOCK key
visible in all VIC video banks, not just banks 0 and 2 as was on the keyboard. The line should be configured as an input to
the case in the Commodore 64. Only the VIC chip will see the read the state of this key. The bit will return a %1 while the
character ROM at these addresses; the processor will still see key is in the up position (CAPS LOCK off), and a %0 when
the locations as RAM or system ROM, depending on the ad- the key is down (CAPS LOCK on). The status of this bit is
dress and bank configuration. read by the SCNKEY routine [$C55D] during each system
To disable this feature and allow the VIC chip to see IRQ, and bit 4 of location 211/$D3 will be assigned the oppo-
RAM at the character set image addresses, the CHAREN bit site setting of this bit.
must be set to % 1 . However, this cannot normally be done di-
rectly because this bit has a shadow at location 217/$D9. Dur- Bit 7: There is no I/O port line connected to this bit, so the
ing the text mode-setup portion of the screen editor IRQ value here is meaningless. The bit always returns a %0 when
routine [$C194], the value of bit 2 of the shadow location is read.
copied into this bit. Thus, to change this bit you should set bit
2 of the shadow location instead. If the screen-setup portion of 2 $02 BANK
the IRQ routine is disabled (by storing the value 255/$FF in Target bank for JMPFAR and JSRFAR
location 216/$D8, for example), the setting of this bit can then The value here determines the bank to which the JMPFAR
be changed directly. The IRQ routine always sets this bit to routine [S02E3] will jump. Because the JSRFAR routine
%1 for bitmapped screen modes or for the bitmapped portion [$02CD] calls JMPFAR as a subroutine, the value here also de-
of split-screen modes. termines the destination bank for a JSRFAR. This location
should be loaded with the number (0-15) of the desired bank
Bit 3: The line for this bit is connected to the CASS WRT (cas- before either JMPFAR or JSRFAR is used.
sette write) line of the cassette port. The setting of this bit de- The BASIC SYS statement is implemented using JSRFAR.
termines whether a signal is being written to the tape. For this In that case, the value here is set from the value in location
purpose, the line must be configured as an output. See Chap- 981/$03D5, which holds the parameter from the most recent
ter 9 for more information about the tape routines. BANK statement (15/$0F by default). The BASIC routine that
Bit 4: The line for this bit is connected to the CASS SENSE searches for a token in the runtime stack [$4FAA] also uses lo-
(cassette button sense) line of the cassette port. If the port line cation 2/$02 for temporary storage.
is configured as an input, this bit can be read to determine When the monitor is entered at the break entry point
whether any buttons are currently pressed on the Datassette. [$B003], this location is loaded with the bank number in
When no buttons are pressed (or when no Datassette is con- which the system was operating when the BRK opcode was
nected to the port), this bit will be % 1 . Pressing any button encountered. When the monitor is entered at the cold-start en-
will change this bit to %0. Unfortunately, the bit merely de- try point [$B000], as by the BASIC MONITOR command, this
tects whether buttons are pressed, and cannot indicate which location is initialized to 15/$0F (for bank 15). The monitor R
specific buttons. If you press FAST FORWARD when in- command displays the value in this location as the first hexa-
structed to press PLAY, the 128 won't notice the difference. decimal digit of the PC value. The register change (;) com-
mand can be used to alter the value stored here. The value
Bit 5: The line for this bit controls the CASS MTR (cassette determines the bank for the monitor G (go to routine) and J
motor) line of the cassette port. When this bit is % 1 , the (jump to subroutine) commands, which use JMPFAR and
power supply to the cassette motor, provided via the CASS JSRFAR, respectively.
18 19
3-4 $03-$04 $05 5

3-4 $03-$04 PC The contents of the status register upon return from the
Target address for JMPFAR and JSRFAR target routine are stored in this location before return from
The values here determine the address to which the JMPFAR JSRFAR, so you can read this location to determine the exit
routine [$02E3] will jump. Because the JSRFAR routine status of the routine. This is useful because system routines
[$02CD] calls JMPFAR as a subroutine, the value here also de- often use status register bits, particularly carry, to return infor-
termines the destination address for a JSRFAR. These locations mation about the success of the operation performed by the
should be loaded with the desired address before either routine.
JMPFAR or JSRFAR is used. Contrary to the normal order of
address bytes, the high byte of the target address should be Figure 2-1. 8502 Processor Status Register
stored in location 3/$03 and the low byte in location 4/$04.
When the monitor is entered at the break entry point
[$3003], these locations are loaded with the program counter
contents stored on the stack when the BRK opcode was en-
countered. Because of the way the microprocessor handles
BRK, this value will be two bytes beyond the address of the
BRK ($00) opcode. When the monitor is entered at the cold-
start entry point [$B000], as by the BASIC MONITOR com-
mand, these locations are initialized to 45056/$B000 (the cold-
start entry address). The monitor R command displays the
value in these locations as the four rightmost hexadecimal dig-
its of the PC value. The register change {;) command can be
used to alter the value stored here. The value determines the
target address for the monitor G (go to routine) and J (jump to
subroutine) commands, which use JMPFAR and JSRFAR,
respectively.
The BASIC 7.0 version of the SYS statement allows you
5 $05 S-REG to specify a status register value, which will be placed in this
Status register storage for JMPFAR and JSRFAR location before the JSRFAR to the specified address. The
The value in this location is transferred to the processor's sta- RREG statement can be used to read the value here. (The sta-
tus register when a routine is called with JMPFAR [$02E3]. Be- tus register value returned by RREG is actually the contents of
cause JSRFAR [$02CD] also uses JMPFAR, the value here will this location.)
also determine the initial status register value for a routine When the monitor is entered at the break entry point
called with JSRFAR. You can use this location to set up par- [$B003], this location is loaded with the status register contents
ticular entry conditions for the target routine. For example, stored on the stack when the BRK opcode was encountered.
certain system routines behave differently depending on When the monitor is entered at the cold-start entry point
whether the carry bit, bit 0 of the status register, is clear (%0) [$BO00], as by the BASIC MONITOR command, this location
or set (%1) when the routine is called. You can specify the en- is initialized to zero. The monitor R command displays the
try setting of the carry bit by setting bit 0 of this location. Fig- value in this location under the heading SR. The register
ure 2-1 shows the function of the various status register bits. If change (;) command can be used to alter the value stored here.
you don't need any special entry conditions, it's best to set The value determines the status register contents for the moni-
this location to 0/$00. tor G (go to routine) and J (jump to subroutine) commands,
which use JMPFAR and JSRFAR, respectively.

20 21
6 $06 $08 8

6 $06 A_REG to determine the exit X register value. The JSRFAR routine it-
Accumulator storage for JMPFAR and JSRFAR self uses the X register after return from the target routine, so
The value in this location is transferred to the processor's ac- you must look to this location for the X register value from the
cumulator {A register) when a routine is called with JMPFAR target routine.
[$02E3J. Because JSRFAR [$02CD] also uses JMPFAR, the The BASIC 7.0 version of the SYS statement allows you
value here will also determine the initial accumulator value for to specify an X register value, which will be placed in this lo-
a routine called with JSRFAR. You can use this location to set cation before the JSRFAR to the specified address. The RREG
up a particular entry value for the target routine. The contents statement can be used to read the value here. (The X register
of the accumulator upon return from the target routine are value returned by RREG is actually the contents of this
stored in this location before return from JSRFAR, so you can location.)
read this location to determine the exit accumulator value. The When the monitor is entered at the break entry point
JSRFAR routine itself uses the accumulator after return from [$B003], this location is loaded with the X register contents
the target routine, so you must look to this location for the ac- stored on the stack by the IRQ/BRK handler [$FF17]. When
cumulator value from the target routine. the monitor is entered at the cold-start entry point [$B000], as
The BASIC 7.0 version of the SYS statement allows you by the BASIC MONITOR command, this location is initialized
to specify an accumulator value, which will be placed in this to zero. The monitor R command displays the value in this lo-
location before the JSRFAR to the specified address. The cation under the heading XR. The register change {;) command
RREG statement can be used to read the value here. (The ac- can be used to alter the value stored here. The value deter-
cumulator value returned by RREG is actually the contents of mines the X register contents for the monitor G (go to routine)
this location.) and J (jump to subroutine) commands, which use JMPFAR and
When the monitor is entered at the break entry point JSRFAR, respectively.
[$B003], this location is loaded with the accumulator contents
stored on the stack by the IRQ/BRK handler [$FF17]. When 8 $08 Y_REG
the monitor is entered at the cold-start entry point [$B000], as Y register storage for JMPFAR and JSRFAR
by the BASIC MONITOR command, this location is initialized The value in this location is transferred to the processor's Y
to zero. The monitor R command displays the value in this lo- register when a routine is called with JMPFAR [$02E3]. Be-
cation under the heading AC. The register change {;) com- cause JSRFAR [$02CD] also uses JMPFAR, the value here will
mand can be used to alter the value stored here. The value also determine the initial Y register value for a routine called
determines the accumulator contents for the monitor G (go to with JSRFAR. You can use this location to set up a particular
routine) and J (jump to subroutine) commands, which use entry value for the target routine. The contents of the Y regis-
JMPFAR and JSRFAR, respectively. ter upon return from the target routine are stored in this loca-
tion before return from JSRFAR, so you can read this location
7 $07 X_REG to determine the exit Y register value.
X register storage for JMPFAR and JSRFAR The BASIC 7.0 version of the SYS statement allows you
The value in this location is transferred to the processor's X to specify a Y register value, which will be placed in this loca-
register when a routine is called with JMPFAR [S02E3J. Be- tion before the JSRFAR to the specified address. The RREG
cause JSRFAR [$02CD] also uses JMPFAR, the value here will statement can be used to read the value here. (The Y register
also determine the initial X register value for a routine called value returned by RREG is actually the contents of this
with JSRFAR, You can use this location to set up a particular location.)
entry value for the target routine. The contents of the X regis- When the monitor is entered at the break entry point
ter upon return from the target routine are stored in this loca- [$B003], this location is loaded with the Y register contents
tion before return from JSRFAR, so you can read this location stored on the stack by the IRQ/BRK handler [$FF17]. When
22 23
9 $09 $0D 13

the monitor is entered at the cold-start entry point [$B000], as 10 $0A ENDCHR
by the BASIC MONITOR command, this location is initialized
to zero. The monitor R command displays the value in this lo- Working storage for various routines
cation under the heading YR. The register change (;) command This location is used for several different purposes by a variety
can be used to alter the value stored here. The value deter- of BASIC routines. It serves as a counter of the number of dig-
mines the Y register contents for the monitor G (go to routine) its in the ASCII representation of a number during the routine
and J (jump to subroutine) commands, which use JMPFAR and which interprets the characters as a numeric value [$50A0]. It
JSRFAR, respectively. holds the value of the character which terminates the search in
the routine which looks for a particular character in a BASIC
program line [$52A2], and in the one that puts a string into
9 $09 STKPTR the string pool [$869A]. It is also used for temporary storage of
Stack pointer storage for JSRFAR and monitor intermediate values while performing BASIC AND or OR op-
This location is used in the JSRFAR routine [$02CD] to record erations [$4C86].
the value in the stack pointer upon return from the target rou-
tine. The value here doesn't affect the setting of the stack 11 $0B TRMPOS
pointer; it merely records the exit value. Current screen column for TAB and SPC calculations
When the monitor is entered via either the cold-start entry The value in this location is used during the portion of the
point [$B000] or the break entry point [$B003], the current BASIC PRINT routine [$5554] that handles the TAB and SPC
stack pointer value is stored in this location. The monitor R functions. In the computation of the target column for the TAB
command displays the value in this location under the head- or SPC, this location will hold the current cursor column
ing SP. The register change (;) command can be used to alter value.
the value stored here. The value here is restored to the
microprocessor's stack pointer before the JMPFAR in the G (go 12 $0C VERCK
to routine) command routine. This location will hold the stack
pointer value after a J (jump to subroutine) command, since BASIC LOAD/VERIFY flag
that routine uses JSRFAR. The same routine is used to perform both the load and verify
operations, so this flag indicates which is being performed, A
zero value here indicates a load operation, and a nonzero
9 $09 CHARAC or INTEGR value indicates verify. The value here is set during the
Working storage for various routines LOAD/VERIFY [$9129] and DLOAD/DVERIFY [$A1A4]
This location is used for several different purposes by a variety routines. Both operations use the Kernal LOAD routine
of BASIC routines. It serves as temporary storage in the rou- [$F265], which has its own load/verify flag at location
tine which interprets ASCII characters as numeric values 147/$93.
[$50A0]. It holds the value of the desired search character in
the routine which searches for a particular character in a 13 $OD COUNT
BASIC program line [$52A2], and in the routine that puts a Working storage for various routines
string into the string pool [$869A]. It holds the low byte of the This location is used for different purposes by several BASIC
integer value generated in the BASIC INT routine [$8CFB]. It routines. It holds the most recently found token during pro-
is also used for temporary storage of intermediate values while gram tokenization [$430A]. In the routine that adds or deletes
performing BASIC AND or OR operations [$4C86], BASIC program lines [$4DE2], this location holds the length of
the current line. It is also used as a counter in the RREG rou-
tine [$50BD], and as a counter in the subroutines that find or
create array-variable elements.

24
25
14 $0E $15 21

14 $0E DIMFLG 18 $12 SUBFLG


Array dimension flag
Integer/subscript prohibit flag
This location is used during the routines that create array vari- This location is used during the routine to find or create a
ables to indicate whether the routines are being called to as variable [$7AAF] to specify whether integer or subscripted (ar-
the result of a DIM statement. For a DIM statement, this loca-
ray) variables are allowed. While the value here is zero, the
tion will contain a nonzero value; otherwise it will be set to
variable being evaluated can be of any type. The FOR and
0/$00. This flag is used in testing for the REDIM'D ARRAY
DEF routines store the value 128/$80 here. For FOR, this pre-
ERROR condition.
vents the use of integer or array variables as loop indexes. For
DEF, this restricts the function definition to floating point vari-
15 $OF VALTYP ables and also prevents the parentheses in the function defini-
Variable type flag tion from being interpreted as indicating an array variable.
This location is used to indicate the type of variable currently This location is reset to zero after each variable is evaluated,
being evaluated. A value of 0/$00 indicates that the variable and also during CLR [$51F8].
is numeric. A nonzero value indicates that the variable is
string type. During the routine that finds or creates a variable $13 INPFLG
[$7AAF], this location is set to 0/$00 if the variable is numeric
19
type, or to 255/$FF if it is string type. Input source flag
BASIC uses a common input handling routine [$56B2] for
READ, GET (including GETKEY and GET#), and INPUT (in-
16 $10 INTFLG cluding INPUT#). This location is used to indicate which oper-
Numeric variable type flag ation is being performed. The value here will be 152/$98 for a
If the variable currently being evaluated is numeric (see the READ operation, 64/$40 for a GET, or 0/$00 for an INPUT.
entry for location 15/$0F above), bit 7 of this location will be
used to indicate the numeric type. If that bit is %0, the vari- 20 $14 TANSGN
able is standard (floating point) type. If the bit is % 1 , the vari- Comparison type flag
able is integer type. During the routine that finds or creates a Tangent sign flag
variable [$7AAF], this location will be set to 0/$00 for floating- The value in this location is used during the string and num-
point variables or 128/$80 for integer variables. ber comparison routine [$4CB6] to specify the type of compari-
son being performed, A value here of 1 indicates greater than
17 $11 GARBFL (>), 2 indicates equal ( —), and 4 indicates less than (<). The
Working storage for various routines values are cumulative, so a test for greater than or equal (> —)
This location is used for different purposes in several BASIC would result in a value here of 3 (1 + 2). This location is also
routines. During string evaluation, it is used as a garbage- used during the TAN function routine [$9459] to indicate the
collection flag. A zero value indicates that no garbage collec- sign of the resulting value.
tion has been performed, while a nonzero value (1/S01)
indicates that garbage collection has taken place. The location 21 $15 CHANNL
is also used as a quote mode flag during LIST; a value of Logical file number for BASIC input and output
0/$00 indicates that quote mode is off, while a nonzero value The value in this location specifies the logical file from which
(l/$01) indicates that quote mode is in effect. In addition, this BASIC will receive input and to which BASIC will direct out-
location is used as temporary storage for the high byte of the put. The default value is 0/$00, which indicates input from
disk status variable during the evaluation of the reserved vari- the keyboard and output to the screen. (Logical file 0 is re-
able DS. served for the system's use; you cannot open logical file 0.)

26
27
22-23 $16-$17 $24-$25 36-37

Statements which get input or send output to other devices, 24 $18 TEMPPT
such as GET#, INPUT#, and PRINT*, will temporarily change Pointer into temporary string descriptor stack
the value here to the channel number specified in the statement. The value in this location points to the next available slot in
The CMD statement can also be used to change the value the temporary string descriptor stack at 27-35/$lB-$23. This
here and direct all output to a specified logical file. However, location can have the following values:
you can't depend on CMD (or POKEing a value here) to keep
all output flowing to the specified logical file. A number of Value Meaning
other BASIC statements reset the value here to 0/$00 each 27/$lB no entries (stack empty)
time they are executed, restoring default input and output de- 3O/$1E one entry
33/$21 two entries
vices. These statements include GET (and GET# and GETKEY), 36/$24 three entries (stack full)
INPUT#, and PRINT*.
25-26 $19-$1A LASTPT
22-23 $16-$ 17 LINNUM Pointer to most recent descriptor stack entry
Integer value of ASCII digit string These locations hold the address of the most recent entry in
These are very busy locations, since the routine which reads the temporary string descriptor stack at 27-35/$lB-$23. Loca-
ASCII characters from program text and converts the result to tion 25/$19 will hold the equivalent of the value in 24/$18
a two-byte line number value [$50A0] stores its results here. less three, and location 26/$lA will hold zero (it is assigned
Other routines which manipulate program lines, such as the this value during the BASIC cold-start sequence). For example,
one which adds or deletes program lines, will use these loca- when there are two entries on the stack, 24/$18 will hold $21,
tions to hold the line number. Any statement which reads a while these two locations will hold $1E and $00, correspond-
line number, including GOTO, GOSUB, LIST, and so on, will ing to address $001E, the address of the second entry in the
expect to find the target line number in these locations. The stack.
TRAP destination line number is held here during the ERROR
routine [$4D3C], and the COLLISION target line number is 27-35 $ lB-$23 TEMPST
held here during the GONE routine [$4A9F].
Temporary string descriptor stack
Machine language programmers can store line number The three 3-byte entries here hold descriptors (length plus a 2-
values in these locations, then jump into a BASIC routine at a byte pointer to the starting address of the string in the string
point beyond the line number evaluation step. For example, a pool) for strings being evaluated or assembled. For strings be-
machine language program can enter a BASIC program at any ing assigned to variables, the descriptor value generated here
line number by jumping into the GOTO routine with the tar- will be transferred to the variable table entry for that string,
get line number in these locations. The following section of
code performs the equivalent of GOTO 100: 36-37 $24-$25 INDEX
LDA #$64 ;Place line number in $16-$17. Multipurpose address pointer
STA $16 These locations are used as an address pointer by several
LDA #$00 BASIC routines, including the one at 927/$039F, which re-
STA $17
trieves characters from bank 0 (BASIC program text), and the
LDA #$0F ;Bank number for BASIC ROM (15). one at 951/$03B7, which retrieves characters from bank 1
STA $02 (BASIC string storage). Numerous BASIC routines call those
LDA #$59 ;Enter GOTO routine at $59FB. character retrieval routines, including the one which inserts or
STA $03
LDA #$FB deletes program lines [$4DE2] and the one which updates
STA $04 variable tags while making space for a new variable. The
JMP $02E3 ;Use JMPFAR to call routine.
28 29
38-39 $26-$27 $31-$32 49-50

pointer is also used in the LIST routine to read characters from 7169/$1CO1 when the graphics area is de-allocated and the
the keyword table, and in the floating-point routines to copy BASIC program text is moved back down to its original
floating values to and from the variable storage area in bank position.
1. In addition, location 36/$24 is used for temporary storage During the NEW and RUN routines, the CHRGET pointer
during formula evaluation, and location 37/$25 is used as a (61-62/$3D-$3E) is initialized with a value one less than the
pointer into the ROM keyword tables when tokenizing pro- address in these locations. You can store new values in these
gram lines [$43E2] or listing (detokenizing) program lines locations to change the starting position of BASIC program
[$5123]. text—for example, if you wish to reserve free memory space in
block 0 RAM below the program. However, two other steps are
38-39 $26-$27 INDEX2 required to properly initialize the system to use the new start-
Multipurpose address pointer ing position: You must also store the value 0/$00 in the loca-
These locations are used as an address pointer by the routine tion immediately before the address specified here (BASIC
at 960/$03C0 which fetches characters from BASIC program requires that program text be preceded by a zero byte), and
text in bank 0. That routine is called by several other BASIC you must perform a NEW to reset other pointers to reflect the
routines, including the one which adds or deletes program new start-of-BASIC position.
lines. These locations are also used by the ERROR routine During execution of BASIC'S SAVE and DSAVE routines,
[$4D3C] as a pointer to the specified error message in the mes- the value here determines the starting address of the data to be
sage table in ROM. saved.

40-44 $28-$2C RESHO 47-48 $2F-$3O VARTAB


Temporary storage area for multiplication and division Start-of-variables pointer
This area is used to hold intermediate values during the The value in these locations points to the first address in block
BASIC routines that perform floating-point multiplication and 1 RAM used for scalar (nonarray) variable storage. The value
division. here is initialized to 1024/$0400 during the BASIC cold-start
sequence, and no other system routine changes that setting.
45-46 $2D-$2E TXTTAB You can store new values in these locations to change the
Start-of-BASIC-program pointer starting position of the variable table—for example, if you
The value in these locations points to the first address block 0 wish to reserve free memory space for data storage in block 1
RAM used for BASIC program text. The value here is initial- RAM below the variables. However, to properly initialize the
ized to 7169/S1C01 during the BASIC cold-start sequence. In system to use the the new starting position, you must perform
the Commodore 64, the value here was initialized to the value a CLR to reset other pointers to reflect the new start-of-variables
in the Kernal MEMSTR pointer, the bottom of memory estab- position. During the CLR routine [$51F8] {which is also per-
lished during the Kernal reset sequence. However, the 128 al- formed during NEW and BASIC cold start), the start-of-arrays
ways initializes the same value here, without regard for the pointer (49-50/$31-$32) and the end-of-arrays pointer (51-51/
value in MEMSTR (2565-2566/$0A05-$0A06). $33-$34) are also set to the value in these locations.
The only Kernal routines that change the value here are
the ones that allocate or de-allocate a bitmapped graphics area 49-50 $31-$32 ARYTAB
for the GRAPHIC statement. When a bitmapped graphics area Start-of-arrays pointer
is allocated, BASIC program text is moved upward to start at The value in these locations points to the first address in block
16385/$4001, above the bitmapped graphics area at 7168-16383/ 1 RAM used for the storage of array variables, which is also
$1COO-$3FFF. In this case, the values in these pointers will be one location above the last address used for array variables.
adjusted accordingly. The value here will be reset to The value here is initialized to the start-of-variables value in

30
31
51-52 $33-$34 $3B-$3C 59-60

locations 47-48/$2F-$30 during the CLR routine [$51F8] performed to remove inactive strings. If garbage collection
(which is also performed during NEW and BASIC cold start). cannot remove enough unused strings to create free space be-
tween the address here and the one in 51-52/$33-$34, an
51 -52 $33-$34 STREND OUT OF MEMORY error occurs. The function FRE(l) will re-
Start-of-free-memory pointer turn the difference between the value here and the one in lo-
The value in these locations points to the lowest address in cations 51-52/$33-$34, the amount of free memory remaining
block 1 RAM available for the storage of strings, which is also for string storage.
one location above the last address used for array variables.
The value here is initialized to the start-of-variables value in 55-56 $37-$38 FRESPC
locations 47-48/$2F-$30 during the CLR routine [$51F8] Temporary pointer into the string pool
(which is also performed during NEW and BASIC cold start). These locations are used by the routines that add strings to the
When the value here equals the value in location 49-50/ string pool as a pointer to the currently referenced string, and
$31-$32, no arrays are being used. The function FRE(l) will as a pointer to the current string during the garbage collection
return the difference between the value here and the one in routines.
locations 53-54/$35-$36, representing the remaining amount
of memory available for string storage. When the value in
57-58 $39-$3A MAX_MEM_1
53-54/$35-$36 (the FRETOP pointer) reaches the value here,
Top-of-memory pointer
garbage collection is performed. If garbage collection cannot
remove enough unused strings to create free space between The value in these locations determines the highest address in
the address here and the one pointed to by FRETOP, an OUT block 1 RAM available for the string pool. (Actually, the ad-
OF MEMORY error occurs. dress value here will be one location beyond the highest loca-
tion used for the string pool.) The string pool is filled down-
ward from the address specified here. The value in locations
53-54 $35-$36 FRETOP 53-54/$35-$36 specifies the address of the bottom of the
Bottom-of-string-space pointer pool. When the value in those locations equals the value here,
The value in these locations points to the lowest address in the pool is empty. The BASIC cold-start routine initializes
block 1 RAM used for the string pool. All character strings these locations to 65280/$FFO0, one location beyond the high-
used in a BASIC program are stored in the area of block 1 be- est contiguous address in block 1 RAM (MMU registers are
tween the address pointed to in 57-58/$39-$3A and the ad- seen at 65280-65284/$FF0O-$FFO4 in all memory configura-
dress pointed to here—an area called the string pool. Each tions). You can reduce the value here to reserve memory at
active string here will have a descriptor in the variable array the top of block 1 for other purposes such as data storage.
table areas at the bottom of block 1, or in the temporary de- However, when you change the value here you should also
scriptor stack at 27-35/$lB-$23. The pool may also contain execute a CLR statement [$51F8] to reset the other string pool
inactive strings that the program is no longer using. The value pointers,
here is initialized to the top-of-memory value in locations
57-58/$39-$3A during the CLR routine [$51F8] (which is also 59-60 $3B-S3C CURLIN
performed as part of NEW and the BASIC cold-start sequence). Current BASIC line number
When the value here equals the value in location These locations hold the line number of the BASIC program
57-58/$39-$3A, no strings have yet been used. Strings are line currently being executed. After each program line is exe-
added from the top of memory downward. When the value cuted, the routine which executes BASIC program lines
here reaches the value in 51-52/$33-$34, garbage collection is [$4AF3] will load these locations with the number of the next
line to be executed. The value here is used by various other

32 33
61-62 $3D-$3E $43-$44 67-68

BASIC routines that need to know which line is currently be- 63-64 $3F-$40 FNDPNT
ing executed, The value here is stored in locations 4608-4609/ Working pointer for various routines
$1200-$1201 by the routine that processes STOP or END These locations are used as a working pointer into the runtime
[$4BCA]. The value stored in those locations will be trans- stack at 2048-2559/$0800-$09FF by the routines that search
ferred back here by the CONT routine [$5A60]. The value for tokens in the stack. The RENUMBER routine [$5AF8] uses
here will be stored in locations 4617-4618/$1209-$120A these locations as an end-of-program pointer. The PRINT
when an error is processed by the ERROR routine [$4D3C]. USING routine [$9520] uses the routine at 939/$03AB (which
The value in those locations will be transferred back here by uses these locations as a pointer) to retrieve characters from
the RESUME routine [$5F62], the template pattern string in block 1 RAM.
61-62 $3D-$3E TXTPTR 65-66 $41-$42 DATLIN
Pointer for main BASIC character retrieval routine Line number of current DATA statement
These locations serve as the pointer into BASIC text for the These locations hold the line number of the BASIC program
CHRGET routine, BASIC'S primary character retrieval routine. line containing the DATA statement from which DATA items
In earlier Commodore computers, the entire CHRGET routine are currently being read. These locations are updated by the
was in zero page. The 128's CHRGET is located higher in the subroutine that searches for the start of the next DATA state-
common area, beginning at address 896/$0380, and only the ment: [$57CA], called during execution of the READ state-
pointer is kept in zero page. CHRGET is designed to retrieve ment. The value here isn't used by any system routine, but it
the next nonspace character of BASIC text, so the first step in can be very helpful when you're debugging a program con-
CHRGET is to increment the address here. The routine also taining DATA statements. Whenever a program stops with an
has an alternate entry point called CHRGOT at 902/$0386, ILLEGAL QUANTITY or TYPE MISMATCH error message in
which retrieves the current character (the one at the address a line containing a READ statement, it's very likely that the
here) without incrementing the pointer. error is actually in the DATA line rather than the line speci-
The NEW, RUN, and LOAD routines all call the subroutine fied in the error statement (the one which contains READ).
[$5254] which initializes this pointer to one byte before the You can find the line number from which the last, possibly er-
start-of-BASIC value in locations 45-46/$2D-$2E. Because the roneous, DATA item was read using PRINT PEEK(65) + 256
CHRGET routine is so heavily used, many BASIC routines af- * PEEK(66).
fect the value here. For example, any of the routines which send
the program to another line, such as GOTO, GOSUB, THEN, 67-68 $43-$44 DATPTR
and so on, must replace the current value here with the ad- Pointer to next DATA item
dress of the target line. The value here is stored in locations These locations are used as a pointer to the address at which
4610-4611/$1202-$1203 by the routine that processes STOP the search for the next available DATA item will begin. The
or END [$4BCA]. The value stored in those locations will be subroutine that searches for the next DATA item [$57CA],
transferred back here by the CONT routine [$5A60]. The value called during execution of the READ statement, will update
here will be stored in locations 4622-4623/$120E-$120F the value here to point to the start of the next DATA item.
when an error is processed by the ERROR routine [$4D3C], The RESTORE statement, when used without a line number
The value in those locations may be transferred back here by parameter, resets the value here to the starting address of
the RESUME routine [$5F62]. BASIC program text (from locations 45-46/$2D-$2E), That
The value here is also used as a pointer for the alternate RESTORE subroutine is also called as part of the CLR routine,
character retrieval routine at 969/$03C9, which fetches the which in turn is called as part of RUN. Thus, the search for
current text character without CHRGET's test for character type. DATA items normally begins at the first program line. The

34 35
69-70 $45-$46 $4F 79

RESTORE statement can be used with a line number param- defined function) routine will load these locations with the ad-
eter to change the value here. In that case, the pointer value dress of the descriptor for the dummy variable in the function
will be reset to the starring address of the specified line. The definition,
specified line need not contain a DATA statement. It merely
specifies the line from which the search for the next DATA 75-76 $4B-$4C FORPNT
statement will begin. Variable descriptor pointer and working storage
These locations are used during the routine that assigns vari-
69-70 $45-$46 INPPTR able values (LET [$53C6]) as a pointer to the variable value or
Text pointer for input string descriptor. For numeric variables, the address here will
The common input routine [$56B2], used in the execution of be the location in block 1 RAM where the value will be
the GET, GETKEY, GET#, INPUT, INPUT*, and READ state- stored. For string variables, the address here will be the loca-
ments, uses these locations as a pointer to the characters to be tion in block 1 RAM where the length and pointer into the
read as input. The value here will be transferred into the string pool for the string will be stored. The FOR statement
CHRGET pointer at 61-62/$3D-$3E so that CHRGET can be uses the value here to find the address of the value for the
used to retrieve characters from the input. The GET, GETKEY, loop index variable.
and GET* statements will initialize the value here to For the WAIT statement [$6C2D], location 75/$4B holds
513/$0201, an input buffer location set to 0/$00 to cause the the test byte pattern and location 76/$4C holds the mask byte
input routine to read the next character. The INPUT and IN- pattern. Location 75/$4B is also used as an index into the cur-
PUT* statements will initialize the value here to 511/$01FF, a rent line during the routine to list BASIC program lines [$5123],
location immediately before the input buffer set to 44/$2C,
the code for the comma character. The actual input will be in 77-78 $4D-$4E VARTXT
the input buffer beginning at 512/$0200. The READ statement Temporary storage for text pointer
will initialize these locations with the starting address of the These locations are used for temporary storage for the
next DATA item (from locations 67-68/$43-$44). CHRGET pointer value from 61-62/$3D-$3E during the com-
mon input routine [$56B2], which uses CHRGET to retrieve
71-72 $47-$48 VARNAM characters from the input source location. Location 77/$4D is
Current variable name also used during the numeric expression evaluation routine
These locations are used during the routine to find or create a [$77EF] as a flag to indicate when the end of the expression
variable [$7AAF] to hold the compressed (two-byte) form of has been reached.
the specified variable name. This compressed form will then
be used as a search pattern to check whether a variable of the 79 $4F OPMASK
same name and type currently exists. If not, the characters Relational operator flag
here will be used as the name for the new variable. When the main expression evaluation routine [$77EF] finds a
relational operator (<, =, or >) in the current expression, it
73-74 $49-$4A VARPNT stores a value here indicating which operator has been found.
Pointer to variable descriptor For greater than (>) operations, the value here will be 1. For
These locations are used as a pointer to the first byte of the equals ( = ), the value will be 2; for less than (<) it will be 4.
descriptor for the variable—the address of the location just be- When the expression is evaluated, this value will be trans-
yond the two-character name in the variable table entry for ferred to location 20/$14.
the variable. The value here is set upon exit from the routines
to find [$7AAF] or create [$7B90] a variable. The FN (user-

36 37
80-81 $50-$51 $5D-^$5F 93-95

80-81 $5O-$S1 DEFPNT cold-start sequence with the value 76/$4C, the 8502 JMP
Defined function pointer and working pointer opcode. The function dispatch routine [$4BF7] loads 87-88/
These locations are used by the routine that retrieves bytes $57-$58 with the address of the routine that performs the de-
from the variable table entry for a function definition (FN). sired function operation. A JSR $0056 instruction then exe-
That routine [$42CE] uses these locations as a pointer for one cutes the function-handling routine.
of the bank 1 character retrieval subroutines [$03AB]. These
locations are also used as a working pointer by one of the 89-93 $59-$5D TEMPF1
routines that reads values during garbage collection. That rou- Floating-point work area
tine [$42FB] also uses a bank 1 data retrieval subroutine [$03AB]. These locations are used as a temporary floating-point work
The routine that allocates the bitmapped graphics area [$9F4F] area during the series evaluation routine [$9086] for the LOG,
uses these locations to hold the number of bytes that must be SIN, COS, TAN, and ATN functions. Location 89/$59 is also
moved upward to make room for the graphics area. used for temporary storage during the routine [$9D7C] which
subtracts the contents of one pair of bitmapped graphics stor-
80-84 $50-$54 TEMPF3 age locations from the contents of another pair of locations.
Temporary storage for floating-point value
These locations are used to temporarily hold the floating-point 90-91 $5A-$5B ARRYPNT
value of the exponent during the routine to handle the ex- Multipurpose working pointer
ponentiation (T) operator [$8FC1]. These locations are used as a pointer to the destination of text
being moved in the routine to add new BASIC program lines
82-83 $52-$53 DSCPNT to memory [$4DE2] and as a pointer into array space when
Variable address storage and working pointer making room for a new variable [$7B90]. They are also used to
The routine that creates space in the string poo] for a new string hold the line link value during RENUMBER [$5AF8].
variable uses these locations to temporarily store the address
of the variable table entry. These locations are also used as a 92-93 $5C-$5D HIGHTR
pointer by the routine that retrieves characters from the string Multipurpose address pointer
poo] for the LEFT$, RIGHT$/ and MID$ functions [$42D8]. These locations serve as a pointer for the routine that reads
the source text being moved in the routine to add new BASIC
85 $55 HELPER program lines. This routine [$42DD] uses one of the common
HELP flag bank 0 character retrieval routines [$039F]. The locations serve
Bit 7 of this location is tested in the routine which lists BASIC as a pointer in the routine to read source bytes when creating
program lines [$5123] to determine whether the line is being space for new variables. This routine [$42E2] uses one of the
displayed by LIST or by HELP. When the bit is % 1 , the sub- common bank 1 character retrieval routines [$03AB]. The loca-
routine at 22956/$59AC will be called to highlight the portion tions are used during the RENUMBER routine [$5AF8] to hold
of the line where the most recent error occurred. The HELP the number of the line currently being renumbered.
statement routine [$5986] sets bit 7 to %1 before it calls the
line-listing routine, and clears it to %0 afterwards. 93-95 $5D-$5F STR1
String length and pointer for MID$
86-88 $56-858 JMPER When MID$ is used as a statement [$5901] (to add characters
BASIC function execution vector to a string), these locations hold the descriptor of the original
This vector is used to execute the routines that handle BASIC string. Location 93/$5D holds the length, and locations
functions. Location S6/$56 is initialized during the BASIC 94-95/$5E-$5F hold the address and are used as a pointer.

38 39
94-98 $5E-$62 $63-$67 99-103

94-98 $5E-$62 TEMPF2 and 104/S68 for the bank value.) The starting address is sub-
Temporary storage for floating-point value tracted from the ending address, and the result is transferred
These locations are used to store an intermediate value from to 99-101/$63-$65. The value in those locations is then used
floating-point accumulator #1 (FAC1) during the series evalua- as a count of bytes to be affected by the operation. The
tion routine [$909C] for the EXP function. compare/transfer routine [$B231], which accepts three address
parameters, uses 102-104/$66-$68 as the pointer to the
source address for the compare or transfer and 96-98/$60-$62
94-95 $5E-$5F as the pointer to the destination address.
Working pointer for garbage collection Some monitor routines also make alternate use of some of
These locations are used as a pointer to the tag bytes for the these locations. The memory display routine [$B152] uses
current string during the routine that performs string pool gar- 96-98/$60-$62 as a count of lines to be displayed. During as-
bage collection [$92EA]. sembly [$B406], 99/$63 holds the length of the current in-
struction, and location 100/$64 holds the addressing mode
95 $5F DECCNT type. Locations 99-100/$63-$64 are used to unpack mnemon-
Decimal point position ics during disassembly [$B6A1], and 99/$63 serves as a
This location is used during the routine [$8E42] that creates a counter during directory display [$BB03].
character string representing the value in floating-point accu-
mulator #1 (FAC1) to hold the position within the string for 97-98 $61-$62 LOWTR
the decimal point. The location is also used as a loop counter Multipurpose address pointer
in the routine [$7E3E] to calculate the amount of memory A wide variety of BASIC routines use these locations as a
needed for an array. pointer. They serve as the pointer for a heavily used routine
[$42EC] to read characters from BASIC program text. (That
96-98 $60-$62 STR2 routine uses one of the common bank 0 character retrieval
Substring length and pointer for MID$ subroutines [$039F].) The routine is called by the routine
When MID$ is used as a statement [$5901] (to add characters which adds or deletes program lines [$4DE2], the one which
to a string), these locations hold the descriptor of the substring searches for a line number [$5064] (in which case the starting
to be added. Location 96/$60 holds the length, and locations address of the line is returned in these locations), LIST
97-98/$61-$62 hold the address and are used as a pointer. [$50E2], and DELETE [$5E87]. These locations also serve as
the pointer for a routine [$4300] to read values from the vari-
96-104 $60-$68 T0-T2 able table. (That routine uses one of the common bank 1 char-
Monitor zero-page pointers and working storage acter retrieval subroutines [$03AB].) The routine is called by
These locations are used by many routines in the monitor. The the routine [$7AAF] which searches the variable table to check
monitor routine [$B7CE] that determines the numeric value of whether a variable with a specified name already exists, and
a parameter in the input buffer leaves the value in locations the one [$7CAB] which performs a similar search for array
96-98/$60-$62 (in low- to high-byte order), so any numeric names. If an existing name is found, the address of the table
value in a monitor command is at least initially held there. For entry for the variable or array will be returned in these
monitor commands that accept two or more address param- locations.
eters, the first address is transferred into locations 102-104/
$66-$68, and the value there is then used as a working 99-103 $63-$67 FAC1
pointer to the byte to be read or written. (The monitor's indi- Floating-point accumulator 1
rect fetch [$B11A], indirect store [$B12A], and indirect compare These locations are the primary work area for all routines
[$B13D] routines use 102-103/$66-$67 for the address pointer which use floating-point math, which includes all of BASIC'S

40 41
104 $68 $70-$71 112-113

mathematical functions. Any numerical value used in a BASIC


program will be converted to a floating-point value here for 1OS $69 SGNFLG
further processing. The result of any BASIC operation which Sign flag during conversion
Count of terms in series evaluation
performs a numerical calculation will be held in these locations.
Floating-point notation is rather complicated. This method This location is used as a flag during the routine [$8D22] that
of representing numbers has three components: the mantissa, calculates the floating-point value equivalent of a string of
the base, and the exponent. You may be familiar with BASIC'S digit characters to indicate whether the string being converted
scientific notation. For example, the value 73,500 will be rep- has a leading negative sign. During the series evaluation rou-
resented as 7.35E4, BASIC'S shorthand for 7.35 X 104. In this tine [$909C], this location holds the number of terms in the
format, the 7.35 is the mantissa, the 10 is the base, and the 4 series.
is the exponent. In BASIC'S internal floating-point format, the
base value is 2; location 99/$63 holds the exponent, and loca- 106-110 $6A-$6E FAC2
tions 100-103/$64-$67 hold the mantissa. The exponent is Floating-point accumulator 2
held in excess-128 format, meaning that 129 has been added These locations are the second floating-point accumulator area,
to the exponent value. (This is a little trick to avoid having to used in those operations that require a second floating-point
deal with negative exponents.) To get the true exponent value, value. Location 106/$6A is the exponent and locations 107-110/
subtract 129. Only the lower 31 bits of the four-byte mantissa $6B-$6E are the mantissa. All operations that involve both ac-
value are used, and the mantissa is normalized—adjusted so cumulators will transfer the results to FAC1.
that its value is always effectively in the range 1-1.9999.
Thus, the formula for converting the FAC1 contents into a 111 $6F ARGSGN
decimal value is:
Sign of FAC2
value = (1 + (mantissa / (2 T 31))) * 2 t (exponent - 129) Bit 7 of this location indicates the sign of FAC2, just as loca-
The routine which converts the contents of FAC1 into a tion 104/$68 does for FAC1.
two-byte integer value will leave the results of the conversion 112 $70 ARISGN
in locations 102-103/$66-$67. Some routines which don't use
floating-point math use these locations for other purposes. Lo- Sign comparison flag
cations 102-103/$66-$67 are used as a pointer by the routine The routines that load values into FAC1 [$8A89] and FAC2
[$42E7] that reads values from the variable table. That routine [$8AB4] perform an exclusive-OR of the values in locations
uses one of the common bank 1 character retrieval subroutines 104/S68 and 111/$6F—the signs of the values in the respec-
[$03AB]. tive floating-point accumulators. Thus, this location will hold
0/$00 if both signs are positive or both are negative, or 255/
$68 $FF if the signs are different.
104 FACSGN
Sign of FAC1 112-113 $70-$71 STRNG1
Bit 7 of this location is used to indicate the sign of the value in Multipurpose address pointer
FAC1. The value here will be 0/$00 for positive values in These locations are used as an address pointer by the routine
FAC1 and 255/$FF for negative values. As long as the floating- [$42F1] which loads characters from strings in BASIC program
point value is held in the accumulator, this location will be text for transfer into the string pool. (That routine uses a com-
used to indicate its sign. When the floating-point value is mon bank 0 character retrieval subroutine [$039F].) The loca-
stored in a variable, the setting of this bit will be copied to the tions are also used as a pointer by the routine [$42F6] that
highest bit of the mantissa. Likewise, when a value is copied reads characters from the first string in a concatenation opera-
from a variable into the accumulator, the setting of bit 7 of the tion. (That routine uses a common bank 1 character retrieval
most significant byte of the mantissa is copied here. subroutine [$03AB].)
42 43
113 $71 $7A-$7C 122-124

113 $71 FACOV ized to 0/$00 (no graphics area) during the BASIC cold-start
Rounding flag for FAC1 sequence. When the graphics area is allocated, this location is
When a pair of floating-point mantissas are adjusted for a decremented (to 255/$FF). The only BASIC statement that re-
math operation, any extra bits that must be shifted out of the sets this location is GRAPHIC CLR-—the value here isn't af-
smaller mantissa are held here and used to round the final re- fected by NEW or CLR—so once a graphics area is allocated it
sult to extend the accuracy of the operation. will remain allocated until the computer is reset or a GRAPHIC
CLR statement is executed.
114-115 $72-$73 STRNG2
Multipurpose address pointer and working storage 119 $77 Z_P_TEMP_1
In the series evaluation routine, these locations are used as a General-purpose working storage
pointer to the constant values used in the series evaluation. In This location is used for temporary storage by a variety of
the VAL routine [$804A], these locations are used as a pointer BASIC routines.
into the character string to be translated into a floating-point
value. These locations are used as working storage in the 120 $78 HULP
routines that calculate the amount of memory required for an String offset pointer
array. In the DEC routine [$8072], these locations are used as This location is used during the routine [$5901] that handles
a work area for converting the hexadecimal string characters MID$ as a statement to hold the offset from the start of the
into a two-byte integer value. string to the substring being replaced. It's also used during the
PLAY string-processing subroutine [$6DE1] to hold the offset
116-117 $74-$75 AUTINC to the next character waiting to be processed in the string.
Step value for autoincretnent
These locations hold the step value for automatically incre- 121 $79 SYNTMP
menting the line number if autoincrement mode is active. Multipurpose temporary storage
After each BASIC program line is entered while this mode is This location is used for temporary storage by a number of
active, the value here will be added to the previous line num- different BASIC routines.
ber and the resulting new line number will be printed on the
screen. Autoincrement mode will be active whenever these lo- 122 $7 A MTXTPTR
cations contain a nonzero value. These locations are reset to Index into input buffer for monitor
0/$00 during the BASIC cold-start sequence, and during the The monitor uses this location to store the position of the
RUN subroutine [$5A81] that resets flags. The value here can next character to be read from the input buffer (512-672/
be set using the AUTO statement. $0200-$02A0).

118 $76 MVDFLG 122-124 $7A-$7C DSDESC


Graphics area flag Descriptor for disk error string DS$
The value here indicates whether the bitmapped graphics These locations are used as the descriptor for the disk status
color and screen area has been allocated at 7168-16383/ string provided by the reserved variable DS$. Location
$1COO-$3FFF, in which case the start of the BASIC program 122/$7A will hold the length of the string, and locations
area will have been moved to 16384/$4000. A value of 0/$00 123-124/$ 7B-$7C will hold the address of the string. The
here indicates that no graphics area is allocated, while a non- length value is initialized to 0/$00, effectively emptying the
zero value indicates that the area has been allocated and the string, during the CLR routine [$51F8], which is also part of
BASIC program area has been moved. This location is initial- NEW and RUN, The routine to generate the error string
[$A778] will set the values here whenever the DS or DS$ vari-
ables are used.
44
125-126 $7D-$7E $83 131

125-126 $7D-$7E TOS 128-129 $80-$81 PARST


BASIC runtime stack pointer Parameter flags for DOS support commands
These locations are used as the pointer into the BASIC The various disk command routines set these locations before
runtime stack at 2048-2559/$0800-$09FF. This stack area is calling the routine [$A32F] that processes parameters for disk
used to hold information for FOR, GOSUB, and DO state- commands. The values here indicate which parameters are
ments (see Chapter 3 for details). The value here is the ad- valid for the command being processed. When a bit is % 1 , the
dress of the next free location in the stack, which is filled from parameter string for the command can include the correspond-
top to bottom—from 2559/$09FF down to 2048/$0800. ing element:
Unlike the processor's stack with its automatic pointer, the
pointer into this stack must be updated explicitly. The pointer Location Bit Parameter element
value is reset to 2559/S09FF during the CLR routine [$51F8], 128/$80 0 source filename
which is also part of NEW and RUN. Each time an entry is 1 destination filename (following TO)
2 logical file number (#)
placed on the stack, the pointer value here is decremented by 3 device number (U)
the number of bytes in the stack entry. Whenever an entry is 4 source drive number (D)
retrieved from the stack, the value is incremented by the num- 5 destination drive number (D following TO)
ber of bytes to be removed. 6 file type parameters (L or W)
7 save-with-replace indicator (@)
127 $7F RUNMOD 129/$81 0 bank number <B)
1 starting address (P)
RUN mode flag 2 ending address (P following TO)
This location is used to indicate the current operating mode of
the computer. When the value here is 0/$00, BASIC is in im- 130 $82 OLDSTK
mediate mode. No program is executing; BASIC is waiting for Storage for processor stack pointer
a command or a program line to be entered. When bit 6 is set This location is used to store the current processor stack
to %1 (flag value of 64/$40), a program is being loaded for pointer value before a BASIC program line is executed
execution (the RUN "filename" statement has been used). [$4AF3]. If an error occurs while the line is being executed, the
When bit 7 is set to %1 (flag value 128/$80), a BASIC pro- value here will be restored to the stack pointer during the
gram is being executed. The value here is reset to 0/$00 dur- error-handling routine [$4D3C],
ing the step of the main BASIC loop that displays the READY
prompt. The RUN subroutine [$5A81] to set flag values will 131 $83 COLSEL
set this location to 128/$80, unless the option to load and run
a disk file has been used. In that case, the flag will be set to Color source for current graphics command
64/$40 while the file is loading, then to 128/$80 when it be- The first parameter in graphics commands such as DRAW,
gins running. CIRCLE, BOX, and so on, is the color source number. That
value is held here after the parameter is evaluated. For the
128 $80 POINT standard bitmapped (GRAPHIC 1) screen, valid values are 0
Decimal point position (background) and 1 (foreground). For multicolor bitmapped
This location is used during the PRINT USING routine [$9] to (GRAPHIC 3) screens, values of 2 and 3 are also valid to se-
hold the number of digits to be printed before the decimal lect the additional multicolor sources. If the parameter is omit-
point. ted, the value here will default to 1 (foreground).

46 47
132 $84 $89-$8A 137-138

132 $84 MULTICOLOR_1 matrix fill byte at 994/$03E2 and the multicolor video matrix
fill byte at 995/$03E3. One of these values, depending on the
Color source 2 storage display mode, will be used to fill the video matrix area when
This location holds the current color number for color source the bitmapped screen is cleared. Thus, the value here eventu-
2. The value here doesn't have any immediate effect on the ally determines the color of standard bitmapped pixels repre-
screen display, but whenever the COLOR statement routine sented by %1 bits or of multicolor bitmapped pixels represented
[$69E2] is executed, the lower four bits of the value here will by %10 bit pairs. During the BASIC cold-start sequence, this
be copied into the lower four bits of the multicolor video ma- location is initialized to 13/$0D (light green). The value here
trix fill byte at 995/$03E3. That value will be used to fill the can be changed using the statement COLOR \,n, where n is a
video matrix area when the multicolor bitmapped (GRAPHIC standard BASIC color number (1-16). Remember that the color
3) screen is cleared. Thus, the value here eventually deter- change is effective only after the screen is cleared.
mines the color of multicolor bitmapped pixels represented by
%10 bit pairs. This is the bit pattern that will be produced for
lines drawn when color source 2 is specified. During the 135-136 $87-$88 SCALE_X
BASIC cold-start sequence, this location is initialized to 1 Horizontal scaling factor
(white). The value here can be changed using the statement These locations hold the horizontal scaling factor for BASIC
COLOR 2,n, where n is a standard BASIC color number graphics routines. If scaling is in effect (indicated when the
(1-16). Remember that the color change is effective only after scaling flag at 4458/$116A holds a nonzero value), the speci-
the multicolor bitmapped screen is cleared. fied horizontal (x) coordinates for all graphics routine param-
eters will be adjusted according to the value here to get the
133 $85 MULTIC0L0R-2 true bitmap coordinates. The value here can be changed using
the SCALE statement. If the first parameter in the statement is
Color source 3 storage 1 (scaling on), the factor here is calculated from the second pa-
This location holds the current color number for color source rameter according to the following formula:
3. The value here doesn't have any immediate effect on the
screen display, but whenever the bitmapped screen is cleared, scaling factor = (65535 * 320)/scaling parameter
block 0 of color memory (55296-56319/$D800-$DBFF) is If the parameter is omitted, a default value of 20480/$5000
filled with the value here. Thus, the value here eventually de- (for a bitmapped screen) or 10240/S2800 (for a multicolor bit-
termines the color of multicolor bitmapped pixels represented mapped screen) is supplied. This allows a scaled screen of
by %11 bit pairs. This is the bit pattern drawn for lines when 1024 horizontal positions (x coordinates 0-1023).
color source 3 is specified. During the BASIC cold-start se-
quence, this location is initialized to 2 (red). The value here 137-138 $89-$8A SCALE-Y
can be changed using the statement COLOR 3,Ji, where n is a Vertical scaling factor
standard BASIC color number (1-16). Remember that the color These locations hold the vertical scaling factor for BASIC
change is effective only after the multicolor bitmapped screen graphics routines. If scaling is in effect (indicated when the
is cleared.
scaling flag at 4458/$116A holds a nonzero value), the speci-
fied vertical {y) coordinates for all graphics routine parameters
134 $86 FOREGROUND will be adjusted according to the value here to get the true bit-
Current foreground color (source 1) storage map coordinates. The value here can be changed using the
This location holds the current color number for color source SCALE statement. If the first parameter in the statement is 1
1. The value here doesn't have any immediate effect on the (scaling on), the factor here is calculated from the third param-
screen display, but whenever the COLOR statement routine eter according to the following formula:
[$69E2] is executed, the lower four bits of the value here will scaling factor = (65535 * 200)/scaling parameter
be copied into the upper four bits of both the standard video
48 49
139 $8B $91 145

If the parameter is omitted, a default value of 12800/13 200 is Bit Bit value Serial bus Tape
supplied. This allows a scaled screen of 1024 vertical positions 0 l/$01 timeout during write
1 2/S02 timeout during read
(y coordinates 0-1023). 4/$04 short block
2
(leader read where data expected)
139 $8B STOPNB 8/$08 long block
(data read where leader expected)
PAINT mode flag unrecoverable read error
16/$10 mismatch during
Bit 7 of this location is used during the PAINT statement rou- verify {or mismatch during verify)
tine [$61A8] to specify whether the fill stops at pixels where 32/$20 checksum mismatch for block
the source color is encountered (indicated when the bit is %0) 64/$40 EOI (end of file) end-of-file marker read
or whether all nonbackground pixels will be filled (indicated 128/$80 device not present end-of-tape marker read
when this bit is %1). This location is normally set according to In BASIC, the reserved variable ST returns the value here
the fourth parameter of the PAINT statement, to 0/$00 if the when the current I/O device is tape (1) or serial (4 or larger).
parameter is 0 or omitted, or to 128/$80 if the parameter is 1. For RS-232 operations, the status is instead recorded in loca-
tion 2580/S0A14.
140-141 $8C-$8D GRAPNT 145 $91 STKEY
Address pointer for graphics routines Scan value of STOP key column
These locations are used as an address pointer by several This location holds the current status of the keyboard column
BASIC graphics routines. The value here points to the address containing the RUN/STOP key. The Kernal UDTIM routine
within the bitmap where a character pattern will be copied [$F5F8], which is part of the system jiffy IRQ sequence, in-
during CHAR [$67D7]. The locations serve as a pointer to the cludes a section which reads the current column of the key-
area being filled during the SCNCLR [$6A79]. In the general board matrix. (See Figure 7-1 in Chapter 7 for a diagram of
pixel-drawing routine, these locations point to the bitmap ad- the keyboard matrix.) The current state of that column is
dress where the pixel will be drawn. stored in this location (unless the key connected to row 7 of
the column has been pressed at the same time as some key in
142-143 $8E-$8F VTEMP columns 1 or 6, which contain the SHIFT keys). The proper
Temporary storage for graphics routines functioning of this routine depends on the fact that the
These locations are used for temporary storage by a variety of SCNKEY routine [$C55D], normally performed earlier in the
BASIC graphics routines. IRQ sequence, leaves the system set to scan column 7, the one
containing the RUN/STOP key (in row 7). When the Kernal
144 $90 STATUS STOP routine [$F66E] is called to determine whether the
Status flag for tape and serial bus operations RUN/STOP key is currently pressed, it checks this location
This location records the status of the most recent tape or se- rather than actually reading the keyboard.
rial bus operation. In general, when the operation has been This location can also be used to read any of the other
successful the value here is 0/$00, while a nonzero value indi- keys in column 7. The value here will be 255/$FF when no
cates that an error has occurred or that the end of the file has key in that column is pressed. Pressing a key sets a cor-
been reached. The value here is reset to zero at the beginning responding bit here to %0. The values here when the respec-
of any load or save, or whenever a file is opened to tape or a tive keys are pressed are as follows:
serial device. Various error conditions are indicated by setting Key Bit Value Key Bit Value
particular bits to % 1 . The bits are used as follows: 0 254/$FE space 4 239/$EF
*- 1 253/$FD Commodore 5 223/$DF
CONTROL 2 251/$FB Q 6 191/$BF
2 3 247/$F7 RUN/STOP 7 127/$7F
50 51
146 $92 $9A 154

146 $92 SVXT 150 $96 SYNO


Tape-timing baseline adjustment factor Cassette block synchronization count
This location is used during routines which read from tape to This location is used during routines which read from tape to
hold a value representing the difference between the actual indicate when the system has read leader bytes and is waiting
time required to read a bit from tape and the standard rime. for the end of the leader segment.
This value is used to adjust other timing constants to compen-
sate for minor variations in tape motor speeds. 151 $97 XSAV
Temporary register storage
147 $93 VERCK This location is used for temporary storage of the Y register
Kernal load/verify flag value during the Kernal GETIN subroutine for RS-232, and for
Monitor operation flag temporary storage of the X register value during the Kernal
The same Kernal routine is used to perform both load and ver- BASIN routine for tape.
ify operations. This location is used during the routines which
read data from tape and disk to specify which operation has 152 $98 LDTND
been called for. The value in the accumulator upon entry to Number of files currently open
the Kernal LOAD routine [$F265] will be stored here. This location records the number of active files—the number
The monitor compare/transfer routine [$B231] uses this of files which have been opened but not yet closed. This value
location as an operation flag. A value of zero here indicates also serves as an index to the next available entry in the logi-
that a compare operation is being performed, while a value of cal file number, device number, and secondary address tables
128/$80 indicates a transfer operation. The monitor byte-pattern at 866-895/$0362-$037F. The value here is reset to 0/$00 (no
search routine [$B2CE] stores the number of characters in the files open) when zero page is cleared during the reset se-
search buffer here. The monitor load/save/verify setup rou- quence. The Kernal CLALL routine [$F222] will also reset this
tine stores the character code of the current command (L, S, or location to 0/$00. The value here is incremented each time a
V) here. logical file is opened, and decremented each time one is
closed. An attempt to open an additional file when this loca-
148 $94 C3P0 tion contains 10/$0A, indicating that the maximum 10 files
Serial deferred character flag are already open, will result in a TOO MANY FILES error.
This location is used to indicate whether a character is waiting
in the one-byte character buffer at 149/$95. Bit 7 of this loca- 153 $99 DFLTN
tion will be %0 if no character is waiting, or %1 if the buffer Current input device
contains a byte awaiting transmission. The value here specifies the current input device number for
the Kernal GETIN and BASIN routines, When a logical file is
149 $95 BSOUR selected for input by the CHKIN routine, the device number
Serial character buffer value for the file is read from that file's entry in the device
This location is used as a buffer for bytes sent over the serial number table at 876-885/$036C-$0376 and stored here. The
bus. The operating system maintains this buffer so that the CLRCH routine will reset the value here to 3/$03, to make
last byte of a file can be sent with the EOI handshake to iden- the keyboard the default input device.
tify it as the final byte. Location 148/$94 is used to indicate
whether the current value here represents a character awaiting 154 $9A DFLTO
transmission. It's very important to close serial bus files Current output device
opened for writing; otherwise, the final byte with the end-of- The value here specifies the current output device number for
file handshake won't be sent. the Kernal BSOUT routine. When a logical file is selected for
52 53
155 $9B $A0-$A2 160-162

output by the CKOUT routine, the device number value for 158 $9E PTR1
the file is read from that file's entry in the device number ta- Tape pass 1 error-log pointer
ble at 876-885/$036C-$0376 and stored here. The CLRCH The Commodore tape system records two copies of each block
routine will reset the value here to 0/$00, to make the screen of data written to tape. If errors are detected while the first
the default output device. copy is being read, the address where the erroneous byte is lo-
cated is stored in the tape error-log area at the bottom of page
155 $9B PRTY 1, This location is used as an offset to the next available two-
Tape character parity byte address slot in the error log. The value here is reset to
This location is used during routines which read from tape to 0/$00 at the beginning of the operation. An unrecoverable er-
calculate the parity of the byte currently being read. Bytes ror occurs if the value here exceeds 60/$3C, indicating that
stored on tape have an extra parity bit added to make an odd more than 31 errors have been logged.
total number of %1 bits in the combined character (eight data This location is also used to hold the offset into the speci-
bits plus parity). This location is used to make sure that an fied filename during the routine which checks to determine
odd total number of bits is read back for each character. whether a particular tape header has been found, and for tem-
porary storage of the type identifier byte when header blocks
156 $9C DPSW are being written to tape.
Tape dipole received flag
This location is used when a byte is being read from tape to 159 $9F PTR2
indicate whether all bits of the byte have been received (indi- Tape pass 2 error-log pointer
cated by a nonzero value), or whether bits are still being read This location is used during the routine which reads the sec-
(indicated by a value of 0/$00). ond copy of each tape data block to indicate the offset to the
next slot in the tape error log. That slot will contain the ad-
157 $9D MSGFLG dress of the next byte that needs correcting in the second pass.
Kernal message control flag This location is also used to hold the offset into the filename
This location controls whether Kernal messages will be dis- in the tape header when the routine is checking whether a
played. The Kernal routines have two types of messages: con- particular tape header has been found.
trol messages (PRESS PLAY ON TAPE, SEARCHING FOR, The monitor assemble routine [$B406] also uses this
and so on) and error messages (I/O ERROR # followed by a location to store the position of the next character to be pro-
number). This location controls which types of messages, if cessed from the instruction address buffer (2720-2729/
any, will be displayed. When the value here is set to 0/$00, $OAA0-$0AA9).
no Kernal messages are displayed. Setting bit 6 to %1 enables
error messages, while setting bit 7 to %1 enables control mes- 160-162 $A0-$A2 TIME
sages. The value here can be set using the Kernal SETMSG Software jiffy clock
routine [$F75C]. The BASIC routine MAIN [$4DB7], which is These three bytes comprise the jiffy clock, a counter main-
responsible for the READY prompt, sets this flag to 128/$80 tained by the operating system. Location 160/$A0 is the high
(control messages only), since BASIC provides its own error byte, 161/$A1 the middle byte, and 162/$A2 the low byte.
messages. When the RUN routine is executed to run a pro- The UDTIM routine [$F5F8], called during each system jiffy
gram, the value here is reset to 0/$00 (no messages). The IRQ interrupt sequence, will increment this counter 60 times
monitor changes the setting to 192/$C0 (all messages). per second. (UDTIM checks and compensates for PAL video

54 55
163 $A3 $A6 166

systems, so these locations are incremented 60 times per sec- 164 $A4 FIRT/BSOUR1
ond regardless of whether interrupts occur at the North Amer- Tape: Half-cycle indicator
ican rate of 60 times per second or the European rate of 50 Serial: Byte received
times per second.) Thus, location 162/$A2 will be incre- When bits are being read from or written to tape, this location
mented every 1/60 second; location 161/$A1 every 1/60 * is used to indicate which half-cycle for the bit is currently be-
256 = 4.27 seconds; and location 160/$A0 every 4.27 * 256 ing received or sent.
= 1092 seconds, or every 18.2 minutes. All three locations
When characters are being received over the serial bus,
(along with the rest of zero page) are reset to 0/$00 during
the reset sequence. The UDTIM routine will also reset the lo- this location is used to assemble received bits into complete
cations to 0/$00 if the value here reaches $4F1AO1, cor- bytes.
responding to 24 hours after the start of the count. The Kernal 165 $A5 CNTDN/COUNT
RDTIM routine [$F65E] can be used to read these locations, Tape: Leader synchronization countdown
and the SETTIM routine [$F665] can be used to change the Serial: Count of bits to send / burst mode byte count
value here. From BASIC, the reserved variables TI and TI$ can
be used to read the values here (TI$ converts the value to During the routines which write blocks of data to tape, this lo-
hours:minutes:seconds format). TI$ can also be used to change cation is used to provide the countdown characters that come
the value here. at the end of each leader segment. The value here is initialized
to 9; it will then be repeatedly written to tape and decremented
Although this timer is easy to use, especially from BASIC until the value reaches zero.
with TI and TI$, it's not particularly accurate for timekeeping When characters are being sent over the serial bus, this
applications. These locations depend on the system IRQ inter- location is used as a countdown of bits to be sent. The value
rupt, which is affected by a number of operations. For ex- here is initialized to 8 for each byte and decremented each
ample, the system interrupt is turned off during loads and time a bit is sent. When bytes are being read from the serial
saves to tape or disk, effectively stopping the clock. The more bus, this location is used to indicate whether an EOI hand-
tape or disk operations you perform, the more inaccurate your shake has been detected. The value is initialized to 0/$00,
clock time becomes. If you need more reliable timekeeping, re- then incremented after the first EOI is received. During high-
fer to the discussion of the CIA chips' time-of-day clocks in speed burst mode loads, this location is used as a count of the
Chapter 8. number of bytes read from the current disk sector.

163 $A3 PCNTR/R2D2 166 $A6 BUFPT


Tape: Count of bits to be read or written
Serial: EOI flag Pointer into cassette buffer
This location is used during the tape BASIN routine to hold
When characters are being read from or written to tape, this the offset to the next character to be read from the cassette
location is used as a countdown for the number of bits re- buffer. This location is incremented after each character is read
maining to be received or sent. from the buffer. When the value here reaches 192/$C0, all
When characters are being sent over the serial bus, this characters have been read from the buffer, so another block of
location is used to indicate when an EOI (end or identify) hand- data will be read into the buffer (if another is available) and
shake should be performed to mark the end of the file. The the value here will be reset to 0/$00. During the tape BSOUT
EOI sequence is added when bit 7 of this location is set to % 1 . routine, this location holds the offset of the next available po-
sition in the cassette buffer. This location is incremented each
time a character is added to the buffer. The buffer is consid-
ered filled when the value here reaches 192/$C0, at which the

56 57
167 $A7 $AC-$AD 172-173

block of data will be written to tape and the value here will be 170 $AA RDFLG/RIDATA
reset to 0/$00.
Tape; Read phase flag
RS-232: Assembly byte for received bits
167 $A7 SHCNL/INBIT
Tape: Leader dipole count / block indicator During the routines which read from tape, this location indi-
RS-232: Current bit received cates the current stage of the operation. When the value here
is 0/$00, the reading routine is waiting for the synchroniza-
During the routines which write to tape, this location is used tion countdown characters to be read. Nonzero values less
as one counter in a timing loop to specify the number of lead- than 64/$40 indicate that block countdown characters are be-
er dipoles to be written. When reading from tape, this location ing read. A value of 64/$40 indicates that the first copy of the
is used to indicate which block is being read. data block has been read, while a value of 128/$80 indicates
When characters are being received over the RS-232 inter- that all characters from the first block have been read and the
face, this location holds the most recently received bit. routine is waiting for the second copy.
When characters are being received over the RS-232 inter-
168 $A8 RER/BITCI face, the bits received are shifted into this location until a full
Tape: Half-cycle indicator for writing / error flag for reading byte has been assembled.
RS-232: Count of bits remaining to be received
When bits are being written to tape, this location is used to 171 $AB SHCNH/RIPRTY
indicate which half-cycle of the dipole for the bit is currently Tape: Leader dipole counter / checksum work byte
being written. When characters are being received from tape, RS-232: Received byte parity
this location is used as a flag to indicate an error in the re- During the routines which write to tape, this location is used
ceived byte. as one counter in a timing loop to specify the number of lead-
When characters are being received over the RS-232 inter- er dipoles to be written. During the routines which read from
face, this location is used as a countdown for the number of tape, this location is used for computing the checksum for the
bits to be received for the current character. The value here block being read.
will be initialized from 2581/S0A15 for each character. When characters are being received over the RS-232 inter-
face, this location is used to indicate whether an odd or even
169 $A9 REZ/RINONE number of %1 bits have been received, to determine the parity
Tape: Word marker flag / half-cycle flag of the received bit.
RS-232: Start bit received flag
When characters are being written to tape, this location is used 172-173 $AC-$AD SAL-SAH
to indicate whether a word marker dipole has yet been written Kernal working address pointer
for the current character. When characters are being read from These locations are used as a pointer to the address of the cur-
tape, this location is used to indicate whether the next half- rent byte to be written to tape or saved to disk, or the address
cycle should be a long or short one. where the byte read from tape or from a disk boot sector is to
When characters are being received over the RS-232 inter- be stored. The Kernal has several routines to service this pointer,
face, this location is used to indicate whether a start bit has including one [$ED51] to load this pointer with the operation
been received yet, A nonzero value here indicates that the sys- starting address in 193-194/$C1-$C2, one [$EEC1] to incre-
tem is still waiting for a start bit, while a value of 0/$00 ment the address here, and one [$EEB7] to compare the ad-
means that a start bit has been received. dress here against the operation ending address at 174-175/
$AE-$AR There is also a routine [$F7CC] to retrieve the char-
acter at the pointer address from the bank specified in 198/$C6,

58 59
172-175 $AC-$AF $B6 182

and one [$F7BC] to store the current accumulator contents at 178-179 $B2-$B3 TAPE1
the pointer address in the bank specified in 198/$C6. pointer to cassette buffer
These locations hold the starting address of the 192-byte cas-
172-175 $AC-$AF sette buffer. The value here is initialized to 2816/$0B0O by the
Work area for disk booting Kernal RAMTAS routine, part of the reset sequence. No
The Kernal BOOT-CALL routine [$F890] uses locations Kernal routine changes this default setting. The routines that
172-173/$AC-$AD to hold the address at which the contents read and write data to tape test these locations to insure that
of additional boot sectors are to be stored. Location 174/$AE the address is greater than 512/$0200.
holds the bank number for the additional data. Location 175/
$AF holds the number of disk sectors to be loaded during the 180 $B4 SNSW1/BITTS
boot process. Tape: leader/data flag
RS-232: Count of bits transmitted
174-175 $ AE-$ AF EAL-E AH During routines which read from tape, this location is used to
Kernal address pointer indicate whether the routine is currently waiting for the start
This location is used during the routines which read from or of a data block (indicated by a value of 0/$00 here) or reading
write to tape, or in saving to disk, to hold the ending address data from a block (indicated by a nonzero value here).
for the operation. For loading from disk, this location is used When bytes are being sent over the RS-232 interface, this
as a working pointer to the address where data is stored. After location holds the count of bits sent for the current character.
all bytes have been loaded, the locations will hold the ending
address. (Actually, in all cases the pointer will hold the ad- 181 $B5 DIFF/NXTBIT
dress of the location immediately following the last one in- Tape: Leader completed flag
volved in the operation.) The Kernal SAVF routine [$F53E] RS-232: Next bit to send
initializes these locations with the contents of the X and Y reg- During routines which read from tape, this location is used to
isters when the routine is called. The Kernal provides a routine indicate when the end of a leader segment has been reached.
[$F7C9] to retrieve the character at the pointer address from The value here is set to 0/$00 when the word marker at the
the bank specified in 198/$C6, and one [$F7BF] to store the end of a leader is read.
current accumulator contents at the pointer address in the When bytes are being sent over the RS-232 interface, bit 2
bank specified in 198/$C6. of this location is used to hold the setting of the next bit to be
sent.
176 $BO CMPO
Tape adjustable baseline compensation factor 182 $B6 PDP/RODATA
This location is used during tape routines to indicate whether Tape: Error flag / end of block flag
the current baseline time (the time allotted for a particular RS-232: Character being sent
type of dipole) needs to be slightly increased or decreased. When an error is detected while a character is being read from
This allows the computer to compensate for slight variations tape, this location is set to a nonzero value to indicate that the
in tape speed. character has not been read successfully. During routines
which write to tape, this location is used as a flag to indicate
177 $B1 TEMP when end-of-block processing should be performed.
Working storage for compensation factor computation When bytes are being sent over the RS-232 interface, this
This location is used as a work byte for computing the base- location holds the character being sent. Bits are pulled off one
line compensation factor at 176/$B0. at a time from right to left.

60 61
183 $B'
$co 192

183 $B7 FNLEN


Length of current filename 189 $BD OCHAR/ROPRTY
This location holds the length of the filename for the current Tape: Byte read from tape / byte to be written to tape
I/O operation. The value here can be set using the Kernal RS-232: Parity calculation working storage
SETNAM routine [$F731]. The starting address for the file- Serial: Current byte during burst mode load
name is held in locations 187-188/$BB-$BC, and the bank For tape operations, this location holds the byte most recently
number where the filename is found is held in location read, or the byte currently being written.
199/$C7. When bytes are being sent over the RS-232 interface, this
location is used to indicate whether an even or odd number of
184 $B8 LA %1 bits have been sent in the current character. This infor-
Logical file number mation is used to determine the value of the parity bit if one is
This location holds the logical file number for the current I/O to be sent.
operation. The value here can be set using the Kernal SETLFS During high-speed burst mode loads from disk, this loca-
routine [$F738]. When a file is opened, the value here will be tion holds the byte most recently received from the drive.
transferred into the logical file number table at 866-875/
$0362-$036B. 190 $BE FSBLK
Block count
185 $B9 SA This location is used during routines which read from or write
Current secondary address to tape to specify which of the two images of the current block
This location holds the secondary address for the current I/O is currently being read or written.
operation. The value here can be set using the Kernal SETLFS
routine [$F738]. When a file is opened, the value here will be 191 $BF MYCH/DRIVE
transferred into the secondary address table at 886-895/ Tape: Assembly area for byte being read
$0376-$037F. Disk: Default drive number for booting
When characters are being read from tape, the bits read are as-
186 $BA FA sembled in this area until a complete byte is formed; then the
Current device number value is transferred to location 189/$BD for evaluation or
storage.
This location holds the device number for the current I/O op-
eration. The value here can be set using the Kernal SETLFS During the BOOT_CALL routine [$F890], this location is
routine [$F738], When a file is opened, the value here will be used to hold the character code for the specified drive number.
transferred into the device number table at 876-885/ The contents of the accumulator when the routine is called
$036C-$0375. will be stored here.

187-188 $BB-$BC FNADR 192 $CO CAS1


Pointer to start of filename Tape motor interlock
These locations hold the starting address of the filename for This location is used to control bit 5 of the processor I/O port
the current I/O operation. The value here can be set using the at location l/$01. The system jiffy IRQ sequence includes a
Kernal SETNAM [$F731]. Location 183/$B7 holds the length subroutine [$EED0] which tests bit 4 of the processor port to
of the filename, and location 199/$C7 holds the bank number determine whether any Datassette buttons are pressed. If no
in which the filename is located. buttons are pressed, this location is set to 0/$00 and bit 5 of
the port is set to %1 to turn off power to the cassette motor.
When a button is pressed, this location is checked. If it con-
62
63
193-194 $C1-$C2 $CC-$CD 204-205

tains a 0/$00, the port bit is set to turn off the power. Thus, here doesn't affect the current system configuration; it only
the cassette motor can't be powered when no button is specifies the bank for load, save, or verify operation data. The
pressed or while this location contains 0/$00. When this loca- Kernal SETBANK routine [$F73F] can be used to set the value
tion is set to any nonzero value, the setting of the port bit is here.
not affected by the IRQ subroutine, so—as long as a button is
pressed—the motor can be turned on and off, changing the 199 $C7 FNBANK
setting of the port bit. Bank where filename for open, save, load, or verify is found
This location holds the bank number in which the filename for
193-194 $C1-$C2 STA the current I/O operation is found. The value here can be set
Kernal address pointer using the Kernal SETBANK routine [$F73F].
These locations are used by the Kernal SAVE routine [$F542]
to hold the starting address of the area of memory to be saved 200-201 $C8-$C9 RIBUF
to disk or tape, The value is loaded from the zero-page pointer Pointer to RS-232 input buffer
specified in the accumulator upon entry to the routine. The value in these locations determines the starting address of
These locations are also used by the Kemal BOOT_CALL the 256-byte RS-232 input buffer—the area where characters
routine. Location 193/$C1 holds the track number and loca- are stored as they are received via the RS-232 interface. The
tion 194/$C2 holds the sector number for the block currently value here is initialized to 3072/S0C00 by the RAMTAS rou-
being read from disk. tine [$E093], part of the reset sequence. This places the input
buffer at its default position, and no system routine changes
195-196 $C3-$C4 TMP2/MEMUSS this setting.
Kernal address pointer
The contents of the X and Y registers upon entry to the Kemal 202-203 $CA-$CB ROBUF
LOAD routine [$F265] are stored here. If the secondary ad- Pointer to RS-232 output buffer
dress that preceded the LOAD was 0/SOO, a relocating load The value in these locations determines the starting address of
was specified, so this address is used as the starting address the 256-byte RS-232 output buffer—the area where characters
for the loaded data. are stored while they await transmission via the RS-232 inter-
These locations are also used as a working pointer in the face. The value here is initialized to 3328/S0D00 by the
routine [$E1FO] to initialize the soft reset vector, RAMTAS routine [$E093], part of the reset sequence. This
places the output buffer at its default position, and no system
197 $C5 DATA routine changes this setting.
Bit read from tape / checksum of block written to tape
During routines which read from tape, this location is used to 204-205 $CC-$CD KEYTAB
indicate the value of the bit most recently read. During Pointer to current keyboard decode table
routines which write to tape, this location is used for working The value in these locations determines the starting address of
storage of the checksum being calculated for the block. the 89-byte area of memory which will be used to decode the
current keyboard matrix code in location 212/$D4. The
198 $C6 BA SCNKEY routine [$C55D], part of the normal IRQ sequence,
Bank where data for save, load, or verify is found checks on the shift-key status (in location 211/$D3) and se-
This location holds the bank number from which data will be lects the proper value from the list of keyboard table pointers
saved by the Kernal SAVE routine or to which data will be at $83u-841/$033E-$0349.
loaded or verified by the Kernal LOAD routine. The value

64 65
206-207 $CE-$CF 5D4 212

206-207 $CE-$CF IMPARM 211 $D3 SHFLAG


Pointer for Kernal PRIMM routine Shift key status flag
These locations are used as a working pointer to the character This location is set during the SCNKEY routine [$C55D] to in-
to be printed during the Kernal PRIMM routine [$FA17]. dicate which of the shift keys—SHIFT, Commodore, CTRL,
ALT, or CAPS LOCK—are currently being pressed. Each key
208 SD0 NDX has a corresponding bit which is set to %1 when the key is
Number of characters in the keyboard buffer pressed:
This location holds the number of characters awaiting process- Key Bit Bit value
ing in the keyboard buffer at 842/$034A. The value here is SHIFT 0 l/$01
initialized to zero by the CINT routine, part of the RESET se- Commodore 1 2/$02
quence. This location is also reset to zero by the STOP routine CONTROL 2 4/$04
ALT 3 8/$08
if the STOP key is pressed. It is incremented during the CAPS LOCK 4 16/$10
SCNKEY routine [$C55D] whenever a character is added to
the buffer, and decremented whenever a key is removed (by The values are cumulative; if both SHIFT and CONTROL are
the Kernal BASIN or GETIN routines). The value here is not pressed simultaneously, the value here will be 5 (4 + 1).
allowed to exceed the maximum keyboard buffer length speci- Based on the value here, the SCNKEY routine chooses a key-
fied in location 2592/$0A20. board table pointer value to be stored in 204-205/$CC-$CD.
Bit 7 of this location is also used as a flag to indicate
209 $D1 KYNDX when the extra characters read using the VIC chip lines are
being scanned.
Number of characters pending from programmable key string
This location holds the number of characters remaining to be 212 $D4 SFDX
read from the string for the most recently pressed programma-
ble key. The value here is initialized to zero by the CINT rou- Current key pressed
tine, part of the RESET sequence. When the press of a This location is used during the SCNKEY routine [$C55D],
programmable key is detected during the SCNKEY routine part of the system jiffy IRQ sequence, to hold a value indicat-
[$C6CA], the length of the string for that key is stored here. ing which key was pressed. Each key has a unique keyscan
The value is then decremented as each character is read from matrix code here, but the code values are different from either
the string (by GETIN or BASIN). character codes or screen codes. Refer to Appendix C for a list
of keyscan codes. The key's keyscan code (0-87) serves as an
210 SD2 KEYIDX offset into the keyboard decoding table pointed to by locations
204-205/$CC-$CD to select the character code to be added to
Pointer into the programmable key definition area the keyboard buffer at 872/$034A. A scan code of 88 indicates
This location holds the offset to the next character to be read that no key was pressed.
from the programmable key definition string area at 4106-4351/ It's possible to read this location as an alternative to using
$100A-$10FF. When the press of a programmable key is de- the BASIC GET or GETKEY statements or the machine lan-
tected during the SCNKEY routine [$C6CA], the offset to the guage GETIN routine when you want to check for the press of
definition string for that key is stored here. The value here is a particular key. For example, the two following statements
incremented as each character is read from the string. produce the same result, a delay until the X key is pressed:
100 IF PEEK(212)<>23 THEN 100
100 GET K$:IF K$o"X" THEN 100

66 67
213 $D5 $D8 216

Certain keyscan codes will not normally be recorded here. RUN/STOP-RESTORE sequences, the screen editor initializa-
The codes for the left and right SHIFT keys, the CONTROL tion routine [$C07B] sets this flag according to the position of
key, the Commodore key, and the ALT key—codes 15, 52, 58, the 40/80 DISPLAY key.
61, and 80, respectively—-are normally intercepted during the While it is often useful to check this flag to determine
SCNKEY routine and used to generate the value at 211/SD3. which display is active, it shouldn't be changed to switch ac-
The CAPS LOCK, 40/80 DISPLAY, and RESTORE keys are tive displays. Instead, use the escape sequence (ESC X) or the
not part of the keyscan matrix, and the SHIFT LOCK key is Kernal SWAPPER routine [$FF5F]. There's more to changing
just a switch that has the effect of holding down the left active displays than just toggling the flag bit—the active and
SHIFT key. inactive screen editor variable tables, line link bitmaps, and
tab stop bitmaps must also be exchanged.
213 $D5 LSTX
Last key pressed 216 $D8 GRAPHM
At the end of the SCNKEY routine [$C55D], the value in Mode flag for 40-column screen
212/$D4 is transferred here. This value is then used during This location is used during the screen IRQ routine [$C194] to
the next pass through SCNKEY to determine if the same key determine which display mode is selected for the 40-column
is still being pressed. If so, no additional character code will be (VIC) screen. The value here has no effect on the 80-column
added to the keyboard buffer unless key repeating is enabled. (VDC) screen. When this location contains 0/$00, text mode is
selected. Bits 5-7 control the graphics mode configurations:
214 $D6 CRSW Bit Bit value Mode selected
Input source flag 5 32/$20 bitmapped
This location is used during the screen editor BASIN routine 6 64/$40 split bitmapped/text
7 128/$80 multicolor
[SC29B] to indicate whether the line of input is to come from
the keyboard or from the screen. The default value of 0/S00 More than one of these can be selected at one time. The stan-
selects input from the keyboard, while a nonzero value selects dard graphics modes place the following values here:
input from the screen. The Kernal BASIN routine [$EF06] will Mode Value
set this location to 3/$03 before calling the screen editor rou- GRAPHIC 0 0/$00
tine when screen input is requested. Bit 7 of this location is GRAPHIC 1 32/$20
used as an end-of-input flag; however, this is not handled GRAPHIC 2 96/$60
GRAPHIC 3 160/JAO
properly for input from the screen. See the entry for the screen GRAPHIC 4 224/$E0
editor routine in Chapter 7 for details.
While the standard screen editor interrupt routine is in
$D7 use, the value here determines how the screen mode will be
215 MODE set up. As a result, you cannot directly change the bitmapped
Active screen flag or multicolor mode control bits of the VIC chip, since those
Bit 7 of this flag determines which text screen is considered bits will be set according to the value here. You can turn off
the active display. While the bit is % 1 , the 80-column display the screen-setup portion of the screen editor IRQ routine by
is selected. While the bit is %0, the 40-column display is ac- storing the value 255/$FF here. This gives you direct control
tive. Note that the inactive screen isn't actually turned off; it over the VIC chip register settings, but disables BASIC'S ability
retains whatever display it had when the other screen was se- to change display modes.
lected. However, only the active screen has a "live" cursor,
and all printing is directed there. During the reset and

68 69
217 $D9 $E2-$E3 226-227

217 $D9 CHAREN Screen Editor Variable Table


CHAREN bit shadow Locations 224-249/$E0-$F9 comprise the screen editor vari-
Bit 2 of this location serves as a shadow for the CHAREN bit able table for the active display. All locations in the table are
bit 2 of the processor I/O port at location l/$01. The value of initialized during the CINT screen editor initialization routine
the bit in this location is copied to the port bit during each [$C07B]. An equivalent table for whichever display is currently
pass through the text screen-setup portion of the screen editor inactive is maintained at 2624-2649/$0A40-$0A59, Whenever
IRQ routine [$C194]. Thus, the setting of the port bit cannot the SWAPPER routine [$CD2Ej is called to switch active
be changed directly while the standard interrupt routine is in screen displays, the contents of this table are exchanged with
use. Instead, you must set the bit here to the desired value the values from the inactive screen table. Thus, the table
and let the interrupt routine set the port bit accordingly. settings here are retained even when the screen is not active.
The setting of the CHAREN bit determines whether the
VIC chip sees the ROM character sets at offsets of 4096/$1000 224-225 $EO-$E1 PNT
and 6144/$1800 in the current video bank. When the bit is Pointer to first screen memory location for current line
%0, the standard ROM character set is visible to the VIC. Whenever the cursor is moved onto a new line, the screen
When the bit is set to % 1 , the VIC instead sees the true con- memory address corresponding to the leftmost column of that
tents of memory in the video bank. line is calculated and stored in these locations. These locations
can then be used as a pointer to screen memory locations for
218-223 $DA-$DF SEDSAL the current line. The value 236/$EC serves as an offset to the
Screen editor zero-page work area current cursor column. The low byte of the address comes
Assorted screen editor routines use these locations for various from the value in the table at 49203/$C033 corresponding to
functions. Location 218/SDA is used as temporary storage by the current row (multiplied by 2 if the 80-column display is
the routines that calculate bit positions in the line link map active). The high byte comes from the value in the table at
[$CB9F] or tab stop table [$C961, $C96C]. During a number of 49228/$C04C corresponding to the current row, adjusted for
routines, location 222/$DE is used as temporary storage for the starting screen memory page value in 2619/$0A3B in the
the current cursor column, and 223/$DF is used as storage for case of the 40-column (VIC) display, or for the starting screen
the current cursor row. memory page value in 2606/$0A2E in the case of the 80-col-
For the PFKEY routine [$CCA2], location 218/$DA holds umn (VDC) display. Since the tables have only 25 valid en-
the length of the current key definition string. Location tries, the screen editor cannot support an output window with
219/$DB holds the total length of all programmable key defi- more than 25 rows.
nitions. Location 220/$DC holds the current key number
(0-9). Location 221/$DD holds the index to the next key defi- 226-227 $E2-$E3 USER
nition beyond the current one. Location 222/$DE holds the Pointer to first attribute memory location for current line
MMU setting for the bank where the definition string is found. Whenever the cursor is moved onto a new line, the color
223/$DF is used as temporary storage for the index in the X memory address corresponding to the leftmost column of that
register. line is calculated and stored in these locations. These locations
For the INIT80 routine [$CE0C], locations 218-219/ can then be used as a pointer to attribute memory locations
$DA-$DB are used as a pointer to the character ROM at for the current line. The value 236/$EC serves as an offset to
53248/$D000. The screen-scrolling routine [$C40D] uses loca- the current cursor column. The low byte of the address comes
tions 218-219/SDA-DB as a pointer to the start of screen from the value in the table at 49203/$C033 corresponding to
memory for the current line. Locations 220-221/$DC-$DD the current row (multiplied by 2 if the 80-column display is
are used as pointers to the start of attribute memory for the active). The high byte comes from the value in the table at
current screen line. 49228/$C04C corresponding to the current row, adjusted for a
70 71
228 $E4 $EA 234

starting page of 216/$D8 in the case of the 40-column (VIC) screen, when the window is reset to full screen size, as when
display, or for the starting color memory page value in the CINT screen editor initialization routine is executed. This
2607/$0A2F in the case of the 80-column (VDC) display. location can be assigned a specific column number using the
Since the tables have only 25 valid entries, the screen editor screen editor WINDOW routine [$CA1B], which has a screen
cannot support an output window with more than 25 rows. editor jump table entry at 49197/$C02D. From BASIC, the
WINDOW statement can be used to change the value here.
228 $E4 SCBOT The ESC T sequence will cause the column number for the
Bottom margin of current window current cursor position to be stored here.
The value in this location determines which screen row will be 231 $E7 SCRT
the bottom margin of the current output window. This value
Right margin of current window
should be greater than or equal to the value in location
229/SE5. This location is reset to the maximum column num- The vaiue in this location determines which screen column
ber from location 237/$ED when the window is reset to full will be the right margin of the current output window. This
screen size, as when the CINT screen editor initialization rou- value should be greater than or equal to the value in location
tine is executed. This location can be assigned a specific row 230/$E6. This location is reset to maximum column number
number using the screen editor WINDOW routine [$CA1B], from location 238/$EE when the window is reset to full screen
which has a screen editor jump table entry at 49197/$C02D. size, as when the CINT screen editor initialization routine is
From BASIC, the WINDOW statement can be used to change executed. This location can be assigned a specific column
the value here. The ESC T sequence will cause the row num- number using the screen editor WINDOW routine [$CA1B],
ber for the current cursor position to be stored here. which has a screen editor jump table entry at 49197/$C02D.
From BASIC, the WINDOW statement can be used to change
the value here. The ESC B sequence will cause the column
229 $E5 SCTOP number for the current cursor position to be stored here.
Top margin of current window
The value in this location determines which screen row will be 232 $E8 LSXP
the top row of the current output window. This value must be Cursor row for start of input
less than or equal to the value in location 228/$E4. The value
This location determines the starting row for the logical line of
here is reset to 0/$00, the top row of the screen, when the
input characters to be read by the BASIN routine [$C29B]. Lo-
window is reset to full screen size, as when the CINT screen
cation 235/$EB will hold the row for the end of the input line.
editor initialization routine is executed. This location can be
assigned a specific row number using the screen editor WIN-
DOW routine [$CA1B], which has a screen editor jump table 233 $E9 LSTP
entry at 49197/$CO2D. From BASIC, the WINDOW statement Cursor column for start of input
can be used to change the value here. The ESC T sequence This location determines the starting column for the logical
will cause the row number for the current cursor position to line of input characters to be read by the BASIN routine
be stored here. [$C29B]. Location 2608/$0A30 will hold the column for the
end of the input line.
230 $E6 SCLF
Left margin of current window 234 $EA INDX
Column of last nonspace character on logical line
The value in this location determines which screen column
will be the left margin of the current output window. This The screen editor includes a routine [$CBC3] to find the posi-
value must be less than or equal to the value in location tion of the last nonspace character in the current logical line.
231/SE7. The value here is reset to 0/$00, the left edge of the That routine stores the column number of the character posi-
tion here.
71 73
235 $EB SEE 238

235 $EB TBLX the value in location 230/SE6, the left margin of the output
Cursor row window. Each time a character is printed to the window, the
This location holds the cursor's horizontal position on the value here is incremented, unless the increment would cause
screen. When the cursor is moved onto a new line, the value the value here to exceed the value in location 231/$E7, In that
here is used as an offset into the screen memory line base case, the value here is reset to the left margin value in 230/
starting address tables during the calculation of the starting $E6. The value here is also reset to the left margin value when-
address for the current screen memory line (224-225/ ever a RETURN character (code 13/SOD) or SHIFT-RETURN
$EO-$E1) and the starting address for the current color mem- (code 141/$8D) is printed.
ory line (226-227/$E2-$E3). When the output window is The PLOT routine [$CC6A] can be used to set or read the
cieared or the cursor is moved to the home position, the value value here, but the coordinates supplied to PLOT are relative
here will be reset to the value in location 229/$E5, the top to the current left margin. That is, the horizontal offset placed
margin of the window. The value here is incremented when- here when PLOT is used will be the horizontal coordinate
ever the cursor wraps around from the right margin of the specified in the PLOT call plus the current left margin value in
window back to the left—or whenever a RETURN character 230/$E6, and the coordinate value returned by PLOT will be
(code 13/$0D), SHIFT-RETURN (code 141/$8D), or cursor- the value here less the current left margin value in 230/SE6.
down (code 17/ $11) is printed—unless the increment would
cause the value here to exceed the bottom margin value in 237 $ED LINES
228/$E4. The action taken in that case depends on whether Maximum number of rows allowed in output window
the scrolling flag (248/$F8) is set to allow new lines to be The value here determines the maximum bottom row for the
scrolled onto the screen. If so, the value here remains un- output window. The current bottom row number is specified
changed and a new line is opened at the bottom of the win- in location 228/$E4. When the window is reset to full screen
dow. If scrolling is not allowed, the value here is reset to the size by printing two {HOME} characters (code 19/$13) in se-
value in 229/$E5 to wrap the cursor to the top of the window. quence (or by directly calling the screen editor window reset
The PLOT routine [$CC6A] can be used to set or read the routine [$CA24]), location 228/$E4 will be reset to the value
value here, but the vertical coordinate used by PLOT is rela- here. This location is set to 24/$18 during the CINT screen
tive to the current top margin. That is, the vertical offset editor initialization routine, which establishes the default max-
placed here when PLOT is used will be the vertical coordinate imum of 25 horizontal rows of characters in the output win-
specified in the PLOT call plus the current top margin value in dow (remember that row numbering begins at zero). No
235/$E5, and the coordinate value returned by PLOT will be system routine changes this setting, but you can reduce the
the value here less the current top margin value in 229/$E5. value here to restrict the maximum height of the output win-
dow. However, you should not increase the value above the
236 $EC PNTR default setting, since the screen editor printing routines will
Position of cursor within current physical line not properly support a window more than 25 lines tall.
This location holds the cursor's horizontal position on the
screen. The value here is used as an offset from the starting 238 $EE COLUMNS
address of the current screen memory line (224-225/$E0-$El) Maximum number of columns allowed per row
to determine the screen memory position of the current char- The value here determines the maximum right margin column
acter, and as an offset from the starting address of the current for the output window. The current right margin column num-
color memory line (226-227/$E2-$E3) to determine the color ber is specified in location 231/$E7. When the window is reset
memory position of the current character. to full screen size by printing two {HOME} characters (code
When the output window is cleared or when the cursor is 19/$13) in sequence (or by directly calling the screen editor
moved to the home position, the value here will be reset to window reset routine [$CA24]), location 231/$E7 will be reset
74 75
239 $EF $F1 241

to the value here. During the CINT screen editor initialization the discussion of the VIC chip in Chapter 8 for details. For the
routine, this location is set to 39/$27 if the 40-column (VIC) 80-column (VDC) display, the lower four bits also hold the
display is the default, or to 79/$4F if the 80-column (VDC) color value, but the relationship of values to colors is different
display is the default. This establishes the default widths of from that for the VIC chip. Refer to the discussion of the VDC
the respective displays (remember that column numbering be- in Chapter 8 for more information.
gins at zero). No system routines change these settings, but When the VDC display is active, the upper four bits of
you can reduce the value here to restrict the maximum width this location hold the attribute value for the next character to
of the output window. However, you should not increase the be printed. Refer to the discussion of the VDC chip in Chapter
value above the default settings, since the screen editor print- 8 for more information on attributes. Bit 4 determines whether
ing routines will not properly support windows wider than the the character will flash. Printing character code 15/$0F will set
respective defaults. bit 4 to % 1 , which specifies a flashing character. Printing char-
acter code 143/$8F resets bit 4 to %0, which turns off the
239 $EF DATAX flashing attribute. Bit 5 determines whether the character will
Character to print be underlined. Printing character code 2/$02 will set bit 5 to
This location is used during the screen editor printing routines % 1 , which specifies an underlined character. Printing charac-
to hold the character code (not the screen code) for the charac- ter code 130/$82 resets bit 5 to %0, which turns off the un-
ter to be printed. derlining attribute. Bit 6 could be used to determine whether
the character is reversed. Setting the bit to %1 specifies a re-
240 $F0 LSTCHR versed image of the character pattern, and resetting the bit to
Last character printed %0 specifies a normal character. However, the 128's screen
This location is used during the screen editor printing routines editor does not make use of this feature. Instead, each stan-
to hold the character code for the previous character printed. dard character set contains both normal and reversed character
After each character is printed, the code for that character is patterns and reversed characters are obtained by selecting the
transferred here from location 239/$EF. The value is used to reversed character pattern. Bit 7 determines which of the two
detect when certain key sequences have been printed, such as character sets will be used. When the bit is %0, the first
the escape (ESC) sequences and the HOME HOME sequence (uppercase/graphics) set is selected, while setting the bit to
%1 selects the second (lowercase/graphics) set. Thus, the
to reset the output window margins. One shortcut to printing VDC allows both character sets to be used on the same dis-
an escape sequence is to set this location to 27/$lB (the code play. When the VDC display is active, printing character code
for the ESC character), then call the screen BSOUT routine 14/$0E sets this bit to % 1 , and printing character code
[$C00C] with the accumulator holding the second character of 142/$8E resets the bit to %0. If character set switching with
the escape sequence. the SHIFT-Commodore key combination is allowed, then that
combination will toggle the value of this bit.
241 $F1 COLOR
Attribute of current character The CINT screen editor initialization routine will set this
The value in this location determines the color (and attribute location to 13/$0D if the VIC screen is the default display, or
for the VDC display) that will be used for the next character to 7/$07 if the VDC screen is the default. This selects light
printed to the output window. When the screen code for the green characters for the VIC display or light cyan characters
character is placed in screen memory, the value here will be with no special attributes for the VDC display. The color value
placed in the corresponding position in color memory. When in the lower four bits can be changed by printing any of the
the 40-column (VIC) screen is the active display, only the 16 color change characters. Refer to Appendix C for a list of
lower four bits of this location are meaningful. Those bits will character code values.
hold the VIC color code (0-15) for the character position, See
76 77
242 $F2 $F6 246

242 $F2 TCOLOR location is reset to zero each time a carriage return character
(code 13/$0D) or shifted return (code 141/$8D) is printed to
Temporary storage for attribute byte end the logical line. This location can also be reset to zero to dis-
This location is used to temporarily preserve the value from able insert mode with either the ESC O or ESC ESC sequences.
241/$F1 during screen editor routines that insert or delete
characters or scroll screen lines. 245 $F5 INSRT
Number of pending inserts
243 $F3 RVS
Reverse mode flag This location holds the number of character positions which
have been inserted in the current logical line. This is signifi-
The value in this location determines whether reverse mode is
cant because insert mode is normally active for inserted char-
active. Reverse mode is active whenever this location contains acter positions. Insert mode is similar to quote mode—cursor
a nonzero value. In this case, bit 7 will be set to %1 in each movement and color change characters are deferred—except
screen code placed in screen memory by the BSOUT screen that the insert key is not deferred in insert mode and the de-
printing routine. This effectively converts screen codes lete key (INST/DEL) is deferred. Insert mode is active when-
0-127/$00-$7F to codes 128-255/$80-$FF. In the default ever this location contains a nonzero value. The value here is
character sets, character patterns in the upper half of each set incremented each time a blank character position is inserted in
are the reverse image of corresponding patterns in the lower the current line, and decremented each time a character is
half. The value here is initialized to 0/$00 (reverse mode off) typed in one of the inserted positions. This location is initial-
by the CINT screen editor initialization routine. This location ized to 0/$00 (insert mode off) by the CINT screen editor ini-
is set to 128/S80 when the reverse-on character (code 18/$12) tialization routine. It is also reset to zero each time a carriage
is printed, and reset to 0/$00 when the reverse-off character return character (code 13/$0D) or shifted return (code
(code 146/$92) is printed. The value here is also reset to zero 141/$8D) is printed to end the line. This location can also be
each time a carriage return character (code 13/$0D) or shifted reset to zero to disable insert mode with either the ESC O or
return (code 141/$8D) is printed to end the line. This location ESC ESC sequences.
can also be reset to zero to disable reverse mode with either
the ESC O or ESC ESC sequences. 246 $F6 INSFLG
Autoinsert mode flag
244 $F4 9TSW Bit 7 of this location determines whether the autoinsert feature
Quote mode flag is active. When the bit is % 1 , autoinsert mode is active, and a
This value in this location determines whether quote mode is space is inserted following each character printed to the
active. Quote mode will be in effect whenever this location screen. If the bit is %0, autoinsert mode is disabled. In this
contains a nonzero value. In this case, cursor movement keys, case, the cursor simply moves to the next character position
CONTROL key combinations, Commodore-number key (color after each character is printed. This location is initialized to
change) combinations, and the insert key (SHIFT-INST/DEL) 0/$00 (autoinsert mode off) during the CINT screen editor ini-
are deferred—they appear as reverse characters within the cur- tialization routine. It is also reset to zero by the BASIC sub-
rent screen line instead of having any direct effect on the routine that sets flag values when a RUN statement is
screen display. The value here is initialized to 0/$00 (quote executed [$5A81]. This location is set to 255/SFF (which sets
mode off) by the CINT screen editor initialization routine. The bit 7 to %1) when the ESC A sequence is printed. It can be re-
value here is exclusive-ORed with l/$01 each time a quote set to 0/$00 with the ESC C sequence.
character (code 34/$22) is printed. Thus, quote mode will nor-
mally be on after an odd number of quotes (1, 3, and so on)
and off after an even number of quotes (2, 4, and so on). This

79
78
247 $F7 $FA 250

247 $F7 LOCKS cursor will wrap around to the top screen line. This bit can be
Case switching / scroll pause control flag set to %1 with the ESC M sequence, and reset to %0 with ESC
Bit 7 of this location determines whether the SHIFT-Commo- L.
dore key combination can be used to switch character sets. If Bit 6 of this location controls whether physical screen
this bit is %0, the SCNKEY routine [$C55D] will switch char- lines can be linked together to form logical lines. For example,
acter sets whenever the SHIFT-Commodore combination is de- BASIC allows logical lines up to 160 characters long. If this bit
tected. Setting this bit to %1 disables character set switching is %0, linking is allowed. The line link bitmap at 862-865/
with SHIFT-Commodore. However, you can still change char- $035E-$0361 will indicate which physical lines are part of
acter sets by printing character 14/$0E for the lowercase/ longer logical lines. Setting this bit to %1 disables line linking,
uppercase set, or character 142/$8E for the uppercase/ in which case no logical line can be more than one physical
graphics set. There is no provision for preventing character set line long. This location is initialized to 0/$00 (linking enabled)
switching using the character codes. This location is initialized during the CINT screen editor initialization routine, and no
to 0/$00 (switching enabled) by the CINT screen editor initial- system routine changes the setting of this bit. Since the screen
ization routine. The bit can be set to %1 by printing character editor doesn't provide a character code or escape sequence for
code 11/$OB, and reset to %0 by printing character code changing this bit, you must change the value here directly if
12/$0C. (Note that this is a change from earlier Commodore you wish to make use of the linking disable feature.
models, where character 8/$08 disabled switching and charac-
ter 9/$09 reenabled switching.) 249 $F9 BEEPER
Bit 6 of this location controls whether the NO SCROLL Bell enable flag
key or CONTROL-S key combination can be used to pause Bit 7 of this location controls whether or not a tone is pro-
output to the screen. If this bit is %0, NO SCROLL or CON- duced when character code 7, the {BELL} character, is printed.
TROL-S will pause printing to the screen until another key is If the bit is %0, then a tone is produced. Setting the bit to %1
pressed. Setting this bit to %1 prevents pausing, so that nei- prevents the tone. The location is tested during the screen
ther NO SCROLL or CONTROL-S will have any effect on BSOUT subroutine that handles character 7 [$C98E], The loca-
screen output. (The Commodore key can still be used to slow tion is initialized to 0/$00 (bell enabled) during the CINT
down printing.) This location is initialized to 0/$00 (pause en- screen editor initialization routine. The flag bit can be set to
abled), and no system routine changes the setting of this bit. %1 using the ESC H sequence, and reset to %0 with ESC G.
Since the screen editor doesn't provide any character code or
escape sequence for disabling the pause feature, you must 250 $FA Unused
change the value here directly if you wish to make use of the
pause disable feature. This location is unused in the sense that it is not intentionally
altered by any 128 Kernal or BASIC routine. However, a bug
in the screen editor CINT [$C07Bj and SWAPPER [$CD2E]
248 $P8 SCROLL routines causes this location to be overwritten whenever those
Scroll/link control flag routines are executed. Because those routines are called during
Bit 7 of this location is tested during the screen editor cursor the RUN/STOP-RESTORE sequence, any value you place in
movement routines to determine whether a new line will be this location will be overwritten any time you press
scrolled onto the output window after printing on the current RUN/ STOP-RESTORE, as well as whenever you switch
bottom line. If the bit is %0, a new blank line will be opened screens. Thus, if you use this location in your programs it
at the bottom of the screen (and the top line will be scrolled should be only as temporary working storage, not for impor-
off the screen) after printing on the bottom line. Setting the bit tant values you might want preserved in the cases mentioned
to %1 prevents scrolling; after printing on the bottom line, the above.

80 81
251-254 $FB-$FE $00FF-$010A 255-266

251-254 $FB-$FE Unused the actual address in page 1.) When a byte of data is pushed
(added) onto the stack, the stack pointer register is automati-
These locations are unused by any 128 ROM routines, and are cally decremented to point to the next available address. When
thus available for use in your BASIC and machine language a byte is pulled (removed) from the stack, the register is auto-
programs. This area is not affected by RUN/STOP-RESTORE, matically incremented. The value is not actually deleted, but
but remember that all zero-page locations, including these, are incrementing the stack pointer will cause the next byte pushed
cleared to zero during a reset (unless the RUN/STOP key is onto the stack to overwrite the old value. The RESET routine
held down during the reset; see the reset routine [$E000] for [$EO00] begins by resetting the stack pointer to 255/$FF, effec-
details). tively emptying the stack.
In addition to the stack's use for processor address infor-
255 $FF mation, BASIC uses it to hold intermediate values during ex-
This location is used as part of the assembly area for character pression evaluation. In earlier Commodore computers, the
strings representing the digits of numeric values. Refer to the system stack was also used to hold information for BASIC
next section for details. statements such as GOSUB and FOR that loop back to another
line. Since every FOR statement requires 18 bytes of stack
Page 1: System Stack space, and every GOSUB or DO requires 5 bytes, only a lim-
ited amount of nesting would be possible before all system
256-511/$0100-$01FF stack space was exhausted. BASIC 7.0 maintains a separate
This page is the system stack, the area where the 8502 stack at 2048-2559/$0800-$09FF for FOR, GOSUB, and DO.
microprocessor stores information such as the return addresses This allows BASIC 7.0 to use more deeply nested FOR-NEXT
and DO-LOOP loops and more levels of subroutines—and
for interrupts and subroutine calls. Some microprocessors hence more complex programs. See Chapter 3 for details of
allow longer stacks or allow the stack to be located at various the BASIC stack.
places in memory, but 6502-family microprocessors like the
128's 8502 have only one 256-byte stack, and it's always page The 8502 normally uses all of page 1 as stack space, but
1. Unlike other Commodore computers, however, the 128 has BASIC manipulates the stack pointer to allow the 128 to use
the ability to make the 8502 see page 1 anywhere in memory. portions of this area in other ways. The BASIC cold-start rou-
The MMU chip has a feature which allows the processor to tine [$4023] resets the stack pointer to 251/$FB, so locations
exchange page 1 with another page, so that all references to 508-511/$01FC-$01FF are not used by BASIC. The CLR rou-
page 1 (including the processor's stack manipulations) are di- tine [$51F8], also part of NEW and RUN, resets the stack
rected to the alternate page, and references to addresses in the pointer to 250/$FA. BASIC limits the stack to 201 bytes, halt-
alternate page are directed to page 1. See the discussion of the ing with an error if all BASIC stack space is exhausted. The
MMU in Chapter 8 for details. The 128 does not normally portions of this page used for purposes other than the stack
behave like any other part of RAM.
make use of this feature; page 1 is normally seen at the true
page 1 locations here.
The storage of data in the stack is controlled by a register 255-266 $00FF-$010A
in the microprocessor called the stack pointer, which serves as Assembly area for numeric value strings
an index to the next available address in the stack. The stack The routine [S8E42] which generates a character string repre-
is filled from top to bottom—from location 511/$01FF down- senting the floating-point value in FAC1 uses this area to as-
ward to 256/$100. When no data is in the stack, the stack semble the characters for the digits of the value. The first
pointer contains 255/$FF, indicating that 511/$01FF is the character of the string will be either a space (for a positive
first available location. (The pointer is a one-byte index, to value in FAC1) or a minus sign (for a negative value). When
which the microprocessor automatically adds 256/$0100 to get numeric values are being printed, the string is assembled start-

82 83
256-268 $0100-$010C $0200-$02A0 512-672

ing at 256/$0100. However, when the string of characters for 291-310 $0123-$136
a line number is assembled, it starts at 255/$00FF. Because PRINT USING work area
the routine to add the characters here to the string pool as- The PRINT USING routine [$9520] uses this area to hold
sumes that the string starts at 256/$0100, this will cause the information about the way the output string is to be
leading space to be omitted for line number values. formatted.
256-268 $0100-$010C 294 $0126
Assembly area for disk boot command Command type indicator for PLAY processing
The Kernal BOOT_CALL routine [$F890] uses this area to as- This location is used during the PLAY statement routine
semble the block read command string to be sent to the drive. [$6DE1] to hold a value indicating which PLAY command (V,
The default command string i s U l : 1 3 0 0 1 00 (held in reverse O, T, X, or U) is currently being processed.
order) to read the contents of sector 0 of track 1, the first boot
sector. If more boot sectors follow, the track and sector param- 311-507 $0137-$01FB
eters will be updated to form the commands to read the addi- Stack space used by BASIC
tional sectors. This is the portion of the stack used while BASIC is active.
The BASIC cold-start routine initializes the stack pointer to
256-317 $O1OO-$O13D 251/$FB, but any subsequent NEW will reinitialize it to
Tape error log 250/$FA. Thus, locations 508-511/$01FC-$01FF (and, after
The Kernal routine which stores blocks of data on tape writes the first NEW, also 5O7/$1FB) are unused and available for
two identical copies of the data. That way, if errors are de- your own programming. BASIC requires that at least 44 bytes
tected when the first copy is read back in, it may be possible be available in the stack at the start of any expression evalua-
to correct that error from the second block. Whenever the rou- tion. The stack pointer is tested during the main expression
tine to load a block of data from tape [$EAEB] detects an error evaluation routine [$77EF]; if it is less than 99/$63, a FOR-
in a byte read from the first copy of the block, it stores the ad- MULA TOO COMPLEX error occurs. (This is a change from
dress of the erroneous byte in this area. Location 158/$9E Commodore 64 BASIC, where the same situation would result
serves as an index to the next available address slot. This area in an OUT OF MEMORY error.)
is sufficient to hold 31 error addresses, so a load error occurs
on the first pass only if more than 31 errors are recorded.
When the second copy of the block is read, any address for Input Buffer
which an error was recorded on the first pass will be loaded
with the corresponding byte from the second copy (unless an 512-672 $0200-$O2AO BUF
error was also detected for that same address in the second BASIC and monitor input buffer
copy; in that case, a load error occurs). This 161-byte area is used to hold input for both BASIC and
the monitor. The BASIC input routine [$4F93] allows logical
272-290 $0110-$0122 program lines up to 160 characters long to be entered. A byte
DOS command work area with the value 0/$00 is added following the last character of
The routine [$A3C3] to assemble command strings for the var- the input. If the line starts with a line number, the line here is
ious BASIC DOS support commands such as HEADER, COPY, tokenized and transferred to the BASIC program text area. An
and SCRATCH uses this area to hold information about the immediate mode line (one with no line number) is tokenized
type of command string to assemble. and then executed from the buffer. This buffer is also used to
hold input characters for the GET, GET#, GETKEY, INPUT,
and INPUT* statements, which is why those statements are
85
673 $O2A1 $02AF-$02BD 687-701

not allowed in immediate mode. The monitor main loop The routine reads and stashes the current MMU configu-
[$B08B] accepts command strings up to 159 characters long, ration register setting, then uses the value in the X register
and also adds a zero byte following the last character of input upon entry as the new configuration register setting. Next, the
to mark the end of the command. contents of the location specified by the address in the pointer
plus the offset in the Y register are loaded into the accumu-
673 $O2A1 Unused lator. The MMU configuration register is restored to its original
The BASIC and monitor input routines restrict the length of an value before exiting.
input line to 160 characters plus a zero byte to mark the end This routine is normally called via its related Kernal rou-
of input in the buffer, for a maximum of 161 bytes. Thus, this tine at 63440/$F7D0, which has a jump table entry at 65396/
location will never be used for input, and is available for other $FF74. When calling via the Kernal routine, the accumulator
uses. should contain the zero-page pointer address; the Kernal rou-
tine stores the accumulator value upon entry in 682/$02AA,
performing that setup step for you. The X register should con-
Common Indirect Routines tain a bank number (0-15) rather than an MMU configuration
The routines at 674-763/$02A2-$02FB are copied here from register setting value, since the Kernal routine also performs
Kernal ROM at 63488-63577/$F800-$F859 by the routine at the chore of converting the bank number into a configuration
57549/$E0CD, part of the reset sequence. The routines are register value,
placed here in page 2 because this is part of the IK block of
memory that is visible in all banks. These routines are the key 687-701 $02AF-$02BD STASH
to the operation of the 128—they make the memory banking
system possible by allowing a routine in one bank configura- Stores a value in any bank
tion to access data or call routines in another configuration. This routine stores the contents of the accumulator at a speci-
For example, these routines allow BASIC ROM routines to use fied location in any bank. Before calling this routine, you must
different blocks of RAM for program text and variables, and to set up a two-byte pointer in zero page to hold the address of
see program text in areas of RAM that lie at the same ad- the target location, then store the one-byte address of the
dresses as BASIC ROM itself. These routines are so integral to 2ero-page pointer in location 697/$02B9. You can use the Y
the successful operation of the 128 that the system will proba- register to specify an offset from the pointer address for the
bly crash almost immediately if the routines are accidentally target address. (If no offset is desired, be sure that the Y regis-
changed or overwritten. ter contains 0/$00.) The X register should contain the MMU
configuration register setting value which will establish a
memory configuration in which the target location is visible.
674-686 $02A2-$02AE FETCH The routine reads and stashes the current MMU configu-
Retrieves a value from any bank ration register setting, then uses the value in the X register
This routine loads the accumulator value with the contents of upon entry as the new configuration register setting. Next, the
a specified location in any bank. To use this routine, you must contents of the accumulator upon entry are stored in the loca-
set up a two-byte pointer in zero page to hold the address of tion specified by the address in the pointer plus the offset in
the target location, then store the one-byte address of the the Y register. The MMU configuration register is restored to
zero-page pointer in location 682/$02AA. You can use the Y its original value before exiting.
register to specify an offset from the pointer address for the This routine is normally called via its related Kernal rou-
target location. (If no offset is desired, be sure that the Y regis- tine at 63450/$F7DA, which has a jump table entry at
ter contains 0/$00.) The X register should contain the MMU 65399/$FF77. When calling via the Kernal routine, the X reg-
configuration register setting value which will establish a ister should instead contain a bank number (0-15), since the
memory configuration in which the target location is visible.

86
1 87
702-716 $02BE-$02CC I $02E3-$02FB 739-763

Kernal routine performs the chore of converting the bank Before calling the routine you must load location 2/$02
number into an MMU configuration register setting value. with the bank number (0-15) of the target routine and loca-
tions 3-4/$03-$04 with the address of the target routine. In
702-716 $02BE-$02CC CMPARE contrast to the usual low-byte/high-byte format, location
Compares accumulator contents against a value from any bank 3/$03 should be loaded with the high byte of the address and
This routine compares the accumulator value against the con- location 4/$04 with the low byte. Location 5/$05 should be
tents of a specified location in any bank. Before calling this loaded with the value you want in the status register when the
routine, you must set up a two-byte pointer in zero page to target routine is called (use 0/$00 if you don't want any status
hold the address of the target location, then store the one-byte register bits set). Optionally, you can also load locations
address of the zero-page pointer in location 712/$02C8. You 6-8/$06-$08 with any values you wish the accumulator, X
can use the Y register to specify an offset from the pointer ad- register, and Y register, respectively, to have when the target
dress for the target address, (If no offset is desired, be sure routine is called.
that the Y register contains 0/$00.) The X register should con- The routine calls JMPFAR to call the subroutine addressed
tain the MMU configuration register setting value which will in locations 3-4 in the bank specified in location 2 and with
establish a memory configuration in which the target location the status register value specified in location 5 and processor
is visible. register values from locations 6-8. Upon return from the target
This routine reads and stashes the current MMU configu- routine, the exit values of the accumulator, X register, and Y
ration register setting, then uses the value in the X register register are stored in location 6-8/$06-$08, respectively. The
upon entry as the new configuration register setting. Next, the value of the status register upon exit from the target routine is
value in the accumulator upon entry is compared against the stored in location 5/$05, and the exit value of the processor
contents of the location specified by the address in the pointer stack pointer is recorded in location 9/$09. Finally, the routine
plus the offset in the Y register. The MMU configuration regis- switches the system to the bank 15 configuration before re-
ter is restored to its original value before exiting. The status turning to the calling routine.
register value will reflect the result of the comparison.
This routine is normally called via its related Kernal rou- 739-763 $02E3-$02FB JMPFAR
tine at 63459/$F7E3, which has a jump table entry at 65402/ Jumps to a routine in any bank
$FF7A. When calling via the Kernal routine, the X register (This routine has a Kernal jump table entry at 65393/SFF71.)
should instead contain a bank number (0-15), since that rou- The routine here will jump to a routine at any address in any
tine performs the chore of converting the bank number into an standard bank configuration. Before calling the routine you
MMU configuration register setting value. must load location 2/$02 with the bank number (0-15) of the
target routine and locations 3-4/$03-$04 with the address of
717-738 $02CD-$02E2 JSRFAR the target routine. In contrast to the usual low-byte/high-byte
Calls a subroutine in any bank format, location 3/$03 should be loaded with the high byte of
(This routine has a Kernal jump table entry at 65390/$FF6E.) the address and location 4/$04 with the low byte. Location
The routine here will jump to a subroutine at any address in 5/$05 should be loaded with the value you want in the status
any standard bank configuration. Upon completion of the tar- register when the target routine is called (use 0/$00 if you
get routine, control is returned to the routine which called don't want any status register bits set). Optionally, you can
JSRFAR, just like a JSR. However, this routine leaves the sys- also load locations 6-8/$06-$08 with any values you wish the
tem in the bank 15 configuration, so a routine that uses accumulator, X register, and Y register, respectively, to have
JSRFAR must be located in an area of memory visible in the when the target routine is called. The routine pushes the ad-
bank 15 configuration for JSRFAR to properly return to the dress and status register values onto the stack, converts the
calling routine.
88
1 bank number value to a configuration register value, stores

89
764-765 $02FC-$02FD $0304-$0305 772-773

that value in the MMU configuration register, loads the pro- BASIC Indirect Vectors
cessor registers from locations 6-8, and executes an RTI in- The next nine vectors, 768-785/$0300-$0311, are used in
struction, which causes the processor to retrieve status register BASIC statement processing routines. The default values for
and address values from the stack and resume processing at these vectors are copied from a table at 16999-17016/
the specified address. $4267-$4278 in BASIC ROM by the BASIC vector initializa-
tion routine [$4251], part of the cold-start sequence. Thus,
unlike the Kernal indirect vectors, the BASIC vectors are not
Indirect Vectors affected by the RUN/STOP-RESTORE sequence. Any changes
The next 66 locations are indirect vectors for a variety of you make to the vectors will remain in effect until the next
BASIC, Kernal, and screen editor routines. An indirect vector cold start of BASIC, as during a reset.
is a pair of locations that hold an address for an indirect jump
instruction, such as JMP ($0300). The target address of the 768-769 $0300-90301 IERROR
JMP will be determined by the value in the specified indirect Indirect vector for BASIC error handling routine
vector. Having ROM routines jump through indirect vectors In BASIC ROM, the jump through this vector is taken at the
greatly increases the flexibility of the computer. Even though it beginning of the error handling routine (ERROR [$4D3C]). At
isn't possible to change a routine in ROM, it's possible to add the point the jump is taken, the X register will contain the cur-
to or modify a routine that has an indirect vector by redirect- rent BASIC error number (0-41, or 128 to print READY) and
ing the vector to a RAM-based routine. the accumulator will hold the last character read from program
text. The default target address of the vector is 19775/$4D3F,
764-765 $02FC-$02FD ESC_FN_VEC which simply reenters the error handling routine at the point
Indirect vector in extended function execution routine immediately following the jump. You can redirect this vector
The indirect jump through this vector is taken in the extended to change the way BASIC handles errors.
function handling subroutine when a two-byte extended func- In addition to modifying error handling, you can also use
tion token is found for which the second byte is greater than this vector to provide an alternate method of adding com-
the largest standard extended function token (10/$0A). When mands to BASIC.
the jump is taken, the accumulator will hold the out-of-range
token value and the status register carry bit will be set. If carry 770-771 $0302-$0303 IMAIN
is not clear upon return from the jump, a SYNTAX error mes- Indirect vector in main BASIC loop
sage will be generated. The vector normally holds 19576/
The jump through this indirect vector is taken in the main
$4C78, the address of the instruction following the call to this
BASIC direct mode routine [$4DB7] at the point immediately
vector. This doesn't change the carry setting, so out-of-range
after the READY prompt has been printed and the mode flag
extended function tokens normally result in an error message.
(127/$7F) has been set for immediate mode. The vector nor-
If you add new functions to BASIC, you'll need to change this
mally holds 19910/$4DC6, the address of the instruction im-
vector to point to the routine which executes your new func- mediately following the indirect jump. You can redirect this
tion. See Chapter 5 for an example. vector to a routine of your own if you wish to change the be-
havior of BASIC'S immediate mode.
766-767 $02FE-$02FF BNKVEC
Reserved indirect vector 772-773 $0304-$0305 ICRNCH
These two locations are not used by system ROM routines. Indirect vector in BASIC tokenization routine
Commodore literature indicates that they are reserved for use
The jump through this indirect vector is taken at the begin-
as an indirect vector for function ROM routines.
ning of the CRUNCH routine [$430A], which is responsible
for converting lines of input text into tokenized program lines.
90 91
774-775 $0306-$0307 $0310-$0311 784-785

The vector normally holds 17165/S430D, the address of the lowing the jump. Thus, the jump normally has no effect. If
instruction immediately following the indirect jump. You can you want to add extended tokens to BASIC, you should redi-
redirect this vector to a routine of your own if you wish to rect this vector to your routine to tokenize the new keywords.
change the way program lines are tokenized. The routine should compare the text pointed to by 61-62/
$3D-$3E with the target keyword. If a match is found, your
774-775 $0306-$0307 IQPLOP routine should return with the second byte of the two-byte ex-
Indirect vector in BASIC detokenization routine tended token in the accumulator. The X register should be set
The jump through this indirect vector is taken in the QPLOP to indicate whether the keyword is a statement or a function.
routine [$5123] at the point where the accumulator contains X should be set to 0/$00 for a function, in which case the first
the next character to be listed from the program line. The vec- byte will be 206/$CE, or to 255/$FF for a statement, in which
tor normally holds 20817/S5151, the address of the instruc- case the first byte will be 254/$FE. The Y register should con-
tion immediately following the indirect jump. You can redirect tain the length of the filename. Finally, you should make sure
this vector to a routine of your own if you wish to change the that the carry bit is clear upon exit so that your new token will
way program lines are listed. be properly processed.

776-777 $0308-$0309 IGONE 782-783 $030E-$030F IQPLOP2


Indirect vector in BASIC execution routine Indirect vector for detokenizing additional keywords
The jump through this indirect vector is taken at the begin- The jump through this indirect vector is taken in the routine
ning of the GONE routine [S4F92], the routine to execute a that lists BASIC program lines at the point where two-byte ex-
program line. The vector normally holds 19106/$4AA2, the tended statement or function tokens have been found which
address of the instruction immediately following the indirect are greater than the largest standard tokens. When the jump is
jump. You can redirect this vector to a routine of your own if taken, the accumulator will hold the second byte of the of-
you wish to change the way program lines are executed. fending token and the X register will hold 0/$00 if the first
byte was 206/$CE, indicating an extended function token, or
778-779 $030A-$030B IEVAL 255/$FF if the first byte was 254/$FE, indicating an extended
Indirect vector in BASIC evaluation routine statement token. The status register carry bit will also be set. If
The jump through this indirect vector is taken at the begin- that bit is still set upon return from this indirect jump, the
ning of the EVAL routine, which determines the value of the character will simply be printed. However, if carry is cleared,
next variable, string, or number in the program. The vector the extended keyword will be listed. The vector normally
normally holds 30938/$78DA, the address of the instruction holds 20941/S51CD, the address of the instruction immedi-
immediately following the indirect jump. You can redirect this ately following the indirect jump, so carry will normally re-
vector to a routine of your own if you wish to change the way main set. If you add new extended keywords to BASIC, you
values are evaluated. should change this vector to point to the routine to support
listing the keywords.
780-781 $030C-$030D ICRNCH2
Indirect vector for tokenizing additional keywords 784-785 $0310-$0311 IGONE2
The jump through this vector is taken in the tokenization rou- Indirect vector in extended statement execution subroutine
tine at the point where the first character of the keyword has The jump through this indirect vector is taken in the statement
been read into the accumulator and the carry bit has been set. execution routine at the point where a two-byte extended
If carry is still set upon return from this jump, the tokenization statement token has been found with a value greater than one
process will proceed normally. The vector normally holds of the standard extended statement tokens (second byte
17185/$4321, the address of the instruction immediately fol- greater than 38/$26). When the jump is taken, the accumu-
92 93
$031A-$031B 794-795
786-787 $0312-$0313

the jump through this vector is taken. If your routine does not
lator will hold the second byte of the extended token and the jump to the standard IRQ handler, it must exit by jumping to
carry bit will be set. If the carry bit is not clear upon return, a the common IRQ exit routine at 65331/$FF33.
SYNTAX error will be generated. The vector normally holds
19369/$4BA9, the address of the instruction immediately fol- 790-791 $0316-$0317 IBRK
lowing the indirect jump. Thus, the out-of-range token will
normally cause an error. If you add new extended-token state- Indirect vector to BRK instruction handling
ments to BASIC, you should change this vector to point to the When an IRQ interrupt occurs or a BRK instruction is exe-
address of the routine which executes the new statement. See cuted, a jump is automatically taken through the processor
Chapter 5 for an example. IRQ vector at 65534/$FFFE to the handling routine at 65303/
$FF17. That routine stores the accumulator, X and Y register,
786-787 $0312-$0313 Unused and bank configuration values on the stack, then checks
whether the routine was called as the result of an IRQ or a
These two locations are not used for any system vector, and BRK. If the execution of a BRK was responsible, a jump is
are thus available for your programming. For example, you taken through this indirect vector. The vector normally holds
could use these locations to set up an indirect vector in one of 45059/$B003, the address of the BRK entry into the machine
your own programs, or to store the original value when language monitor. You can redirect this vector to a routine of
changing one of the other vectors. your own if you want some other handling of BRK
instructions.
Kernal Indirect Vectors 792-793 $0318-$0319 INMI
The next 16 vectors, 788-819/$0314-$0333, are initialized
from a table at 57459-57490/$E073-$E092 in Kemal ROM by Indirect vector to NMI interrupt handling routine
the RESTOR routine [$E056]. The RESTOR routine is called When an NMI interrupt occurs, a jump is automatically taken
during both the reset and RUN/STOP-RESTORE sequences, through the processor NMI vector at 65530/$FFFA to the NMI
so either of those will reinitialize the vectors. The values in handling routine at 65285/$FF05. That routine stores the ac-
this vector table can be read or modified using the Kernal cumulator, X and Y register, and bank configuration values on
VECTOR routine [$E05BJ. the stack, then configures the system for bank 15 and takes a
jump through this indirect vector. The vector normally holds
788-789 $0314-$03l5 IIR9 64064/$FA40, the address of the standard system NMI service
Indirect vector to IRQ interrupt handling routine routine. You can redirect this vector to a routine of your own
When an IRQ interrupt occurs or a BRK instruction is exe- to add custom steps to the NMI process. However, your rou-
cuted, a jump is automatically taken through the processor tine must be in an area of memory visible in bank 15, since
IRQ vector at 65534/$FFFE to the handling routine at 65303/ that is how memory will be configured when the jump is
$FF17. That routine stores the accumulator, X and Y register, taken. If your routine does not jump to the standard NMI han-
and bank configuration values on the stack, then checks dler, it must exit by jumping to the common IRQ exit routine
whether the routine was called as the result of an IRQ or a at65331/$FF33.
BRK. If an IRQ was responsible, a jump is taken through this
indirect vector. The vector normally holds 64101/$FA65, the 794-795 $031A-$031B IOPEN
address of the standard system IRQ routine. You can redirect Indirect vector to Kernal OPEN routine
this vector to a routine of your own to add custom steps to the This vector is the normal link between the Kernal jump table
IRQ process. However, your target routine must be visible in entry at 65472/$FFC0 and the OPEN routine at 61373/
bank 15, since that is how memory will be configured when $EFBD, You can redirect this vector to a routine of your own if
you wish to modify the behavior of OPEN.
95
796-797

796-797 $031C-$031D
$O31C-$O31D

ICLOSE
I $032E-$032F

806-807 $0326-$0327 IBSOUT


814-815

Indirect vector to Kernal CLOSE routine Indirect vector to Kernal BSOUT routine
This vector is the normal link between the Kernal jump table This vector is the normal link between the Kernal jump table
entry at 65475/$FFC3 and the CLOSE routine at 61832/ entry at 65490/$FFD2 and the BSOUT routine at 61305/
$F188. You can redirect this vector to a routine of your own if $EF79. You can redirect this vector to a routine of your own if
you wish to modify the behavior of CLOSE. When the jump is you wish to modify the behavior of BSOUT. When this rou-
taken, the accumulator should hold the number of the logical tine is called, the value to be output should be in the
file to be closed. accumulator.
798-799 $031E-$O3IF ICHKIN 808-809 $0328-^0329 ISTOP
Indirect vector to Kernal CHKIN routine Indirect vector to Kernal STOP routine
This vector is the normal link between the Kernal jump table This vector is the normal link between the Kernal jump table
entry at 65478/$FFC6 and the CHKIN routine at 61702/ entry at 655O5/$FFE1 and the STOP routine at 63086/$F66E.
$F106. You can redirect this vector to a routine of your own if You can redirect this vector to a routine of your own if you
you wish to modify the behavior of CHKIN. When the jump is wish to modify the behavior of STOP. The routines which call
taken, the X register should hold the number of the logical file STOP expect it to return with the status register Z bit set if the
selected as the input source. RUN/STOP key was pressed, or clear otherwise.

800-801 $0320-$0321 ICKOUT 810-811 $032A-$032B IGETIN


Indirect vector to Kernal CKOUT routine Indirect vector to Kernal GETIN routine
This vector is the normal link between the Kernal jump table This vector is the normal link between the Kernal jump table
entry at 65481/$FFC9 and the CKOUT routine at 61772/ entry at 65508/$FFE4 and the GETIN routine at 61163/
$F14C. You can redirect this vector to a routine of your own if $EEEB. You can redirect this vector to a routine of your own if
you wish to modify the behavior of CKOUT. When the jump you wish to modify the behavior of GETIN. The routines
is taken, the X register should hold the number of the logical which call GETIN expect it to return a character code in the
file selected as the output source. accumulator.

802-803 S0322-S0323 ICLRCH 812-813 $032C-$032D ICLALL


Indirect vector to Kernal CLRCH routine Indirect vector to Kernal CLALL routine
This vector is the normal link between the Kernal jump table This vector is the normal link between the Kernal jump table
entry at 65484/$FFCC and the CLRCH routine at 61990/ entry at 65511/$FFE7 and the CLALL routine 61986/$F222.
$F226. You can redirect this vector to a routine of your own if You can redirect this vector to a routine of your own if you
you wish to modify the behavior of CLRCH. wish to modify the behavior of CLALL,

804-805 S0324-$0325 IBASIN 814-815 $032E-$032F IEXMON


Indirect vector to Kernal BASIN routine Indirect vector in monitor command execution routine
This vector is the normal link between the Kernal jump table This indirect vector appears in the machine language monitor's
entry at 65487/$FFCE and the BASIN routine at 61190/ main loop [$B08B] at the point where the first nonspace char-
$EF06. You can redirect this vector to a routine of your own if acter has been read from the input buffer and is ready to be
you wish to modify the behavior of BASIN. The routines interpreted as a command. The vector normally holds the ad-
which call BASIN expect it to return a character in the dress 45062/$B006, which in turn is a vector back to 45234/
accumulator. $B0B2, the address immediately following the indirect jump.
96 97
816-817 $0330-$0331 $0336-$0337 822-823

However you can redirect this vector to a routine of your own 818-819 $0332-$0333 ISAVE
if you wish to add commands to the machine language moni- Indirect vector in Kernal SAVE routine
tor. The following example adds two new monitor com- This indirect vector appears in the Kernal SAVE routine
mands—P, which behaves like D (disassemble) but routes [$F53E] at the point after the ending address has been stored
output to the printer, and Q, which closes the file to the in 174-175/$AE-$AF and the starting address has been stored
printer: in 193-194/$C1-$C2. The vector normally holds 62798/
0D00 LDA #$0B ;Redirect vector to new handling routine $F54E, the address immediately following the indirect jump.
0D02 STA $032E You can redirect this vector to a routine of your own if you
0D05 LDA #$0D wish to modify the behavior of SAVE.
OD07 STA $032F
ODOA RTS
ODOB CMP #$51 ;Is character code for Q? Screen Editor Indirect Vectors
ODOD BNE $OD1A The next five vectors, 820-829/$0334-$033D, are copied from
ODOF LDA #$04 ;If so, close logical file 4 a table at $C065-$C06E in screen editor ROM by the CINT
0D11 JSR $FFC3 routine [$C07B] during the reset sequence. CINT is also part of
0D14 JSR $FFCC ;Restore normal I/O channels (CLRCH) RUN/STOP-RESTORE, but a flag in the routine is normally
0D17 JMP $B08B ;Retum to monitor main loop used to skip the vector initialization step in this case. As a re-
0D1A CMP #$50 ;Is character code for P?
sult, vector addresses aren't usually changed by RUN/STOP-
GD1C BNE $0D3S
0D1E LDA #$04 ;H so, OPEN 4,4,0 RESTORE.
0D2O TAX
0D21 LDY #00 820-821 $0334-$0335 CTLVEC
0D23 JSR $FFBA Indirect vector in screen BSOUT handling
0D26 LDA #$00 The jump through this indirect vector is taken as the first step
0D28 JSR $FFBD in the screen BSOUT subroutine [$C7B6] which processes
0D2B JSR $FFCO character code values less than 32/$20. At the time the jump
0D2E LDA #$04 ;Set logical file 4 for output is taken, the accumulator holds the current character code. The
0D30 JSR $FFC9 vector normally holds 51129/$C7B9, the address immediately
D033 LDA #$44 ;Change monitor command to D
following the indirect jump. You can change this vector to
(disassemble)
0D35 JMP $B006 ;Return to monitor command processing point to a routine of your own if you wish to change the
printing behavior of character codes in the range 0-31/
loop
$00-$lF. All codes in this range perform cursor movements,
816-817 $0330-$0331 ILOAD color changes, or other control functions rather than printing
characters. If you wish to add new control functions, codes 0,
Indirect vector in Kernal LOAD routine 1, 3, 4, 6, 16, 21-23, 25, and 26 are currently unused.
This indirect vector appears in the Kernal LOAD routine
[$F265] at the point after the starting address (in X and Y 822-823 $0336-$0337 SHFVEC
when the routine is entered) has been stored in 195-196/
$C3-$C4. The accumulator should still contain a value indicat- Indirect vector in screen BSOUT handling
ing whether the operation is a load or a verify (0/$00 for load, The jump through this indirect vector is taken as the first step
nonzero for verify). The vector normally holds 62060/$F26C, in the screen BSOUT subroutine [$C802] which processes
the address immediately following the indirect jump. You can character code values greater than 127/$7F. At the time the
redirect this vector to a routine of your own if you wish to jump is taken, the accumulator holds the current character
modify the behavior of LOAD. code. The vector normally holds 51205/$C805, the address

98 99
824-825 $0338-$0339 $033C-$O33D 828-829

immediately following the indirect jump. You can change this 826-827 $033A-$033B KEYVEC
vector to point to a routine of your own if you wish to change Indirect vector in keyboard scanning routine
the printing behavior of character codes in the range The jump through this indirect vector is taken during the
128-255/$80-$FF. Codes 128-159/$81-$9F perform cursor SCNKEY routine [$C55D] at the point following completion of
movements, color changes, or other control functions rather the keyscan and the evaluation of the shift key status. At the
than printing characters. If you wish to add new control func- point the jump is taken, the accumulator (along with location
tions, codes 128, 131, and 132 are currently unused. 212/$D4) will contain the current keyboard matrix code, and
location 211/$D3 will reflect the current shift key status. The
824-825 $0338-$0339 ESCVEC vector normally holds the address 5O657/$C5E1, the point in
Indirect vector in ESC sequence handling routine the keyscan routine immediately following the indirect jump,
The jump through this indirect vector is taken as the first step but you can redirect the vector if you wish to change the be-
in the screen BSOUT subroutine [$C9BE] which processes ESC havior of the keyscan routine.
(escape) key sequences. At the time the jump is taken, a test
will have determined that the previous character was ESC 828-829 $033C-$033D KEYCHK
(code 27/$lB). The accumulator holds the current character Indirect vector in keyboard scanning routine
code, the one which followed ESC. The vector normally holds The jump through this indirect vector is taken during the
51649/$C9C1, the address immediately following the indirect SCNKEY routine [$C55D] after the character code for the
jump. You can redirect this vector to add your own ESC se- keypress has been read from the decoding table and immedi-
quences. The following example adds ESC T, which moves the ately before the test for a programmable key. At the point the
position of the bitmap/text division of a screen line up one jump is taken, the accumulator will contain the character code
row each time the sequence is used: corresponding to the current keypress and the X register will
1400 LDA #$0B ;Redlrect vector to handling routine contain the current shift key status (from 211/$D3). The vec-
1402 STA $0338 tor normally holds 50861/$C6AD, the point in the keyscan
1405 LDA #$14 routine immediately following the indirect jump, but you can
1407 STA $0339 redirect this pointer to modify the behavior of the keyscan.
140A RTS One use of this vector is to disable programmable keys.
140B CMP #$5E ;Is character t? While the definition strings are handy, sometimes—particu-
140D BEQ $1412 larly when you are adapting programs from the Commodore
140F JMP $C9C1 ;If not, jump to normal processing 64—you might like for them to instead generate their standard
routine
1412 LDA $D8 ;Is a split screen in use? character codes. One way to achieve this is to change this
1414 AND #$40 pointer so that the test for programmable keys is bypassed:
1416 BEQ $140F ;If not, use normal processing routine POKE 828,183
1418 LDA $0A34 ;Is the split already at the top row of the
screen? This changes the low byte of the pointer so that the target ad-
141B CMP #$3A dress becomes 50871/$C6B7, the point in the routine immedi-
141D BCC $140F ;If so, ignore this sequence ately beyond the test for programmable keys.
141F SBC #$08 ;Move the split position up one row (8
scan lines)
1421 STA $0A34 Screen Editor Tables
1424 RTS Locations 830-865/$033E-$0361 are the domain of the screen
editor.

100 101
830-841 $033E-$0349 $034A-$0353 842-851

830-841 $033E-$0349 DECODE the CAPS LOCK decoding table used the wrong value for the
Keyboard table pointers Q key entry. The following shows how to fix the CAPS-Q bug
These six 2-byte pointers hold the starting addresses of the 89- by setting up a new copy of the decoding table for that shift
byte tables used to translate the matrix code for the current pattern:
keypress into a character code: 100 REM ** COPY CAPS LOCK TABLE TO RAM
Pointer Shift pattern Default table address 110 FOR 1 = 0 TO 88:POKE 6912 + I,PEEK(64484 + I):NEXT
830-831/$033E-$033F Unshifted 64128/$FA80 120 REM ** CHANGE INCORRECT CHARACTER CODE FOR Q
832-833/$0340-$0341 SHIFT 64217/$FAD9 130 POKE 6912 + 62,209
834-835/$0342-$0343 Commodore 64306/SFB32 140 REM ** REDIRECT POINTER TO NEW TABLE
836-837/$0344-$0345 CONTROL 64395/$FB8B 150 POKE 840,0:POKE 841,27
838-839/$0346-$0347 ALT 64128/$FA80 (same as A custom table should consist of 89 values in matrix code
unshifted) order. Refer to Tables 9-1-9-5 for a listing of the default ta-
840-841/$0348-$0349 CAPS LOCK 64484/$FBE4 bles. The final value in the table should be 255/$FF, and you
The status of the five shift keys, recorded in 211/$D3, is used should be sure to include the shift key codes in the proper lo-
to select one of the table addresses from this area. If no shift cations. The following program sets up a Dvorak-style
key is pressed, the unshifted table is used. If one shift key is keyboard:
pressed, the appropriate decoding table is selected. If more
than one shift key is pressed simultaneously, the table is se- 100 FOR 1=0 TO 88:READ K:POKE 691.2 + 1 ,K:NEXT
lected as follows: CONTROL has the highest priority; when it 110 POKE 830,0:POKE S31,27:END
is pressed in combination with any other shift keys, the CON- 120 DATA 2 0 , 1 3 , 2 9 , 1 3 6 , 1 3 3 , 1 3 4 , 1 3 5 , 1 7 , 5 1 , 4 4
130 DATA 6 5 , 5 2 , 5 9 , 7 9 , 4 6 , I , 5 3 , 8 0 , 6 9 , 5 4
TROL table is used. The SHIFT and Commodore keys are next 140 DATA 7 4 , 8 5 , 8 9 , 8 1 , 5 5 , 7 0 , 7 3 , 5 6 , 8 8 , 6 8
in priority; however, when they are pressed simultaneously, 150 DATA 7 1 , 7 5 , 5 7 , 6 7 , 7 2 , 4 8 , 7 7 , 8 4 , 8 2 , 6 6
no decoding table is selected (although the combination may 160 DATA 4 3 , 7 6 , 7 8 , 4 5 , 8 6 , 8 3 , 4 7 , 8 7 , 9 2 , 4 2
cause character set switching). ALT and CAPS LOCK have the 170 DATA 5 9 , 1 9 , 1 , 6 1 , 9 4 , 9 0 , 4 9 , 9 5 , 4 , 5 0
lowest priority. They are effective in selecting the decoding ta- 180 DATA 3 2 , 2, 3 9 , 3, 1 3 2 , 5 6 , 5 3 , 9, 5 0 , 52
190 DATA 5 5 , 4 9 , 2 7 , 4 3 , 4 5 , 1 0 , 1 3 , 5 4 , 5 7 , 5 1
ble only if no other shift keys are being pressed. If pressed 200 DATA 8 , 4 8 , 4 6 , 1 4 5 , 1 7 , 1 5 7 , 2 9 , 2 5 5 , 255
simultaneously, both are ignored and the unshifted table is
used. Once a table is selected, its address is loaded into
204-205/$CC-$CD, and the current matrix code in 212/$D4 842-851 $034A-$0353 KEYBUF
is used as an offset to the specific character code to be re- Keyboard buffer
trieved from the table. This ten-byte area is the keyboard buffer. When the SCNKEY
The default decoding table addresses are copied here from routine [$C55D] detects a valid keypress, it generates a cor-
a table at 49263/$C06F in screen editor ROM by the CINT responding character code. The character code is then stored
screen editor initialization routine [$C07B] during the reset se- in this buffer to await processing. (The Kernal GETIN and BA-
quence. CINT is also part of the RUN/STOP-RESTORE se- SIN routines are normally used to retrieve characters from this
quence, but it includes a flag that normally prevents the buffer.) Location 208/$D0 holds the number of characters cur-
vectors from being reinitialized in that case. To redefine the rently waiting in the buffer. The maximum number of charac-
128 keyboard, you need only set up a new decoding table in ters that can be held in the buffer is determined by the value
RAM and change one of the address values here to point to in location 2592/$0A20. If the value there is greater than 10,
the new table. For example, if you've used the CAPS LOCK the keyboard buffer will overwrite the following memory
key, you've probably discovered that it doesn't appear to af- areas such as the tab stop bitmap. When the value in 208/$DO
fect the Q key. Actually, the problem is that whoever prepared equals the value in 2592/$0A20, the buffer is full; any further
102 103
842-851 $034A-$0353 $035E-$0361 862-865

keypresses will be ignored until one or more characters are re- 852-861 $0354-$035D TABMAP
moved from the buffer. Tab stop bitmap
This key buffering system allows for a powerful program- These ten bytes provide an 80-bit map of the display's hori-
ming technique known as the dynamic keyboard. By storing zontal character positions. Each horizontal position in the cur-
character code values in the buffer and storing the number of rently active display has a corresponding bit in the map. For
characters in 208/$D0, a program can appear to type on the the VIC chip's 40-column display, only the first five bytes (40
keyboard. For example, the following lines add a default an- bits) are used. When a bit is set to % 1 , a tab stop is estab-
swer to the INPUT prompt: lished at the corresponding screen column. Printing the TAB
200 POKE 842,89: POKE 208,1: REM PLACE Y IN BUFFER character, code 9/$09, or pressing the TAB key will move the
210 INPUT'ARE YOU SURE";A$ cursor rightward to the next tab stop (or the right window
margin if no tab stops are set between the current cursor posi-
When the INPUT statement begins to look for characters, it tion and the right margin).
will find the Y already in the buffer.
An even more powerful use of the dynamic keyboard During the CINT screen editor initialization sequence, all
technique is to allow a program to execute a series of com- locations in the map are set to 128/$80, which establishes a
mands after it ends. When a program is finished executing, tab stop every eighth column. Printing character code 24/$18
BASIC looks to the keyboard buffer for the characters of the (or pressing SHIFT-TAB) toggles the map bit corresponding to
next command. Thus, any characters placed in the buffer the current cursor column, setting a tab stop if the bit was pre-
while a program is running will effectively be typed if the pro- viously %0 or clearing the tab stop if the bit was previously
gram ends. Since the buffer can hold only ten characters, the % 1 . The ESC Z sequence can be used to clear all tab stops (all
common practice is to print commands at carefully planned locations in the map will be filled with 0/$00), and the ESC Y
places on the screen, then fill the buffer with cursor move- sequence can be used to restore default tab stops (all locations
ment and RETURN characters to execute the commands. The in the map will be filled with 128/S80).
following program illustrates this technique. It creates DATA When the active display is switched, screen editor SWAP-
statements for one of the sprite patterns. You can adapt the PER routine [$CD2E] exchanges the contents of this area with
program for your own needs by changing the values in line the contents of locations 2656-2665/$0A60-$0A69, the stor-
10. AD is the starting address of the data, NI is the number of age area for the inactive display tab stop bitmap. Thus, tab
DATA items to be generated, and LN is the line number of stop settings are preserved while the screen is inactive,
the first DATA statement to be generated. The program prints
a DATA line and a GOTO statement on the screen, then 862-865 $035E-$0361 LNKMAP
places {HOME} {RETURN} {RETURN} in the buffer and ends. Line link bitmap
The buffered characters are executed, entering the DATA line These four bytes are used to provide a 25-bit map of the 25
and restarting the program. rows of the active screen display (bits 0-6 of location
865/$361 are unused). Each row of the currently active dis-
10 AD=3584:NI=64:LN=100!l=0 play has a corresponding bit in the map. When a bit is set to
20 IF I=>NI THEN END % 1 , the corresponding row is linked to the row above as part
30 PRINT"[CLR}";LN;"DATA";:LN=LN+I0:J=0 of a logical line. Bits set to %0 indicate unlinked lines (or rows
40 PRINT P E E K ( A D + I ) ; : I = I + 1 : I P I=>NI THEN 60 that are the first physical line of a logical line). These locations
50 J = J + 1 ; I F J < 8 THEN PRINT"{LEFT},";:GOTO 40
60 PRINT:PRINT"GOTO 20"
are cleared to 0/$00, unlinking all lines, whenever the output
70 POKE 842,I9:POKE 843,13:POKE 844,.13:POKE 2 0 3 , 3 : E window is cleared or reset to full screen size, or whenever the
ND screen editor WINDOW routine is used to change the size of
the output window. A screen line is normally linked to the
one above when the cursor moves onto the line by wrapping

104
A. 105
866-875 S0362-S036B $0380-$039E 896-926

from the right margin of the line above. Line linking can be output, the device number for the selected file will be read
disabled by setting the flag bit in location 248/$F8. from this table. When a file is closed, the Kernal CLOSE rou-
When the active display is switched, the screen editor tine [$F188] removes the file's entry from this table.
SWAPPER routine [$CD2E] exchanges the contents of this
area with the contents of locations 2666-2669/$0A6A-$0A6D, 886-895 $0376-$037F SATBL
the storage area for the inactive display line link bitmap. Thus, Secondary address table for currently open files
the line link status is preserved when the screen is inactive. When a logical file is opened, the OPEN routine [$EFBD] will
OR the specified secondary address for the file with the value
Kernal File Tables 96/$60, then store the result in the next available entry in this
The following three ten-byte tables hold information on any table. When the Kernal CHKIN [$F106] or CKOUT [$F14C]
currently open logical files. The three tables are parallel; the routines are used to select a logical file for input or output, the
entry for a particular file will appear at the same position in secondary address for the selected file will be read from this
all three tables. Location 152/$98 serves as an index to the table. When a file is closed, the Kernal CLOSE routine [$F188]
next available entry in the tables. The fact that there are only removes the file's entry from this table.
ten bytes per table means that no more than ten logical files The Kernal includes a routine [LKUPSA, $F786] to search
may be opened simultaneously. for a particular secondary address in this table.

866-875 $0362-$036B LATBL BASIC Working Storage


Logical file number table for currently open files The remainder of page 3, locations 896-1023/$0380-$03FF, is
When a logical file is opened, the OPEN routine [$EFBD] ex- used to hold BASIC character retrieval subroutines and to
amines the contents of this table. A FILE OPEN error occurs if store values for a variety of BASIC routines. The subroutines
an existing file already uses the specified logical file number, in locations 896-980/$0380-$03D4 are copied here from loca-
and a TOO MANY FILES error occurs if ten files are already tions 17017-17101/$4279-$42CD in BASIC ROM during the
open. Otherwise, the logical file number for the file is stored BASIC cold-start sequence. The routines are not reinitialized
in the next available entry in this table. When the Kernal by RUN/STOP-RESTORE.
CHKIN [$F106] or CKOUT [$F14C] routines are used to select
a logical file for input or output, this table is searched for the 896-926 $0380-$039E CHRGET
specified logical file number. A FILE NOT OPEN error occurs Main BASIC character retrieval routine
if the file number is not found in the table. Otherwise, the cor- This is BASIC'S primary routine for reading program text for
responding device number and secondary address will be read interpretation and execution. The routine is designed to re-
from the respective tables. When a file is closed, the Kernal trieve the next nonspace character from a BASIC line (in bank
CLOSE routine [$F188] removes the file's entry from this table. 0), and to return information about the type of character re-
The Kernal includes a routine [LKUPLA, $F79D] to search trieved. The routine begins by incrementing the current ad-
for a particular file number in this table. dress in the text pointer at locations 61-62/$3D-$3E. The
system is set for the bank 0 configuration, the value at the lo-
876-885 $036C-$0375 DNTBL cation specified in the pointer is loaded into the accumulator,
Device number table for currently open files and the system is reset for the bank 14 configuration. The rou-
When a logical file is opened, the OPEN routine [$EFBD] tine then performs a series of tests that will set the processor
stores the device number for the file in the next available en- status register to reflect the type of character that was read. If
try in this table. When the Kernal CHKIN [$F106] or CKOUT a space character (code 32/$20) is read, the routine loops back
[$F14C] routines are used to select a logical file for input or to read another character (which is why spacing is not usually

106 107
927-938 $039F-$03AA $03D2-$03D4 978-980

significant in BASIC program lines). If the character is one of 951-959 $03B7-$03BF INDIN1_RAM1
the numbers 0-9, the carry bit will be clear (carry will be set if
the character is not a digit). If the character was a colon (:), Alternate routine to retrieve a character from variable storage
BASIC'S end-of-statement marker, or a zero byte, BASIC'S This routine retrieves a character from the variable storage
end-of-line marker, the status register Z bit will be set; other- area (bank 1) using locations 36-37/$24-$25 as a pointer and
wise, the Z bit will be clear. the contents of the Y register as an offset from the address in
the pointer. The character will be in the accumulator upon re-
This routine has an alternate entry point at 902/$386, turn from the routine and the system will be left in the alter-
called CHRGOT, which retrieves and tests the current charac- nate bank 14 configuration that includes block 1 RAM.
ter, the one at the address currently in 61-62/$3D-$3E, with-
out updating the pointer.
Since this routine is in RAM, it can be modified to change
960-968 $03C0-$03C8 INDIN2
the way BASIC program text is read. Refer to Chapter 5 for Alternate routine to retrieve a character from program text
details on how you can use this technique to add new com- This routine retrieves a character from program text (bank 0)
mands to BASIC. using locations 38-39/$26-$27 as a pointer and the contents
of the Y register as an offset from the address in the pointer.
927-938 $039F-$03AA INDSUB_RAMO The character will be in the accumulator upon return from the
Alternate routine for reading characters from program text routine and the system will be left in the bank 14
This routine retrieves a character from program text (bank 0). configuration.
The value in the accumulator upon entry specifies the address
of the zero-page pointer containing the base address, and the 969-977 $03C9-$03Dl INDTXT
value in the Y register specifies the offset from this base ad- Alternate routine to retrieve current program text character
dress to the character to be read. The character will be in the This routine retrieves the current program text character using
accumulator upon return from the routine and the system will 61-62/$3D-$3E as a pointer. The character will be in the ac-
be left in the bank 14 configuration. BASIC ROM includes a cumulator upon return from the routine and the system will
collection of character retrieval subroutines (17102-17159/ be left in the bank 14 configuration. The routine is similar to
$42CE-$4307) that make use of this routine. the CHRGOT entry into GHRGET, but without the tests for
character type.
939-950 $03AB-$03B6 INDSUB_RAM1
Alternate routine for reading characters from variable storage 978-980 $03D2-$03D4 ZERO
This routine retrieves a character from the variable storage Null descriptor
area (bank 1). The value in the accumulator upon entry speci- If the routine [$7AAF] which searches for a variable name in
fies the address of the zero-page pointer containing the base the variable table fails to find the name when called by EVAL
address, and the value in the Y register specifies the offset [$7978] or POINTER [$82FA], the address of this area is re-
from this base address to the character to be read. The charac- turned as the variable descriptor address. This prevents vari-
ter will be in the accumulator upon return from the routine able table entries from being created if a variable name is first
and the system will be left in the alternate bank 14 configura- used in an expression argument or in the POINTER function.
tion that includes block 1 RAM. BASIC ROM includes a col- For example, if you use B$ = A$ or AD = POINTER(A$) when
lection of character retrieval subroutines (17102-17159/ no variable A$ exists, no entry for A$ will be created. These
$42CE-$4307) that make use of this routine. three locations are all filled with the value 0/$00, copied here
from ROM along with the preceding subroutines.

108 109
981 S03D5
S03E2 994

981 $03D5 CURRENT-BANK 991 $03DF BITS


Bank number for BASIC operations
The value in this location specifies the bank number used dur- Floating-point overflow byte
ing BASIC routines which directly access memory. The value This location is used for working storage while aligning float-
here doesn't affect the current system configuration—only the ing-point values for mathematical operations, or for converting
configuration that will be established for certain operations. floating-point values into integers. The value here is initialized
The value here specifies the bank to which data will stored to O/$0O during the BASIC cold-start sequence, and will be re-
when the POKE statement is used, or from which data will be set to that value during CLR or warm start.
read when the PEEK statement is used. The value here deter-
mines the bank configuration in which the target address for a 992-993 $03E0-$03El SPRTMP
SYS statement will be seen. It also determines the bank for the Temporary pointer storage
address used in the WAIT statement. The value here deter- These locations are used during the SPRSAV routine [$76EC]
mines the default bank for the BOOT, BLOAD, and BSAVE to temporarily preserve the current value in the CHRGET
statements. It also determines the system bank affected by the pointer (61-62/$3D-$3E).
STASH, FETCH, and SWAP statements.
The value here is initialized to 15/$0F during the BASIC 994 $O3E2 FG_BG
cold-start sequence, so bank 15 is the default. The BANK Standard bitmap color fill value
statement can be used to change the value here. This location holds the color memory fill pattern for standard
bitmapped mode. When the SCNCLR routine [$6A79] is used
982-985 $03D6-$03D9 TMPDES to clear the standard bitmapped (GRAPHIC 1 or GRAPHIC 2)
Pointers for INSTR evaluation display, all locations in the video matrix area will be filled
These locations are used as working pointers for the INSTR with the value here. (The SCNCLR routine is also used when
statement routine [$99C1]. Locations 982-983/$03D6-$03D7 the clear parameter is specified in a GRAPHIC statement.) In
hold the address of the first string parameter and locations standard bitmapped mode, the video matrix area holds fore-
984-985/$03D8-$03D9 hold the address of the second string. ground and background color information, so the value here
determines the default foreground and background colors for
$03DA FIN_BANK all screen positions after the screen is cleared.
986 Whenever the BASIC graphics routines are used to draw
String block flag
anything on the standard bitmapped display, the value in this
This location is used during the routine [$8D22] to convert
location will determine the color of the line drawn. If color
character strings into floating-point values to indicate whether source 0 was specified for the line, the value in the lower four
the string being converted resides in BASIC program text bits here will be stored in the lower four bits of the video ma-
(block 0 RAM) or in the string pool {block 1 RAM). trix locations corresponding to the line's location in the bit-
987-990 $03DB-$03DE SAVSIZ map. If color source 1 is specified, the value in the upper four
bits here will be stored in the upper four bits of the video matrix
Temporary storage for SHAPE data locations corresponding to the line's location in the bitmap.
These locations are used during the SSHAPE routine [$642B]
The value in this location is updated whenever the
to hold coordinates of the area being saved, and during the COLOR statement [$69E2] is executed. The high four bits here
SPRSAV routine [$76EC] to hold the descriptor of the first pa- are set to the value in the lower four bits of the foreground
rameter value. color in location 134/$86. The lower four bits here are set to
the value in the lower four bits of the VIC background color
register at 53281/$D021. These locations are initialized during

110
111
995 S03E3 $03FD-$03FF 1021-1023

the BASIC cold-start sequence to the default foreground and 1008-1020 $03F0-$03FC DMA
background colors, so this location will initially hold 219/$DB, DMA_CALL execution routine
for a light green foreground and dark gray background. The This area holds the RAM-resident portion of the Kernal
value here is not affected by RUN/STOP-RESTORE. DMA_CALL routine [$F7A5]. The routine is copied here from
Kernal ROM during the reset sequence. It is designed to initi-
995 $03E3 FG-JMC1 ate a DMA (direct memory access) command to the REC
Multicolor bitmap color fill value (RAM expansion controller) chip in an installed memory ex-
This location holds the color memory fill pattern for multicolor pansion module. The routine loads the current memory con-
bitmapped mode. When the SCNCLR routine [$6A79] is used figuration register contents, then stores the contents of the Y
to clear the multicolor bitmapped (GRAPHIC 3 or GRAPHIC register in the REC command register address (57089/$DF01)
4) display, all locations in the video matrix area will be filled and stores the contents of the accumulator in the MMU mem-
with the value here. (The SCNCLR routine is also used when ory configuration register (65280/$FF00). If the REC is config-
the clear parameter is specified in a GRAPHIC statement.) In ured in its default state, storing the value in the MMU register
multicolor bitmapped mode, the video matrix area holds color should trigger the specified REC operation. See Chapter 8 for
information for pixels with %01 and %10 bit patterns, so the more information about the REC chip. Upon completion of the
value here determines the default colors for those pixel pat- operation, the original memory configuration register setting
terns in all screen positions after the screen is cleared. will be restored.
For the BASIC graphics routines that draw on the multi-
color bitmapped display, the value in this location will deter- 1021-1023 $03FD-$03FF Unused
mine the color of any lines drawn using color sources 1 or 2. The locations in this range are not used by any system ROM
If color source 1 was specified for the line, the value in the routine, and are thus available for your own programming.
upper four bits here will be stored in the upper four bits of the
video matrix locations corresponding to the line's location in
the bitmap. If color source 2 was specified, the value in the
lower four bits here will be stored in the lower four bits of the
video matrix locations corresponding to the line's location in
the bitmap.
The value in these locations can be changed with the
COLOR statement [$69E2]. The high four bits here are set to
the value in the lower four bits of the foreground color in lo-
cation 134/$86. The lower four bits here are set to the multi-
color 1 value in the lower four bits of location 132/$84. The
location is initialized during the BASIC cold-start sequence to
the default multicolor pixel colors for %01 and %10 patterns,
so this location will initially hold 2O9/$D1, for light green
%01 pixels and white %1O pixels. The value here is not af-
fected by RUN/STOP-RESTORE.

996-1007 $03E4-$03EF Unused


The locations in this range are not used by any system ROM
routine, and are thus available for your own programming.

112 113
Bank 0 Working
Storage
VIC Default Screen Memory
1024-2047/$0400-$07FF
This IK area is the default location for the VIC chip's screen
memory in character (GRAPHIC 0) mode. It's not used by
the system for any other purpose. Screen memory can be relo-
cated to any other IK block in RAM by changing the appro-
priate bits in the registers at 53272/$D018 and 56576/$DD00.
For example, screen memory for the system bitmapped modes
(GRAPHIC 1 or GRAPHIC 3) is located at 7168-7423/
$1COO-$1CFR However, the screen editor CINT routine
[$C07B] and Kernal IOINIT routine [$E109], both included in
the reset and RUN/STOP-RESTORE sequences, will reset the
registers to have screen memory at this default area. Conve-
niently, this is the same area used for default screen memory
in the Commodore 64.
When used for screen memory, the first 1000 locations of
this area (1024-2023/$0400-$07E7) correspond to the 1000
character positions of the VIC chip's 40-column X 25-row
screen display. The value in each screen memory location de-
termines what will be displayed in the corresponding position
on the screen. The screen memory values, called screen codes,
are used as indexes into character pattern memory. Any char-
acter pattern can be displayed at any screen location by stor-
ing the appropriate screen code in the appropriate screen
memory location. Appendix C lists the standard character pat-
tern for each screen code. Clearing the screen fills these 1000
memory locations with 32/$20, the screen code for the space
character.
While this area is used as screen memory, the highest
eight locations (addresses 2040-2047/$07F8-$07FF) are used
to hold definition pointers for the eight sprites supported by
the VIC chip. The pattern definition for a sprite requires 64
bytes, so there is room within a 16K VIC video bank for 16384
/ 64, or 256 sprite definitions. These pointer locations each

117
1024-2047 $0400-$07FF $0800-$09FF 2048-25S9

hold a value between 0-255/$00-$FF indicating which 64- GRAPHIC 4) it is possible for the same sprite to have different
byte area within the current video bank will be used to hold shapes in the text and bitmapped portions of the display. The
the pattern definition for the corresponding sprites. Changing SCNCLR routine (also called when you add an extra ,1 to the
the shape of a sprite is as simple as changing the correspond- GRAPHIC statement) copies the text screen sprite pointer val-
ing sprite pointer to select a new pattern definition. To find ues from locations 2040-2047/$07F8-$07FF to the bitmapped
the address specified by the pointer value, multiply the value screen sprite pointers at 8184-8191/$1FF8-$1FFF, but there's
by 64/$40 and add the base address for the video bank. The no ROM routine to perform a copy in the opposite direction—
default pointer values, established by the BASIC cold start ini- from bitmapped screen sprite pointers to text screen sprite
tialization subroutine [$4045], are as follows: pointers—so your text screen pointers should be preserved
Location Sprite Default pointer value even if you change the pointers for sprites displayed on the
2040/S07F8 0 56/$38 bitmapped screen.
2041/$07F9 1 57/$39 The remaining 16 locations in this area, addresses
2042/$07FA 2 58/$3A 2024-2039/$07E8-$07F7, are unused by any system routine.
2043/$07FB 3 59/$3B They are not affected by clearing the screen or changing sprite
2044/S07FC 4 60/$3C pointers, or by reset or RUN/STOP-RE STORE. Thus, they are
2045/S07FD 5 61/$3D available for your own programming uses.
2046/$07FE 6 62/$3E
2047/$07FF 7 63/$3F
The default values point to the eight sprite definition BASIC Runtime Stack
areas at 3584-4095/$0E00-$OFFF. While BASIC initializes 2048-2559/$0800-$09FF
each pointer to a different definition area, this is not manda-
tory. For example, if you want all eight sprites to have the This 512-byte area is used by BASIC for its runtime stack.
same shape you can just design one sprite pattern and store When you use the machine language JSR instruction to call a
the pointer to that pattern in all eight locations. BASIC doesn't subroutine, there must be some way to record the address to
have any statement specifically for changing pointers, so you'll return to upon completion of the subroutine. As explained in
have to use POKE to change the values here. Because the de- the entry for locations 256-511/$D1OO-$O1FF, the return ad-
fault definition area only has room for eight sprites, you'll dress is placed in a special area of memory called the proces-
have to use some other area of free memory if you want to sor stack. BASIC'S GOSUB statement and looping statements
use more than eight sprite shapes. All sprite pattern defini- like FOR and DO also need some place to store the address to
tions must lie within the current 16K video bank. For the de- return to upon completion of the subroutine or loop. In earlier
fault video bank (0-16383/$0000-$3FFF in block 0 RAM), the versions of Commodore BASIC, this information was also kept
free space at 4864-7167/$1300-$lBFF can be used. in the processor stack. However, only 256 bytes of storage
Remember that the sprite pointers are dependent on the space are available in the processor stack, and BASIC allows
current screen memory block, and aren't an absolute feature of only a portion of that to be used while it is in control. This
these locations. The sprite pointers always appear at an offset limits the level to which loops and subroutines can be nested.
of 1016-1023/$03F8-$03FF bytes beyond the specified starting For example, each FOR-NEXT loop requires 18 bytes of stack
address of screen memory. For example, when one of the bit- space, so the Commodore 64's BASIC 2.0 allows loops to be
mapped modes is selected, screen memory (in that case used for nested only nine levels deep. Because the more complex mem-
color information and usually referred to as the video matrix) ory banking routines in the 128 require more machine lan-
moves to 7168-8191/$1COO-$1FFF, so the sprite pointers for guage subroutine calls, the 128's BASIC 7.0 would allow even
the default bitmapped screen are instead located at 8184-8191/ fewer levels of nesting if it used this same system. However,
$1FF8-$1FFR Thus, in split-screen displays (GRAPHIC 2 or BASIC 7.0 instead stores the information for GOSUB, FOR,
and DO in this totally separate runtime stack area.
118 119
2560-2687 $0A00-$0A7F $OA03 2563

Because this storage area does not have to be shared with change the value here to 16387/$4003—the address of the
processor return addresses, as is the case with the processor BASIC warm start routine.
stack, the entire 512-byte space is available. Thus, you can The RUN/STOP-RESTORE sequence in the NMI han-
have up to 28 nested FOR-NEXT loops (each requires an 18- dling routine [$FA40] ends with a JMP ($0A00). Because of the
byte entry on the stack), or up to 102 nested DO loops or cold start's routine initialization, this will normally cause a
GOSUB subroutines (each of which requires a 5-byte entry), or warm start of BASIC. However, you can make RUN/STOP-
any combination thereof. RESTORE cause a jump to another routine by changing the
Using this runtime stack requires slightly more software value in these locations to point to the address of the new
overhead than using the processor stack. The 8502 processor routine. The only restriction is that the target routine must be
has an internal stack pointer register that indicates the position visible in the bank 15 configuration, since that is how memory
of the next available position in the processor stack, and it also is arranged when the JMP is executed.
has PHA and PLA instructions specifically for adding and re- The monitor X command routine [$B0E3] also performs a
moving instructions from this stack. None of this is handled JMP ($0A00), so the value in these locations determines the
automatically for the BASIC runtime stack; instead, the routines address of the routine which will be executed when you use
which use the stack must explicitly update locations 125-126/ that command to exit the built-in machine language monitor.
$7D-$7E, the runtime stack pointer. The GOSUB [$59CF],
FOR [$5DF9], and DO [$5FE0] statement routines add entries 2562 $0A02 DEJAVU
to the stack, and the RETURN [$5262], NEXT [$57F4], and Memory initialization status flag
LOOP [$608A] statement routines can remove entries from the This location is used to indicate whether the RAMTAS routine
stack. The COLLISION statement [$7164] also causes the has been performed. If the RESET routine [$E000] detects that
equivalent of a GOSUB entry to be placed on the stack when the RUN/STOP key is being held down, indicating that the
a collision of the specified type occurs. reset sequence should end by entering the monitor rather than
This area is not used by the system for any purpose other BASIC, then the value here will be tested. If this location con-
than the BASIC stack, so this entire area is available for use by tains the value 165/$A5, the RAMTAS routine will be omitted
machine language programs that don't require BASIC. from this reset sequence. The routine will hold a random
value when the computer is first turned on, but the first call of
the RAMTAS routine [$E093] will initialize this location to
165/$A5. Thus, once RAMTAS has been performed at least
Kernal and Screen Editor Working once, the test of this flag location can be used to prevent its
being performed again when entering the monitor after a re-
Storage set. This allows you to preserve the contents of zero page,
2560-2687/$0A00-$0A7F normally cleared by RAMTAS during the reset.
2560-2561 $OA00-$0AOl SYSTEM-VECTOR $0A03 PALNTS
BASIC restart vector
2563
PAL/NTSC flag
This pair of locations contains the address of the routine that
The IOINIT routine [SE109], part of the RESET sequence,
will be used to restart BASIC. The RAMTAS routine [$E093],
checks the number of scan lines produced by the VIC chip to
part of the reset sequence, puts the value 163 84/$4 000 here— determine whether the 128 is using a NTSC (North American)
the address of the BASIC cold start routine. Unless the Com- or PAL (European/British) video system. This location is set to
modore or RUN/STOP keys are held down, the RESET rou- reflect the result of that test: to 0/$00 for NTSC systems or
tine [$EO0O] ends with a JMP ($0A00) to cold start BASIC. 255/$FF for PAL systems. Later routines that initialize the
One of the final steps in the BASIC cold start routine is to

120 121
2564 S0AO4 S0A09-S0A0A 2569-2570

video chips and timers can then adjust the default settings ac- patterns are normally initialized only during the reset se-
cordingly. This eliminates the need for different versions of quence, which resets this bit to %0 before calling IOINT. Cus-
the Kernal ROM for different countries. tom 80-column characters are usually preserved during RUN/
STOP-RESTORE, which does not affect this bit.
2564 $0A04 INIT_STATUS
System initialization status flag 2565-2566 SO A05-S0A06 MEMSTR
This location is initialized to 0/$00 near the beginning of the Kernal MEMBOT pointer
Kernal RESET routine [$EOOOj. Bits are then set to %1 by later This pair of locations holds the default value of the lowest
routines to indicate that certain initialization steps have been memory address available in block 0 RAM. The value here can
performed. be read or changed using the Kernal MEMBOT routine
Bit 0: This bit is set to %1 during the BASIC cold start routine [$F772], which has a Kernal jump table entry at 65436/$FF9C.
[$4023] to indicate that the cold start has been performed. The The RAMTAS routine, part of the RESET sequence, calls
IRQ handling routine [$FA65] checks this bit and calls the MEMBOT to initialize these locations to 7168/$1COO. How-
BASIC IRQ routine [$A84D] only if the bit is % 1 . The BASIC ever, the value here is not used by any other system routine,
IRQ routine, which handles sprite movement sprite collision so changing this value will not affect system operation in any
detection, and sound generation, copies the contents of a num- way. This is a change from the Commodore 64, where the
ber of shadow locations into VIC and SID hardware registers. value in the MEMSTR pointer is used to establish the lowest
One way to turn off this interrupt routine and gain direct ac- address available of BASIC. In the 128, the start-of-BASIC
cess to the hardware registers is to set this bit to %0. pointer is always initialized to 7169/$1CO1, regardless of the
value here.
Bits 1-5: Unused.
Bit 6: This bit is tested during the screen editor initialization 2567-2568 $0AO7-$0A08 MEMSIZ
(CINT) routine [$C07B] to determine whether the keyboard ta- Kernal MEMTOP pointer
ble pointers and function key definitions need to be initialized. This pair of locations holds the default value of the highest
If the bit is %0, the default pointer values and key definitions memory address available in block 0 RAM. The value here can
will be copied from ROM into the proper areas of RAM; then be read or changed using the Kernal MEMTOP routine
this bit will be set to % 1 . While this bit is % 1 , the pointer and [$F763], which has a Kernal jump table entry at 65433/$FF99.
function key initialization portion of the routine will be skipped. The RAMTAS routine, part of the RESET sequence, calls
CINT is part of both the reset and RUN/STOP-RESTORE se- MEMTOP to initialize these locations to 65280/$FF00. How-
quences, but the pointers and key definitions are normally ini- ever, the value here is not used by any other system routine,
tialized only during the reset sequence, which resets this bit to so changing this value will not affect the system operation in
%0 before calling CINT. Custom keyboard table pointers and any way. This is a change from the Commodore 64, where the
function key definitions are usually preserved during RUN/ value in the MEMSIZ pointer is used to establish the highest
STOP-RESTORE, which does not affect this bit. address available for BASIC variable storage. In the 128, the
Bit 7: This bit is tested during the IOINIT routine [$E109] to top-of-BASlC pointers are always initialized to 65280/$FF0O/
determine whether the 80-column (VDC) character set needs regardless of the value here.
to be initialized. If the bit is %0, the INIT80 routine [$CE0C]
will be called to copy the standard character patterns from 2569-2570 $OA09-$OAOA IRQTMP
ROM into the VDC chip's private RAM; then this bit will be Temporary storage for IIRQ vector during tape operations
set to % 1 . While this bit is % 1 , the character initialization por- These locations are used for temporary storage of the address
tion of the routine will be skipped. IOINT is part of both the value in the IIRQ vector at 788-789/$0314-$0315 during tape
reset and RUN/STOP-RESTORE sequences, but the character operations. The tape routines stash the current IIRQ address
122 123
2571 SOAOB $0A10 2576

here, then substitute the address of the IRQ service routine to not used by any other 128 routine, and is provided strictly to
handle the tape operation. Upon completion of the operation, maintain Kernal jump table compatibility with previous Com-
the original address stored here will be restored to the IIRQ modore models.
vector.
Location 2570/$0A0A is also used as a flag to indicate
whether or not a tape IRQ routine is active. That location is 2575 $0A0F ENABL
initialized to 0/$00 by the IOINIT routine, part of the RESET RS-232 activity flag
sequence, and will also be reset to that value upon completion This location is used during the RS-232 routines to record the
of the tape operation. Thus, a nonzero value in the flag loca- value in the CIA #2 interrupt control register (56589/$DD0D).
tion indicates that a tape interrupt routine is active. CIA #2 interrupt requests generate the NMI interrupts that
drive RS-232 transmission and reception. While the CIA #2
2571 $0AOB CASTON interrupts for RS-232 are disabled, this location will be set to
CIA #1 control register A log 0/$00. When bits are set in the CIA #2 interrupt control regis-
This location is used to record the status of CIA #1 control ter to enable RS-232 operations, the corresponding bits are
register A (56334/$DC0E) during tape operations. also set in this location. If any of the following bits is set to
% 1 , the corresponding interrupt is enabled:
2572 $0A0C Bit Interrupt source RS-232 activity
CIA #1 interrupt control register log 0 Timer A bits being transmitted
1 Timer B bits being received
This location is used to record the status of the CIA #1 inter- 4 FLAG line waiting for start bit to be received
rupt control register (56333/$DC0D) during tape operations.
This location is initialized to 0/$00 during the IOINIT routine
2573 $0A0D [$E109], part of the reset and RUN/STOP-RE STORE
CIA #1 timer A status log sequences.
The CIA #1 control register A log value from 25 71 /$0AOB is
stored here during certain tape operations to preserve the 2576 $0A10 M51CTR
timer A status. RS-232 control register
This location controls some of the operating characteristics of
2574 $0A0E TIMOUT the RS-232 interface. When a file is opened to device 2, the
IEEE timeout flag first character of the filename is copied here. Although RS-232
When the VIC-20 was introduced, its Kemal included a jump communications in the 128 are managed by software, the bits
table entry (SETTMO, at 65442/$FFA2) to support a proposed of this location are defined to simulate the control register of a
IEEE bus interface. The IEEE bus is the parallel data bus used 6551 UART chip, a hardware device for controlling serial com-
by Commodore's original PET/CBM models for communica- munications. The bits are used as follows:
tions with peripheral devices. The interface was never intro- Bits 0-3: These bits determine the baud rate for both transmis-
duced, but the Kernals of all subsequent Commodore models sion and reception—the rate (in bits per second) at which bits
have slavishly included the SETTMO jump table entry. In the will be sent or received. Valid settings are as follows:
128, the SETTMO routine [$F75F] does nothing more than
store the accumulator contents in this location. This location is

124 125
2577 $OA11 $OA11 2577

Bits Baud rate second character of the filename, if any, is copied here. Al-
Bit though RS-232 communications in the 128 are managed by
3 2 1 0 Value
0 0 0 0 0/$0 user defined software, the bits of this location are defined to simulate the
0 0 0 1 1/*1 50 baud command register of a 6551 UART chip, a hardware device for
0 0 1 0 2/$2 75 baud controlling serial communications. The bits are used as follows:
0 0 1 1 3/$3 110 baud Bit 0: This bit controls the handshaking mode for RS-232
0 1 0 0 4/$4 134. 5 baud transmission and reception. The RS-232 interface consists of
0 1 0 1 5/$5 150 baud
1 1 0 300 baud three primary signal lines—transmitted data, received data,
0 6/$6
and ground—plus a number of supplementary control lines—
0 1 1 1 7/%7 600 baud
1 0 0 0 8/$8 1200 baud data set ready (DSR), data terminal ready (DTR), ready to send
1 0 0 1 9/$9 1800 baud (RTS), and clear to send (CTS). The control lines are called
1 0 1 0 10/$A 2400 baud handshaking lines because they allow the sending and receiv-
When the user-defined rate is selected, the baud rate is deter- ing units to exchange signals (handshakes) indicating whether
mined by the value in locations 2578-2579/$0A12-$0A13. data is being successfully transmitted and received. The 128's
The remaining possible bit patterns, %1011-%llll / result in RS-232 software interface can operate in two different modes:
3-line, where none of the handshaking lines are used, and x-
invalid baud rates. line, where all of the handshaking lines are used. These bits
Bit 4: Unused. control the interface mode as follows:
Bits 5-6: These bits determine the number of data bits in each Bit 0 Interface mode
character sent or received (sometimes referred to as the word 0 3-line interface {no handshaking)
size). The total character length will also include a start bit, 1 x-line interface {full handshaking)
possibly a parity bit, and one or more stop bits. For 3-line mode, the output handshaking lines (DTR and RTS)
Bits Bit Number of will be held at a constant high ( + 5 volts) level. The input
6 5 value data bits handshaking lines {DSR and CTS) will be ignored.
0 0 0/$00 8 data bits
0 1 32/$20 7 data bits Bits 1-3: Unused.
1 0 64/$40 6 data bits Bit 4: For unknown reasons, Commodore literature continues
1 1 96/S60 5 data bits to indicate that this bit controls the duplex mode of the RS-
Bit 7: This bit determines the number of stop bits in each 232 interface. The bit is supposed to select full duplex when
character. Stop bits are %1 bits added to the end of the char- set to %0 or half duplex when set to % 1 . However, this bit is
acter. They represent the minimum amount of time the com- not checked by any RS-232 routine, and its setting has no ef-
munications line will remain at the low (%1 bit) level before fect on the operation of the interface.
the next start bit can be sent or received. Duplex is often confused with local echo. A full-duplex
interface can simultaneously send and receive data, while a
Bit 7 Bit value Number of stop bits half-duplex interface can send data and receive data, but not
0 0/$00 1 stop bit both at the same time. The 128's RS-232 interface always op-
1 128/S80 2 stop bits erates in full-duplex mode. In casual usage, however, duplex is
often used to describe whether or not the system echoes back
2577 $OA11 M51CDR the characters it receives. In remote echo mode {incorrectly re-
RS-232 command register ferred to as full duplex), the system displays only characters
This location controls some of the operating characteristics of received from the remote unit (the one being called). The as-
the RS-232 interface. When a file is opened to device 2, the sumption is that the remote unit will send back an "echo" of
127
126
2577 $OA11 S0A14 2580

each character it receives from the system. In local echo mode bit for each received character will be ignored. When space
(incorrectly called half duplex), the system displays the charac- parity is selected, the transmitted parity bit will always be %0
ters it sends as well as the ones it receives. The assumption in and the received parity bit will be ignored.
this case is that the remote unit will not echo the characters it
receives. 2578-2579 $0A12-$0A13 M51AJB
Bits 5-7: This bit controls the parity generated for transmitted RS-232 baud-rate factor
characters and the parity tested for in received characters. Par- The value in these locations determines the baud-rate timing
ity is a simple method of detecting some errors in data trans- factor. When a file is opened to device 2, the third and fourth
mission. A parity bit can be added between the data and stop characters of the filename are copied here (if the filename has
bits in the character. The value of the parity bit is selected to that many characters). However, the filename characters are
make the total number of %1 bits in the character (not count- meaningful only if a user-defined baud rate has been speci-
ing stop bits) either even or odd. The receiving unit can then fied—if bits 0-3 of the first character of the filename (copied
count the number of %1 bits in the received character to de- into 2576/$0A10) are %0000. In that case, the value in these
termine if bits have been garbled in transmission. Parity locations specifies the baud rate according to the following
checking did not work properly in the original versions of the formula:
Commodore 64 Kernal ROM, but that problem has been cor- baud rate = clock frequency/(2 * (rate factor + 100))
rected in the 128's Kernal (and in the version of 64 Kernal
ROM for the 128's 64 mode). Possible parity selections are as For the standard baud-rate settings, the Kernal RS-232 OPEN
follows: routine copies the proper rate factor into these locations from
tables in Kernal ROM (59472-59491/$E850-$E863 for NTSC
Bits Parity selection systems or 59492-59511/$E864-$E877 for PAL systems). The
7 6 5 two separate tables are required because the different video
x x 0 parity not used
0 0 1 odd parity systems use different clock frequencies.
Oil even parity There's rarely a need to specify a custom baud rate, since
10 1 mark parity the standard settings encompass all standard rates that the 128
1 1 1 space parity can support. (The 128 cannot handle RS-232 communications
If bit 5 is %0, no parity bit will be generated in transmit- faster than 2400 baud, so don't try to specify a faster rate.)
ted characters and the system will expect incoming characters However, should you ever want to do so, the formula for the
to have no parity bit. This selection is common when a word rate factor is as follows:
size of eight data bits per character is used. Odd parity means rate factor = {(clock frequency / desired baud rate)/ 2) — 100
that a parity bit will be generated for each transmitted charac- The clock-frequency value is 1022730 for NTSC (North Amer-
ter such that the character will have an odd total number of ican) systems or 985250 for PAL (European) systems. The low
%1 bits (not counting the stop bits). When even parity is se- byte of the resulting factor should be stored in 2578/$0A12
lected, the parity bit will be set to make the total number of and the high byte in 2579/$0A13.
%1 bits in the character even. For either even or odd parity,
the number of %1 bits in each character received will be 2580 $0A14 RSSTAT
counted and compared against the parity selection. If the num- RS-232 status register
ber does not match the specified parity type, the error will be Although RS-232 communications in the 128 are managed by
indicated by setting bit 0 of the status register location (2580/ software, the bits of this location are defined to simulate the
$0A14) to % 1 . Mark and space parity are alternate forms of no status register of a 6551 UART chip, a hardware device for
parity. When mark parity is selected, the parity bit for each controlling serial communications.
transmitted character will always be set to % 1 , and the parity
128 129
2580 S0A14 $0A16-$0A17 2582-2583

It is possible to read the value here directly, but this loca- low (0 volts) state during either transmission or reception of
tion can also be read using the Kernal READSS routine characters. When x-line handshaking is used, the external de-
[$F744] if the current device number in location 186/$BA is 2 vice connected to the interface is expected to hold the DSR
(for RS-232). The READSS routine also has a Kernal jump ta- line high ( + 5 volts). If the line goes low, it is taken as an indi-
ble entry at 65463/$FFB7. From BASIC, the reserved variable cation that nothing is connected to the interface.
ST will reflect the value in this location as long as the current
device number is 2. This location is initialized to 0/$00 each Bit 7: This bit is the break indicator. A break occurs when,
time the Kernal OPEN routine is called to open a file to device during reception of characters, a byte is received consisting of
2, the RS-232 interface. The value here is also reset to zero all %0 bits not followed by stop bits (which are always %1).
after each call to the READSS routine when device 2 is active, In other words, a break occurs if the received data signal line
including each reference to the ST variable in a BASIC program. is held at the %0 bit ( + 5 volt) level for longer than the time
required to receive a character.
Bit 0: This bit is the parity-error indicator. It is used only
when either even or odd parity is selected, and is relevant S0A15 BITNUM
only to received characters. The bit is set to %1 whenever a
2581
character is received for which the calculated total of %1 bits RS-232 bit count
received for the character does not match the specified parity This location will hold the number of bits prior to the parity
selection. and stop bits for each character received or transmitted. The
location is initialized during the RS-232 OPEN routine [$F040]
Bit 1: This bit is the framing-error indicator. The bit is set to to the number of data bits (specified in bits 5-6 of 2576/
%1 when a framing error occurs—when no stop bits are found $0A10) plus 1. For transmission, the value here is copied into
following the specified number of data and parity bits. location 180/$B4, the countdown of bits to send. For recep-
Bit 2: This bit is the receiver buffer-overflow indicator. It will tion, the value here is copied into location 168/$A8, the
be set to %1 when a character is received after the RS-232 in- countdown of bits remaining to be received.
put buffer at 3072/$0C00 is already full.
2582-2583 $0A16-$0A17 BAUDOF
Bit 3: This bit is the receiver buffer-empty indicator. It will be
RS-232 baud-rate timing constant
set to %1 whenever there are no characters waiting to be read
Commodore's insistence on providing an exact software emu-
from the input buffer. This bit should be tested before each at-
tempt to read characters from the RS-232 interface. lation of the 6551 UART chip leads to some odd software gy-
rations. The baud-rate timing factor specified in locations
Bit 4: This bit is the CTS-missing error indicator. It is used
2578-2579/$0A12-$0A13 must be converted back into an ab-
only when x-line handshaking is selected. The bit will be set
to %1 if the CTS (clear to send) input line drops to a low (0 solute timing value. The Kernal OPEN routine for RS-232 per-
volts) state while data is being transmitted. When x-line forms the following calculation:
handshaking is used, the external device connected to the in- timing constant = (rate factor * 2) — 200
terface is expected to hold the CTS line at a high ( + 5 volts) Given the formula for rate factor, this is equivalent to:
state. If the line goes low, it is taken as an indication that the timing constant = clock frequency / baud rate
external device is not ready to receive data, so transmission is This yields the number of system clock cycles required to send
suspended until CTS goes high. or receive each bit at the specified baud rate. The resulting
Bit 5: Unused. This bit should always be %0 when read. value is stored in these locations. When transmission or recep-
Bit 6: This bit is the DSR-missing error indicator. It is used tion is initiated, the value here is copied into one of the CIA
only when x-line handshaking is selected. The bit will be set #2 timers. This determines the time between the NMI inter-
to %1 if the DSR (data set ready) signal input line drops to a rupts that drive the transmission or reception of bits.

130 131
2584 $0A18 S0A1D-60A1F 2589-2591

2584 S0A18 RIDBE In that case, the buffer is already full, and some characters
Index to first character in RS-232 input buffer must be transmitted before any more can be added to the buffer.
This location holds the offset from the start of the RS-232 in-
put buffer to the position where the next character received 2588 $OA1C SERIAL
will be stored. The input buffer normally begins at location Fast serial mode flag
3072/$0C00. The value here is incremented before each re- This location is used to indicate whether the currently speci-
ceived character is added to the buffer, unless incrementing fied serial bus device, such as the 1571 disk drive, is capable
would make the value here equal to the value in location of fast serial communications. The location is initialized to
2585/$0A19. In that case, a buffer overflow has occurred 0/$00, the value for standard (slow) communications, during
{more characters have been received than the buffer can hold), the IOINIT routine [$E109]. The routines that handle the serial
so bit 2 of the status location (2580/S0A14) is set to % 1 . bus TALK and LISTEN commands attempt a fast serial hand-
shake. If the external device responds properly, bits 6 and 7 of
2585 $0A19 RIDBS this location will be set to % 1 . Bit 7 indicates that the external
Index to last character in RS-232 input buffer device is capable of fast transmission and reception of individ-
This location holds the offset from the start of the RS-232 in- ual bytes. The bit is reset to %0 during the Kernal routines
put buffer to the position of the next character waiting to be that handle the serial bus UNTALK and UNLISTEN routines.
removed from the buffer. The buffer normally begins at 3072/ Bit 6 indicates that the system is capable of high-speed burst
$0C00. The value here is incremented after each character is mode loading.
retrieved from the buffer. When the value here equals the
value in location 2584/$0A18, all characters have been re- 2589-2591 $OA1D-$OA1F TIMER
moved and the buffer is empty. In this case, bit 3 of the status Software jiffy timer
location (2580/$0A14) will be set to % 1 . The three-byte value in these locations is decremented 60
times per second by the Kernal UDTIM routine [$F5F8], part
2586 S0A1A RODBS of the IRQ sequence. Thus, these locations function in a man-
Index to first character in RS-232 output buffer ner opposite that of the jiffy clock at 160-l62/$A0-$A2,
This location holds the offset from the start of the RS-232 out- which is incremented 60 times per second by UDTIM. The or-
put buffer to the position of the next character awaiting trans- der of bytes here is the opposite of the order of bytes in the
mission. The output buffer normally begins at 3328/$0D00. jiffy clock: $OA1D is the low byte and $OA1F is the high byte.
The value here is incremented after each character is removed Since the countdown for this timer is handled automati-
from the buffer for transmission. When the value here equals cally during the IRQ, it is useful for many timing applications.
the value in location 2587/$0AlB, all characters awaiting The way to use this timer is to load the locations with the
transmission have been sent and the buffer is empty. value in jiffies (1/60-second intervals) for the desired delay
period, then test for a value of $FF in location 2591/$OA1F.
2587 $OA1B RODBE That location will contain $FF after the three-byte value rolls
Index to last character in RS-232 output buffer over from $000000 to $FFFFFF at the end of the countdown.
The highest allowable initial value when using this scheme is
This location holds the offset from the start of the RS-232 out-
$FF0000, which corresponds to 16,711,680 jiffies—a little over
put buffer to the position where the next character will be
three days.
added to await transmission. The output buffer normally be-
There is one caution in using this location from BASIC.
gins at 3328/S0D00. The value here is incremented before
The SLEEP statement routine [$6BD7] uses this timer for its
each character is added to the buffer, unless the incrementing
delay countdown, so any use of the SLEEP statement will
would make the value here equal the value in 2586/$0AlA.
overwrite any values you may have stored in these locations.

132 133
2592 $0A20 $0A25 2597

2592 $0A20 XMAX 2595 $0A23 KOUNT


Maximum number of keys in the keyboard buffer Countdown between key repeats
The value in these locations determines the maximum number This location is used as a counter to establish the delay be-
of characters that can be held in the keyboard buffer pending tween repeats when a key is held down. Once repeating has
processing. The value is initialized to 10/$OA—the full length begun, indicated by a value of 0/S00 in location 2596/$0A24,
of the standard keyboard buffer at 842-851/$034A-$0353— the value here will be decremented on each pass through the
by the CINT screen editor initialization routine [$C07B], part SCNKEY routine [$C55D] as long as the same key is held
of the reset sequence. During the SCNKEY routine [$C55D], down. Each time the count reaches zero, the key is repeated
the value here is compared against the value in location and this location is reinitialized to 4/$04. This results in a
208/$D0, the count of characters currently in the buffer, to key-repeat rate of 15 times per second. The starting value of 4
determine if there is room in the buffer to record another for this countdown is loaded from ROM in the SCNKEY rou-
keypress. tine, and thus cannot be changed, so the delay period between
You can reduce the value here to decrease the number of repeats is not programmable.
unprocessed keypresses that can accumulate in the buffer.
However, you should not increase the value above 10, as this 2596 $0A24 DELAY
will cause overflow from the buffer to overwrite the tab stop Countdown until key repeating begins
table at 852-861/$0354-$035D. This location is used as a counter to establish the delay before
repeating begins when a key is held down. (Location 2594/
2593 $OA21 PAUSE $0A22 controls which keys, if any, will repeat if held down.)
Scroll pause flag If the scan code of the current key is the same as the scan
This location is used to pause printing. During the screen code detected on the last pass through the SCNKEY routine
BSOUT routine [$C72D], the value here is tested. If it is non- [$C55D], the value here will be decremented. When the count
zero, the routine will wait indefinitely for the location to be reaches zero, repeating can begin at the rate determined by lo-
reset to zero. The value is initialized to 0/$00 by the CINT cation 2595/$0A23. When the key is released, this location is
routine [$C07B]. To implement the pause feature, the SCNKEY reinitialized to 16/$10. This results in a delay before repeating
routine [$C55D], part of the system IRQ sequence, sets this lo- of about 1/4 second. The starting value of 16 is loaded from
cation to 13/$0D when either the NO SCROLL or CONTROL-S ROM in the SCNKEY routine, and thus cannot be changed, so
keys are pressed, and resets the location to 0/$00 when the the delay before repeating begins is not programmable.
next key is pressed.
2597 $0A25
2594 $OA22 RPTFLG Delay between case-switching repeats
Key repeat flag This location is used to provide a delay between character case
The value here determines which keys, if any, will repeat if switches when the SHIFT-Commodore key combination is
held down. If bit 7 of this location is %1 (value 128/S80), all held down. This location isn't a countdown. Rather, it is ini-
keys repeat. If bit 6 is %1 (value 64/$40), no keys repeat. tialized to 128/$80; then the value is shifted one bit to the
Otherwise, only the cursor, space, and INST/DEL keys repeat. right on each pass through the SCNKEY routine until it be-
This location is initialized to 128/S80—all keys repeat—by comes zero. This provides a delay of about 1/8 second.
the screen editor CINT routine [$C07B], This is different from
the Commodore 64, where the default value is 0/$00—only
cursor, space, and INST/DEL repeating.

134 135
2598 $0A26 $0A2C 2604

2598 $0A26 BLNON blink rate for the VIC screen is about every 2/3 second. The
Cursor blink flag initialization value is read from ROM, so the 40-column blink
Bit 6 of this location controls whether the cursor on the 40- rate is not programmable.
column (VIC) screen will blink. When the bit is %0, the cursor
blinks at a rate determined by location 26O0/S0A28. When the 2601 $0A29 GDBLN
bit is % 1 , the cursor will be a solid, unblinking block. This lo- Character under cursor
cation is initialized to 0/$00 during the CINT screen editor This location is used to hold the original (unblinked) screen
initialization routine [$C07B], so the default cursor will be code for the character at the current 40-column screen cursor
blinking. The bit can be set to %1 using the ESC E key se- position. If the cursor is moved from the current position with-
quence, and cleared to %0 using ESC F. out printing a new character, this value will be restored to the
Bit 7 of this location indicates the blink phase of the position when the cursor is moved.
cursor on the 40-column (VIC) screen. When the bit is %0, the
character at the cursor position is in its original state. When 2602 $0A2A GDCOL
the bit is % 1 , the character is reversed to provide the cursor Color under cursor
blink effect. This location is used to hold the original color of the character
at the current 40-column screen cursor position. If the cursor is
2599 $0A27 BLNSW moved from the current position without printing a new char-
Cursor enable flag acter, this value will be restored to corresponding color mem-
This location controls whether a cursor will be present on the ory location for the position when the cursor is moved.
40-column (VIC) screen. The cursor will be enabled when the
value here is zero and disabled when this location contains any 2603 $0A2B CURMOD
nonzero value. This location can be used to enable the cursor VDC cursor mode
when it is normally turned off. For example, the following This location is a shadow for VDC internal register 10/SOA.
statement provides a cursor at the prompt (GET and GETKEY See the entry for that register in Chapter 8 for details. The
don't normally provide a cursor): value here is copied into the register every time the screen
300 POKE 2599,0: PRINT"PRESS A KEY: ";: GETKEY K$ editor routines are used to print a character to the 80-column
screen.
2600 $0A28 BLNCT
Cursor blink countdown 2604 $0A2C VM1
This location determines the delay between cursor blinks for VIC text screen and character base
the 40-column (VIC) screen. Bit 6 of location 2598/$0A26 This location is a shadow for the VIC chip screen and character
must be %0 to enable cursor blinking. The value here is base address register (53272/$D018) for the text (GRAPHIC 0)
decremented on each pass through the screen editor IRQ rou- screen, or for the text portion of a split display. The value here
tine. Whenever the value reaches zero, the blink phase of the is copied into the VIC register during the text screen-setup
cursor changes and bit 7 of the screen code at the cursor posi- portion of the screen editor IRQ routine [$C194]. Refer to the
tion is toggled. This reverses the character at thai position. discussion of the register in Chapter 8 for details. During the
The value here is reinitialized to 20/$ 14 whenever it counts screen editor initialization [$C07B], this location is set to
down to zero. It takes two countdowns to complete a cursor 20/$14. That value places screen memory at 1024/$0400 and
blink (one while the character is in its normal state and one character memory at 4096/$1000. If the SHIFT-Commodore
while it is reversed), so 40 passes of the screen editor IRQ rou- combination is detected during the SCNKEY routine [$C55D],
tine are required for each cursor blink. As a result, the cursor- bit 1 of this location is toggled. This switches the character set
base address between 4096/S1000 and 6144/$1800.
136 137
2605 S0A2D $0A34 2612

2605 $0A2D VM2 2608 $0A30 LINTMP


VIC bitmap and video matrix base Ending row for screen input
This location is a shadow for the VIC chip bitmap and video- This location is used by the routines which accept lines of in-
matrix base address register (53272/$D018) for the bitmapped put from the screen or keyboard to hold the number of the
(GRAPHIC 1 or GRAPHIC 3) screen, or for the bitmapped screen row on which the displayed line of characters ends.
portion of a split display. The value here is copied into the This value is tested to determine when the end of the input
VIC register during the bitmapped screen-setup portion of the has been reached. For input from the screen, the BASIN rou-
screen editor IRQ routine [$C194]. Refer to the discussion of tine [$C29B] fails to set this location, so the row number for
the register in Chapter 8 for details. During the screen editor the end of the input line must be set explicitly by storing the
initialization routine [$C07B], this location is set to 120/$78. proper value (0-24) in this location.
This value places the default video-matrix area at 7168/$1COO
and the bitmap at 8192/$2000. 2609-2610 $0A31-$0A32 SAV80
Temporary storage for 80-column memory manipulation
2606 $0A2E VM3 These locations are used to store the current row and column
Starting page for VDC screen memory number values during the routines that clear or scroll lines on
The value in this location is used during the screen editor the 80-column screen. Location 2609/$0A31 holds the row
routines to determine the starting page within VDC RAM for number and 2610/$0A32 holds the column number.
80-column screen memory. During the screen editor initializa-
tion routine [$C07B], this location is set to 0/$00, which 2611 $0A33 CURCOL
places screen memory at address 0/$0000 in VDC RAM. Attribute of current cursor position
The value here determines where the screen editor thinks This location is used to hold the original attribute of the char-
VDC screen memory begins, but not the actual starring ad- acter at the current 80-column screen cursor position. If the
dress of the screen. (This location is not a shadow for a VDC cursor is moved from the current position without printing a
register.) The actual screen starting address is determined by new character, this value will be restored to corresponding
the value in VDC internal registers 12-13/$0C-$0D. If you attribute memory location for the position when the cursor is
change the register value, you should also change the value in moved.
this location, and vice versa.
2612 $0A34 SPLIT
2607 $0A2F VM4 Scan line for screen split
Starting page for VDC attribute memory This location holds the scan line for the raster interrupt which
The value in this location is used during the screen editor will set up the lower (text) portion of a split bitmapped/text
routines to determine the starting page within VDC RAM for screen. When a split screen is selected (when bit 6 of location
80-column attribute memory. During the screen editor initial- 216/SD8 is set to %1), the value here will be copied into the
ization routine [$C07B], this location is set to 8/$08, which VIC raster compare register (53266/$D012) during the bit-
places attribute memory at address 2048/S0800 in VDC RAM. mapped screen-setup portion of the screen IRQ routine [$C194].
The value here determines where the screen editor thinks This will cause a raster interrupt at the specified scan line,
VDC attribute memory begins, but not the actual starting ad- which will execute the text screen-setup portion of the interrupt
dress of attributes. (This location is not a shadow for a VDC routine to establish the text portion of the split screen. To find
register.) The actual attribute starting address is determined by the scan-line value corresponding to a character row number,
the value in VDC internal registers 20-21/$14-$15. If you use the following formula:
change the register value, you should also change the value in scan line = (row number * 8) + 48
this location, and vice versa.
138 139
2613 $0A35 $0A3B 2619

The default value for this location, set during the screen editor the operation and the register is reset to 0/$00 to disable all
initialization routine [SC07B], is 208/$D0, which places the sprites for the duration of the operation. The VIC chip requires
default split at screen row 20. The value here can be changed extra timing cycles while sprites are active, so they are dis-
in BASIC by specifying a split parameter with the GRAPHIC abled to avoid disrupting the precise timing required for tape
statement. and serial operations. Once the operations are complete, the
value here is restored to the VIC register.
2613 $OA35 FNADRX
Temporary storage for X register 2617 $0A39 BLANKING
This location is used to preserve the contents of the X register Temporary storage for VIC control register
during the Kernal routine that reads a character from a file- This location is used to hold the value in the VIC control reg-
name [$F7AE]. ister at 53265/$D011 during tape operations. The register
value is stored here at the beginning of the tape operation,
2614 $0A36 PALCNT before bit 4 of the register is set to %0 to blank the screen
Jiffy clock compensation flag during the operation. Upon completion of the tape operation,
In systems using the PAL video format, this location is used as the value here is restored to the register.
a counter during the Kernal UDTIM routine [$F5F8], It is in-
cremented each time UDTIM is called to update the jiffy clock 2618 $0A3A HOLD_OFF
locations (160-162/$A0-$A2). When the count has reached 5, Custom mode flag
the UDTIM routine is repeated and the counter is reset to Normally, the system clock is set for the slow (1-MHz) rate
zero. This triggers an extra update of the jiffy clock every fifth and sprites are disabled during tape and disk operations to in-
IRQ in PAL systems, so that ten extra jiffy clock "ticks" occur sure proper timing. However, this location can be used to
for each 50 IRQs. This means that the jiffy clock still incre- allow the VIC clock and sprite registers to retain their current
ments 60 times per second on PAL-video 128s where the IRQ settings during such operations. When bit 7 of this location is
rate is only 50 per second. For systems using the NTSC for- set to % 1 , the registers are left unchanged. This location is ini-
mat, this portion of the UDTIM routine is skipped, so the loca- tialized to 0/$00 by the IOINIT routine [$E109], part of the re-
tion will always hold its initial value of zero. set sequence. That setting is not changed by any ROM routine,
so this feature is not used by the system.
2615 $0A37 SPEED
Temporary storage for clock rate register 2619 $0 A3B LDTB 1_SA
This location is used to hold the value in the VIC system clock Starting page for 40-column screen memory
rate register (53296/SD030) during tape and serial bus opera- The value in this location is used during the screen editor
tions. The current register value is stored here at the beginning routines to determine the starting page for 40-column (VIC)
of the operation and the register is reset for slow (1-MHz) screen memory. During the screen editor initialization routine
mode for the duration of the operation; then the value here is [$C07B], this location is set to the value in location 49228/
restored to the register once the operation is completed. $C04C, which is currently 4/$04. This specifies screen mem-
ory at address 1024/$0400.
2616 $0 A38 SPRITES The value here determines where the screen editor thinks
Temporary storage for sprite enable register VIC screen memory begins, but not the actual starting address
This location is used to hold the value in the VIC sprite enable of the screen. (This location is not a shadow for a VIC regis-
register (53269/$D015) during tape and serial bus operations. ter.) The actual screen starting address is determined by the
The current register value is stored here at the beginning of

140 141
2620-2621 $0A3C-$0A3D $0AA0-$0AA7 2720-2727

value in bits 4-7 of the VIC register at 53272/SD018. If you


change the register value, you should also change the value in switched, the screen editor SWAPPER routine [$CD2E] ex-
this location, and vice versa. changes the contents of this area with the tab-stop bitmap for
the active screen at 852-861/$0354-$035D.
2620-2621 $0A3C-$0A3D CLR_EA
Working pointer into 80-column memory 2666-2669 $0A6A-$0A6D
Storage for inactive line-link bitmap
These locations are used to hold an address in VDC memory
during the routine that clears a line of text on the 80-column The line-link bitmap for whichever screen (40- or 80-column)
screen [$C4C0] and the one that copies a line up or down for is currently inactive is stored here. When the screens are
scrolling [$C53C], switched, the screen editor SWAPPER routine [$CD2E] ex-
changes the contents of this area with the line-link bitmap for
2622-2623 $0A3E-$0A3F Unused the active screen at 862-865/$035E-$0361.
These locations are unused by any system ROM routine, and 2670-2687 $0A6E-$0A7F Unused
are thus available for your own programming.
None of the locations in this 18-byte area is used by any system
2624-2650 $0A40-$0A5A ROM routine, so they are available for your own programming.
Screen editor variable storage for the inactive screen
The screen editor variables for whichever screen (40- or 80- Monitor Working Storage Area
column) is currently inactive are stored here. When the screens
are switched, the screen editor SWAPPER routine [$CD2E] ex- 2688-2751/$0A80-$0ABF
changes the contents of this area with the values for the active
screen at 224-250/$E0-$FA. Thus, the active and inactive 2688-2703 $0A80-$0A8F FNBUFF
screens are totally independent, and all window size settings Filename buffer for load, save, or verify
for the inactive screen will be preserved until the screen be- The load/save/verify setup routine stores the filename associ-
comes active again. ated with a monitor L, S, or V command here (up to 16
Location 2650/$0A5A should not be included in this characters).
range. Only locations 224-249/$E0-$F9 actually hold screen
editor variables. However, the SWAPPER routine incorrectly 2688-2719 $0A80-$0A9F HBUFF
copies 27 values instead of the proper 26, so the contents of Search pattern buffer
location 2650/$0A5A and location 250/$FA will be exchanged The monitor H (hunt for byte pattern) routine [$B2CE] fills
whenever the active screen is switched. Both locations are nor- this buffer with the byte pattern being searched for (up to 32
mally unused. characters). Characters in the specified memory range are then
compared against the buffer contents to search for a matching
2651-2655 $0A5B-$0A5F Unused pattern in memory. If the address range for the search in-
cludes this buffer, an artificial match will be found—the buffer
None of the locations in this range is used by any system rou-
tine, so all are available for your own programming, contents will always match themselves.

2656-2665 $0A60-$0A69 2720-2727 $0AA0-$0AA7 XFORM


Storage for inactive tab-stop bitmap Working storage for base conversion
The tab-stop bitmap for whichever screen (40- or 80-column) r The hex-to-decimal conversion routine [$BA07] uses these lo-
cations for working storage during the conversion, leaving the
is currently inactive is stored here. When the screens are
results in 2720-2723/$0AA0-$0AA3 in BCD (binary coded
142 143
2720-2729 $0AA0-$0AA9 $0AB4 2740

decimal) format. The base conversion routine [$BA47] puts the and the routine to test the next buffer character [$B8E7] all
value to be converted into 2720-2723/$0AA0-$0AA3 for stash the X register contents here upon entry, and restore the
manipulation. The routine to print octal, binary, or decimal value to the X register upon exit. The routine to decrement the
values uses 2720-2723/$0AA0-$0AA3 to hold the value to be pointer address or line count stored in 96-98/$60-$62 uses
displayed. this location to hold the amount by which the stored value is
to be decremented.
2720-2729 $0AA0-$0AA9 ASMBUF
Instruction assembly buffer 2736 $0AB0 Unused
The assemble routine [$B406] packs the three-character mne- This location is not used by any 128 ROM routine, and is thus
monic in the instruction being assembled into two bytes and available for your own programming.
stores them in 2720-2721/$0AA0-$0AAl. If characters follow
the mnemonic, they are copied into 2722-2729/$0AA2-$0AA9. 2737 $0ABl OPCODE
If a numeric parameter is found, a dummy value consisting of Calculated opcode
a $ character followed by either two or four zeros (depending The assemble routine [$B406] uses this location to hold the
on whether the value is greater than 255) is substituted. This opcode calculated for the instruction being assembled.
character pattern is then evaluated to determine the addressing
mode for the instruction. 2738 S0AB2 XSAVE
Temporary storage for X register
2730 $0AAA FORMAT The monitor indirect fetch [$B11A], indirect store [$B12A], and
Instruction format flag indirect compare [$B13D] routines stash the value in the X reg-
The routine to calculate the mnemonic and addressing mode ister here upon entry, then restore the value to the X register
for an opcode [$B659] uses this location to hold a flag value upon exit.
indicating the addressing mode in use, which determines the
format in which the instruction must be displayed or entered. 2739 $0AB3 DIRECTION
Transfer direction flag
2731 $0AAB LENGTH The monitor compare/transfer routine [$B231] uses this loca-
Instruction length tion in execution of the T (transfer) command to indicate the
The routine to calculate the mnemonic and addressing mode direction in which bytes are to be transferred. For downward
for an opcode [$B659] uses this location to hold the number of moves (source address greater than destination address), the
bytes which should follow the opcode in the instruction (0-2). flag will be set to zero; for upward moves (destination address
greater than source address), the flag will be set to 128/S80.
2732-2734 $0AAC-$0AAE MSAL
Three-character mnemonic pattern 2740 $0AB4 COUNT
The assemble routine [$B406] stores the first three-character Digit counter
group from the input line in these locations for evaluation as The routine to convert input parameters into numeric values
an ML mnemonic. [$B7CE] uses this location to hold a count of the hexadecimal
digits in the converted value. The routine to print values in oc-
2735 $0AAF SXREG tal, binary, or decimal [$BA47] uses this location as a counter
Temporary storage tor X register of digits printed in the value being displayed.
The subroutine to determine the proper opcode for a mne-
monic [$B57C], the routine to print hexadecimal byte values,

144 145
2741 $0AB5 $0AC6-$0AFF 2758-2815

2741 $0AB5 NUMBER Thus, this location will normally contain 255/$FF upon com-
Temporary storage for parameter conversion pletion of either routine.
The routine to convert input parameters into numeric values
[$B7CE] uses this location to hold the numeric value of the in- 2753-2756 $0ACl-$0AC4 PAT
put digit currently being evaluated. Table of identifiers for function ROMs
The Kernal routine which tests for the presence of function
2742 $0AB6 SHIFT ROMs [$E26B] initializes these locations to 0/$00 before
Number of bits per digit for base checking any of the four possible ROM address slots. A ROM
The routine to convert input parameters into numeric values is considered present in the slot if the character codes for the
letters CBM are found at an offset of seven bytes from the
[$B7CE] and the routine to print values in octal, binary, or starting address of the slot. If this test pattern is found, the
decimal [$BA47] use this location to hold the number of bits to function ROM ID byte is copied from an offset of six bytes be-
be interpreted per digit for the value being converted or yond the starting address of the slot into the corresponding lo-
displayed. cation in this table:
2743-2745 $0AB7-$0AB9 TEMPS Location ROM slot address
Monitor temporary storage 2753/$0ACl 32768/$8000 internal
2754/$0AC2 49152/$C0O0 internal
The routine to convert input parameters into numeric values 2755/$0AC3 32768/S8000 external
[$B7CE] uses these locations as working storage when evaluat- 2756/$0AC4 49152/$C0O0 external
ing decimal digits. Monitor routines which accept two or more
address parameters store the second (ending) address here. For If the identifier byte is l/$01, the cartridge is autostarting
upward transfers, the compare/transfer routine [$B231] moves and the test routine immediately calls the cold-start vector for
the value here to the working pointer at 102-104/$66-$68. that ROM. Otherwise, the Kernal PHOENIX routine [$F867],
part of the BASIC cold-start sequence, will call the cold-start
2746-2751 $OABA-$OABF Unused vector for any ROM slots with nonzero entries in this table.
These locations are not used by any 128 ROM routines, and 2757 $0AC5 DK_FLAG
are thus available for your own programming.
This location is mentioned in Commodore literature as "reserved
for foreign screen editors/' but its exact use is unclear. It is un-
Kernal Working Storage used by any routine in the U.S. version of the system ROMs.
2752-2815/$OAC0-$OAFF 2758-2815 $0AC6-$0AFF Unused
2752 $OACO CURBNK This 58-byte area is described in Commodore literature as "re-
Counter for function ROM testing served for system use." However, no routines in the current
version of the system ROMs make use of any of these loca-
Both the Kernal routine which checks for the presence of ROM tions. Still, unless you are desperate for free locations outside
in the internal and external (cartridge) ROM address slots the BASIC area, it's probably best to avoid using these loca-
[$E26B] and the Kernal PHOENIX routine [$F867] which ini- tions to insure compatibility with future versions of the ROM.
tializes function ROMs use this location as a countdown for
the number of slots remaining to be tested. The location is set
to 3, then decremented each time a slot is checked or initial-
ized. The routines end when the value here rolls over from
0/$00 to 255/$FF after the fourth slot is tested or initialized.
146 147
2816-3071 $0B00-$0BFF $0C00-$OCFF 3072-3327

Cassette Buffer and Disk Boot Buffer track 1 of the disk are read into this area. The first three bytes
of the buffer are then examined. If those locations (the first
2816-3071/$0B00-$0BFF three bytes from the sector) contain the character codes for the
The first 192 bytes of this area (2818-3007/$0B00-$0BBF) are letters CBM, then the routine assumes that a boot disk has
used for the cassette buffer. When you're reading from tape, been found and proceeds with the boot process. Refer to the
file headers are loaded into this area until one is found with entry in Chapter 9 for details. It would be possible to simulate
the specified filename. When you're writing to tape, this area a boot by filling the buffer with the proper values, then jump-
is used to assemble the tape header for the file. When the ing into the BOOT_CALL routine at address 63737/$F8F9.
buffer contains a tape header, the locations are used as follows: The B0OT_CALL routine is normally executed during
Location Function each reset as part of the BASIC cold-start sequence. It can also
2816/$0BO0 Header type identifier be called from the Kernal jump table entry at 65363/$FF53,
2817-2818/$0B01-$0BO2 Starting address for file and can be initiated from BASIC via the BOOT statement.
2819-2820/$OB03-$OB04 Ending address for file Actually, the cassette buffer is not located absolutely at
2821-3007/$OB05-$OBBF Filename this area. The base address of the cassette buffer is determined
A header type identifier of 1 indicates a relocatable program by the value in locations 178-179/$B2-$B3. Those locations
file; 3 indicates a nonrelocatable program file; 4, a data file; are initialized to 2816/$0BO0 during the RAMTAS routine
and 5, an end-of-tape marker. A type identifier value of 2 [$E093], part of the reset sequence. No system ROM routines
means that the block contains data rather than a header. Al- change that setting, but another free 192-byte area could be
though the filename can be up to 187 bytes long, such names used, with two restrictions: the buffer must start at an address
are unusual. When a header is read into the buffer, only the greater than 511/S1FF, and the buffer must be visible in the
first 16 characters of the filename will be displayed following bank 15 memory configuration. The disk-booting routines, on
the FOUND message. When a header is being assembled, all the other hand, do use the absolute address of this area. This
unused filename bytes will be set to 32/$20, the value for the area will always be used as the boot sector buffer, regardless
space character. of the value in the cassette buffer pointer.
The cassette buffer is used to hold blocks of data when If tape data storage is not being used, this 256-byte area is
data files are read from or written to tape. When a data file is available for other uses, such as to hold short machine lan-
being written, after the header is written to tape, the first byte guage routines. The cassette buffer has been a popular area for
here is set to 2, the identifier for a data block; then the re- ML since the days of the first Commodore PET/CBM comput-
maining 191 bytes are filled with the data to be written to the ers. However, the contents of this area will be overwritten
file. Only when the buffer is completely full is the block of whenever the system attempts to boot a disk, including the
data actually added to the file. This is why it is important to time during any reset when the drive is turned on and con-
properly close any file opened for writing. If the file is not tains a disk. You should choose another area if you want your
closed, the last block of data will not be written to tape. When machine language to survive intact following a reset.
a file is opened for reading, after the proper header is identi-
fied, the first block of data is read into the buffer. Subsequent
bytes will be read from the buffer—not directly from tape— RS-232 Input Buffer
until all 191 data bytes have been read from the buffer; then 3072-3327/$0C00-$0CFF
the next block will be read into the buffer. See Chapter 9 for The routines that receive characters via the RS-232 interface
more information on tape data storage. are executed during NMI interrupts. Any characters received
In the 128, this area has a second function: the boot sector are held in this area until they can be read, usually by using
buffer. If the BOOT_CALL routine [$F890] finds a disk in the the Kernal GETIN routine. This is a circular buffer with no
specified drive when it is called, the contents of sector 0 of fixed beginning or end. Location 2585/S0A19 holds the offset

148 149
3328-3583 $ODOO-$ODFF $1000-$10FF 4096-4351

from the starting address of the buffer to the next character changes the address in the pointer, so the buffer will be lo-
waiting to be read (called the head of the buffer). Location cated here unless you explicitly move it. However, the buffer
2584/$0A18 holds the offset to the next free position in the can be moved to another free area of memory simply by
buffer (called the tail of the buffer). The buffer is considered changing the address in the pointer. (The area selected must
empty when the two offset addresses are equal, and full when be visible in the bank 15 configuration.)
the buffer tail offset is one less than the head offset. Bits 2 and If RS-232 communications are not used, this buffer area,
3 of the RS-232 status byte at 2580/$0A14 indicate, respec- along with the one at 3072-3327/$0CO0-$0CFF, is available
tively, when the buffer is full or empty. for other purposes such as machine language routines or addi-
Actually, the buffer is not located absolutely at this area. tional sprite definitions.
The starting address of the RS-232 input buffer is determined
by the value in locations 200-201/$C8-$C9. The pointer loca-
tions are initialized to 3072/S0C00 by the RAMTAS routine
Sprite Pattern Storage Area
[$E093], part of the reset sequence. No other system routine 3584-4095/$0E00-$0FFF
changes the address in that pointer, so the buffer will be lo- This area is reserved by the system to hold sprite pattern defi-
cated here unless you explicitly move it. However, the buffer nitions. Each sprite pattern requires 64 bytes and must start at
can be moved to another free area of memory simply by an address which is an exact multiple of 64/$40. Other free
changing the address in the pointer. (The area selected must locations within the current video bank which meet these cri-
be visible in the bank 15 configuration.) teria can also be used for sprite pattern storage, but BASIC
If RS-232 communications are not used, this buffer area, sprite routines such as SPRSAV and SPRDEF assume that
along with the one at 3328-3583/$0D00-$0DFF, is available sprite patterns reside in this area. The sprite pointers for the
for other purposes such as machine language routines or addi- default screen memory position (2040-2047/$07T8-$07FF) are
tional sprite definitions. initialized during the BASIC cold-start sequence as follows:
Pattern area Pointer value Default sprite
3584-3647/$0E00-$0E3F 56/$38 0
RS-232 Output Buffer 3648-371l/$0E40-$0E7F 57/$39 1
3328-3583/$0D00-$0DFF 3712-3775/$OE80-$0EBF 58/S3A 2
The routines that transmit characters via the RS-232 interface 3776~3839/$0ECO-$0EFF 59/$3B 3
are executed during NMI interrupts. Characters are stored in 3840-3903/$OFOO-$OF3F 60/$3C 4
this area, usually by the BSOUT routine, while awaiting trans- 3904-3967/$0F40-$0F7F 61/$3D 5
3968-4O31/$0F80-$0FBF 62/$3E 6
mission. This is a circular buffer with no fixed beginning or 4032-4095/$0FCO-$0FFF 63/$3F 7
end. Location 2586/S0A1A holds the offset from the starting
address of the buffer to the next character waiting to be sent No system ROM routines change these settings. If your pro-
(called the head of the buffer). Location 2587/S0A1B holds gram doesn't require sprites, this area can be used for other
the offset to the next free position in the buffer (called the tail purposes such as to hold machine language routines.
of the buffer). The buffer is considered empty when the two
offset addresses are equal, and full when the buffer tail offset Programmable Key Definition String Area
is one less than the head offset.
Actually, the buffer is not located absolutely at this area. 4096-4351/$1000-$10FF
The starting address of the RS-232 output buffer is determined This 256-byte area is used to hold the strings for the ten pro-
by the value in locations 202-203/$CA-$CB. The pointer lo- grammable keys supported by the 128's screen editor routines:
cations are initialized to 3328/$0D00 by the RAMTAS routine F1-F8, SHIFT-RUN/STOP, and HELP. Each of the first 10
[$E093], part of the reset sequence. No other system routine

150 151
4096-4351 $1000-$!OFF $1133-$1134 4403-4404

bytes of the area (4096-4105/$1000-$1009) holds the length BASIC Working Storage
of one of the definition strings:
Location Key 4352-4607/$1100-$1IFF
4096/$1000 Fl
4097/$1001 F2 4352-4400 $1100-$1130 DOSSTR
4098/$1002 F3 DOS command assembly area
4099/$1003 F4 The BASIC statements that issue DOS commands—for ex-
4100/$1004 F5 ample, HEADER, COPY, CATALOG, and SCRATCH—use
4101/$1005 F6 this area to assemble the command string to be sent to the
4102/$1006 F7 disk drive.
4103/$1007 F8
4104/$1008 SHIFT-RUN/STOP 4401-4402 $1131-$1132 XPOS
4105/$1009 HELP
Bitmapped-screen pixel-cursor horizontal position
The remaining 246 bytes (4106-435l/$100A-$lOFF) are These locations hold the horizontal (x) coordinate of the cur-
available for definition strings. There is no particular limit on rent position of the pixel cursor on the bitmapped screen. The
the length of an individual definition string, except that the
range of values here depends on the scale factor currently in
combined length of all the definition strings cannot exceed 246
use. If scaling is not used, the value can be found in the range
bytes. The definition strings correspond to keys in the order
0-319. In any case, a value of zero specifies the left edge of
shown above. The offset to the first character in a particular
the screen. The value here is set to 0/$00 whenever the bit-
string is found by adding the lengths of all preceding defini-
tions. No special characters are used to separate the strings. It mapped screen is cleared, either by the SCNCLR routine or by
is possible for a key to have no associated definition string, in adding the clear parameter to a GRAPHIC statement. After
which case the length location for the key should be set to execution of any BASIC graphic statement, this location will
0/$00. The default definitions for the keys are as follows: hold the value of the final horizontal pixel position affected by
the operation. The value here can be set explicitly using the
Key Default definition LOCATE statement, which stores the specified horizontal posi-
Fl GRAPHIC tion in this location. If the DRAWTO form of the DRAW state-
F2 DLOAD" ment is used, the line will begin at the horizontal position
F3 DIRECTORY {RETURN} specified here.
F4 SCNCLR {RETURN}
F5 DSAVE" 4403-4404 $1133-$1134 YPOS
F6 RUN {RETURN}
F7 LIST {RETURN} Bitmapped-screen pixel-cursor vertical position
F8 MONITOR{RETURN} These locations hold the vertical (y) coordinate of the current
SHIFT-RUN/STOP DL"*{RETURN}RUN{RETURN} position of the pixel cursor on the bitmapped screen. The
HELP HELP{RETURN} range of values here depends on the scale factor currently in
These definitions, along with the corresponding length values, use. If scaling is not used, the value can be found in the range
are copied from locations 52904-52980/$CEA8-$CEF4 in 0-199. In any case, a value of zero specifies the top edge of
screen editor ROM during the Kernal CINT routine [$C07B]. In the screen. The value here is set to 0/$00 whenever the bit-
BASIC, the KEY statement can be used to change definitions. mapped screen is cleared, either by the SCNCLR routine or by
From machine language, the Kernal PFKEY routine [$FF65] (or adding the clear parameter to a GRAPHIC statement. After
screen editor KEYSET routine [$C021]) can be used. Pro- execution of any BASIC graphic statement, this location will
grammable keys are handled by a subroutine [$C6CA] within hold the value of the final vertical pixel position affected by
the screen editor keyscan routine. the operation. The value here can be set explicitly using the

152 153
4405-4406 $1135-$1136 $116D 4461

LOCATE statement, which stores the specified vertical posi- 4458 $ 116A SCALEM
tion in this location. If the DRAWTO form of the DRAW state- Scaling flag
ment is used, the line will begin at the vertical position This location indicates whether the scaling feature is to be
specified here. used when graphics are drawn on the bitmapped screen.
While this location contains 0/$00, scaling will not be used.
4405-4406 $1135-$1136 XDEST When the location contains any nonzero value, the horizontal
Final horizontal pixel position for graphics operations and vertical coordinates for all graphics routines will be scaled
These locations hold the calculated ending horizontal pixel- according to the values in locations 135-136/$87-$88 and
cursor position for BASIC graphics operations. The operation is 137-138/$89-$8A. This location is initialized to 0/SOO (scal-
complete when the value in locations 4401-4402/$1131-$1132 ing off) during the BASIC cold-start sequence, and also when-
equals the value here. ever the clear-screen parameter is included in a GRAPHIC
statement. The routine to execute the SCALE statement
4407-4408 $1137-$1138 YDEST [$6960] will store the first parameter following SCALE (0 or 1)
Final vertical pixel position for graphics operations here.
These locations hold the calculated ending vertical pixel-cursor
position for BASIC graphics operations. The operation is com- 4459 $116B WIDTH
plete when the value in locations 4403-4404/$1133-$1134 Line width for bitmapped graphics routines
equals the value here. The value here determines whether the lines drawn by BASIC
bitmapped graphics routines are to be standard width (indi-
4409-4455 $1139-$1167 cated when this location contains 0/$00) or double width (in-
Working storage for assorted graphics routines dicated when this location contains any nonzero value). The
BASIC graphics routines such as BOX, CIRCLE, DRAW, and value here is initialized to 0/$00 (normal width) during the
PAINT use various locations in this range to perform the cal- BASIC cold-start sequence. The routine to execute the WIDTH
culations necessary to plot the points for the figure being statement [$71B6] will store the width parameter minus 1 in
drawn. The MOVSPR routine also uses some of these loca- this location.
tions for sprite position calculations in those cases where the
sprite is moved relative to the pixel cursor. 4460 $116C FILFLG
BOX fill flag
4456 $ 1168 CHRPAG This location is used during the BOX routine [$62B7] to specify
Starting page for character pattern definitions whether the shape is to be open or filled. If the value here is
This location is used during the CHAR routine [$67D7] in the 0/$00 the shape will be open; otherwise, it will be filled. This
calculations to determine where character shapes are to be location is initialized to 0/$00 (open shapes) during the
placed on the bitmapped screen. The value here is the starting BASIC cold-start sequence. When a BOX statement is exe-
page of character memory. This location will hold the value cuted, the seventh parameter (paint) following the statement
from either 4588/$llEC or 4587/$llEB. will be copied here. If that parameter is omitted, it will default
to 0/$00.
4457 $1169 BITCNT
Bit counter for shape retrieval 4461 S116D BITMSK
This location is used during the GSHAPE routine [$658D] as a Bit mask value
counter for the bits to be read from each byte of the storage This location is used as a mask value to select individual bits
string. during the DRAW and SPRDEF routines.

154 155
4462 $116E $117C-$117D 4467-4477

4462 $116E NUMCNT 4472 $1178 VTEMP4


Temporary storage for assorted routines Working storage for graphics parameter evaluation
This location is used for temporary working storage during the This location is used during the routine that evaluates param-
CHAR, MOVSPR, and SPRDEF routines. eters for graphics routines [$9E6D] to hold the offset to the pa-
rameter being evaluated.
4463 $116F TRCFLG
Trace mode flag 4473 $1179 VTEMP5
This location is used to indicate whether BASIC is in trace Working storage for graphics parameter evaluation
mode. When a program is executed in trace mode, the line This location is used during the routine that evaluates param-
number of each program line is printed as it is executed. Trace eters for graphics routines [$9E6D] to hold a value indicating
mode is off when bit 7 of this location is %0, and on when bit the parameter type.
7 is % 1 . This location is initialized to 0/$00 (trace off) during
the BASIC cold-start sequence. It is also reset to 0/$00 during 4474-4475 $117A-$117B ADRAY1
the NEW routine. The value here can be changed using the Pointer to floating point-to-integer conversion routine
TRON and TROFF statements. TRON sets this location to These locations point to the routine that converts the floating-
255/$FF, and TROFF resets it to 0/$00. point value in FAC1 (99-103/$63-$67) into a two-byte integer
value in the accumulator (low byte) and Y register (high byte).
4464-4467 $1170-$1173 RENUM_TMPS The BASIC cold-start sequence initializes the value here to
Working storage for RENUMBER 33951/$849F/ the address of that routine in the current ver-
These locations are used for working storage during BASIC'S sion of BASIC ROM.
RENUMBER routine [$5AF8], Locations 4464-4465/$1170-$1171
This pointer is especially useful in conjunction with the
hold the line number at which renumbering is to begin, and USR function. See the entry in Chapter 5 for details. To per-
4466-4467/$1172-$1173 hold the increment by which subse- form this conversion, it's best to use the indirect JMP ($117A)
quent lines are to be renumbered. instead of the absolute JMP $849F. That way, your program
will still work if the ROM is revised in future versions.
4468 $1174 T3
Loop counter for reading directory entries 4476-4477 $117C-$117D ADRAY2
This location is used during the CATALOG/DIRECTORY rou- Pointer to integer-to-floating point conversion routine
tine [$A07E] as a counter in the loop to discard extraneous
These locations point to the routine that converts a two-byte
characters before the block count.
integer value in the accumulator (low byte) and Y register (high
byte) to a floating-point value in FAC1 (99-103/$63-$67).
4469-4470 $1175-$1176 T4 The BASIC cold-start sequence initializes the value here to
Block count for directory entry 31036/$793C, the address of that routine in the current ver-
These locations are used during the CATALOG/DIRECTORY sion of BASIC ROM.
routine [$A07E] to hold the block count for each file entry This pointer is especially useful in conjunction with the
read from the drive. USR function. See the entry in Chapter 5 for details. To per-
form this conversion, it's best to use the indirect JMP ($117F)
4471 $1177 VTEMP3 rather than the absolute JMP $793C. That way, your program
Working storage for graphics parameter scaling will still work if the ROM is revised in future versions.
This location is used for working storage during the routine
that scales graphics parameters [$9DAE] when the SCALE op-
tion is in effect.
156 157
4478-4565 $117E-$11D5 $11D6-$11E6 4566-4582

4478-4565 $ 117E-$ 1 IDS SPRITE-DATA All locations in this range are initialized to 0/$00 during
Sprite movement control data the BASIC cold-start sequence. The warm-start sequence per-
The MOVSPR statement has an option to set sprites in motion forms the less dramatic initialization step of resetting all the
at a given angle and speed. These locations hold data concern- speed locations to 0/$00, which stops all sprite motion.
ing sprite motion. For moving sprites, the values here will be
used to generate position values that will be copied to the 4566-4582 $11D6-$11E6 VIC-SAVE
shadow registers at 4566-4582/$llD6-$llE6. The locations Shadows for VIC sprite position registers
are used as follows: The contents of these locations are copied into the VIC chip
Sprite 0 Sprite 1 Sprite 2 Sprite 3 sprite position registers (53248-53264/$D000-$D010) during
Speed 4478/$117E 4489/J1189 4500/$1194 4511/$119F each pass through the BASIC IRQ routine [$A84D]. As long as
Speed countdown 4479/$117F 4490/I118A 4501/$1195 4512/$11AO the BASIC IRQ routine is active, the VIC registers cannot be
Direction 4480/S1180 4491/$118B 4502/$1196 4513/$11A1
Horizontal increment (low) 4481/$1181 4492/$118C 4503/$1197 4514/$11AZ changed directly. Instead, you should store the desired register
(high) 4482/$1182 4493/$118D 4504/$1198 4515/$11A3 value in the corresponding shadow location. All locations in
Vertical increment (low) 4483/$1183 4494/$118E 4505/$1199 4516/S11A4 this range are initialized to 0/$00 during the BASIC cold-start
(high) 4484/S1184 4495/$118F 4506/$119A 4517/S11A5
Horizontal position (low) 4485/$1185 4496/$1190 4507/S119B 4518/$11A6 sequence. The values here can be set using the MOVSPR
(high) 4486/$1186 4497/S1191 4508/$119C 4519/$11A7 statement. The MOVSPR routine [$6CC6] sets the value here
Vertical position (low) 4487/$1187 4498/$1192 4509/$119D 4520/$11 A3 directly when a static sprite position is specified. When a mov-
(high) 4488/$1188 4499/S1193 4510/$119E 4521/$11A9
ing sprite is specified, the movement information is stored in
Sprite 4 Sprite 5 Sprite 6 Sprite 7 the table at 4478-4565/$117E-$llD5 and the values here are
Speed 4522/$! 1AA 4533/$llB5 4544/$llC0 4555/$llCB updated during each pass through the BASIC IRQ routine
Speed countdown 4523/$ 11AB 4534/S11B6 4545/$llO 4556/$llCC
Direction 4524/$ 11 AC 4535/$]1B7 4546/$11C2 4557/S11CD [$A84D]. The locations are used as follows:
(low) 4525/$ 11 AD 4536/$11B8 4547/S11C3 4558/$llCE
Horizontal increment (high) 4526/$llAE 4537/$11B9 4548/$llC4 4559/$llCF Location Register Function
(low) 4527/$llAF 4538/$ 11BA 4549/$llC5 4560/$11 DO 4566/$llD6 53248/$D0O0 Sprite 0 horizontal position
Vertical increment (high) 4528/S11B0 4539/S11BB 455O/$11C6 4561/$I1D1 4567/$llD7 53249/$D001 Sprite 0 vertical position
(low) 4529/$llBl 4540/$11BC 4551/$11C7 4562/$IlD2 4568/$llD8 53250/$D002 Sprite 1 horizontal position
Horizontal position (high) 453O/$11B2 4541/$11BD 4552/$HC8 4563/$llD3
(low) 4531/S11B3 4542/$llBE 4553/$llC9 4564/$llD4 4569/$llD9 53251/$D003 Sprite 1 vertical position
Vertical position (high) 4532/S11B4 4543/$llBF 4554/$llCA 4565/$ 11D5 4570/$1 IDA 53252/$D004 Sprite 2 horizontal position
4571/S11DB 53253/$D005 Sprite 2 vertical position
In addition to using the MOVSPR routine, the values here 4572/$llDC 53254/$D006 Sprite 3 horizontal position
can be set directly to set a sprite in motion. (The correspond- 4573/$llDD 53255/$D007 Sprite 3 vertical position
ing sprite must be enabled before the motion values have any 4574/$llDE 53256/$D008 Sprite 4 horizontal position
effect.) The speed value (0-15) determines how many times 4575/$llDF 53257/$D009 Sprite 4 vertical position
per IRQ interrupt the horizontal and vertical increment values 4576/$llE0 53258/$D00A Sprite 5 horizontal position
will be applied to the horizontal and vertical position values. 4577/$llEl 53259/$D00B Sprite 5 vertical position
If the speed value is 0/$00, the corresponding sprite will not 4578/$llE2 53260/$D00C Sprite 6 horizontal position
be moved. The speed value is copied to the countdown value 4579/$llE3 53261/$D0OD Sprite 6 vertical position
during each interrupt. The direction value can have one of the 458O/$11E4 53262/$D00E Sprite 7 horizontal position
following values: 4581/$11E5 53263/$D00F Sprite 7 vertical position
4582/S11E6 53264/$D010 Most significant bits of horizontal
Direction value Sprite motion position
0 x increasing, y decreasing
1 x increasing, y increasing
2 x decreasing, y increasing
3 x decreasing, y decreasing
159
158
4583-4584 $11E7-$11E8 $11EC 4588

4583-4584 $11E7-$11E8 statement for bitmapped screens (see location 4588/$llEC for
Shadows for VIC sprite-collision registers more information). CHAR will always begin using the charac-
During any pass through the BASIC IRQ routine [$A84D] ter set pointed to in location 4588/$llEC. To switch to the al-
where either or both of the sprite-collision latch flags {bits 1-2 ternate character set, the CHAR string must include character
of 53273/$D019) are found to be set to % 1 , the contents of code 14/$0E. Character code 142/$8E switches back to the
the corresponding VIC chip sprite-collision register will be re- default set. This location is initialized to 216/$D8 during
corded in these locations. For sprite-foreground collisions (in- BASIC cold start. That value selects the ROM lowercase/
dicated when bit 1 of the flag is set), any bits in the register at uppercase set at 55296/$D800 as the alternate character pat-
53279/$D01F which are set to %1 will also be set to %1 in lo- tern source. If you use a custom character set, you can change
cation 4584/$llE8. Likewise, for sprite-sprite collisions (indi- the value here to have CHAR use your new characters. How-
cated when bit 2 of the flag is set), the %1 bits in the register ever, the new character set must be visible in the bank 14
at 53278/$D01E will be recorded in location 4583/$llE7. memory configuration, since that is how the system will be
Thus, these locations will accumulate collision readings until configured when character pattern data is read.
they are cleared, rather than simply holding the most recent
collision values. The routine for the BASIC function BUMP 4588 $11EC UPPER-GRAPHIC
[$837C] returns values based on the contents of these loca- Starting page for default character set during CHAR
tions, rather than on the actual register contents. BUMP(l) re- The value here determines the starting page in system mem-
turns the sprite-sprite collision value in 4583/$llE7, and ory for the default set of characters used during the CHAR
BUMP(2) returns the sprite-foreground collision value in statement. The value here doesn't affect any statement other
4584/$llE8. Either location will be reset to 0/$00 after being than CHAR, and is used only when character shapes are being
read by BUMP. Both locations are also initialized to 0/$00 placed on a bitmapped screen. (When CHAR is used to place
during the BASIC cold-start sequence. characters on the text screen, the screen editor printing routines
are used instead.) For bitmapped screens, CHAR will always
4585-4586 $1lE9-$11EA begin using the character set pointed to here, regardless of the
Shadow for VIC light pen registers character set in use on the text screen. To switch to the alter-
During any pass through the BASIC IRQ routine [$A84D] nate character set (starting page in 4587/$llEB), the CHAR
where the light pen latch flag (bit 3 of 53273/$D019) is found string must include character code 14/$0E. Character code
to be set to % 1 , the contents of the VIC chip light pen regis- 142/$8E switches back to the character set pointed to here.
ters at 53267-53268/$D013-$D014 will be copied into these Thus, it is possible to mix the two character sets in a single
locations. The routine for the BASIC function PEN [$82AE] re- CHAR statement. This location is initialized to 208/$D0 dur-
turns values based on the contents of these locations, rather ing BASIC cold start. That value makes the ROM uppercase/
than on the actual register contents. PEN(O) returns the value graphics set at 53248/$D000 the default character pattern
in 4585/S11E9, multiplied by 2. PEN(l) returns the value in source. If you use a custom character set, you can change the
4586/S11EA. Either location will be reset to 0/$00 after being value here to have CHAR use your new characters. However,
read by PEN. Both of these locations are also initialized to the new character set must be visible in the bank 14 memory
0/$00 during the BASIC cold-start sequence. configuration, since that is how the system will be configured
when character pattern data is read.
4587 $11EB UPPER-LOWER
Starting page for alternate character set during CHAR
The value here determines the starting page in system mem-
ory for the alternate set of characters used during the CHAR

160 161
4589 $11ED $1208 4616

4589 SUED DOSSA 4612-4615 $1204-$1207 PUCHRS


Channel number for BASIC relative file operations Character definitions for PRINT USING
The channel number (secondary address) for BASIC relative The values in these locations determine which characters will
file operations is stored in this location. be used for the redefinable characters in the PRINT USING
format. The default values are copied from locations $5250-
4590-4607 $11EE-$11FF Unused $5253 in BASIC ROM during the CLR routine, so the default
None of these locations is used by any system ROM routine. definitions will be restored each time a program is run. In
BASIC, the definitions here can be changed using the PUDEF
statement.
BASIC General-Purpose Working Storage 4612/$1204: This location holds the filler character for the pat-
4608-4863/$1200-$12FF tern, the one which will be used to fill unused positions in the
format. The default value is 32/$20, the space character.
4608-4609 $1200-$1201 OLDLIN 4613/$1205: This location holds the comma character for the
Line number where program stopped pattern. The character with the code specified here will be
Whenever a BASIC program stops because of an END or substituted wherever a comma appears in the PRINT USING
STOP statement, or because the end of the program has been format. The default value is 44/$2C, the comma character.
reached, or because the RUN/STOP key has been pressed, 4614/$1206: This location holds the decimal point character for
then the STOP/END routine [S4BCB] will be executed. That the pattern. The character with the code specified here will be
routine stores the line number where the program stopped in substituted wherever a decimal point (period) appears in the
this pair of locations (in low-byte/high-byte format). The PRINT USING format. The default value is 46/$2E, the period
CONT routine [$5A60] uses the value here to determine where (.) character.
to restart the program. These locations are also used for tem-
porary storage during the RENUMBER routine [$5AF8]. 4615/$1207: This location holds the monetary symbol charac-
ter for the pattern. The character with the code specified here
4610-4611 $1202-61203 OLDTXT will be substituted wherever a dollar sign ($) appears in the
Pointer to the start of current line PRINT USING format. The default value is 36/$24, the dollar
Each time a BASIC program line is executed, the address of sign character.
the first character of program text in the line is stored in these
locations. The high byte (4611/$1203) is also used as a flag to 4616 $1208 ERRNUM
indicate whether the program can continue after being halted. Number of most recent error
The CONT routine [$5A60] will give a CAN'T CONTINUE er- Whenever a BASIC error occurs, the ERROR routine [$4D3C]
ror message if the flag byte is 0/$00. The flag location is ini- stores the error number here. The reserved variable ER always
tialized to 0/$00 during the CLR routine [$51F8]—you can't reflects the value in this location. Refer to the entry for the er-
CONTinue a program before it is run. If the program halts with- ror message table in Chapter 5 [$484B] for a complete list of
out errors, the flag location will hold the high byte of the ad- error numbers. Once an error number is stored here, the value
dress of the line where the program stopped, which will always is retained until another error occurs or until the location is
be nonzero, so the program can be CONTinued. However, if reinitialized. This location is initialized to 255/$FF during CLR
the program stopped because of an error, or if any lines are [$51F8] (also executed as part of NEW and RUN). This setting
changed after the program has stopped, then the flag location results in a value of —1 in the reserved variable ER, so when
will be reset to zero and the program cannot be CONTinued. ER contains that value no error has yet occurred.

162 163
4617-4618 $1209-$120A $1212-$1213 4626-4627

4617-4618 $1209-$120A ERRLIN 4622-4623 $120E-$120F ERRTXT


Line number where most recent error occurred Pointer to start of statement where last error occurred
Whenever a BASIC error occurs, the ERROR routine [$4D3C] Whenever an error occurs, the ERROR routine [$4D3C] copies
checks the run mode flag (127/$7F) to see if the error oc- the value in 4610-4611/$1202-$1203 into these locations.
curred in a program line or an immediate mode line. If the er- The HELP subroutine that highlights the portion of the line
ror was in a program line, the current line number is copied where the error occurred uses the value here to determine
here from locations 59-60/$3B-$3C. The reserved variable EL where to begin the highlighting. The RESUME routine [$5F62]
always reflects the value in these locations. Once a line num- uses the value here to determine where to resume execution.
ber is stored here, it will be retained until another error occurs
or until the locations are reinitialized. These locations are ini- 4624-4625 $1210-$1211 TEXT_TOP
tialized to 65535/$FFFF during CLR [$51F8] (also executed as End-of-program pointer
part of NEW and RUN). Thus, when the reserved variable EL These locations contain the address of the location immedi-
contains 65535 no error has yet occurred. ately following the end of BASIC program text. The NEW
statement [$51D6] initializes the value here to two bytes be-
4619-4620 $120B-$120C TRAPNO yond the address in the start-of-program pointer (45-46/
Target line number for TRAP statement $2D-$2E). The value here is updated to reflect the new ending
When error trapping is enabled with the TRAP statement, the address whenever a line is added or deleted from the program.
target line number to which the program will be directed An OUT OF MEMORY error occurs if the value here ever ex-
when an error occurs is stored here (in standard low- ceeds the value in 4626-4627/$1212-$1213. Following a
byte/high-byte order). Location 4620/$120C is also used as a LOAD or DLOAD, these locations are set to one byte beyond
flag to determine whether trapping is enabled. The flag loca- the last location to which data was loaded. For a SAVE or
tion is initialized to 255/$FF during CLR (which is also part of DSAVE, the value here determines the last address from
NEW and RUN), Since the high bytes of all valid line num- which data will be saved.
bers are less than 255/$FF, trapping is considered disabled as
long as the flag location contains that value. When trapping is 4626-4627 $1212-$1213 MAX_MEM_0
enabled, the ERROR routine [$4D3C] will transfer control to
the line number indicated here whenever a BASIC error occurs. Top-of-BASIC pointer
The value in this pair of locations determines the top of free
memory in block 0 RAM. The address will be one location be-
4621 $120D TMPTRP yond the highest one available for BASIC program text. An
Temporary storage for high byte of TRAP line number OUT OF MEMORY error will occur when the value in loca-
When an error is trapped to a specified line, the ERROR rou- tions 4624-4625/$1210-$1211 exceeds the value here. The
tine [$4D3C] copies the high byte of the target line number BASIC cold-start initialization subroutine [$4045] writes the
from 4620/$120C into this location, then stores the value value 65280/$FF00 here, so that all block 0 RAM below the
255/$FF in 4620/$120C. This disables the trapping of errors MMU registers is available for program text. You can reserve
during the error-handling routine, which would otherwise put an area at the top of program memory by reducing the value
the program into an infinite loop. The value here is copied in these locations. Unlike some of the other pointers, you need
back into 4620/S120C during execution of the RESUME state- only store the new value here; no subsequent NEW or CLR is
ment [$5F62]. required.

164 165
4628-4629 $1214-$1215 $1223-$1228 4643-4648

4628-4629 $1214-$1215 TMPTXT as the seed for the next random number. Location 4635/$121B
Temporary text pointer storage for DO is initialized to 0/$00 during the BASIC cold-start routine.
This pair of locations is used to temporarily hold the CHRGET That is a change from previous Commodore models, where all
text pointer value (from 61-62/$3D-$3E) during execution of five bytes of the seed value were initialized. The zero byte has
the DO statement [$5FE0]. the effect of making the initial seed value 0, so the first ran-
dom number value generated after the computer is turned on
4630-4631 $1216-$1217 TMPLIN or after a reset will always be 1.07870447E-03.
Temporary line number storage for DO
This pair of locations is used to temporarily hold the current 4640 $1220 CIRCLE_SEGMENT
line number value (from 59-60/$3B-$3C) during execution of Degrees between segments for CIRCLE routine
the DO statement [$5FE0]. This location is used during the BASIC CIRCLE statement rou-
tine [$668E] to hold the number of degrees to turn for each
4632-4634 $1218-$121A USRPOK segment of the circle. The value here is set from the ninth pa-
USR function jump vector rameter in the CIRCLE statement, and defaults to 2 if that pa-
The BASIC function USR calls a machine language routine, rameter is omitted.
like SYS, but it also allows a numeric value to be passed to
and from the ML routine. The routine in BASIC ROM that ex- 4641 $1221 DEJAVU1
ecutes USR ends with a JMP $1218. Location 4632/$1218 Although Commodore literature states that this location holds
contains 76/$4C, the machine language JMP instruction. Loca- a value relating to the reset status, no reference to this location
tions 4633-4634/$1219-$121A should contain the address of occurs in any ROM routine.
the target machine language routine (in the usual Iow-
byte/high-byte format). You must explicitly load these loca- 4642 $1222 TEMPO-RATE
tions with the address of the target routine before you use Tempo setting for PLAY statement
USR. This location is initialized to 32040/$7D28 during The value here determines the tempo for notes played by the
BASIC cold start. This is the address of the routine that issues BASIC PLAY statement. The value here is subtracted from the
the ILLEGAL QUANTITY ERROR message, which is what sound duration value for each voice (in locations 4643-4648/
you'll get if you use USR without changing locations $1223-$1228) during each pass through the BASIC IRQ rou-
4633-4634/$1219-$121A. Refer to Chapter 5 for more infor- tine. The larger the value here, the faster the duration de-
mation on passing values to and from the called routine. creases and the faster each note plays. The value here is
initialized to 16/$10 during the SID initialization routine
4635-4639 $121B-$121F RNDX [$4112], part of both the BASIC cold start and warm start se-
Random number seed value quences. In BASIC, the TEMPO statement can be used to
This five-byte area holds the seed value for BASIC'S random- change the value here.
number-generator routine [$8434]. When a positive argument
is supplied, the RND routine generates the next random num- 4643-4648 $1223-$1228 VOICES
ber by performing calculations and manipulations with the Durations for currently active notes
value here. The generated values aren't really random—any These locations hold the durations of the current PLAY state-
given seed value here will always produce the same result. ment notes for each of the SID chip voices:
However, the process is sufficiently complicated that the re- Voice 0: 4643-4644/$1223-$1224
sults aren't easily predictable. Whenever any random number Voice 1: 4645-4646/$1225-$1226
is generated, the resulting value is stored here for possible use Voice 2: 4647-4648/$1227-$1228

166 167
4649-4650 $1229-$122A $123O-$1232 4656-4658

Bit 7 of each of the high bytes (4644/$1224, 4646/$1226, and 4652 $122C SHARP
4648/$1228) is used to indicate whether a note is currently Sharp/flat flag
being played by that voice. The voice is active when that bit is The value in this location holds a value that indicates whether
%0. The duration value for each active voice is decremented the current note will be either sharp or flat. The location nor-
by the tempo value specified in location 4642/$1222 during mally holds 0/$00 for natural notes. When a # character is
each pass through the BASIC IRQ routine [$A84D]. When a found in the PLAY string, this location will be set to l/$01 to
duration is decremented below $0000, the high byte will roil indicate that the next note should be sharp. When a $ charac-
over to $FF, which will set bit 7 to % 1 , marking the end of the ter is found in the string, this location will be set to 255/$FF
note. At this point, the gate bit for the voice will be turned off, to indicate that the next note should be flat.
stopping sound output for that voice. Large tempo values
cause the value here to decrease more rapidly, increasing the 4653-4654 $122D-$122E PITCH
speed at which notes are played, while small tempo values in-
crease the note time. Frequency for current note
When the PLAY statement prepares a note, the frequency for
The high bytes for all three voices are set to 255/$FF by the note is calculated in these locations before being trans-
the SID initialization routine [$4112], part of both the BASIC ferred into the SID chip registers for the specified voice. The
cold start and warm start sequences. This makes all voices ini- frequency is calculated by loading a base frequency for the
tially inactive. When the PLAY statement plays a note, the du- specified note from the table at 28665-28688/$6FF9-$7010,
ration for that note will be copied from 4649-4650/$ 1229-$122A adjusted for the octave specified in 4651/$122B. If the flag at
into the slot for the voice specified for that note. 4652/$122C indicates that the note is to be sharp or flat, the
frequency is adjusted accordingly.
4649-4650 $1229-$122A NTIME
Duration of current note 4655 $122F VOICE
When the PLAY statement prepares a note, the duration for Voice number for current note
the note is first calculated in this location, then transferred to The value in this location specifies which voice will be used to
the proper slot in 4643-4648/$1223-$1228. The value here is play the next note. The value here is set to 0/$00 by the SID
set to 288/$0120, the value for a quarter note, by the SID ini- initialization routine [$4112], part of both the BASIC cold start
tialization routine [$4112], part of both the BASIC cold start and warm start sequences. This selects voice 0 as the default
and warm start sequences. voice. The value here will remain in effect until changed by a
V parameter in the PLAY string. The parameter value will be
4651 $122B OCTAVE reduced by 1 to convert the BASIC voice number (1-3) to a
Octave for current note VIC voice number (0-2).
The value in this location determines the octave for the cur-
rent notes played by the PLAY statement. This value will af- 4656-4658 S1230-S1232 WAVE
fect the calculation of the frequency for the notes. The value Waveforms for current notes
here is set to 4/$04, the octave containing middle C, by the The values in these locations determine which waveforms will
SID initialization routine [$4112], part of both the BASIC cold be used for each of the three voices:
start and warm start sequences. The octave value here remains
in effect until changed by an O parameter in the PLAY string. Voice 0: 4656/$1230
Voice 1: 4657/$1231
Voice 2: 4658/$1232

168 169
4659 $1233 $123F-$1270 4671-4720

These locations hold the waveform value for the instrument 4667-4669 $123B-$123D TONVAL
specified for the voice. All three voices are initialized to the Envelope parameters for current instrument
default value for instrument 0. This selects a default pulse The current parameters for the specified instrument are read
waveform for all three voices. The value here remains in effect from the instrument table into these locations at the beginning
until changed by a T parameter in the PLAY string. The T pa- of the ENVELOPE routine [$7OC1]:
rameter causes the value for the current voice to be changed to
the waveform value for the specified instrument from the table Attack/decay: 4667/$123B
at 4671-4720/$123F-$1270. Sustain/release: 4668/$123C
Waveform: 4669/$123D
4659 $1233 DNOTE If the ENVELOPE statement specifies new values for any of
Dotted-note flag these parameters, the new values replace the original values
The value in this location determines whether the next note here. The values here are then copied back into the table en-
will be normal or "dotted." Dotted notes play IV2 times as tries for the specified instrument number.
long as a standard note. This location normally holds 0/S00,
but will be set to 35/$23 if a period (.) is found in the play 4670 $123E PARCNT
string. In this case, the duration of the next note will be in- Index into instrument table for current instrument
creased by 50 percent. This value is used during the ENVELOPE routine [$7OC1] to
hold the index to the current set of instrument parameters.
4660-4663 $1234-$1237 FILTSAV
Temporary storage for filter parameters 4671-4720 $123F-$1270
The filter parameters are copied here from 4721-4722/ Instrument parameter tables
$1271-$1272 at the beginning of the FILTER statement rou- This area is used to hold the envelope parameters for the ten
tine [$7046], The filter parameter manipulations are then per- defined instruments supported by the PLAY statement [$6DE1]:
formed on these locations, and the results are copied back to Instrument Attack/ Sustain/ Waveform Pulse width
Decay Release low byte high byte
the working storage area. 0 4671/S123F 4681/S1249 4691/S1253 4701/$125D 4711/S1267
1 4672/$1240 4682/$124A 4692/$1254 4702/$125E 4712/S1268
4664 $1238 FLTFLG 2 4673/$1241 4683/$124B 4693/S1255 4703/$125F 4713/$1269
4674/$1242 46S4/S124C 4694/$1256 4704/S1260 4714/$126A
Filter type index 4 4675/$1243 4685/$124D 4695/$1257 4705/J1261 4715/S126B
This location is used as a mask value to select individual filter 5 4676/$1244 4686/$124E 4696/$1258 4706/S1262 4716/$126C
6 4677/S1245 4b87/$124F 4697/S1259 4707/S1263 4717/$126D
control bits when evaluating the FILTER statement parameters. 7 4678/S1246 4688/51250 469S/$1Z5A 4708/$1264 4718/S126E
8 4679/$1247 4689/$125I 4699/S125B 4709/$1265 4719/S126F
4665 $1239 NIBBLE 9 4680/S1248 4690/$1252 4700/S125C 4710/$1266 4720/S1270
Temporary storage All three voices are initially assigned the envelope parameters
This location is used as working storage by the FILTER and for instrument 0. These settings remain in effect until changed
ENVELOPE routines. with a T parameter in the PLAY string.
The values for any table entry can be changed using the
4666 $123A TONNUM ENVELOPE statement. Default instrument table values are
Current instrument number copied into this area from a table in ROM at 28689-28728/
This location will hold the instrument number specified in the $7011-$7038 during the SID initialization routine [$4112], part
most recent ENVELOPE statement. of both the BASIC cold start and warm start sequences. The
default values are as follows:

170 171
4721-4722 $1271-$1272 $1276-$1278 4726-4728

Envelope Attack/ Sustain/ Waveform Pulsewidth


Decay Release 4724 $1274
0 (piano) 9/$09 0/$00 65/$41 (pulse) 1791/$06FF Current filter type selection
1 (accordion) 192/$C0 192/$C0 33/$21 (sawtooth) 0/$0000 Bits 4-6 of this location determine the type of filtering cur-
2 (calliope) 0/$00 240/$F0 17/$ 11 (triangle) 255/SOOFF rently enabled. The setting of those bits can be changed using
3 (drum) 5/$05 80/$50 129/S81 (noise) 0/$0000
4 (flute) 148/$94 64/$40 17/$11 (triangle) 255/$00FF
the FILTER statement. Because the SID register that controls
5 (guitar) 9/$09 33/S21 33/$21 (sawtooth) 0/$D000 filter type also controls volume, bits 0-3 of this location reflect
6 (harpsichord) 9/$09 0/$00 65/$41 (pulse) 767/$02FF the current volume setting as well. When an XI parameter is
7 (organ) 9/$09 144/$90 65/$41 (pulse) 2048/$0800 included in a PLAY string, the value here is copied into the
8 (trumpet) 137/$89 65/$41 65/$41 (pulse) 767/$02FF SID register at 54296/$D418 to enable the specified filter type.
9 (xylophone) 9/$09 0/$00 17/$11 (triangle) 0/$0000 This location is set to 15/$0F, the value for all filters off and
Note that the pulsewidth values here are different from those maximum volume, during the SID initialization routine [$4112],
specified in Commodore literature. The official values assume part of both the BASIC cold start and warm start sequences.
that all pulsewidth low bytes will be 0/$00. However, these
bytes are not explicitly initialized, so they will hold their pre- 4725 $1275
vious values after a reset. On power on, alternating pulse- Current SID chip volume setting
width low-byte locations will hold 255/$FF instead of 0/$00. Bits 0-3 of this location reflect the current volume setting for
the SID chip. The value here can be changed either with the
4721-4722 $1271-$1272 FILTERS VOL statement or with the U parameter in a PLAY string. Be-
Current filter cutoff frequency cause the SID register which controls volume also controls fil-
These locations hold the current cutoff frequency register set- ter type selection, bits 4-6 of this location will reflect filter
ting, an 11-bit value divided among the two locations with type as well. The value here is set to 15/$0F, the value for
bits 0-2 of the value in location 4721/$1271 and bits 3-10 of maximum volume, during the SID initialization routine [$4112],
the value in location 4722/$1272. The value is copied to the part of both the BASIC cold start and warm start sequences.
SID cutoff frequency registers (54293-54294/$D415-$D416)
when the XI parameter is included in the PLAY string. 4726-4728 $1276-$1278 INT_TRIP_FLAG
Collision flags
4723 $1273 The VIC internal interrupt register (53273/$D019) is read dur-
Current filter control and resonance setting ing each pass through the BASIC IRQ routine [$A84D] to de-
Bits 0-3 of this location determine which voices will be filtered termine if a sprite collision has occurred or if a new light pen
and bits 4-7 control the filter resonance setting. The resonance value has been latched. Because that register is automatically
setting can be changed using the FILTER statement. When an cleared after a read, the system uses these locations to record
XI parameter is included in the PLAY string, the filter control which conditions were detected:
bit in this location corresponding to the current voice will be Location Collision type
set to %1 and the value here will be copied into the SID regis- 4726/$1276 Sprite-sprite collision
ter at 54295/SD417 to enable filtering of that voice. When an 4727/S1277 Sprite-foreground collision
X0 parameter is included, the corresponding voice bit will be 4728/S1278 Light pen latch
set to %0 and the value will again be copied to the SID regis- If a collision has occurred, the corresponding flag location will
ter to turn off filtering for that voice. be set to 255/$FF, but only if the collision type has been en-
abled by setting to %1 the appropriate bit in location 4735/
$127F. All three of these locations are set to 0/$00 during the

172 173
4729-4734 $1279-$127E $1282-$12A2 4738-4770

SID initialization routine [$4112], part of both the BASIC cold 4737 $1281 SOUND-VOICE
start and warm start sequences. A location set to 255/SFF will Voice for current SOUND statement
be reset to 0/$00 after COLLISION processing in the GONE The value in this location specifies which group of entries in
routine [$4A9F]. the following table should be loaded with the current SOUND
parameters. The value here is set to the value of the first pa-
4729-4734 $1279-$127E INT_ADR rameter in the SOUND statement, minus 1 to convert the
Target line numbers for COLLISION BASIC voice number (1-3) into a SID voice number (0-2).
If the trapping of sprite collisions or light pen latches is en-
abled, a BASIC subroutine will be called (effectively a GOSUB) 4738-4770 $1282-$12A2
whenever one of the selected events occurs. These locations Table of SOUND statement settings
are used to hold the number (in low-byte/high-byte integer
format) of the starting BASIC program line of the subroutine These locations hold the current SOUND parameters for the
to be called. (The subroutine should end with a RETURN three SID chip voices:
statement.) The values here can be set with the COLLISION Parameter Voice 0 Voice 1 Voice 2
Duration (low) 4738/$1282 4739/$1283 4740/$1284
statement. (high) 4741/$1285 4742/$2286 4743/$1287
Low byte High byte Collision type Frequency (low) 4744/S1288 4745/$1289 4746/$128A
4729/$1279 4732/$127C sprite-sprite (high) 4747/5128B 4748/$128C 4749/$128D
473O/$127A 4733/$127D sprite-foreground Minimum frequency (low) 4750/$128E 4751/$128F 4752/$1290
(high) 4753/$1291 4754/$I292 4755/$1293
4731/$127B 4734/S127E light pen Step direction 4756/$1294 4757/$1295 4758/$1296
Step size (low) 4759/51297 4760/51298 4761/$1299
4735 $127F INTVAL (high) 4762/$129A 4763/$129B 4764/$129C
Collision enable flag Current frequency (low) 4765/$129D 4766/$129E 4767/$129F
(high) 4768/$12A0 4769/$12Al 4770/$12A2
Bits 0-2 of this location indicate the collision types for which
trapping is currently enabled: Bit 7 of each of the duration high-byte values (locations
Bit Collision type 4741-4743/$1285-$1287) is used to indicate whether any
0 sprite-sprite SOUND statement is active for the corresponding voice. If the
1 sprite-foreground bit is %0, the voice is assumed to have an active sound, and
2 light pen the current frequency value for the voice will be copied into
Trapping is enabled if the bit is set to % 1 . Enabling trapping the SID chip frequency registers during each pass through the
will allow the corresponding collision type to be recorded in BASIC IRQ routine [$A84D]. See Chapter 5 for a discussion of
the flags at 4726-4728/$1276-$1278. Bits 3-7 of this location the other SOUND effects, such as frequency sweeps. Also dur-
are unused. The value here is reset to 0/$00 during the BASIC ing each pass through the interrupt routine, the duration value
cold-start sequence. This disables all COLLISION branching. for each active voice will be decremented. When the value is
decremented below $0000, the high byte will roll over to
255/$FF, setting bit 7 to % 1 , which marks the end of the
4736 $1280 COLTYP sound. At this point the gate bit for the voice will be set to %0
Collision type index to turn off the sound.
The value here is used during the COLLISION routine [$7164] Each of the duration high-byte locations will be set to
to hold an index into the line number table at 4729-4734/ 255/$FF during the SID initialization routine, part of both the
$1279-$127E. BASIC cold start and warm start sequences. This will turn off

174 175
4771-4776 $12A3-$12A8 $12F6-$12F9 4854-4857

SOUND output for all three voices. The values in these loca- 4787-4790 $12B3-$12B6 WINDOW_TEMPS
tions are updated when the contents of 4771-4776/$ 12A3-$12A8 Temporary parameter storage for WINDOW statement
are copied to the entries for the specified voice during execution When the WINDOW statement [$72CC] is executed, the pa-
of the SOUND statement [$71EC]. rameter values associated with the statement are stored in
these locations before the screen editor WINDOW routine
4771-4776 $12A3-$12A8 [$C02D] is called to actually set the new window margins.
Parameters for most recent SOUND statement Location Parameter
These locations are used to assemble the parameters for the 4787/$12B3 left column
current SOUND statement. The SOUND statement must in- 4788/$12B4 top row
clude voice number, frequency, and duration parameters. The 4789/$12B5 right column
remaining parameters are optional; if they are omitted, default 4790/$12B6 bottom row
values are supplied. The base frequency value is initialized to
the specified starting frequency. The locations and default val- 4791-4806 $12B7-$12C6
ues are as follows: Filename buffer for DOS support commands
Parameter Locations Default value The routine which handles the BASIC 7.0 DOS support com-
Duration 4771-4772/$12A3-$12A4 mands such as SCRATCH and RENAME copies the filename
Frequency 4773-4774/$12A5-$12A6 portion of the command here temporarily while the remainder
Minimum frequency 4775-4776/$ 12A7-S12A8 0/$0000 of the command is being processed. Once the command is set
Step direction 4777/$12A9 0/$00 (sweep up) up, the filename here is copied into the DOS command buffer
Step size 4778-4779/$ 12AA-S12AB 0/$0000 (no sweep)
Base frequency 4780-4781/$12AC-$12AD at 4352-4399/$1100-$112F.
Pulsewidth 4782-4783/$12AE-$12AF 2048/S0800
Waveform 4784/$12B0 2/$02 (pulse) 4791-4853 $12B7-$12F5 SAVRAM
After all the parameters for a SOUND statement have Sprite pattern storage
been evaluated and assembled here, the values are transferred These locations are used during the SPRDEF statement routine
to the entries in the table at 4738-4770/$1282-$12A2 for the [$7372] to hold the original sprite pattern while a sprite is be-
specified voice. The base frequency value is used as the begin- ing defined. If the STOP key is pressed to cancel the current
ning current frequency value. modifications, the pattern definition here will be restored to
the definition area for the sprite. The first 63 of these locations
4785 $12B1 POT_TEMP_1 are also used during the SPRSAV routine [$76EC] to hold the
Temporary storage for POT and PEN routines sprite pattern to be transferred to a string variable.
This location is used as temporary storage during the routines
to perform the BASIC functions POT [$824D1 and PEN 4854-4857 $12F6-$12F9
[$82AE]. Sprite pattern suffix
During the SPRSAV routine [$76EC], these locations are ini-
4786 $ 12B2 POT_TEMP_2 tialized with the pattern $17 $00 $14 $00. When a sprite pat-
Temporary storage for POT routine tern is saved in a string variable, these bytes are appended to
During execution of the POT function routine [$824D], the the sprite pattern in 4791-4853/$12B7-$12F5 before the data
potentiometer reading from the SID chip register is stored here is transferred to the string pool. Two bytes are needed as the
temporarily while the paddle buttons are being read. tag for the variable, but exactly what this four-byte pattern is
intended to achieve is unclear.

176 177
4858 $12FA $13OO-$1BFF 4864-7167

4858 $12FA DEFMOD 4862-4863 $12FE-$12FF Unused


Sprite mode indicator for SPRDEF These locations are not used by any 128 ROM routine.
This location is used during the SPRDEF statement routine
[$7372] to hold a value indicating the mode of the sprite cur-
rently being defined. A value here of 0/$00 indicates a stan- Application Program Area
dard sprite, while a value of 128/$80 indicates a multicolor 4864-7167/$1300-$lBFF
sprite. None of the 2304 (2V4-K) locations in this area are used by
any system ROM routines. Thus, this area is free for your own
4859 $ 12FB LINCNT programming uses—machine language routines, alternate
Sprite pattern line count for SPRDEF screens, and so on. Because this is the largest block of free
This location is used during the SPRDEF statement routine RAM protected from BASIC, the area is becoming extremely
[$7372] to hold the number of the vertical line (0-20) within popular with machine language programmers, much like the
the sprite pattern which is currently being defined. area at 49152/$C000 in the Commodore 64. As a result, you'll
probably encounter instances where two programs you want
4860 $12FC SPRITE_NUMBER to use simultaneously will be incompatible because they reside
Sprite number for SPRDEF at overlapping addresses within this range.
This location is used during the SPRDEF statement routine One thing this area cannot normally be used for is to hold
[$7372] to hold the number (0-7) of the sprite currently being additional sprite patterns or custom character patterns. While the
defined. standard ROM-based character sets are enabled, the VIC chip
will see character ROM at addresses 4096-8191/$1000-$lFFF.
4861 $ 12FD IR9_WRAP_FLAG As a result, this RAM is not visible to the VIC chip and cannot
BASIC IRQ activity flag be used for sprite or character information. Sprite or character
This location is tested at the beginning of the BASIC IRQ ser- patterns can be stored here if the ROM-based characters are
vice routine [$A84D]. If it contains any nonzero value, the disabled; refer to the entry for location l/$01 in Chapter 2 for
routine exits immediately. The location is initialized to 0/$00 details.
during the SID initialization routine [$4112]. The BASIC IRQ
routine increments this location (to l/$01) when it begins, so
the test prevents the routine from being restarted if another in-
terrupt occurs before the current pass is completed. The IRQ
routine resets the value here to 0/$00 before exiting.
The BASIC portion of the IRQ sequence is responsible for
moving sprites, detecting sprite collisions, and handling the
BASIC sound statements. The routine maintains a number of
shadow locations which are copied into VIC and SID chip
hardware registers during each interrupt. Sometimes you may
want to turn off these shadow locations to have direct access
to the hardware registers. One way to do that is to store some
nonzero value in this location. While turning off the BASIC
IRQ routine will give you direct access to the hardware regis-
ters, you should keep in mind that it will also effectively dis-
able the BASIC statements MOVSPR, COLLISION, SOUND
and PLAY.
178 179
RAM Usage
The Commodore 128, as its name implies, has 128K of pri-
mary RAM in two 64K blocks. Memory configurations are dis-
cussed in detail in Chapter 1, but in general the 128 sees RAM
from block 0 in even-numbered banks (0, 4, 8, 14) and RAM
from block 1 in odd-numbered banks (1, 5, 9). A notable ex-
ception is bank 15, where RAM from block 0 is seen. Another
significant exception is that in every bank the system normally
sees RAM from block 0 in locations 2-1023/$0002-$03FF.
(Remember that locations 0-l/$00-$01 are used for the pro-
cessor's on-chip I/O port and are never seen as RAM.) This
means that the lowest IK of RAM in block 1 normally remains
invisible and unused. As explained in Chapters 2 and 3, the
common IK block and locations 1024-7167/$0400-$lBFF in
block 0 have special uses. Also, remember that MMU registers,
rather than RAM or ROM, are seen at addresses 65280-65284/
$FF00-$FF04 in every bank configuration.
Two pointers in page 10/$0A indicate the range of loca-
tions in block 0 considered free RAM. Locations 2565-2566/
$0A05-$0A06 point to the lowest free address, and locations
2567-2568/$0A06-$0A07 point to one byte beyond the high-
est free address. These pointers are initialized during the
RAMTAS subroutine [$E093], part of the reset sequence, to
7168/S1C00 and 65280/$FF00, respectively. The pointer val-
ues can also be changed with the Kemal MEMTOP [SFF99]
and MEMBOT [$FF9C] routines. However—unlike earlier
Commodore computers—these pointers have no effect on the
range of addresses used by BASIC and are not read by any
other Kernal or BASIC routine.

BASIC RAM Usage


For BASIC programming, the areas of RAM normally available
for storage of programs and variables are locations 7168-65279/
$1COO-$FEFF in block 0 and 1024-65279/$0400-$FEFF in
block 1. This is a total of 122,368 bytes of available RAM
space (illustrated in Figure 4-1). This explains why part of the
message you see when you turn on or reset the computer says
122365 BYTES FREE. (The missing three bytes are to account
183
for the zero byte required by BASIC before the first program Figure 4-1. BASIC RAM Usage
line and the two zero bytes used to mark the end of the
program.) Bank 0
Actually, it's a bit misleading to claim that many free
bytes, since you can't write a BASIC program 120,000 bytes
long. For BASIC, the free RAM is divided into two distinct
segments: the 58,112 bytes in block 0 for BASIC program text
and the 64,256 bytes in block 1 for variables and strings. (By
comparison, the Commodore 64 offers 38,911 bytes for pro-
gram text and variables combined.)
As noted in Figure 4-1, there is one additional factor
which affects the amount of memory available for program
text. When you use a GRAPHIC statement to set up a high-
resolution screen, an additional 9K is reserved in block 0: IK
at 7168-8191/$1COO-$1FFF for color information and 8K at
8192-16383/$2000-$3FFF for the high-resolution-screen bit-
map. In this case, the amount of RAM available for BASIC
program text is reduced to 48,896 bytes (locations 16384-65279/
$4000-$FEFF in block 0). If a program is already in memory
when the GRAPHIC statement is executed, the program is
moved upward in memory (the starting address will be
changed from 7169/$1CO1 to 16385/$4001) and relinked to
work at the new addresses. Once a high-resolution memory
area is established, it remains allocated until a GRAPHIC CLR
statement is executed, at which time the program text is moved
down to start at 7169/$1CO1 again.
Pointers in zero page and page 18/$ 12 are used to specify
the length of program text and variables. BASIC program text
is assumed to begin at the address in block 0 specified in loca-
tions 45-46/$2D-$2E. That pointer is initialized to 7169/
$1CO1 during the BASIC cold start routine [$4023]. Unlike the
Commodore 64, which sets its start-of-BASIC pointer accord-
ing to the value in the system's start-of-free-memory pointer,
the 128 sets the address value without regard for the value in
2565-2566/$0A05-$0A06. Locations 4626-4627/$1212-$1213
point to one byte beyond the highest available address in
block 0. That pointer is initialized during BASIC cold start to
65280/$FF00, again without regard to the Kernal memory
pointer value in 2567-2568/$0A07-$0A08. The actual ending
address of the program text currently in memory is specified
by the value in 4624-4625/$1210-$1211. That pointer is ini-
tialized during the BASIC CLR routine [$51F8] to two bytes

184
beyond the starting address in 45-46/$2D-$2E. An OUT called "reserved" in Commodore literature). This 2304-byte
OF MEMORY error occurs if the address in 4624-4625/ area is the largest unused area of protected RAM in the 128,
$1210-$1211 reaches the value in 4626-4627/ $1212-$1213. and it is becoming extremely popular with 128 ML program-
The ending address pointer is set after a BASIC LOAD [$912C], mers—much like the $C000 block in the Commodore 64. You
and the BASIC SAVE routine [$9112] uses the values in the can expect to see many ML programs using this area.
starting and ending address pointers as the starting and end- Other, shorter blocks are also available if certain BASIC
ing address for the block of memory to be saved. features are not used. If tape is not used, the 256 bytes at
The address in the pointer at locations 47-48/$2F-$30 2816-3071/$0B00-$0BFF are available. However, unlike other
marks the start of scalar (nonarray) variables in bank I. The free blocks, this page may be overwritten during a reset be-
pointer is initialized to 1024/$0400 during the BASIC cold cause disk boot sectors are read into this area. Thus, the time-
start routine. A pointer at 49-50/$31-$32 marks the end of honored Commodore tradition of using the cassette buffer for
scalar variables and the beginning of arrays; another pointer at short ML routines is less suitable in the 128. (It's annoying to
51-52/$33-$34 marks the end of arrays and the beginning of have to reload your routine after each reset.) If your program
free memory in block 1. Both of these pointers are reset to the doesn't use RS-232 communications, the two RS-232 buffers at
value in 47-48/$2F-$30 during the BASIC CLR routine. The 3072-3583/$0C00-$0DFF provide a 512-byte workspace. This
pointer at 57-58/$39-$3A holds an address which is one byte is probably the best area for short ML routines that you wish
beyond the highest address of free memory in block 1. It is to use in conjunction with BASIC. (Unlike the cassette buffer,
initialized during BASIC cold start to point to 65280/$FF00. this area survives reset intact.) If your program does not use
The free memory in block 1 is used to hold strings of all sprites, the 512-byte sprite definition area at 3584-4095/
types—constants, variables, and arrays. The string pool starts $0E00-$0FFF is also available. Of course, if your program uses
at the top of free memory and is filled downward toward the neither tape nor RS-232 nor sprites, you can use the full 1280
bottom of free memory indicated in 51-52/$33-$34. The bytes at 2816-4095/$0B00-$0FFF or any subsection thereof.
pointer at 53-54/$35-$36 marks the current address of the
To use a large ML program in conjunction with BASIC,
bottom of the string pool. That pointer is reset to the value in
there is an easy way to reserve over UK of protected RAM.
57-58/$39-$3A by the BASIC CLR routine. An OUT OF
However, this technique works only if neither the BASIC nor
MEMORY error occurs when the value in 53-54/$35-$36
the ML program requires high-resolution graphics. The trick is
reaches the value in 51-52/$33-$34.
to use the BASIC GRAPHIC statement to set aside a high-
resolution screen area at 7168-16383/$lC00-$3FFF. As men-
Reserving RAM tioned above, this area remains allocated until a GRAPHIC
There are occasions when you will want to divert an area of CLR statement is executed. Simply begin your BASIC program
RAM from its normal usage. For example, you may need to set with a line like GRAPHIC 1:GRAPHIC 0 (or GRAPHIC
aside space for a machine language routine, an alternate 1:GRAPHIC 5 if you want to use the 80-column display).
screen display, or a data buffer. For machine language (ML) Then BLOAD the machine language program into the reserved
programming, you can use any area of RAM if you are willing area. In addition to the 9K screen area, you can also use the
to learn the intricacies of the 128's banking scheme. Other- contiguous unused area just below, at 4864-7167/$1300-$lBFF.
wise, it's best to restrict your programming to certain known If you want to use a machine language program in conjunction
areas. For a machine language routine to be used in conjunc- with BASIC and high-resolution graphics, you'll have to resort
tion with a BASIC program, you'll need to select an area to bank-switching techniques if the program is too large to fit
which BASIC doesn't normally use, or to take away some in the unused area at 4864/$1300.
memory that otherwise would be used for program text or It's possible to reserve space above or below either the
variable storage. As noted in Chapter 3, locations 4864-7167/ BASIC or variable/string areas. To reserve space below the
$13OO-$1BFF are currently unused (even though they are BASIC program text, increase the value in the start-of-BASIC
186 187
pointer at 45-46/$2D-$2E by the number of bytes you want You can also reserve space in block 1, either above or be-
to reserve. (To reserve an even number of 256-byte pages, you low the variable/string area. To reserve space below variables,
need only change the value in 46/$2E.) Two other steps are add a value corresponding to the number of bytes to be re-
also necessary: BASIC requires a zero byte below the first lo- served to the address in the pointer at 47-48/$2F-$30, (As
cation in its program text space, and a NEW operation is re- with the other pointers, you can simply increase the value in
quired to reset other important memory pointers. For example, 48/$30 if you are reserving an even number of 256-byte
to reserve three pages (768 bytes) below the normal start of pages.) This step must be followed by a BASIC CLR statement
BASIC, you would use a statement like this: to reset other variable pointers, so it should be performed
POKE 46,31:POKE 31*256,0:NEW early in the program (CLR erases all variable values). The fol-
After this statement is executed, the area at 7168-7935/ lowing line reserves an additional IK at the bottom of variable
$1COO-$1EFF is protected from BASIC until the next time the space, locations 1024-2047/$0400-$07FF in block 1:
BASIC cold start routine is performed (normally during the 100 POKE 48,8:CLR
next reset sequence). The pointer value is unaffected by Once established, the reserved area will remain intact until the
RUN/STOP-RESTORE. This technique is less useful when a next time the BASIC cold start routine is executed, normally
high-resolution screen area is allocated. In that case, the start at the next reset. The setting is unaffected by RUN/STOP-
of BASIC is moved to 16384/$4000. The technique for reserv- RESTORE.
ing space at the start of BASIC still works, but the reserved Since this reserved RAM is in block 1, it can't be used for
memory will lie above 16383/$3FFF, which is the highest ad- ML routines as easily as the RAM from block 0. There is no
dress seen as RAM in bank 15—the bank in which Kernal standard bank configuration that makes BASIC and Kernal
ROM is visible and to which BASIC defaults. Thus, a routine ROM visible in conjunction with block 1 RAM. Of course, it is
above that boundary will be invisible unless you tinker with
the MMU configuration register. possible to access Kernal or BASIC routines indirectly by using
the JSRFAR or JMPFAR routine. One use for a reserved area in
Space can be reserved at the top of the BASIC program block 1 would be for an alternate 40-column screen. See the
area by reducing the value in the pointer at 4626-4627/ entry for the MMU RAM configuration register (54535/$D506)
$1212—$1213 by the desired number of bytes. (Again, if you information on using block 1 for VIC-II screen memory.
wish to reserve an even number of 256-byte pages, you can To reserve space above strings, subtract a value cor-
simply reduce the value in 4627/$l213.) No additional steps responding to the number of bytes to be reserved from the ad-
are required other than changing the pointer value. This tech- dress in the pointer at 57-58/$39-$3A. (As with the other
nique was often used in the Commodore 64 to reserve space pointers, you can simply increase the value in 58/$3A if you
for machine language routines; its usefulness is more limited are reserving an even number of 256-byte pages.) This step
in the 128 because of the 16384/$4000 boundary of RAM visi- must also be followed by a BASIC CLR statement to reset
ble in bank 15, which was mentioned above. To easily use the other string pointers, so it should be performed early in the
reserved area for an ML routine in conjunction with BASIC, program (CLR erases all variable values). The following line
the top of memory must be lowered sufficiently to make at reserves 31K at the top of string space, locations
least a portion of the reserved area appear below the bound-
ary of RAM visible in bank 15; this dramatically reduces the 32768-65279/$8000-$FEFF in block 1:
amount of memory available for program text. It's not even 100 POKE 58,128:CLR
possible when a high-resolution screen area is allocated. The Once established, the reserved area will remain intact until the
technique can, however, be useful for setting aside an area in next time the BASIC cold start routine is executed—normally
block 0 for a buffer, a reserved area of memory for data at the next reset. The setting is unaffected by RUN/STOP-
storage. RESTORE. As mentioned above, this area can't be easily used
for machine language routines since it is in block 1. One ap-
188 189
propriate use for a reserved area here would be for a data important routines and vectors. The MMU configuration and
buffer—to hold downloaded text in a telecommunications pro- load configuration registers always appear in the lower five
gram, for example. bytes of this area, locations 65280-65284/$FF00-$FF04. They
should never be disturbed unless you know the effect of the
Using ML Without BASIC values you are storing there (see Chapter 8 for more infor-
You have several options when using ML programs alone, mation on the MMU). You should also exercise care when
without BASIC. The simplest, if your program is less than 9K changing the contents of locations 65285-65348/$FF05-$FF44
(9216 bytes) long, is to leave the system in its default bank 15 in either RAM block, as these areas contain copies of the inter-
configuration and use the visible area of block 0 RAM at rupt and reset handling routines. (These areas are initialized
7168-16383/$lC00-$3FFF. (If you need a few more bytes, by the Kernal RESET routine [$E000].) If an interrupt or reset
you can stretch the start of the program down to the bottom occurs while the system is configured for a bank where Kernal
of the reserved area at 4864/$1300.) With this setup, you have ROM is not visible—bank 0 or 1, for example—a crash will
full access to the I/O chip registers and all the routines in occur if the area in the visible RAM block does not contain a
BASIC and Kernal ROM. routine to redirect the reset or interrupt to a proper handling
If you need more space, but still want access to Kernal routine. See the entries for these addresses in Chapter 9,
"Kernal ROM," for more information.
routines, you can change the settings of bits 1-3 of the MMU
configuration register to switch out BASIC ROM. In this case, Free space in this page includes the 181 bytes at locations
you'll have access to over 43K of contiguous RAM, locations 65349-65529/$FF45-$FFF9 in block 0 and the 176 bytes at
4864-49151/$1300-$BFFF. If you want to use a high-resolution 65349-65524/$FF45-$FFF4 in block 1. However, locations
screen in conjunction with your ML routine, it's easiest to set 65488-65519/$FFD0-$FFEF in block 0 will be overwritten
up the screen in its normal location (7168-16383/$1COO-$3FFF). whenever the computer is reset. As mentioned in Chapter 1,
This means that—if your program is too long to fit below the the Z80 microprocessor has control briefly after a reset or
screen areas—you'll need to switch out BASIC to have some when the computer is first powered on. The initialization steps
RAM visible with Kernal ROM. (You could still use the Kernal performed by the Z80 include copying two routines into block
JSRFAR routine to access BASIC routines—if you wanted to 0 RAM. One, at 65488-65503/$FFD0-$FFDF, is an 8502 ma-
chine language routine to surrender control to the Z80; the
use some of the graphics drawing routines, for example.) other, at 65504-65519/$FFE0-$FFEF, is a Z80 machine lan-
Although it is possible to set up a custom MMU configu- guage routine to surrender control to the 8502. These routines
ration that makes block 1 RAM visible with either BASIC or have no use in 128 mode—they can be used only in CP/M
Kernal ROM (or both), there's rarely a need for such gyrations. mode—but they are recopied to block 0 during each reset.
It's usually easiest to locate your executable machine language {Actually, there is one situation where disturbing these routines
in block 0 and use block 1 for data storage. can cause a problem. If you overwrite the routine at 65488/
Several obscure techniques are available to squeeze a few $FFD0 and then attempt to start CP/M with a BASIC BOOT
more bytes out of the 128. For example, you can gain access to command, the system will crash. The machine language in the
the lowest IK of block 1 RAM, which is normally covered by CP/M boot sector expects that routine to be intact.)
the common area from block 0, by changing the value in the
MMU RAM configuration register (54534/$D506). See the dis- Locations 65525-65529/$KFF5-$FFF9 in block 1 have a
cussion of the MMU in Chapter 8 for details. special use. The first three bytes, locations 65525-65527/
$FFF5-$FFF7, are an initialization signature; after the Kernal
Page 255/$FF RESET routine [$E000] has been performed at least once, these
The highest page of memory, locations 65280-65535/ locations will contain the character codes for the letters CBM.
$FFO0-$FFFF, in each RAM block is normally unused by
BASIC and contains a few bytes of free RAM as well as some

190 191
As long as the signature locations contain these codes, the ini- least the IOINIT and CINT routines, and it should also disable
tialization test subroutine will take an indirect jump to the ad- RUN/STOP-RESTORE by redirecting the NMI vector. Here is
dress specified in locations 65528-65529/$FFF8-$FFF9, called a short example:
the system vector or soft reset vector. This vector normally
points to 57892/$E224 in Kernal ROM, a routine that does ocoo LDA #$F8 ;Use Kernal INDSTA routine to
0C02 STA $C3 change system reset vector
nothing more than reinitialize the signature and vector. You 0C04 LDA #$FF ; in bank 1 to point to the
can change the vector to point to a routine of your own to add OC06 STA $C4 ; routine at $0C28
additional steps to the reset sequence or to initiate an entirely 0C08 LDA #$C3
new reset sequence. One restriction applies: The routine you OCOA STA $02B9
specify in the vector must be visible in the bank 15 configura- OCOD LDA #$28
tion since that is how the system is set up when the jump OCOF LDX #$01
through the vector is taken. 0C11 LDY #$00
When tapping into the RESET routine, you need to be 0C13 JSR $FF77
aware of what has happened before the vector jump is taken 0C16 LDA #$0C
and what hasn't happened yet. Before entering the subroutine 0C18 LDX #$01
that takes the jump through the vector, the RESET routine 0C1A INY
0C1B JSR $FF77
[$E000] resets the stack pointer to the top of the stack, config- 0C1E LDA #$33 ;Change the INMI indirect vector
ures the system for bank 15, resets the other MMU registers to 0C20 STA $0318 ; to point to the interrupt return
their default values, and recopies the common routines to 0C23 LDA #$FF ; routine (disables RUN/STOP-
65285-65348/$FF05-$FF44, 674-763/$02A2-$02FB, and 0C25 STA $0319 ; RESTORE)
1008-1020/$03F0-$03FC. However, the initialization routines OC28 JSR $FF84 ;Kernal IOINIT routine
IOINIT, RAMTAS, RESTOR, and CINT are normally called 0C2B JSR $cooo ;Kernal CINT routine
after the return from the jump. This means that you can't use 0C2E LDX #$00 ;Loop to print message repeatedly
the vector diversion to change default indirect vector settings 0C30 LDA $0C40,X ; text at $0C40
or to alter screen parameters if your routine ends with RTS to 0C33 BEQ $0C2E
return to the normal reset sequence. It also means that when 0C35 JSR $FFD2
you use the vector to substitute your own reset sequence, you 0C38 INX
may need to call one or more of these subroutines to complete 0C39 BNE $0C30
system initialization. At least the IOINIT routine [$E109] or ;Text for message
some equivalent initialization routine is necessary, since the >0C40 49 20 43 41 4E 27 54 20
>0C48 42 45 20 53 54 4F 50 50
reset signal generated by pressing the RESET button also re- >0C50 45 44 21 0D0DO0
sets the VIC and VDC (8563) video chips, clearing all chip
registers to zero. IOINIT initializes the video chip registers to Use J F0C00 {from the monitor) or BANK 15:SYS 3072
their standard settings. (from BASIC) to set the new pointer values and start the rou-
tine. Once started, it cannot be stopped with either reset or
One interesting use of this vector is to make a machine RUN/STOP-RESTORE. Obviously, you should make sure
language program unstoppable by anything short of turning that your ML program is fully debugged—and be sure that
off the computer. To accomplish this, change the vector to you have a backup copy, just in case it isn't—before you use
point to the initialization routine of the program to be made this technique to make the program unstoppable.
unstoppable. That initialization step should include calls to at The highest six addresses in each RAM block, locations
65530-65535/$FFFA-$FFFF, contain copies of the processor

192 193
reset and interrupt vectors. This area is initialized during the
reset sequence, and, like the handling routines to which these
vectors point, these vector addresses should be changed with
care. The system will crash if a RAM vector does not contain
the address of a valid handling routine when an interrupt or
reset occurs while that block is visible. See the entries for
these addresses in Chapter 9 for more information on the pro-
cessor vectors.

194
BASIC ROM
The Commodore 128's BASIC 7.0 occupies the 28K of ROM
between 16384-45055/$4000-$AFFF. That represents signifi-
cant growth from the BASIC 2.0 of the Commodore 64, which
filled only about 9K. The expansion is the result of the addi-
tion of a variety of graphics, sound, and sprite statements, as
well as enhanced commands for disk operations. Because
BASIC is so large, it's not practical to provide a detailed de-
scription of every routine—that would fill another book. In-
stead, the entry points to most of BASIC'S important routines
are listed, with short explanations of what the target routines do.

Adding to BASIC
Even with all the added features of BASIC 7.0, you may find
it lacking and wish to modify BASIC to add new commands.
One common way to do this in the Commodore 64 is to copy
BASIC ROM into RAM, then modify and use the RAM-based
version. This scheme can't be used on the 128, even though it
does have RAM under BASIC ROM like the 64. While it's pos-
sible to copy BASIC into ROM, there's no easy way to keep a
RAM-based version of BASIC executing in RAM. The bank-
switching routines in 128 BASIC ROM keep the system con-
figured for banks 14 or 15, where BASIC ROM is visible,
while BASIC routines are being executed.
The formal method of adding new statements or functions
is to tap into the indirect vectors at 780-785/$030C-$0311
and 764-765/$02FC-$02FD. This allows you to add new
statements or functions that use the two-byte extended tokens.
Currently, extended statement tokens 39-255/$27-$FF and
extended function tokens ll-255/$0B-$FF are unused and
thus available for your additional keywords.
Three separate steps are required to add a new keyword.
You must provide for it to be tokenized, detokenized (listed),
and executed. The indirect vector at 780-781/$030C-$030D
lets you patch into the CRUNCH routine to tokenize your new
extended token keywords. The vector at 782-783/
$030E-$030F lets you patch into the IQPLOP routine to
detokenize these new keywords when a line containing a new
197
keyword is listed. The other two vectors allow you to patch 1647 CLC
into the statement and function execution routines to provide 1648 BCC $164D ;Exit with carry clear if keyword found
for the handling of the new keywords (784-785/$0310-$0311 164A SEC
164B LDA $02 ;Restore text character
for statements and 764-765/$02FC-$02FD for functions). The 164D JMP $4321 .Return to ICRNCH routine
following example shows the addition of a statement and a >1650 53 54 4F 52 C5 00 ;STORE
function. The statement, STORE, can be used to store values >1656 52 41 C4 00 ;RAD
in the VDC chip internal registers (see Chapter 8 for details of ;List (detokenize) new keywords
the VDC chip). The format of the statement is STORE register, 165A CPX #$00 ;Was this statement or token?
165C BNE S166C
value. The register parameter is the VDC register number 165E CMP #$28 ;Was statement token less than 40?
(0-36) and the value parameter is the value (0-255) to be 1660 BCS $1678
stored in that register. The function, RAD, converts an angle 1662 LDY #$50 ;Use table entry at $1650 to list
value from degrees to radians, the system used in BASIC func- 1664 LDA #$16
tions. The format for the function is KAD(angle), where angle 1666 STY $24
1668 STA $25
is the angle value in degrees. Since this is a function, it must 166A BCC $1678
be used on the right side of an operation, as in A = RAD(45). 166C CMP #$0C ;Was function token less than 12?
;Redirect ICRNCH2 vector to $1629 to 166E BCS $1678
1600 LDA #$29
1602 STA $030C ; tokenize new keywords 1670 LDY #$56 ;Use table entry at $1656 to list
1605 LDA #$16 1672 LDA #$16
1607 STA $030D 1674 STY $24
160A LDA #$5A ;Redirect IQPLOP2 vector to $165A to 1676 STA $25
160C STA S030E ; list new keywords 1678 JMP S51CD ;Return to IQPLOP routine
160F LDA #$16 ; Handle execution of statement
1611 STA $030F 167B CMP #$28 ;Was statement token less than 40?
1614 LDA #$7B ;Redirect IGONE2 vector to $167B to 167D BCS $1685
1616 STA $0310 ; handle new statement 167F LDA #$16 ;Put address of execution routine - 1 on stack
1619 LDA #$16 1681 PHA ; (execution routine is at $1866)
161C STA $0311 1682 LDA #$87
161E LDA #$A2 ;Redirect ESC_FN vector to $16A2 to 1684 PHA
1620 STA $02FC ; handle new (unction 1685 JMP $4BA9
1623 LDA #$16 ; STORE routine
1625 STA $02FD 1688 JSR $8803 ;Evaluate register number and value parameters
1628 RTS 168B TXA ;Move value lo accumulator
;Tokenize new keywords 168C LDY $17 ;High byte of register number should be zero
1629 STA $02 .Stash current character 168E BNE $169D
162B LDY #$50 ;Search for keyword in table at $1650 1690 LDX $16 ;Low byte (in X) should be less than 37
162D LDA #$16 1692 CPX #$25
1694 BCS $169D
162F JSR 543E2
1632 BCC $163A ;If no match found, try other table 1696 STY $FF00 ;Set for bank 15 so VDC chip is visible
1634 ADC #$A6 ;Convert index (with bit 7 set) to token (39/$27) 1699 JSR $CDCC;Use screen editor routine
1636 LDX #$00 ;Set flag for extended statement token 169C RTS
1638 BEQ $1647 169D LDX #$0E ;Illegal quantity error if incorrect value supplied
.Search for keyword in table at $1656 169F JMP ($0300)
163A LDY #$56
163C LDA #$16 ;RAD routine
163E JSR $43E2 16A2 CMP #$0C ;Was token less than 12?
1641 BCC $164A ;Exit if no match found 16A4 BCS $16B4
1643 ADC #$8A .Convert index (with bit 7 set) to token (11/$OB) 16A6 JSR $7956 ;Check that parameter ended with a closing
1645 LDX #$FF ;Set flag for extended function token parenthesis
16A9 LDA #$B5 ;Load value from $16B5 into FAC2
198 199
$4006 16390

16AB LDY #$16 1334 LDX $16 (target register number in X)


16AD JSR SAF5D 1336 CPX #$25
16B0 JSR $AF21 ^Multiply by argument in FAC1 1338 BCC $133E
16B3 CLC 133A LDX #$0E ;If register number is too large,
16B4 RTS 133C BNE $1326 ; exit with ILLEGAL QUANTITY error
>16B5 7B OE FA 35 12 ;Floating point value for TT/180 133E STY $FFO0 ;Configure for bank 15 (Y contains $00)
1341 JSR $CDCC;Use screen editor register setup routine
An alternate method of adding new statements to BASIC 1344 JMP $AF90 ;Continue processing program text
involves creating intentional errors. To use this scheme, your
new keyword must consist of an existing keyword preceded The BASIC Jump Table
by a letter (or another keyword)—LLIST or COPYCHAR, for One new feature of BASIC 7.0 that will be very valuable to
example. A syntax error will occur when the new keyword is machine language programmers is the jump table at
encountered, but you can use the IERROR indirect vector 44800-44967/$AFOO-$AEA7. Many of the most useful BASIC
(768-769/$0300-$0301) to trap the error and process the key- routines now have static entry points like those the Kernal
word. The advantage of this technique is that you don't have jump table provides for Kernal routines. Wherever possible,
to worry about tokenizing or detokenizing the new keyword. you should use the jump table entry into the routine to main-
The following example program illustrates the technique. It tain compatibility in the event that BASIC ROM is revised.
supports a new statement, VPOKE, which performs like the
STORE statement in the example above. Use VPOKE register, BASIC Entry Vectors
value to store a value in a VDC chip register. After a SYS 4864
to patch in this routine, VPOKE can be used in either program 16384 $4000 JHARD-RESET
or immediate mode, just like any other keyword.
;Redirect IERROR vector to $130B BASIC cold-start entry point; jumps to 16419/$4023, the ad-
1300 LDA #$0B
1302 STA $0300 dress of the routine which performs a complete initialization
1305 LDA #$13 of BASIC. This is the normal entry point following a system
1307 STA $0301 reset.
130A RTS
130B CPX #$0B ;Was this a SYNTAX error? 16387 $4003 JSOFT_RESET
130D BNE $1326
130F CMP #$97 ;If §o, did it occur at a POKE token? BASIC warm-start entry point; jumps to 16393/$4009, the ad-
1311 BNE $1326 dress of the routine which reinitializes BASIC and Kernal vec-
1313 LDA $3D ;Calculate pointer to character tors and screen editor vectors and variables. This is the normal
1315 SBC #$01 ; immediately before the POKE token
1317 STA $26 ; (If the keyword uses a two-byte
entry point during a RUN/STOP-RE STORE NMI interrupt.
1319 LDA $3E ; extended token, you must back up
131B SBC #$00 ; two positions instead of one.)
131D STA $27
16390 $4006 JBASIC-IR9
131F JSR $03C0 ;Retrieve character before token BASIC IRQ entry point; jumps to 43085/$A84D, the address
1322 CMP #$56 ;Was it a V? of the routine which handles the BASIC portion of the system
1324 BEQ $1329 ;If so, branch to handle VPOKE IRQ interrupt sequence. The target routine supports sprite
1326 JMP $4D3F ;Process all other errors normally
1329 JSR $0380 ;Move CHRGET pointer beyond token
movement, sprite collision detection, light pen reading, and
132C JSR $8803 .Evaluate parameters following VPOKE the BASIC music statements. This is the normal entry point
132F TXA ;Move value parameter to accumulator during the system IRQ service routine.
1330 LDY $17 ;Check that register parameter is
1322 BNE $133A ; less than 37

200 201
16393 $4009 $43B0 17328

16393 $4009 SOFT-RESET 16795 $419B


Performs a warm start of BASIC Displays the power-on message
This routine is the normal final step of the RUN/STOP- This routine displays the text from the following area of ROM,
RESTORE sequence. It resets the SID registers and sound loca- Note that the free memory figure is part of the ROM message,
tions, and calls the routine at 16781/$418D to stop sprite and may not reflect the actual amount of memory available to
movement. However, it does not reinitialize the BASIC vectors BASIC.
or pointers.
16827 $4IBB
16416 $4020 Unused Text for power-on message
Three unused bytes filled with the value 255/$FR {CLR}
COMMODORE BASIC V7.0 122365 BYTES FREE
16419 $4023 HARD_RESET (O1985 COMMODORE ELECTRONICS, LTD.
Performs a cold start of BASIC (O1977 MICROSOFT CORP.
This routine is the normal final step of the reset sequence. It ALL RIGHTS RESERVED
performs a complete initialization of BASIC, including reset-
ting all vectors, pointers, and working storage locations to 16977 $4251
their default values. This routine also includes a call to the Initializes BASIC indirect vectors
Kernal PHOENIX routine [$FF56], which will start any func- This routine copies the BASIC indirect vectors from the fol-
tion ROMs that may be present, or boot a disk if one is in the lowing table to locations 768-785/$0300-$0311, and initial-
drive, izes the vector at 764-765/$02FC-$02FD.
16453 $4045 16999 $4267
Initializes BASIC painters and constants Table of default vector values
This is the main initalization routine of the cold-start se- This area contains the default addresses copied into the page 3
quence. It is responsible for setting all RAM working storage indirect vectors by the routine at 16977/$4251.
locations for BASIC to their default values.
17017 $4279
16658 $4112 Text for character retrieval routines
Initializes SID registers and sound routine locations This area contains the code for CHRGET and the other page 3
This routine sets all SID chip registers to 0/$00 and initializes character retrieval subroutines. The routines are copied into
all locations associated with the SOUND and PLAY RAM.
statements.
17102 $42CE
16762 $417A Assorted character retrieval subroutines
Initializes MMU preconfiguration registers
17162 $430 A CRUNCH
16781 $418D Tokenizes keywords in lines of BASIC program text
Initializes sprite speed and direction table
This routine copies a 0/$00 into the speed control byte for 17328 S43B0
each entry in the sprite movement table at 4478/$117E, effec-
tively halting all sprite motion. Handles extended tokens

202 203
17356 $43CC $4609 17929

17356 $43CC Token Keyword Token Keyword


Deletes a character in the input buffer 192/$C0 TAN 224/$E0 CHAR
193/$C1 ATN 225/$E1 BOX
17378 $43E2 194/$C2 PEEK 226/$E2 CIRCLE
195/$C3 LEN 227/$E3 GSHAPE
Searches keyword tables for match
196/$C4 STR$ 228/$E4 SSHAPE
197/$C5 VAL 229/$E5 DRAW
17431 $4417 198/$C6 ASC 230/$E6 LOCATE
BASIC keyword tables 199/$C7 CHR$ 231/$E7 COLOR
The following table holds the BASIC 7.0 keywords in token 200/$C8 LEFT$ 232/$E8 SCNCLR
number order. Bit 7 of the last character of each keyword will 201/$C9 RIGHT$ 233/$E9 SCALE
be set to %1 to indicate the end of the keyword. 202/$CA MID$ 234/$EA HELP
203/$CB GO 235/$EB DO
Token Keyword Token Keyword 204/$CC RGR 236/$EC LOOP
128/S80 END 160/$A0 CLOSE 205/$CD RCLK 237/$ED EXIT
129/S81 FOR 161/$A1 GET 206/$CE function token extender 238/$EE DIRECTORY
130/$82 NEXT 162/$A2 NEW 207/$CF JOY 239/$EF DSAVE
131/$83 DATA 163/$ A3 TAB( 208/$D0 RDOT 240/$F0 DLOAD
132/$84 INPUT# 164/$A4 TO 2O9/$D1 DEC 241/$F1 HEADER
133/$85 INPUT 165/$A5 FN 210/SD2 HEX$ 242/$F2 SCRATCH
134/$86 DIM 166/$A6 SPC( 211/$D3 ERR$ 243/$F3 COLLECT
135/$87 READ 167/SA7 THEN 212/$D4 INSTR 244/$F4 COPY
136/$88 LET 168/SA8 NOT 213/$D5 ELSE 245/$F5 RENAME
137/S89 GOTO 169/SA9 STEP 214/$D6 RESUME 246/$F6 BACKUP
138/$8A RUN 170/$AA 215/$D7 TRAP 247/$F7 DELETE
+ 216/$D8 TRON RENUMBER
139/S8B IF 171/$AB - 248/$F8
RESTORE 172/$ AC 217/$D9 TROFF 249/$F9 KEY
140/S8C *
141/$8D GOSUB 173/$AD 218/$DA SOUND 250/$FA MONITOR
/ 219/$DB VOL USING
142/$8E RETURN 174/JAE t 251/$FB
REM 175/$AF AND 220/SDC AUTO 252/$FC UNTIL
143/$8F 221/$DD PUDEF WHILE
144/$90 STOP 176/$B0 OR 253/$FD
ON 177/SB1 > 222/SDE GRAPHIC 254/$FE statement token extender
145/$91 223/$DF PAINT
146/$92 WAIT 178/$B2 —
147/$93 LOAD 179/$B3 <
148/$94 SAVE 180/$B4 SGN
149/$95 VERIFY 181/$B5 INT
150/$96 DEF 182/$B6 ABS 17929 $4609
151/$97 POKE 183/$B7 USR Table of extended token statements
152/$98 PRINT# 184/$B8 FRE BASIC 7,0 has too many keywords to have a one-byte token
153/$99 PRINT 185/SB9 POS for each. Additional statements use a two-byte token where
154/$9A CONT 186/$8A SQR the first byte is always 254/$FE. This table holds the extended
155/$9B LIST 187/$BB RND token statement keywords in order of the second byte of the
156/S9C CLR 188/SBC LOG token, like the standard keywords, bit 7 of the last character
157/$9D CMD 189/$BD EXP
of each keyword will be set to % 1 .
158/S9E SYS 190/$BE COS
159/S9F OPEN 191/$BF SIN
204 205
18121 $46C9 $4828 18472

Token Keyword Token Keyword


handled, the values here are actually one less than the address
2/$02 BANK 21/$15 DCLEAR of the target routine. See Appendix F for a list of keyword exe-
3/$O3 FILTER 22/$16 SPRSAV cution addresses.
4/$04 PLAY 23/$17 COLLISION
5/$05 TEMPO 24/$18 BEGIN
6/$06 MOVSPR 25/$19 BEND 18242 $4742
7/$07 SPRITE 26/$lA WINDOW Table of statement dispatch addresses
8/$08 SPRCOLOR 27/S1B BOOT This area holds the address of the routines to execute tokens
9/$09 RREG 28/$lC WIDTH 213-250/$D5-$FA. Because of the way statement execution is
10/SOA ENVELOPE 29/$lD SPRDEF handled, the values here are actually one less than the address
11/$OB SLEEP 3O/$1E QUIT of the target routine. See Appendix F for a list of keyword exe-
12/$0C CATALOG 31/$1F STASH cution addresses.
13/$0D DOPEN 32/$20 (no keyword for this token)
14/$0E APPEND 33/$21 FETCH
15/SOF DCLOSE 34/$22 {no keyword for this token) 18172 $46FC
16/$10 BSAVE 35/$23 SWAP Table of statement dispatch addresses
17/S11 BLOAD 36/$24 OFF This area holds the address of the routines to execute ex-
18/$12 RECORD 37/$25 FAST tended statement tokens 2-38/$02-$26. Because of the way
19/$13 CON CAT 38/$26 SLOW statement execution is handled, the values here are actually
20/$14 DVERIFY one less than the address of the target routine. See Appendix
F for a list of keyword execution addresses.
18121 $46C9
Table of extended token functions 18317 $478D
BASIC 7.0 has too many keywords to have a one-byte token Table of function dispatch addresses
for each. Additional functions use a two-byte token where the This area holds the address of the routines to execute tokens
first byte is always 206/$CE. This table holds the extended 180-211/$B4-$D3. See Appendix F for a list of keyword exe-
token function keywords in order of the second byte of the cution addresses.
token. Like the standard keywords, bit 7 of the last character
of each entry is set to % 1 . 18454 $4816
Token Keyword Table of function dispatch addresses
2/$02 POT This area holds the address of the routines to execute ex-
3/$03 BUMP tended function tokens 2-10/$02-$0A. See Appendix F for a
4/$04 PEN list of keyword execution addresses.
5/$05 RSPPOS
6/$06 RSPRITE
7/$07 RSPCOLOR 18472 $4828
8/$08 XOR Table of operator priorities and dispatch addresses
9/$09 RWINDOW Each mathematical operator such as + , — , * , and / has a
10/$0A POINTER three-byte entry in this table. The first byte is the priority of
the operator for expression evaluation and the next two are
18172 $46FC the address of the routine to perform the specified operation.
Table of statement dispatch addresses
This area holds the address of the routines to execute tokens
128-162/$80-$A2. Because of the way statement execution is
206 207
18502 $4846 $4C83 19587

18502 $4846 Error number Error message


Prints unimplemented command message 32/$20 LOOP NOT FOUND
BASIC 7.0 contains two unused keywords, QUIT and OFF. 33/$21 LOOP WITHOUT DO
Either of those will use this routine to print the UNIMPLE- 34/$22 DIRECT MODE ONLY
MENTED COMMAND error message. 35/$23 NO GRAPHICS AREA
36/$24 BAD DISK
37/$25 BEND NOT FOUND
18507 $484B 38/$26 LINE NUMBER TOO LARGE
Table of BASIC error messages 39/$27 UNRESOLVED REFERENCE
This area holds text for the BASIC error messages in error 40/$28 UNIMPLEMENTED COMMAND
number order. Bit 7 in the last character of each message will 41/$29 FILE READ
be set to %1 to mark the end of the message.
19074 S4A82
Error number Error message Sets pointer to error message
1/S01 TOO MANY FILES
2/$02 FILE OPEN Sets locations 38-39/$26-$27 to point to the error number
3/$03 RLE NOT OPEN specified in the accmulator upon entry.
4/$04 FILE NOT FOUND
5/$05 DEVICE NOT PRESENT 19103 $4A9F GONE
6/$06 NOT INPUT RLE Main BASIC statement execution routine
7/$07 NOT OUTPUT FILE This routine handles COLLISION processing, then falls
8/$08 MISSING FILE NAME through into the next routine to execute the current BASIC
9/$09 ILLEGAL DEVICE NUMBER
statement.
10/$0A NEXT WITHOUT FOR
11/$OB SYNTAX
12/$0C RETURN WITHOUT GOSUB 19190 $4AF6 NEWSTT
13/$0D OUT OF DATA Executes the next BASIC statement
14/$0E ILLEGAL QUANTITY
15/$0F OVERFLOW 19381 $4BB5
16/flO OUT OF MEMORY Tests for RUN/STOP keypress
17/S11 UNDEF'D STATEMENT This routine tests whether the RUN/STOP key is being
18/$12 BAD SUBSCRIPT pressed. If so, a branch will be taken into the following
19/$13 REDIM'D ARRAY routine.
20/$14 DIVISION BY ZERO
21/$15 ILLEGAL DIRECT
22/$16 TYPE MISMATCH 19403 $4BCB STOP/END
23/$17 STRING TOO LONG Handles the STOP and END statements
24/$18 FILE DATA
25/$19 FORMULA TOO COMPLEX 19447 $4BF7
26/$lA CANT CONTINUE Handles the execution of function keywords
27/$lB UNDEF'D FUNCTION
28/$lC VERIFY 19587 S4C83
29/$lD LOAD Displays the SYNTAX ERROR message
30/$ IE BREAK
31/$1F CANT RESUME

208 209
19590 $4C86 $528F 21135

19590 $4C86 OR 20478 $4FFE


Handles the OR logical operator Decrements the runtime stack pointer
19593 $4C89 AND 20503 $5017
Handles the AND logical operator Checks foT available string space
This routine tests whether there is sufficient space in the string
19638 $4CB6 pool before a string is added. If no space is available, garbage
Handles relational operators (<, =, >) collection is attempted.

19754 $4D2A 20569 $5059


Prints the READY prompt Increments runtime stack pointer
19767 $4D37 READY 20580 $5064 FNDLIN
Enters MAIN with a READY prompt Searches program text for a specified line number
This routine is the normal path back to immediate mode after
a program or previous immediate mode line has been exe- 20640 $50AO LINGET
cuted. It prints the READY prompt and falls through into the Creates integer value from a character string
MAIN routine. This routine converts a string of characters at the current
text pointer address into a two-byte integer value in locations
19770 $4D3A 22-23/$16-$17.
Displays an OUT OF MEMORY error message
20706 $50E2 LIST
19772 $4D3C ERROR Handles the LIST statement
Handles BASIC errors
20771 $5123
19836 $4D7C Lists a single BASIC program line
Prints a specified error message
20950 $51D6 NEW
19895 $4DB7 MAIN Handles the NEW statement
Handles immediate mode and program line entry
20984 S51F8 CLR
19938 $4DE2 Handles the CLR statement
Adds or deletes BASIC program lines
21076 $5254
20303 $4F4F LNKPRG Resets the CHRGET text pointer
Relinks BASIC program lines This routine resets the CHRGET text pointer, locations 61-62/
$3D-$3E, to the beginning of the BASIC text area.
20371 $4F93
Reads a line of input into the buffer 21090 $5262 RETURN
20394 $4FAA Handles the RETURN statement
Searches for a particular token in the runtime stack 21135 $528F BEND/DATA
Handles the BEND and DATA statements
211
210
21149 $529D $5A3D 23101

21149 $529D REM 22516 $57F4 NEXT


Handles the REM statement Handles the NEXT statement

21189 $52C5 IF 22648 $5878 DIM


Handles the IF statement Handles the DIM statement

21280 $5320 22661 $5885 SYS


Skips a BEGIN-BEND block Handles the SYS statement

21393 $5391 ELSE 22708 $58B4 TRON/TROFF


Handles the ELSE statement Handles the TRON and TROFF statements

21411 $53A3 ON 22717 S58BD RREG


Handles the ON statement Handles the RREC statement

21446 $53C6 LET 22785 $5901 MID$


Handles variable value assignments Handles MID$ when used as a statement
This routine evaluates the expression on the right of a rela- 22901 $5975
tional operator and assigns the resulting value to the variable AUTO
Handles the AUTO statement
on the left.
21818 $553A PRINT* 22918 $5986 HELP
Handles the HELP statement
Handles the PRINT* statement
22956 $59AC
21824 $5540 CMD Highlights the portion of a listed line containing an error
Handles the CMD statement
22991 $59CF GOSUB
21844 $5554 PRINT Handles the GOSUB statement
Handles the PRINT statement
23003 $59DB GOTO
22034 $5612 GET Handles the GOTO statement
Handles the GET statement (also GET# and GETKEY)
23069 $5A1D
22088 $5648 INPUT* Places RETURN parameters in the runtime stack
Handles the INPUT* statement
23101 $5A3D GO
22114 $5662 INPUT Handles the GO statement
Handles the INPUT statement
Begins by testing whether the GO token is followed by the
22185 $56A9 token for TO, indicating that GOTO was entered as GO TO.
READ The acceptance of GO TO as a synonym for GOTO is unique
Handles the READ statement to Commodore.
22474 $57CA
Moves the CHRGET text pointer to the next DATA statement
212 213
23136 S5A60 $6A4C
27212

23136 $SA60 CONT 24842 $610 A KEY


Handles the CONT statement Handles the KEY statement
23169 $5A31 24989 $619D
Sets flags for running a program Table of characters for KEY
23195 S5A9B RUN 25000 $61A8
Handles the RUN statement PAINT
Handles the PAINT statement
23242 $5ACA RESTORE 25271 $62B7 BOX
Handles the RESTORE statement Handles the BOX statement
23280 S5AF0 25643 $642B SSHAPE
Table of tokens for RENUMBER Handles the SSHAPE statement
23288 S5AF8 RENUMBER 25997 $658D GSHAPE
Handles the RENUMBER statement Handles the GSHAPE statement
24057 $5DF9 FOR 26254 $668E CIRCLE
Handles the FOR statement Handles the CIRCLE statement
24199 $5E87 DELETE 26448 $6750 CIRSUB
Handles the DELETE statement Bitmapped graphics circle-drawing subroutine
24372 $5F34 PUDEF 26519 $6797 DRAW
Handles the PUDEF statement Handles the DRAW statement
24397 $5F4D TRAP 26583 $67D7 CHAR
Handles the TRAP statement Handles the CHAR statement
24418 $5F62 RESUME 26965 $6955 LOCATE
Handles the RESUME statement Handles the LOCATE statement
24544 $5FE0 DO 26976 $6960 SCALE
Handles the DO statement Handles the SCALE statement
24633 $6039 EXIT 27096 $69DS
Handles the EXIT statement Table of scaling factors
24714 $608A LOOP 27106 $69E2
Handles the LOOP statement
COLOR
Handles the COLOR statement
24801 $6OE1 27212 $6A4C
Assigns a definition string to a programmable key Table for translating VIC color values to VDC color values
214
215
27228 $6A5C
$77D7

27228 S6A5C
Calculates color fill values 29028 $7164 COLLISION
Handles the COLLISION statement
27257 $6A79 SCNCLR This routine sets up the conditions for COLLISION checking.
Handles the SCNCLR statement The actual testing for collisions occurs during the BASIC IRQ
routine [$A84D].
27482 $6B5A GRAPHIC
Handles the GRAPHIC statement 29072 $7190 SPRCOLOR
Handles the SPRCOLOR statement
27593 $6BC9 BANK
Handles the BANK statement 29110 $71B6 WIDTH
Handles the WIDTH statement
27607 $6BD7 SLEEP
Handles the SLEEP statement 29125 $71C5 VOL
Handles the VOL statement
27693 $6C2D WAIT
Handles the WAIT statement 29164 $71EC SOUND
Handles the SOUND statement
27727 $6C4F SPRITE
Handles the SPRITE statement 29388 $72CC WINDOW
Handles the WINDOW statement
27846 $6CC6 MOVSPR
Handles the MOVSPR statement 29493 $7335 BOOT
Handles the BOOT statement
28129 $6DE1 PLAY If a filename is provided, the routine does the equivalent of
Handles the PLAY statement BLOAD followed by SYS, rather than actually attempting to
This routine has many suboutines to handle parsing and exe- boot a disk.
cution of the strings of music data. PLAY is actually a mini-
language within BASIC. 29554 $7372 SPRDEF
Handles the SPRDEF statement
28631 $6FD7 TEMPO
Handles the TEMPO statement ^ P ^ V 6 3 1 1 7 a : ! t a t e m e n t ; j t ' s a b ^ - i n machine lan-
guage sprite-design utility program.
28644 S6FE4
30444 $76EC SPRSAV
Data tables for PLAY string processing
Handles the SFRSAV statement
28689 $7011
30643 $77B3 FAST
Default values for ENVELOPE instrument tables
Handles the FAST statement
28742 $7046 FILTER
30660 $77C4 SLOW
Handles the FILTER statement
Handles the SLOW statement
28865 $7OC1 ENVELOPE
Handles the ENVELOPE statement
30679 $77D7
Evaluates an expression with a test for type mismatch
216
217
30703 $77EF $837C 33660

30703 $77EF FRMEVL 32842 $804A VAL


Evaluates an expression Handles the VAL function
30935 $78D7 EVAL 32886 $8076 DEC
Evaluates a single term of a numeric expression Handles the DEC function
31084 $796C 32965 $80C5 PEEK
Displays a SYNTAX ERROR message Handles the PEEK function
31096 $7978 32997 $80E5 POKE
Evaluates a variable value Handles the POKE statement
This routine is also responsible for processing all the BASIC
reserved variables: TI, TI$, ST, DS, DS$, ER, and EL. 33014 $80F6 ERR$
Handles the ERR$ function
31407 $7AAF
Finds or creates a variable 33090 $8142 HEX$
This routine searches the variable table in bank 1 for a speci- Handles the HEX$ function
fied variable, and creates the variable if it does not already 33154
exist.
$8182 RGR
Handles the RGR function
31632 $7B90 33179 $819B
Creates an entry in the variable table for a new scalar variable RCLR
Handles the RCLR function
31846 $7C66 33283 $8203
Moves arrays upward in bank 1 to make room for a new scalar JOY
Handles the JOY function
variable
31915 $7CAB 33357 $824D POT
Handles the POT function
Finds or creates an array variable
32386-32767 $7E82-$7FFF 33454 $82AE PEN
Handles the PEN function
This unused area of BASIC ROM is filled with the value
255/$FE 33530 $82FA POINTER
Handles the POINTER function
32768 $8000 FRE
Handles the FRE function 33566 $83 IE RSPRITE
Handles the RSPRITE function
32800 $8020
Prints designers' message 33633 $8361 RSPCOLOR
When you use the statement SYS 32800,123,45,6, you'll get a Handles the RSPCOLOR function
rather political message from the designers of the 128. 33660 $837C BUMP
Handles the BUMP function
218 219
33687 $8397 $880F 34831

33687 $8397 RSPPOS 34408 $8668 LEN


Handles the RSPFOS function Handles the LEN function
33761 $83E1 XOR 34423 $8677 ASC
Handles the XOR function Handles the ASC function
33799 $8407 RWINDOW 34437 $8685
Handles the RWINDOW function Displays the ILLEGAL QUANTITY error message
33844 $8434 RND 34440 $8688
Handles the RND function Creates space for a string in the string pool
33936 $8490 34458 $869A
Table of floating-point constants for RND calculation Stores a string in the string pool
34000 $84D0 POS 34573 $870D
Handles the POS function Performs string concatenation
34009 $84D9 34683 $877B
Checks that BASIC is in run mode Evaluates a string parameter
This routine returns with locations 36-37/$24-25 set to point
34032 $84F0 to the string and the Y register holding the length of the
Checks that BASIC is in immediate mode string.
34042 $84FA DEF 34801 $87F1
Handles the DEF statement Evaluates a numeric expression
34107 S853B FN This routine evaluates a numeric parameter and checks that it
is in the range 0-255/$00-$FF. If the parameter is valid, it
Handles user-defined functions using FN will be returned in the X register.
34222 $85AE STR$
Handles the STR$ function 34819 $8803
Evaluates parameters for POKE or WAIT
34239 $85BF CHR$ This routine retrieves a pair of parameters: The first, a value in
Handles the CHR$ function the range 0-65535/$0000-$FFFF, will be returned in locations
22-23/$16-$17, and the second, a value in the range 0-255/
34262 $85D6 LEFT$ $OO-$FF, will be returned in the X register.
Handles the LEFT$ function
34831 S880F
34314 $860A RIGHT$ Checks that the next character is a comma
Handles the RIGHTS function
34332 $861C MIDS
Handles the MID$ function
220 221
.
$8815 $8B49 35657
34837

34837 $8815 35274 S89CA LOG


Handles the LOG function
Evaluates a numeric parameter
This routine retrieves a numeric parameter, checking that it is 35342 $8A0E
in the range 0-65535/$0000-$FFFF. If the value is valid, it Adds 0.5 to FAC1
will be returned in locations 22-23/$16-$17.
35364 $8A24
34862 SS82E Multiplies value in memory by FAC1
Subtracts value in memory from FAC1 Loads FAC2 with the five-byte floating-point value pointed to
Loads FAC2 with the five-byte floating-point value pointed to by the accumulator and Y register (low byte/high byte), then
by the accumulator and Y register (low byte/high byte), then multiplies the value in FAC2 by the one in FAC1, leaving the
subtracts the value in FAC2 from the one in FAC1, leaving the results in FAC1.
results in FAC1.
35367 $8A27
34865 $8831 Multiplies value in memory by FAC1
Subtracts FAC1 from FAC2 Loads FAC2 with the five-byte floating-point value pointed to
Subtracts the value in FAC2 from the one in FAC1, leaving by the accumulator and Y register (low byte/high byte), then
the results in FAC1. multiplies the value in FAC2 by the one in FAC1, leaving the
results in FAC1.
34885 $8845
Adds value in memory to FAC1 35465 $8A89
Loads FAC2 with the five-byte floating-point value pointed to Loads FAC2 with value from the current bank
by the accumulator and Y register (low byte/high byte), then Loads FAC2 with the five-byte floating-point value pointed to
adds the value in FAC2 to the one in FAC1, leaving the re- by the accumulator and Y register (low byte/high byte).
sults in FAC1.
35508 $8AB4
34888 $8848 Loads FAC2 with value from bank 1
Adds FAC1 to FAC2 Loads FAC2 with the five-byte floating-point value in bank 1
Adds the value in FAC2 to the one in FAC1, leaving the re- pointed to by the accumulator and Y register (low byte/high
sults in FAC1. byte),

34993 S88B1 35607 $8B17


Normalizes FAC1 Multiplies FAC1 by 10
35110 $8926 35640 $8B38
Forms twos complement of FAC1 Divides FAC1 by 10
35165 $895D 35657 $8B49
Displays OVERFLOW error message Divides value in memory by FAC1
Loads FAC2 with the five-byte floating-point value pointed to
35170 $8962 by the accumulator and Y register (low byte/high byte), then
Performs byte alignment of FAC1 divides the value in FAC2 by the one in FAC1, leaving the re-
sults in FAC1. 223
222
35660 S8B4C $9086 36998

35660 $8B4C 36120 $8D18


Divides FAC2 by FAC1 Fills FAC1 with the value in the accumulator
Divides the value in FAC2 by the one in FAC1, leaving the re-
36130 $8D22
sults in FAC1.
Generates floating-point value representing character string
35796 $8BD4 This routine reads a character string from BASIC program text
Loads FAC1 from memory and generates the equivalent floating-point value in FAC1.
Loads FAC1 with the five-byte floating-point value pointed to
by the accumulator and Y register (low byte/high byte). 36390 $8E26
Prints IN and a line number
35840 $8C00
Copies FAC1 value into memory 36398 $8E2E
Stores the value in FAC1 in five bytes pointed to by the X and Prints a line number
Y registers (low byte/high byte). This routine generates a string based on the value in
59-60/$3B-$3C, then prints the results,
35880 $8C28
Copies FAC2 into FAC1 36418 $8E42
Generates a character string representing the value in FAC1
35896 $8C38 This routine generates a string of characters in the work area
Copies FAC1 into FAC2 at 256/$0100 representing the value in FACL

35911 $8C47 36791 $8PB7 SQR


Rounds FAC1 Handles the SQR function
This routine calculates the square root of the value in FAC1,
35927 $8C57 taking advantage of the fact that SQR(X) = X t 0.5.
Determines the sign of the value in FAC1
35941 $8C65 SGN 36801 $8FC1
Handles the exponentiation (T) operator
Handles the SGN function This routine raises the value in FAC1 to the power specified in
35972 $8C84 ABS FAC2. This routine takes advantage of the fact that At B =
EXP(LOG(A) * B).
Handles the ABS function
35975 $8C87 36869 $9005
Compares FAC1 against FAC2 Table of floating-point constants for EXP evaluation

36039 $8CC7 36915 $9033 EXP


Converts FAC1 to a four-byte integer Handles the EXP function
36091 $8CFB INT 36998 $9086
Handles the INT function Performs series evaluation

224 225
37080 S90D8 $9520 38176

37080 $90D8 37457/$9251 READSS


Calls the Kernal OPEN routine 37463/$9257 SETLFS
37469/$925D SETNAM
37087 $90DF 37475/$9263 BASIN
Calls the Kernal BSOUT routine 37481/$9269 BSOUT
37487/$926F CLRCH
37093 S90E5 37493/$9275 CLOSE
Calls the Kernal BASIN routine 37499/$927B CLALL
37505/$9281 PRIMM
37117 $90FD 37511/19287 SETBANK
Calls the Kernal CHKIN routine 37517/$928D PLOT
37523/$9293 STOP
37129 $9109
Calls the Kernal GETIN routine 37529 $9299
Creates space in the string pool for a temporary string
37138 $9112 SAVE
Handles the SAVE statement 37610 $92EA GARBA2
Performs garbage collection on string pool
37161 $9129 VERIFY
Handles the VERIFY statement 37897 $9409 COS
Handles the COS function
37164 $912C LOAD This routine takes advantage of the fact that COS(X) = SIN (X
Handles the LOAD statement + Ti/2).
37261 $918D OPEN 37904 $9410 SIN
Handles the OPEN statement Handles the SIN function
37274 $919A CLOSE 37977 $9459 TAN
Handles the CLOSE statement Handles the TAN function
This routine takes advantage of the fact that TAN(X) = SIN(X)
37294 $91AE / COS(X).
Evaluates parameters for SAVE, LOAD, and VERIFY
38021 $9485
37366 $91F6 Table of constants for trig function evaluation
Evaluates parameters for OPEN and CLOSE
38067 $94B3 ATN
37433 9243 Handles the ATN function
Clears DS$ after disk operations
38115 $94E3
37457 $9251 Table of constants for trig function evaluation
BASIC calls to Kernal routines
The subroutines in this area are BASIC'S formal calls to Kernal 38176 $9520 PRINT USING
routines:
Handles the PRINT USING statement
226
227
39361 $99C1 $A346 41798

39361 $99C1 INSTR 41268 $A134 APPEND


Handles the INSTR function Handles the APPEND statement
39692 $9B0C RDOT 41303 SA157
Handles the RDOT function Finds an available secondary address
39728 $9B30 DRAWLN 41327 $A16F DCLOSE
Bitmapped graphics line-drawing routine Handles the DCLOSE statement
39931 $9BFB 41347 SA183
Bitmapped point-plotting routine Closes all open files for a specified device
40010 $9C4A 41356 $A18C DSAVE
Scales graphics parameters Handles the DSAVE statement
40366 $9DAE 41380 $A1A4 DVERIFY
Applies scaling factor to a specified parameter Handles the DVERIFY statement
40557 $9E6D 41383 $A1A7 DLOAD
Evaluates graphics parameters Handles the DLOAD statement
40712 $9F08 41416 $A1C8 BSAVE
Handles relative graphics parameters Handles the BSAVE statement
40783 $9F4F 41496 $A218 BLOAD
Allocates the bitmapped graphics area Handles the BLOAD statement
40903 $9FC7 41575 $A267 HEADER
Adjusts BASIC program pointers for graphics area allocation or Handles the HEADER statement
de-allocation
41633 $A2A1 SCRATCH
40994 $A022 Handles the SCRATCH statement
De-allocates the bitmapped graphics area
41687 $A2D7 RECORD
41076 SA074 Handles the RECORD statement
Confirms that the graphics area has been allocated
41762 $A322 DCLEAR
41086 $A07E CATALOG/DIRECTORY Handles the DCLEAR statement
Handles the CATALOG and DIRECTORY statements
41775 $A32F COLLECT
41245 SA11D DOPEN Handles the COLLECT statement
Handles the DOPEN statement
41798 $A346 COPY
Handles the COPY statement
228 229
41826 SA362 $AF03 44803

41826 $A362 CONCAT 43556 SAA24 FETCH


Handles the CONCAT statement Handles the FETCH statement
41838 $A36E RENAME 43561 SAA29 SWAP
Handles the RENAME statement Handles the SWAP statement
41852 $A37C BACKUP 43630-44642 $AA6E-SAE62 Unused
Handles the BACKUP statement All locations in this unused area of ROM are filled with the
value 255/lFF.
41923 $A3C3
Evaluates parameters for disk commands 44643-44799 $AE63-$AEFF
42535 SA627 This area contains a heavily encoded message from the de-
Table of disk command templates signers of the 128.

42599 SA667 BASIC Jump Table


Sets up disk command buffer The Commodore 128's BASIC 7.0 includes a feature not found
in previous versions: a jump table. Like the Kernal and screen
42872 $A778 editor jump tables, the BASIC table provides stable entry
Reads disk status string (DSS) points to a number of important BASIC routines. If you want
to call a BASIC routine from within one of your own machine
42977 $A7E1 language programs, you should use the jump table entry if
Provides ARE YOU SURE query one is provided. If you call a BASIC ROM routine directly,
your program will not work if the address of the routine is
43021 SA80D changed in a future version. Presumably, Commodore will up-
Clears disk status string date the jump table if BASIC ROM is ever revised, so that
jump table calls will remain valid.
43077 $A845
In the discussions below, FAC1 refers to floating-point ac-
Switches to bank 15 configuration cumulator #1, locations 99-103/$63-$67, and FAC2 refers to
43085 $A84D floating-point accumulator #2, locations 106-110/$6A-$6E.
BASIC IRQ service routine
This routine supports the MOVSPR sprite movement state- 44800 $AF00 JAYINT
ment, the COLLISION statement, and the PEN function. It is Entry point for the AYINT routine, currently at 33972/$84B4.
also responsible for updating the duration timers for the This routine converts the contents of FAC1 into a two-byte
SOUND and PLAY statements, signed integer value in locations 102-103/$66-$67 (high byte
in 102/$66, low byte in 103/$67). The routine tests the origi-
43504 $A9F0 nal value and generates an ILLEGAL QUANTITY error mes-
Common exit point from BASIC IRQ routine sage if it is not in the range -32768-32767.

43551 $AA1F STASH 44803 $AF03 JGIVAYF


Handles the STASH statement Entry point for the GIVAYF routine, currently at 31036/
$793C. This routine converts the two-byte signed integer
230 231
44806 $AF06 $AF21 44833

value in the Y register and accumulator (low byte in Y, high 44818 $AF12 JFSUB
byte in the accumulator) into a floating-point value in FAC1.
Entry point for the FSUB routine, currently at 34862/S882E.
44806 $AF06 JFOUT This routine subtracts the floating-point value in FAC1 from
the five-byte floating-point value from the address in bank 1
Entry point for the FOUT routine, currently at 36418/$8E42. specified in the accumulator (low byte) and Y register (high
This routine creates a string of characters representing the byte). (The bank 1 value will be loaded into FAC2.) The result
floating-point value in FAC1. The string starts at location will be left in FAC1.
253/$0100 and is terminated with a zero byte. The first char-
acter of the string is a space (code 32/$20) if the value was 44821 $AF15
positive, or a minus sign ( —) if the value was negative. JFSUBT
Entry point for the FSUBT routine, currently at 34865/$8831.
44809 $AF09 JVAL_1 This routine subtracts the value in FAC1 from the value in
FAC2. The result will be left in FAC1.
Entry point for the VAL_1 routine, currently at 32850/$8052.
This routine reads a string of characters from bank 1 and gen- 44824 $AF18 JFADD
erates the equivalent floating-point value in FAC1. Locations Entry point for the FADD routine, currently at 34885/S8845.
36-37/$24-$25 point to the the starting address of the string This routine adds the floating-point value in FAC1 to the five-
and the accumulator holds the length of the string. This rou- byte floating-point value from the address in bank 1 specified
tine will leave the system in BASIC'S alternate bank 14 con- in the accumulator {low byte) and Y register (high byte). (The
figuration in which block 1 RAM is visible, so it shouldn't be bank 1 value will be loaded into FAC2.) The result will be left
called by a routine in bank 0. in FAC1.
44812 $ AFOC JGETADR 44827 $AF1B JFADDT
Entry point for the GETADR routine, currently at 34837/ Entry point for the FADDT routine, currently at 34888/$8848.
$8815. This routine converts the current value in FAC1 into a This routine adds the value in FAC1 to the value in FAC2.
two-byte unsigned integer in locations 22-23/$16-$17 (low The result will be left in FAC1,
byte in 22/$ 16, high byte in 23/$17). The integer value will
also be in the Y register (low byte) and accumulator (high 44830 $AF1E JFMULT
byte) upon return. Before performing the conversion, the rou-
tine checks that the value FAC1 is in the range 0-65535, and Entry point for the FMULT routine, currently at 35364/$8A24.
generates an ILLEGAL QUANTITY error message if it is not. This routine multiplies the floating-point value in FAC1 by the
five-byte floating-point value from the address in bank 1 spec-
44815 $AF0F JFLOATC ified in the accumulator (low byte) and Y register (high byte),
(The bank 1 value will be loaded into FAC2.) The result will
Entry point for the FLOATC routine, currently at 35957/ be left in FAC1.
$8C75. This routine converts the two-byte unsigned integer in
locations 100-101/$64-$65 (low byte in 101/$65, high byte 44833 $AF21 JFMULTT
in 100/$64) into a floating-point value in FAC1. For this rou-
tine to function properly, you must also load the X register Entry point for the FMULTT routine, currently at 35367/
with the value 144/$90 and make sure the status register $8A27. This routine multiplies the value in FAC1 by the value
carry bit is set. in FAC2. The result will be left in FAC1.

232 233
44836 $AF24 $AF48 44872

44836 $AF24 FDIV the five-byte floating-point value from bank 1 beginning at the
Entry point for the FDIV routine, currently at 35657/$8B49. address specified in the accumulator and Y register (low byte
This routine divides the five-byte floating-point value from the in the accumulator, high byte in the Y register). The exponent
address in bank 1 specified in the accumulator (low byte) and value will be loaded into FAC1. The result of the operation
Y register (high byte) by the floating-point value in FAC1. will be left in FAC1.
(The bank 1 value will be loaded into FAC2.) The result will
be left in FAC1. 44857 $AF39 JFPWRT
Entry point for the FPWRT routine, currently at 368O1/$8FC1.
44839 $AF27 JFDIVT This routine raises the value in FAC2 to the power specified in
Entry point for the FDIVT routine, currently at 35660/$8B4C. FAC1, effectively FAC2 t FAC1. The result of the operation
This routine divides the value in FAC2 by the value in FAC1. will be left in FAC1.
The result will be left in FAC1.
44860 $AF3C JEXP
44842 $AF2A JLOG Entry point for the EXP routine, currently at 36915/$9033.
Entry point for the LOG routine, currently at 35274/$89CA. This routine calculates the natural exponential of the value in
This routine calculates the natural logarithm of the value cur- FAC1, effectively e T FAC1, where e = 2.71828. This is the in-
rently in FAC1, the log to the base e. The result will be left in verse of the LOG operation. The result will be left in FAC1.
FAC1.
44863 $AF3F JCOS
44845 $AF2D JINT Entry point for the COS routine, currently at 37897/$9409.
Entry point for the INT routine, currently at 36091/$8CFB. This routine calculates the cosine of the current value in
This routine calculates the whole number portion of the cur- FAC1, which will be interpreted as an angle in radians. The
rent value of FAC1, removing any fractional portion. The frac- result will be left in FAC1.
tional portion is simply truncated; no rounding is performed.
The result is a floating-point value in FAC1, not an integer 44866 $AF42 JSIN
value. Entry point for the SIN routine, currently at 37904/$9410.
This routine calculates the sine of the current value in FAC1,
44848 $AF30 JSQR which will be interpreted as an angle in radians. The result
Entry point for the SQR routine, currently at 36791/S8FB7. will be left in FAC1.
This routine calculates the square root of the current value in
FAC1. The result will be left in FAC1. 44869 $AF45 JTAN
Entry point for the TAN routine, currently at 37977/$9459.
44851 $AF33 JNEGOP This routine calculates the tangent of the current value in
Entry point for the NEGOP routine, currently at 36858/ FAC1, which will be interpreted as an angle in radians. The
$8FFA. This routine switches the sign of the current value in result will be left in FAC1.
FAC1, making the value negative if it was positive, or positive
if it was negative. 44872 $AF48 JATN
Entry point for the ATN routine, currently at 38067/$94B3.
44854 $AF36 JFPWR This routine calculates the inverse tangent (arctangent) of the
Entry point for the FPWR routine, currently at 36798/$8FBE. current value in FAC1. The result, which can be interpreted as
This routine raises the value in FAC2 to the power specified in an angle in radians, will be left in FAC1.
234 235
44875 $AF4B $AF69 44905

4487S $AF4B JROUND according to the setting of the status register N and Z bits
Entry point for the ROUND routine, currently at 35911/ upon entry. The resulting value will be left in FAC1. If the N
bit is set upon entry, the value in FAC1 will be used as the
$8C47. This routine will round the least significant bit of seed, producing a predictable result. If the Z bit is set, the
FAC1 according to the value in the FAC1 rounding byte, loca- value in the CIA. #1 time-of-day clock is used as a seed. Other-
tion 113/S71. wise, the previous random number in locations 4635-4639/
$121B-$121F is used as a seed for the next value.
44878 $AF4E JABS
Entry point for the ABS routine, currently at 35972/$8C84. 44890 $AF5A JCONUPK
This routine will calculate the absolute value of the current Entry point for the CONUPK routine, currently at 35508/
value in FAC1, making the value positive regardless of its pre- $8AB4. This routine loads FAC2 with the five-byte value at
vious sign. the address in bank 1 pointed to by the accumulator and Y
register (low byte/high byte).
44881 SAF51 JSIGN
Entry point for the SIGN routine, currently at 35927/$8C57. 44893 $AF5D JROMUPK
This routine sets the accumulator (and processor status regis- Entry point for the ROMUPK routine, currently at 35465/
ter) according to the current value in FAC1. If the value is $8A89. This routine loads FAC2 with the five-byte value at
zero, the accumulator will hold 0/$00 upon return (and the the address in the current bank pointed to by the accumulator
status register Z bit will be set). If the FAC1 value is positive, and Y register (low byte/high byte).
the accumulator will hold l/$01 (and the status register Z and
N bits will both be clear). If the FAC1 value is negative, the 44896 $AF60 JMOVFRM
accumulator will hold 255/$FF (and the status register N bit
will be set). Entry point for the MOVFRM routine, currently at 31365/
$7A85. This routine loads FAC2 with the five-byte value at
44884 $AF54 JFCOMP the address pointed to by locations 36-37/$24-$25.
Entry point for the FCOMP routine, currently at 35975/ 44899 $AF63 JMOVFM
$8C87, This routine compares the floating-point value in
FAC1 against the five-byte floating-point value from the ad- Entry point for the MOVFM routine, currently at 35796/
dress in bank 1 specified in the accumulator (low byte) and Y $8BD4. This routine loads FAC1 with the five-byte value at
the address in the current bank pointed to by the accumulator
register (high byte). The accumulator (and processor status and Y register (low byte/high byte).
register) will be set according to the result of the comparison.
If the two values are equal, the accumulator will hold 0/$00
upon return (and the status register Z bit will be set). If the 44902 $AF66 JMOVMF
FAC1 value is greater than the value in bank 1, the accumu- Entry point for the MOVMF routine, currently at 35840/
lator will hold l/$01 (and the status register Z and N bits will $8C00. This routine copies the contents of FAC1 into a five-
both be clear). If the FAC1 value is less than the value in bank byte area beginning at the address in the current bank pointed
1, the accumulator will hold 255/$FF (and the status register to by the X and Y registers (low byte/high byte).
N bit will be set).
44905 $AF69 JMOVFA
44887 $AF57 JRND-0 Entry point for the MOVFA routine, currently at 35880/
Entry point for the RND_0 routine, currently at 33857/$8437. $8C28. This routine copies the contents of FAC2 into FAC1.
This routine generates a pseudorandom floating-point value
236
44908 $AF6C
$AF99 44953

44908 $AF6C JMOVAF


Entry point for the MOVAF routine, currently at 35896/ 44932 $AF84 JNEW
$8C38. This routine copies the contents of FAC1 into FAC2. Entry point for the NEW routine, currently at 20950/S51D6.

44911 $AF6F JOPTAB 44935 $AF87 JLNKPRG


This table entry is not a jump vector. Location 44911/$AF6F Entry point for the LNKPRG routine, currently at 20303/
does contain a JMP instruction, but the target address is not a $4F4F. This program updates the line links for all lines in the
valid routine. Instead, locations 44912-44913/$AF70-$AF71 current program.
provide a fixed reference to the address of the BASIC operator
table. This table, currently at 18472/$4828, holds the priorities 44938 $AF8A JCRUNCH
and dispatch addresses for the mathematical operators such as Entry point for the CRUNCH routine, currently at 17162/
+ , - , * , and/. $430A. This routine is the one responsible for converting lines
of text into tokenized BASIC statements.
44914 $AF72 JDRAWLN
Entry point for the DRAWLN routine, currently at 39728/ 44941 $ AF8D JFNDLN
$9B30. This is the basic bitmapped graphics line-drawing Entry point for the FNDLN routine, currently at 20580/$5064.
routine. This routine searches through program text for the line num-
ber specified in locations 22-23/S16-17. Upon exit, the carry
44917 $AF75 JGPLOT bit will be clear if no match was found, or set if the specified
Entry point for the GPLOT routine, currently at 39931/$9BFB. line was located.
This routine plots a point on the bitmapped screen using the
currently specified color source. 44944 SAF90 JNEWSTT
Entry point for the NEWSTT routine, currently at 19190/
44920 $AF78 JCIRSUB $4AF6. This routine prepares for the execution of the next
Entry point for the CIRSUB routine, currently at 26448/$6750. BASIC statement.
This is the basic bitmapped graphics circle-drawing
subroutine. 44947 $AF93 JEVAL
Entry point for the EVAL routine, currently at 30935/$78D7.
44923 $AF7B JRUN This routine evaluates a single numeric term or variable into a
Entry point for the RUN routine, currently at 23195/$5A9B. value in FAC1.

44926 $AF7E JRUNC 44950 $AF96 JFRMEVL


Entry point for the RUNC routine, currently at 20979/S51F3. Entry point for the FRMEVL routine, currently at 30703/
RUNC is actually an alternate entry point into NEW to reset $77EF. This routine evaluates a numeric expression, leaving
the text pointer to the start of program text and perform CLR. the results in FAC1.

44929 $AF81 JCLR 44953 $AF99 JRUN_A_PROGRAM


Entry point for the CLR routine, currently at 20984/$51F8. Entry point for the RUN routine, currently at 23206/$5AA6.
This routine performs the portion of the RUN routine nor-
mally executed for running a program after it has been loaded
from disk. The extra steps in this case include relinking the
238 program before it is run,
239
44956 $AF9C

44956 $AF9C JSETEXC


Entry point for the SETEXC routine, currently at 23169/
$5A81, This routine sets BASIC flags to indicate that a pro-
gram is running.

44959 $AF9F JLINGET


Entry point for the LINGET routine, currently at 20640/
$50A0. This routine reads a string of characters and generates
a two-byte integer number in locations 22-23/$16-$17, The
value must be less than 64000 or a SYNTAX ERROR will
occur.

44962 $AFA2 JGARBA2


Entry point for the GARBA2 routine, currently at 37610/
$92EA. This routine performs a garbage collection, removing
inactive strings from the string pool to increase the amount of
available string space.

44965 $AFA5 JEXECUTE_A_LINE


Entry point for the MAIN routine, currently at 19917/S4DCD.
This routine is BASIC'S primary immediate mode loop.

44968-45055 $AFA8-$AFFF Unused


All locations in this unused area of ROM are filled with the
value 255/$FF.

240
Machine Language
Monitor ROM
The duplicate use of the word monitor in computer terminology
may be confusing at first. The term can refer to either hard-
ware, a dedicated video screen used to display information
from the computer, or software, a program used to examine
and modify the contents of memory. Once you understand the
difference, the meaning of monitor is usually obvious from the
context. This chapter describes the 128's built-in software moni-
tor, which resides in the 4K block of ROM from 45056-49151/
$B000-$BFFF. In addition to examining and changing memory,
this monitor allows you to assemble, disassemble, and execute
ML routines; examine and change microprocessor register con-
tents; and copy, compare, save, load, and verify blocks of
memory.
Like the 128's BASIC, its machine language monitor has a
long heritage from previous Commodore models. All of the
original CBM models (except for very early PETs) included a
rudimentary monitor in ROM which allowed users to examine
and modify memory and registers, execute ML programs, and
load and save data, but had no provision for assembling or
disassembling machine language.
The VIC-20 and Commodore 64 had no monitor in built-
in ROM, but sophisticated monitors for both were available on
cartridge. A number of public-domain RAM-resident monitors
were also available, most notably Superman and Micromon. Fi-
nally, the Plus/4 and 16 once again included a monitor pro-
gram in ROM, a version called Tedmon.
The 128's monitor shares many characteristics with all of
its predecessors, but it includes a number of enhancements as
well. One of the most notable is that it allows the entry of
numbers in decimal, octal, or binary in addition to hexadeci-
mal. Whenever the monitor expects a number, you can use a
decimal value if it's prefixed with a + character, or a binary
number if it's prefixed with a % character (in the rare case
when you might want to use an octal—base 8—number, pre-

243
fix it with an ampersand, &). If no prefix is used, then hexa- dresses can span banks—T ED000 EDFFF 1C000, for example.
decimal is assumed. (Hex can also be explicitly specified by Thus, the monitor can effectively see the 16 separate banks as
using a $ character as a prefix.) a single 1024K (16 * 64K) block of memory. One exception is
the F (fill memory) command, which cannot cross bank bound-
Moving Between BASIC and the Monitor aries, because doing so would overwrite the vital contents of
In general, the monitor is aloof from the rest of the 128 ROM locations $00 and $01.
routines. Unlike BASIC—which in a number of places by- The fact that the monitor can see the 128's memory as a
passes the Kernal jump table and calls Kemal routines di- continuous block has an important consequence for the H
rectly—the monitor calls all the Kernal routines it uses (hunt for byte pattern) command. Remember that the banks
through their formal jump table entries. Neither BASIC nor are not really 16 separate blocks of memory, but rather 16 dif-
the Kernal calls any monitor routines other than through jump ferent arrangements of the available RAM and ROM. The low-
table entries. The monitor does not make use of any BASIC est IK of memory (including the input buffer at 512/$0200) is
ROM routines or data tables and for the most part does not in- common to all banks, and at least the lower 4K of block 0
terfere with memory locations used by BASIC. Thus, you may RAM {including the buffer at 2688/$0A80, where the search
pass freely back and forth between the monitor and BASIC pattern is stored) appears in all even-numbered banks and in
without fear of upsetting the BASIC program currently in banks 13/$D and 15/$F.
memory. This greatly enhances the monitor's function as a de- Thus, if you search any bank from beginning to end (for
bugging tool. example, H 10000 1FFFF 'C-128), you'll always find at least
One notable—and highly unfortunate—exception to this one match for your search pattern—in the input buffer at
independence from BASIC is that the monitor uses addresses $0200, where the search command is stored. If you search any
in the range 96-104/$60-$68 as working pointers in most op- even-numbered bank from beginning to end, you'll find at
erations. This area includes the addresses used by BASIC for least two matches for your search pattern—once in the input
its floating-point accumulator 1 (FAC1), where the results of buffer at $0200 and again in the search buffer at $0A80. And
mathematical operations are stored. As a result, it is impossi- if you search all banks from beginning to end (for example, H
ble to use the 128's monitor to directly examine or change the 00000 FFFFF 'COMPUTE!), then you'll always find at least 26
contents of FAC1. This severely limits the usefulness of the matches because of all the times the memory areas used by
monitor for experimenting with BASIC floating-point routines. the input buffer and search buffer appear in the different
One other overlap between BASIC and the monitor is that banks. It's important to choose your address range carefully
the two share the same input buffer area for accepting and when searching for a byte pattern.
processing commands (512-673/$0200-$02Al). Thus, it is not A final note on banks and the monitor: If no bank is ex-
possible to use the monitor to examine the BASIC input buffer plicitly specified, bank 0 is assumed. This is different from
contents or to manipulate data in the input buffer, since the BASIC, which retains the setting specified in a previous BANK
buffer will be at least partially overwritten by the monitor statement, starting with a default of bank 15. So when using
command to display or change the memory area. the monitor, you must always explicitly specify the bank if
you wish to use any bank other than bank 0, It is particularly
Memory Management important to remember this when using the G and J com-
Another particularly attractive feature of the 128's monitor is mands, lest you send the processor off to some uncharted re-
the ease with which it interfaces with the computer's memory gion of memory.
management system. Addresses in monitor commands are For the programmer wishing to make use of ROM
specified as five-digit hexadecimal values, where the first digit routines, those in the monitor are generally less useful than
refers to the bank and the remaining four specify the address those in the BASIC, screen editor, and Kernal portions of the
within the bank. Monitor commands that accept a range of ad- ROM. The monitor JMPs rather than JSRs to the routines used

244 245
45056 $B000 $B08B 45195

to perform monitor commands, so most major routines end by lowing the IMON jump. See IMON for information on how
jumping directly back to the monitor's main loop rather than the indirect vector can be used to wedge in additional monitor
with an RTS opcode. You probably wouldn't want to incorpo- commands.
rate calls to such routines in your own programs because the
routines never return from the monitor. However, the main
command execution routines use a number of subroutines that 45065 $B009 MONBRK
do end with RTS opcodes, and you may find some of these Monitor entry routine when BRK instruction encountered.
useful, particularly the routines to convert and print byte val- Prints BREAK and a {BELL} character, then retrieves and
ues as decimal numbers (at 47623/$BA07 and 47687/SBA47) stores the bank number, program counter, and microprocessor
or as hexadecimal numbers (at 47250/$B892). An example is register values that were placed on the stack by the IRQ/BRK
provided at the end of the chapter. handling routine [$FF17], then branches into the following
routine to fall through to the register display and main loop.

Monitor Jump Table 45089 $B021 MONINIT


Like the BASIC screen editor, and Kernal jump tables, each Cold-start routine for monitor.
three-byte entry in the following table consists of a JMP Switches to bank 15, loads all register storage locations with
opcode followed by the address of an important routine. zeros, sets the program counter storage to $B000 and bank
storage to 15, and prints MONITOR. Next (at $B046) the stack
45056 $B000 JMONINIT pointer is stored and Kernal error messages are enabled. The
Monitor cold-start entry point; jumps to 45089/$B021, which routine then falls through to display the stored register values
enters the monitor with default microprocessor register values. and enter the main loop.
This is the entry point when the RUN/STOP key is held
down during power-on/reset, or when the MONITOR com- 45136 $B050 SHOWREG
mand is executed in BASIC. Handles R (register display) command.
Prints a heading for the register display, then displays the con-
45059 $B003 JMONBRK tents of the storage locations (2-9/$02-$09) that represent the
Monitor break entry point; jumps to 45065/$B009, which en- program counter (prefixed with the current bank number); status;
ters the monitor with the current program counter, bank, and and A, X, Y, and stack pointer register values. The storage lo-
microprocessor A, X, and Y register values preserved. The cations are filled upon entry to the monitor and can be changed
monitor is normally called via this entry point whenever a with the register change (;) command. To simplify the process
BRK opcode is executed because the Kernal RESTOR routine of changing register values, this routine adds a semicolon before
[$E056], part of the RESET sequence, initializes the CBINV the displayed values so that you can change the stored values
vector at 790-791/$0316-$0317 to point here. CBINV deter- by typing over the displayed values and pressing RETURN.
mines where control is passed after a BRK. The routine ends by falling through into the main loop.

45062 $B006 JIMONRTN 45195 $B08B MONMAIN


Reentry point from the IMON indirect vector. Like the BASIC Main command execution loop for the monitor.
and Kernal indirect vectors, the monitor's command execution Clears a line for input, then gets a command line into the in-
routine has an indirect vector, IMON (814-815/$032E-$032F), put buffer (512-672/$0200-$02AO). The routine accepts char-
which is initialized by the Kernal RESTOR routine [$E056] to acters until RETURN is pressed. Characters are then retrieved
point here. From this point, control is transferred back to from the buffer until one is found that is not a space. This
45234/$B0B2 in the main loop, the address immediately fol- character is assumed to be a monitor command (all monitor
246 247
45283 SB0E3 SB12A 45354

commands consist of a single character). With this character in from the stack, it adds 1 to the address value before placing
the accumulator, the routine jumps through the IMON indirect the value in the 8502's program counter. The actual execution
vector at 814-815/$032E-$032F. Normally, this vector points addresses for each of the commands handled by this table are
to the jump table entry at $B006, which immediately returns as follows:
to the address following the indirect jump. However, this vec-
tor can be changed to allow additional commands to be added A {Assemble instruction) SB406
C (Compare memory blocks) SB231
to the monitor. See the discussion at IMON for more details.
D {Disassemble instruction) $B599
The routine then compares the command character in the F {Fill memory) SB3DB
accumulator against characters from the command table at G (Go to routine) $B1D6
45286/$B0E6. If no match is found, an error is assumed, and H (Hunt for byte) $B2CE
(at $B0BC) the error signal (a question mark) is printed follow- J (Jump to subroutine) $B1DF
ing the command. The routine then loops back to process an- M (Memory display) $B152
other command. If a match is found among the first 15 char- R (Register display) $B050
acters in the command table, then the command is executed T (Transfer memorv) $B234
by pushing an address from the table at 45308/$B0FC onto X (eXit to BASIC) $B0E3
the stack, then jumping to read the parameter following the @ (send disk command) $BA90
command. The RTS at the end of the parameter decoding rou- (same as A) $B406
tine [$B7A7] will cause control to be passed to the command > (change memory) $B1AB
execution address stored on the stack. If the matching charac- (change register) $B193
ter is among characters 16-19 in the table ($-%), then a jump
is taken to the base conversion routine [$B9B1]. If the match- 45338 SB11A MINDFET
ing character is among characters 20-22 in the table (L-V), INDFET call for the monitor.
then a jump is taken to the routine that prepares for load,
save, or verify [$B337]. Calls the Kernal INDFET routine [$FF74] to retrieve a charac-
ter into the accumulator from the bank specified in 104/$68 at
the address pointed to in 102-103/$66-$67, and with the off-
45283 SB0E3 EXITMON set specified by the contents of the Y register. The use of
Handles X {exit to BASIC) command. $66-$68 as working addresses makes it impossible to use the
Leaves the monitor and returns to BASIC by jumping indi- monitor to examine the contents of floating-point accumulator
rectly through BASIC'S restart vector at 2560-2561/ 1 (FAC1), since the value in FAC1 will be changed by the
$0A00-$0A01. monitor M command (which uses this routine).
45286 $B0E6 COMTBL 45354 $B12A MINDSTA
Table of monitor commands. INDSTA call for the monitor-
Each of the 22 commands consists of a single character: Calls the Kernal INDSTA routine [$FF77] to store the value in
the accumulator into the bank specified in 104/$68 at the ad-
A C D F G H J M R T X @ . > ; $ + & % L S V
dress pointed to in 102-103/$66-$67, and with the offset
45308 $B0FC EXECTBL specified in the Y register. The use of $66-$68 as working ad-
Table of execution addresses for the monitor commands. dresses makes it impossible to use the monitor to load values
Each two-byte entry in the table consists of the address minus directly into floating-point accumulator 1 (FAC1), since the
1 of the routine to perform the corresponding command. The value in FAC1 will be changed by the > (memory change)
entries are one less than the actual address because of the way command (which uses this routine).
the RTS opcode behaves: When RTS pulls a return address
248

J 249
45373 $B13D 8B1AB 45483

45373 $B13D MINDCMP 45460 SB194 CHNGREG


INDCMP call for the monitor. Handles ; (change register) command.
Calls the Kernal INDCMP routine [$FF7A] to compare the Allows you to change the contents of the bank, program
value in the accumulator against the value at the address counter, and register storage locations (2-9/$02-$09). Since
pointed to in 102-103/$66-$67, with the offset specified in the values in the storage locations are reloaded into the cor-
the Y register, from the bank specified in 104/$68. The only responding registers by the G and J commands, this allows
monitor routine that uses indirect comparison is the you to change values that the various microprocessor registers
compare/transfer routine [$B321], and that routine calls will hold when ML routines are executed from the monitor.
INDCMP directly, using instead 96-97/$60-$61 as the ad- The register contents are usually changed by editing the val-
dress pointer and 98/$62 for the bank value. ues displayed by the R {register display) command [$B050].
Since that routine automatically provides the semicolon (;) in
45394 $B152 SHOWMEM front of the values, you may not even have realized that this
Handles M (memory display) command. is a separate command. You are free to use the ; command in-
Displays the contents of a specified area of memory as hexa- dependently of the register display, but it is somewhat less
decimal values and ASCII characters. The routine functions by convenient.
repeatedly calling the subroutine display lines of byte and The routine expects to read the values in order, so you
character values [$B1E8]. must supply values for all registers with storage locations
The format depends on the screen mode: 8 bytes per line lower than the one you wish to change. This isn't a problem if
in 40-column mode or 16 bytes per line in 80-column mode. you're editing the register display, but if you're using the ;
No parameters are required, but either one or two parameters (semicolon) command independently, you must supply values
can be specified. If no parameters are specified, the display be- for all registers that are normally displayed to the left of the
gins at whatever address is currently in 102-103/$66-$67 value you wish to change. For example, even if you want to
from the bank specified in 104/$68. Before other operations change only the Y register value, you must still also supply
are performed, the value in those locations is not predictable. address, status register, accumulator, and X register values (in
After another M command, these locations will hold an ad- order) before the Y register value.
dress one line (8 or 16 bytes) higher than the previous ending
address. Twelve lines of data will be displayed, representing 45483 6B1AB CHNGMEM
either 96 bytes (40-column mode) or 192 bytes (80-column
mode). If one address is specified, 12 lines are displayed start- Handles > (change memory) command.
ing at the specified address. If two addresses are specified, all Allows you to change the contents of one or more memory lo-
bytes between the addresses are displayed; the NO SCROLL cations—to a maximum of either 8 or 16 locations, depending
key may be used to pause the screen and the STOP key will on whether the 40- or 80-column screen is in use. Memory
halt the process. The routine always displays full lines, so a contents are usually changed by editing the lines of byte val-
few bytes beyond the specified ending address may also be ues displayed by the M (memory display) command [$B152].
shown. It is possible to wrap from bank to bank; the next ad- Since that routine automatically provides the > in front of the
dress after $FFFF in one bank is $0000 in the next higher address and values, you may not even have realized that this
bank. Thus, the M command treats the 16 banks like a con- is a separate command. You are free to use the > command
tinuous block of memory. However, the address will not wrap independently of the memory display; in fact, it's more
from $FFFFF to $00000. The routine ends by jumping back to convenient when you need to change only one or two bytes.
the main loop If no parameters are found following the > command,
then a line of byte values is displayed beginning at the ad-
dress in 102-103/$66-$67 from the bank in 104/$68. If no

250 251
45526 3B1D6 $B231 45617

monitor commands involving ranges of addresses—for ex-


ample, M, T, or C—have yet been performed, the value in loaded from 5-8/$05-$08. Upon return from the JSRFAR, the
these locations is unpredictable. Following the M command, routine jumps back to the main loop [$B08B].
the locations will hold an address one line (8 or 16 bytes, de- To get back to the monitor cleanly after using J, you'll
pending on the display width) higher than the address of the need to be sure that the routine at the target address ends
last line displayed. with an RTS opcode. Execution of a BRK opcode will also
Only hexadecimal byte value parameters can be inter- cause a return to the monitor (via the break entry point
preted; you cannot change memory by changing the ASCII [$B003]), but in that case the JSRFAR return address will be
characters displayed at the end of each line. The routine to left on the stack.
display a line of memory [$B1E8] is called to redisplay the
changed locations. A full line (8 or 16 bytes) is always 45544 $B1E8 SHOWLIN
redisplayed, even if you have changed only one or two bytes. Displays a line of memory as hex bytes and ASCII characters.
The routine ends by jumping back to the main loop [$B08B]. Clears a screen line, then prints a > character to facilitate use
of the memory change command [$B1AB], Next, the bank and
45526 SB1D6 GOTOLOC address of the first location in the current display line (in
Handles C (go to routine) command. 102-104/$66-$68) are printed. A loop reads bytes from mem-
Loads the bank and program counter storage locations (2-4/ ory and prints two-digit hexadecimal numbers representing
$02-$04) with the specified values if a target address is sup- the byte values. The loop repeats for either 8 or 16 bytes, de-
plied. The stack pointer is restored to the value it had upon pending on the screen width (determined by checking the
entry to the monitor (stored in 9/$09). This negates the effects value in 215/$D7). After this, the routine prints a colon (so
of any stack operations the monitor routines may have per- that the following ASCII characters will not be counted as part
formed. Finally, the Kernal JMPFAR routine [$FF71] is called of the input for the memory change command) and an {RVS}
to transfer control to the address specified in 3-4/$03-$04, character (so that the following ASCII characters will be dis-
and in the bank specified in 2/$02, with the microprocessor played in reverse video). Finally, a second loop is used to read
registers loaded from 5-8/$05-$08. the same 8 or 16 bytes again, but this time to display the
There's normally no returning from a JMPFAR. If you equivalent ASCII character for the byte value. To prevent
want to get back to the monitor after executing an ML routine cursor or color control characters from being printed and up-
using G, then the routine at the target address must end with setting the screen display, the character code for the period (.)
a BRK ($00) opcode. Execution of the BRK will return you to is substituted if the byte value to be displayed is less than
the monitor via the break entry point [$B003], 32/$20 or between 128-159/$80-$9F.
If you use G to go to a routine that ends with an RTS,
you'll be returned to BASIC at the end of the routine. If you'd 45617 SB231 CMPXFR
prefer to be returned to the monitor when a program termi- Compares or transfers blocks of memory.
nates with RTS, use J instead of G. Begins by loading an operation flag (147/$93) with a value
that indicates which function is being performed: 0/$00 if the
45535 $B1DF JMPSUB routine is entered at $B231 for C (compare) or 128/$80 if en-
Handles J (jump to subroutine) command. tered at $B234 for T (transfer). The transfer operation might
Loads the bank and program counter storage locations (2-4/ more properly be called a copy, because the contents of the
$02-$04) with the specified values if a target address is sup- source block of memory are not changed unless the blocks
plied. The Kernal JSRFAR routine [$FF6E] is called to transfer overlap. A direction flag (2739/$0AB3) is also used during
control to the address specified in 3-4/$03-$04, and in the transfers to indicate whether bytes are being copied downward
bank specified in 2/$02, with the microprocessor registers in memory (flag value 0/$00) or upward (flag value 128/$80).
The direction of a transfer is significant—downward moves
252
253
45774 SB2CE SB39F 45983

must work from the starting address toward the ending ad- tine [$FFE1], so the RUN/STOP key can be used to be used to
dress, while upward moves must work from end to start. Oth- terminate the search. The routine ends by jumping back to the
erwise, if the source and destination ranges overlap, a single main loop [$B08B],
value would be rippled through the destination range. Be sure to see the warning in the introduction to this
The routine loads bytes from the source address range chapter about using the H command for searching wide ad-
and, if a transfer operation is indicated, stores the value in the dress ranges.
corresponding destination address using the Kernal INDSTA
routine [$FF77]. Next, it compares the byte in the source range 45879 $B337 MONLSV
against the byte in the destination range using the Kernal Prepares for load, save, or verify.
INDCMP routine [$FF7A]. This performs the compare opera- Begins by setting default values for the device number, sec-
tion (the bytes should always be equal for a transfer opera- ondary address, bank, filename length, and filename address.
tion). If the bytes do not match, the address of the mismatch is Setting these values directly (rather than using Kernal routines
printed. Then the source and destination addresses are either like SETLFS, SETNAM, and SETBANK) is an exception to the
incremented (for a compare or downward transfer) or decre- monitor's otherwise strict use of Kernal jump table calls. If no
mented (for an upward transfer). This loop is repeated until all characters follow the command, then a branch to 45995/$B3AB
bytes in the range have been compared or transferred; then allows the L and V commands to be used alone to load or ver-
the routine jumps back to the main loop [$B08B], However, ify using "nameless" tape files.
the loop also includes a call to the Kernal STOP routine If anything follows the command, it is assumed to be a
[$FFE1], so the RUN/STOP key can be used to halt the com- filename and must start with a quotation mark character ("),
pare or transfer. or else an error will be signaled. Characters following the
opening quotation mark are copied into the monitor buffer at
45774 $B2CE SEARCH 2688/$0A80 until a closing quotation mark is found. An error
Searches memory for byte pattern. is signaled if no closing quotation mark is found or if more
Evaluates the address parameters and calculates the number of than 16 characters are used in the filename. If no other param-
bytes to search, then fills the buffer at $0A80 with the search eters are found following the closing quotation mark, a branch
pattern. If the first nonspace character following the ending to 45995/$B3AB attempts to load or verify a tape file with the
address parameter is the apostrophe ('), then the following specified name.
characters are copied directly from the input buffer into the If a parameter value follows the closing quotation mark,
search buffer, so the search will be for the actual ASCII char- the low byte of the value is copied into the device number lo-
acters. If the apostrophe is not found, the characters following cation (186/$BA). The next parameter value is assumed to be
the ending address are converted into byte values before being a starting address, A load or verify is attempted if the param-
placed in the buffer. eter is absent. The final parameter, if any, is assumed to be the
ending address. If it's missing, a branch to 46O33/$B3D1 at-
Once the search buffer is prepared, a byte is loaded from
tempts a relocating load or verify. If it is present, the com-
memory and compared against the first byte in the search
mand is checked, and an error is signaled if it is not S (an
buffer. If the two bytes match, the next byte in memory is
ending address cannot be specified for a load or verify).
compared to the next byte in the buffer, and so on, until either
a mismatch occurs or the end of the search buffer is reached
(which indicates that the pattern has been matched). In the 45983 $B39F MONSAVE
case of a match, the starting address of the match is printed, Handles save for monitor.
followed by two spaces. The testing process normally repeats Changes the secondary address setting to zero to specify a re-
until all bytes in the specified address range have been locatable file if the device is the tape drive. The Kernal SAVE
checked, but the loop includes a call to the Kemal STOP rou-

254 255
45995 SB3AB $B406 46086

routine [$FFD8] is used to write the data to the specified de- bytes in the specified addresses. Overwriting either of these
vice. The routine ends by jumping back to the main loop areas will likely result in a system lockup.
[SB08B].
46086 $B406 ASSMBLE
45995 $B3AB MONLOAD Handles A (assemble) command or its equivalent (.).
Handles load and verify. Checks for values following the A or period (.) and signals an
Checks that the command is either V or L, and signals an er- error if none is found. The period is accepted as a synonym
ror if not. For V, the character code for V (86/$56) is left in for A to simplify the assembly process by allowing you to edit
the accumulator; for L, a zero is placed in the accumulator. the lines displayed by the D (disassemble) command. Since
The Kernal LOAD routine [$FFD5] is then called, which will the D command automatically provides the period before each
perform a load if the accumulator holds zero (for L) or a verify line, you may not have realized that it is treated as a separate
if the accumulator holds a nonzero value {for V). The routine command, but you can substitute it freely for A.
tests for a verify error; if one occurs, the message ERROR is If only an address is found following the command, the
printed to signal that the data in memory does not match the routine simply returns to the main loop [$B08B], Next, the
file on disk or tape. The routine ends by jumping back to the routine searches for the first group of three nonspace charac-
main loop [$B08B], ters. Any values on the input line with fewer than three char-
acters are ignored;this explains why the two-digit hexadecimal
46033 6B3D1 byte values displayed in front of the three-character mnemonic
Prepares for relocating load or verify. by the disassemble routine are ignored when the instruction is
Loads the specified ending address value and changes the sec- edited. It also explains why changes to the two-digit byte val-
ondary address (185/$B9) from 1 to 0, indicating a relocating ues are ignored by this routine. The three-character pattern is
load is to be attempted. The routine then branches to attempt then packed into a two-byte value. This packing scheme is a
load or verify [$B3AB], holdover from the RAM-resident monitors of earlier Commo-
dore computers. It's really unnecessary in the 128, which has
46043 $B3DB FILLMEM room to spare in this block of memory, but Commodore's pro-
grammers probably found it easier to reuse the existing code.
Fills memory with specified byte value.
All 8502 ML mnemonics consist of combinations of the alpha-
Evaluates the starting and ending addresses, and calculates the betic characters A-Z. Since there are only 26 different valid
number of bytes to fill. If the starting and ending banks are characters, any single character can be represented by a five-
not the same, an error is signaled to prevent the fill operation bit value (which can hold 0-31), and three five-bit values can
from crossing bank boundaries and overwriting the important fit nicely into two eight-bit bytes.
values in locations $00 and $01. If the address range is valid,
the fill byte value is read, and a loop begins to store fill byte As an example of how this packing works, suppose the
in all memory locations in the specified range. The loop nor- pattern found is LDA—corresponding to hex bytes $4C $44
mally repeats until the specified number of bytes have been $41. First, the value 63/$3F is subtracted from each byte,
filled, but it includes a call to the Kernal STOP routine yielding $0D $05 $02. The binary equivalents are %00001101
[$FFE1], so the RUN/STOP key can be used to halt the fill. %00000101 %00000010. The rightmost five bits of each value
are shifted rightward into two bytes. The resulting packed
The routine ends by jumping back to the main loop [$B08B].
mnemonic in these locations is %01101001 %0l000100, or
When filling, you must be careful not to overwrite page 0
$69 $44.
or page 2, both in the area of memory common to all banks.
Page 0 contains the pointer to the byte to fill (102-104/$66- Next, the routine infers an addressing mode from the pa-
$68), and page 2 contains the INDSTA routine used to store rameter following the three-character pattern. The packed pat-
tern is compared against those in the table at 46881/$B721.
256 257
46489 8B599 $B707 46855

(The packing scheme does make the testing for valid mne- monies column. A call to 46753/SB6A1 unpacks and prints
monics slightly faster, since only two bytes need to be com- the mnemonic. The associated parameter value is then printed,
pared instead of three.) An error is signaled if no match is along with such characters as #, (, and ), to identify the ad-
found; otherwise, the position of the matching mnemonic in dressing mode for the instruction. For relative branching in-
the table is used along with the addressing mode to calculate structions, the target address of the branch is printed instead
the proper opcode for the specified instruction. The opcode of the relative offset value.
and its associated parameter (if any) are then stored in mem-
ory, and the routine at 46556/$B5DC is called to disassemble 46681 $B659 CALCMN
the line just assembled. This provides the hex values of the
Calculates mnemonic and addressing mode.
ML bytes. Finally, the routine loads the input buffer with an A
and the next address value so that these will be found when Manipulates the specified opcode (in the accumulator upon
the routine ends by jumping back to the main loop [$B08B], entry) to provide the offset into the table for the correspond-
This greatly simplifies the assembly of further instructions. ing packed mnemonic, an addressing mode identifier value,
and a count of associated data bytes (0-2).
46489 8B599 DISASSM 46753 $B6A1 PRNTMN
Handles D (disassemble) command. Prints mnemonic for opcode.
Calculates the number of bytes to disassemble, then calls Unpacks and prints a mnemonic from the table at 46881/$B721.
46548/$B5D4 as many times as necessary to disassemble that Upon entry, the accumulator holds the offset into the table for
many bytes. If no parameter is specified, 20 bytes are dis- the mnemonic to be printed. As an example of how the un-
assembled beginning at the address in 102-104/$66-$68. (Ac- packing works, the first table entry is $1C $D8. The binary
tually, up to 22 bytes may be disassembled, depending on equivalent is %0001110011011000. Divided into three five-bit
how many are necessary for the last full instruction.) If no pre- groups (and ignoring the rightmost bit), that's %00011 %10011
vious commands have been executed, the address value is un- %01100, or $03 $13 $0C. Adding $3F to each yields $42 $52
predictable. After an earlier D command, the value will be the $4B, corresponding to the character codes for the letters BRK.
next address beyond the last one previously disassembled. If You would expect this to be the first table entry, since the BRK
only a starting address is provided, 20 bytes are disassembled instruction has the lowest possible opcode ($00).
beginning at the specified address. If both starting and ending
address parameters are provided, all instructions between 46787 $B6C3 OPCDTBL
those addresses will be disassembled. However, the disassem-
Opcode decoding table.
bly loop includes a call to the Kernal STOP routine [$FFE1], so
the RUN/STOP key can be used to halt the disassembly. You The values in this table are used by the mnemonic and mode
may also use the NO SCROLL key to pause the disassembly. calculation routine [$B659] to determine the packed mnemonic
The routine ends by jumping back to the main loop [$B08B], table offset for the specified opcode value.

46548 $B5D4 DISASM1 46855 6B707 INDCTBL


Disassembles a single instruction. Table of addressing mode indicators.
Prints a period (to simplify editing of instructions), then the Each 8502 mnemonic may have several possible addressing
bank and address of the opcode byte to be disassembled. A modes, each with a different opcode. The values from this ta-
call to 46681/SB659 calculates the addressing mode and offset ble are used to indicate the mode which should be associated
into the packed mnemonic table for this opcode. The hex with a mnemonic to represent the current opcode.
value of the opcode and up to two associated data bytes are
then printed. They're padded with spaces to align the mne-
258 259
46869 $B715 SB8C2 47298

46869 $B715 MODETBL 47242 $B88A BASETBL


Table of mode identification characters. Table of bases and bits-per-digit.
The characters in this table are used by the assemble routine This table is used by the parameter transformation routine
[$B406] to determine the addressing mode being used, and by [$B7CE] to determine how many bits to read for each digit of a
the disassembly routine [$B5D4] to disassemble an instruction number in the corresponding base.
to add the proper characters to indicate the mode being used.
47250 $B892 PRNTHEX
46881 $B721 MNEMTBL Prints a hexadecimal value.
Table of mnemonics in packed form. Prints a five-digit hexadecimal value followed by a space. The
Each three-character mnemonic is packed into two bytes (see first digit comes from the low nybble of 104/168, the next two
the assemble routine [$B406] for details). The table is in two from 103/$67, and the final two from 102/S66. When entered
halves: entries at 46881-46944/$B721-$B760 are the first byte at 47263/SB89F, the routine prints a four-digit hexadecimal
for the corresponding packed mnemonic, and entries at 46945- value representing the value in the accumulator (low byte) and
47102/$B761-$B7A0 are the second byte. X register (high byte). When entered at 47269/$B8A5, a two-
digit hex value representing the value in the accumulator is
47013 $B7A5 GETPARM printed. When entered at 47272/$B8A8, only a space is printed.
Evaluates a parameter in the input buffer.
Interprets the next numeric parameter in the input buffer
(using the parameter conversion routine [$B7CE]), then sets
47277 $B8AD
the status register accordingly: carry clear if a parameter has Moves cursor to start of current line.
been found and the following character is a space, comma, or Uses the Kernal PRIMM routine [$FF7D] to print a carriage re-
the end of the input line, or carry set if no parameter has been turn, CHR$(13), followed by a cursor up, CHR$(145).
found. Upon exit, the accumulator holds the number of digits
in the parameter. 47284 8B8B4
Moves cursor to start of next line.
47054 $B7CE CVTPARAM Uses the Kernal BSOUT routine [$FFD2] to print a carriage re-
Transforms numeric parameter into byte value. turn, CHR$(13).
Reads a parameter value from the input buffer and converts it
into a three-byte value in 96-98/$60-$63 (in low-byte to 47289 $B8B9 CLRLIN
high-byte order). The parameter can be in any one of four dif- Clears a screen line.
ferent numeric bases: hexadecimal, decimal, octal, or binary. Uses the Kernal PRIMM [$FF7D] routine to print a carriage re-
Hex is assumed unless another base is specifically indicated by turn, CHR$(13), followed by ESC Q (to clear a screen line)
a prefix character: $ for hexadecimal, + for decimal, & for oc- and a space.
tal, and % for binary. Upon exit, location 2740/$0AB4 will
hold a count of digits in the parameter (zero if no parameter 47298 $B8C2 PRNTBYT
was found). The status register's carry bit will be set if the Prints two ASCII characters for a byte value.
parameter value is too large to be interpreted (greater than Calls the byte conversion routine [$B8D2] to generate two
1048575/$FFFFF), and clear otherwise. ASCII characters representing the hex digits for the byte in the
accumulator, then uses the Kernal BSOUT routine [$FFD2] to
print these characters.

260 261
47314 8B8D2 8B983 47491

47314 8B8D2 CVTBYT 47420 $B93C DECCNT


Converts a byte value into two ASCII characters. Decrements byte count.
Generates two ASCII characters representing the hexadecimal Decrements the count of bytes for the current operation
digits for the byte value in the accumulator upon entry. The (99-100/$63-$64). If the value there rolls over from $0000 to
characters are returned in the accumulator (high nybble) and X $KFFF, the count of banks (101/$65) is also decremented.
register (low nybble). Upon exit, carry bit in the status register will be clear if the
countdown is complete; otherwise, the carry bit will be set.
47335 $B8E7 TESTCHR
Tests next character in the input buffer. 47440 $B950 INCPTR
Tests the character in the input buffer at the previous pointer Increments address pointer.
position (or, if entered at 47337/$B8E9, at the current pointer Increments the address pointer (102-103/$66-$67) by 1 if en-
position). If the character is a colon, question mark, or the zero tered at 47440/$B950, or by the value in the accumulator if
byte marking the end of input, the carry bit will be set upon entered at 47442/$B952. If the incrementing causes the ad-
exit to indicate that the end of the input line has been dress value to roll over from $FFFF to $0000, the bank pointer
reached. Otherwise, carry will be clear to indicate that charac- (104/$68) is also incremented.
ters remain to be read.
47456 8B960 DECPTR
47361 $B901 MOVEVAL Decrements address pointer.
Transfers address and bank values to working pointer. Decrements the address pointer (102-103/$66-$67). If the
Loads the working address pointer (102-103/$66-$67) with decrementing causes the address value to roll over from $0000
the parameter value calculated by the routine to transform in- to $FFFF, the bank pointer (104/$68) is also decremented.
put characters into byte values [$B7CE] in 96-97/$60-$61.
The calculated bank value in 98/$62 is loaded into the bank 47476 SB974 CHNGADD
pointer at 104/$68, Changes bank and address.
If the parameter evaluation routine [$B7A7] finds an address
47374 $B90E CALCCNT parameter for the command (indicated by a clear carry status
Calculates number of bytes and banks to display or move. bit), the address is loaded into the program counter storage lo-
Calculates the number of bytes and banks in an address range cations, 3-4/$03-$04, and the bank value is loaded into the
by subtracting the starting address value in 102-103/$66-$67 bank storage location, 2/$02. If no address parameter is pro-
from the ending address value in 96-97/$60-$61. The result vided, the values in the storage locations remain unchanged.
of the subtraction is left in 96-97/$60-$61. The number of
whole banks in the range is found by subtracting the starting 47491 $B983 PREPPTR
bank, in 104/$68, from the ending bank, in 98/$62, with the Prepares pointers for dual-address operations.
result left in 98/$62. Sets up the required pointers for those commands that require
both starting and ending address parameters (C, F, H, and T).
47394 8B922 The starting address is loaded into 102-103/$66-$67, with the
Decrements pointer/counter starting bank in 104/$68. The ending address is loaded into
Decrements the contents of 96-98/$60-$62 by 1 if entered at 2743-2744/$0AB7-$0AB8, with the ending bank in 2745/
47394/$B922, or by the value in the accumulator if entered at $0AB9. The number of bytes and banks affected, the differ-
47396/SB924. This is the line count for the display routine, ence between the starting and ending addresses, is calculated
the byte count for the disassemble routine, or the target ad- and stored in 99-101/$63-$65. If either address is missing or
dress pointer for compare/transfer routine.
262 263
47537 8B9B1 $BB72-$BFFF 47986-49151

if the ending address is less than the starting address, the and with 8/$08 (maximum number of digits) in the accumu-
carry status bit will be set upon exit to signal the error. lator and 3/$03 (number of bits-per-digit minus 1) in the Y
register.
47537 $B9B1 NUMXVRT
Performs number base conversion. 47760 8BA90 DISKCMD
Evaluates the parameter following the base symbol, then Handles @ (disk) commands.
prints the value of the number in four different number bases: Checks whether a parameter was found following the com-
hexadecimal, decimal, octal, and binary. The routine can con- mand. If so, the low byte of the value specifies the device
vert values in the range 0-1,048,575. For the hex value, a dol- number for the disk command. If no parameter is specified, a
lar sign is printed followed by four hex digits (five if the value device number of 8—the most common number for disk
is greater than 65535/$FFFF). For decimal, octal, and binary, drives—is used. If the first nonspace character following the
this routine provides the leading character (+ for decimal, & device number is a dollar sign, then the routine branches to
for octal, and % for binary), then uses the subroutine at 47875/$BB03 to display a disk directory. Any other characters
47687/$BA47 to display the values. The routine ends by following the device number parameter are sent over the serial
jumping back to the main loop " device as a command to the specified device. The routine ends
by jumping back to the main loop [$B08B],
47623 SBA07 HEXDEC Because the first item following the @ is always inter-
Converts a hexadecimal value to decimal. preted as a device number, you must specify some device
Converts the three-byte hexadecimal value in 96-98/$60-$62 number value (@8 10 is a valid command, but @I0 isn't be-
into a decimal value in BCD (binary coded decimal) format in cause the 10 will be interpreted as an invalid device number).
2720-2723/$0AA0-$0AA3. For example, converting the value However, an alternate syntax is possible. The parameter eval-
258/$102, stored in 96-98/$60-$62 as $02 $01 $00, will result uation routine [$B7A7] exits when it encounters a comma, so a
in $00 $00 $02 $58 being left in 2720-2723/ $0AA0-$0AA3. comma can be used alone to specify a null parameter. Thus, a
This routine takes advantage of the 8502's rarely used decimal command of the form @,I0 is acceptable—the default device
mode. To prevent the complications that would likely be number (8) will be used.
caused by interrupts occurring while the processor is set for
decimal mode, interrupts are disabled until the 8502 is reset to 47875 $BB03 SHOWDIR
its normal (binary) mode. Displays disk directory.
If the first nonspace character in the command string following
47687 $BA47 PNTOBD the @ command is a dollar sign, this routine is branched to
Prints octal, binary, or decimal values. because a disk directory requires more elaborate screen for-
Prints the octal or binary equivalent of a three-byte value. En- matting than the simple disk status messages otherwise re-
ter with 96-98/$60-$62 holding the three-byte value, the ac- turned by the @ command. This routine is a good model for a
cumulator holding the maximum number of digits allowed directory display using machine language. (You can't use this
(8/$08 for octal, 24/$18 for binary), and the Y register hold- routine directly because it ends with a branch that returns to
ing the number of bits to interpret per printed digit minus 1 the monitor main loop [$B08B].)
(2/$02 for octal, 0/$00 for binary). To print a decimal value,
enter at 47709/$BA5D with the decimal value in 2720-2723/ 47986-49151 $BB7 2 -$BFFF Unused
$OAA0-$OAA3 in BCD format (see the routine 47623/$BA07), The final 1166 bytes in the monitor ROM block are unused and
contain 255/SFF (except the last two bytes, which are $00 $3A).

264 265
Programming Example
The following program, which prints a countdown in both
decimal and hexadecimal, illustrates how several of the moni-
tor routines can be incorporated into your own ML programs.
Use the command J $F0B00 to execute the routine:
0B00 LDA #$10 ;Load $60-$62 w i t h t h e
0B02 STA $60 ; initial count
0B04 LDA #$27
0B06 STA $61 ; $002710 (10,000 decimal)
0808 LDA #$00 ; in this example
0B0A STA $62
0B0C JSR $B8B4 ;Clear a line for the display
OBOF JSR $B8AD ;Move print position to clear line
0B12 JSR $BA07 ;Convert byte value to decimal
0B15 LDA #$00 ;Set up for decimal p r i n t i n g
0B17 LDX #$08
0B19 LDY #$03
0B1B JSR $BA5D ;Print decimal value
0B1E JSR $B8A8 ;Print a space
0B21 JSR $B901 ;Transfer value to working storage
0B24 JSR $B892 ;Print hexadecimal value
0B27 JSR $B922 ;Decrement count v a l u e
0B2A BCS $0B0F ;Loop until value reaches zero
0B2C RTS

266
Screen Editor ROM
If the 128 is your first computer, or if you have upgraded to
the 128 from an earlier Commodore model, then you may not
appreciate the power and versatility of the 128's full-screen
editor. The editor is so well integrated into the system that
you may take it for granted. However, if you've ever worked
with an Apple, Radio Shack, TI-99, or other computer with
limited editing features, you'll appreciate the ability to move
the cursor to any position on the screen, insert and delete
characters, and reenter entire lines just by pressing RETURN
anywhere on the line. (Imagine the frustration of having to re-
type an entire line of input just because a single character was
mistyped.) And, with the addition of ESC key sequences, the
128's screen editor is even more powerful and versatile than
the earlier Commodore editors from which it is descended.
In earlier Commodore models, the screen editing routines
were an integral part of the Kernal ROM, but in the 128 the
routines have been separated and moved to their own block of
ROM, occupying locations 49152-53247/$C000-$CFFF. The
routines in this block handle keyboard input and all aspects of
text screen output for both the 40- and 80-column displays.
Special features such as bitmapped graphics and sprites are
handled in BASIC ROM, but editor routines set up the bit-
mapped and multicolor bitmapped screens.
The 40- and 80-column text displays constitute the main
output device for the 128, and thereby its primary mechanism
for communicating with the user. For the fundamentals of
how each display is generated, refer to the description of the
respective 40- and 80-column video chips in Chapter 8. Note
that both video sources remain on at all times, so it's possible
to connect both a composite and an RGBI or monochrome
monitor and have simultaneous 40- and 80-column displays.
At any given time, however, one of the screens will be consid-
ered active and the other inactive, That is, the cursor will
"live" on only one of the displays, and all printing will be di-
rected to that screen. The active screen is considered device 3,
the default output device for the system.

269
Windows tains a four-byte line link bitmap at 862-865/ $035E-$0361.
One of the most significant new features of the 128's screen
output is that it's window-oriented. That is, printing and Each screen line has a corresponding bit in the map. A bit set
cursor movement are confined to the boundaries of a win- to %1 indicates that the corresponding line is linked to the
dow—a defined area of the screen—rather than to the abso- one above. See the entries for location 862/$035E and for the
lute height and width of the screen. The window can be, and routines at 52084-52144/$CB74-$CBB0 for more information.
most often is, the full size of the screen, but it can be as small The 128 also implements a tab feature using a similar bit-
as a single character. Once you change the window bound- mapping scheme. The ten bytes at 852-861/$0354-$035D
aries, you must think in terms of windows rather than screens. provide a bit corresponding to each screen column, A bit in
For example, you should think of the SHIFT-CLR/HOME key the map set to %1 corresponds to a tab stop. See the entry for
as "clear window" rather than "clear screen." Only the cur- location 852/$0354 and for the routines at 51535-51597/
rently defined window area will be cleared when that key $C94F-$C98D for more information.
combination is pressed. You can also limit printing to certain The other major function of the screen editor is to handle
areas of the screen by modifying the window margins. The input from the keyboard. Although you tend to think of the
128's windowing capabilities are no match for those of more keyboard as an integral part of the computer, the system sees
advanced computers like the Macintosh and Amiga, but they it as just another peripheral, device 0. The keyboard is the de-
do offer exceptional control over display formatting. fault input device for the 128. It is normally scanned during
In order to understand how characters in the window are the jiffy IRQ sequence. See the entry for the SCNKEY routine
manipulated, you must first understand the distinction between [$C55D] for details. The system's two major Kernal input
physical lines and logical lines. A physical line is just one hor- routines, GETIN [$EEEB] and BASIN [$EF06], both call screen
izontal row of the window—the characters between the left editor routines to retrieve input from the keyboard.
and right margins. However, when you print characters on the An enhanced feature of the 128's keyboard is programma-
screen and the printing overflows from one row into the next, ble keys. Definition strings can be assigned to the eight func-
the editor will consider the physical lines to be linked together tion keys, F1-F8, and to the SHIFT-RUN/STOP combination
into a single logical line. Lines will continue to be linked until and the HELP key. The definitions can be of variable lengths,
either the RETURN or SHIFT-RETURN characters are encoun- with the restriction that the combined lengths of all ten defini-
tered. A logical line can be as short as a single physical line or tions cannot exceed 246 characters.
as long as the entire window, depending on how many char- The screen editor has another feature that makes redefin-
acters are printed before the RETURN or SHIFT-RETURN. (By ing the keyboard much easier than on previous Commodore
contrast, the Commodore 64 allows logical lines to span a models. The tables for decoding keyscan codes into character
maximum of two physical lines.) Some screen editor routines codes are still in ROM, but the pointers to the tables are now
operate on physical lines, others on logical lines. The entries maintained in RAM. Thus, redefining the keyboard is as sim-
in this chapter indicate when an operation affects an entire ple as redirecting the pointer to a new decoding table set up in
logical line. RAM. See the entry for locations 830-841/$033E-$0349 for
details.
Line Links
The system for linking lines on the 128 is considerably differ- Screen Editor Jump Table
ent from that of earlier Commodore models. For example, the Most major screen editor routines can, and should, be entered
Commodore 64 maintains a table at 217-242/$D9-$F2 which through their respective entries in the following jump table.
contains the high bytes of the first address on each screen line, Each three-byte table entry consists of a JMP opcode followed
with the high bit of each address byte used to indicate whether by the address of the target routine.
the line is linked. The 128 has no such table; instead, it con-

270
271
49152 3C00F 49167
$cooo

49152 $cooo JCINT RETURN character, the value 13/$0D. If the flag is zero, the
Entry point for the routine at 49275/$C07B/ which establishes routine accepts characters from the keyboard and displays
the default characteristics for both the 40- and 80-column dis- them on the screen until RETURN is pressed. It then returns
plays. This entry is part of both the reset and RUN/STOP- the first character of the input in the accumulator and sets the
RESTORE sequences. No preliminary setup is required, but source flag to a nonzero value so that subsequent calls retrieve
the behavior of the routine is affected by the setting of the ini- characters from the input line displayed on the screen. In
tialization status flag (2564/$0A04). The keyboard decoding either case, the source flag should be set only before the first
table pointers and screen editor indirect vectors are initialized call to this routine for any given line of input.
only when bit 6 of the flag is %0. If you wish to preserve de- For keyboard input, the starting and ending columns and
coding table pointers or indirect vectors while resetting other the row for the input line are set automatically. For screen in-
screen editor characteristics, set this bit to %1 before you call put, the character is read from the row specified in 235/$EB at
the routine. the column specified in 236/$EC. These locations normally
hold the current cursor position and are advanced one position
to the right after each call to this routine. However, the loca-
49155 $C003 JDISPLY tions can also be reset to any row and column you desire. The
Entry point for the routine at 52276/SCC34, which deposits a screen input line ends on the row specified in 2608/$0A30 at
screen code and attribute value at the current cursor position. the column specified in 234/$EA. Neither of these locations is
Call this entry with the accumulator holding the screen code set automatically, so you must specify the ending position
(not the character code) for the desired character and the X before calling for input from the screen. The X and Y register
register holding the attribute value for the character. contents will be preserved during this routine.
49158 SC006 JKEYIN 49164 $C00C JPRINT
Entry point for the routine at 49716/SC234, which retrieves a Entry point for the routine at 50989/$C72D, which prints a
single character from the keyboard. (In official Commodore lit- character at the current cursor position using the current
erature, this routine has the rather nondescriptive name LP2.) attribute (in 241/$F1). This routine is used by the Kernal
This entry is used by the Kernal GETIN routine [SEEEB] when BSOUT routine [$EF79] when the screen is specified as the
the keyboard is the input device. (The keyboard, device 0, is output device. (The screen, device 3, is the 128's default out-
the 128's default input device.) Upon return, the accumulator put device.) Call the entry with the accumulator containing the
will contain the retrieved character. Be sure to see the warning character code (not the screen code) for the character to be dis-
in the KEYIN entry about calling this routine directly. played. The accumulator and X and Y register contents are
preserved during this routine.
49161 C009 JGETSCRN
Entry point for the routine at 49819/$C29B, which retrieves a 49167 $C00F JSCRORG
character from a line of keyboard or screen input. (In official Entry point for the routine at 52315/$CC5B, which returns
Commodore literature, this routine has the rather nondescrip- information about the current window size. This entry is the
tive name LOOP5.) This entry is used by the Kernal BASIN target of the Kernal jump table entry JSCRORG [$FFED], Upon
routine [$EF06] when input is requested from the keyboard return, the X register will hold the number of columns (minus
(device 0) or the screen (device 3). The input source is deter- 1) in the current window, and the Y register will hold the
mined by the value in the flag at 214/SD6. When the flag has number of rows (minus 1). The accumulator will hold the
a nonzero value, the character at the current cursor position is maximum column number for the active screen (39 for the 40-
read and returned in the accumulator. When the end of the column display or 79 for the 80-column display).
line of input is reached, the routine returns the code for the
272 273
49170 $C012 $C02A 49194

49170 $C012 JSCNKEY 49182 $C01E JESCAPE


Entry point for the routine at 50525/$C55D, which scans the Direct entry point into the escape sequence handling routine
keyboard matrix for a keypress. This entry is the target of the [$C9BE], Normal entry into the handler begins with an indi-
Kernal jump table entry JSCNKEY [$FF9F]. If a key is found to rect jump through the ESCVEC vector (824-825/$0338-$0339).
be pressed, its corresponding character code will be placed in That vector normally points to this table entry, which in turn
the keyboard buffer for retrieval by the GETIN or BASIN jumps back into the handling routine at the point immediately
routines, unless the key is a shift key or programmable key. following the indirect jump.
Both of those get special handling (see the SCNKEY routine
for details). 49185 $C021 JKEYSET
Entry point for the routine at 52386/$CCA2, which redefines
49173 $C015 JREPEAT a programmable key. This entry is the target of the Kernal
Entry point for the routine at 50769/$C651, actually an alter- jump table entry JPFKEY [$FF65]. Call this entry with the X
native entry into the SCNKEY routine. At this point, the rou- register containing the key number (1-10), the Y register con-
tine expects location 212/$D4 to contain the keyscan matrix taining the length of the definition string, and the accumulator
code for the current key, 211/SD3 to hold the status of the holding the address of a two-byte zero-page pointer to the
shift keys, and 204-205/$CC-$CD to point to the keyboard string. The zero-page byte immediately following the pointer
decoding table selected according to the shift key status. This should contain the number of the memory bank in which the
table entry is most useful when intercepting the KEYVEC indi- string resides.
rect vector (see the entry at 82 6/$ 033A for details).
49188 $C024 JSCNIR9
49176 $C018 JPLOT Entry point for the routine at 49556/SC194, which handles
Entry point for the routine at 52330/$CC6A, which reads or the screen editor portion of the IRQ handling sequence. This
sets the cursor position. This entry is the target of the Kernal includes setting up the screen display mode, scanning the key-
jump table entry JPLOT [$FFF0], If called with the carry bit board, and managing the cursor for 40-column display.
clear, the cursor is moved to the row specified in the X register
and the column specified in the Y register (the row and col- 49191 $C027 JIN1T80
umn settings are relative to the current home position of the Entry point for the routine at 52748/SCE0C, which initializes
window). The carry bit will be set upon return if the specified the character patterns for the 80-column display. This entry is
position is outside the current window boundaries. If called the target of the Kernal jump table entry JINIT80 [$FF62]. The
with the carry set, the routine returns with the row number of routine copies the contents of the 40-column display's charac-
the current cursor position in the X register and the column ter ROM ($D000-$DFFF in bank 14) into the character defini-
number in the Y register (again, the numbers will be relative tion area of the 8563 chip's private block of RAM.
to the current home position of the window).
49194 $C02A JSWAPPER
49179 $C01B JCRSR80 Entry point for the routine at 52526/$CD2E, which switches
Entry point for the routine at 52567/$CD57, which moves the active screen displays. This entry is the target of the Kernal
cursor on the 80-column display to the row and column speci- jump table entry JSWAPPER [$FF5Fj. The routine exchanges
fied in 235/$EB and 236/$EC, respectively. The 40-column the screen variable tables, tab stop tables, and line link tables,
display's cursor is maintained by software, so it follows these and toggles the active screen flag (215/$D7). This will redirect
pointers automatically, but the position of the 80-column printing to whichever screen was previously inactive.
cursor must be set explicitly.

274 275
49197 8C02D 8C07B 49275

49197 SC02D JWINDOW 49275 $C07B CINT


Entry point for the routine at 51739/$CA1B, which sets the Initializes screen editor constants, variables, tables, and vectors.
position of a corner of the output window. To set the top row (This routine has a screen editor jump table entry at 49152/$CO00
and left column of the window, call this entry with the carry and a Kernal jump table entty at 65409/SFF81.)
bit clear, the accumulator holding the row number, and the X Sets the default values for all working storage memory loca-
register holding the column number. To set the bottom row tions used by screen editor routines. This routine is part of
and right column of the window, call this entry with the carry both the reset and RUN/STOP-RESTORE sequences. The CIA
bit set, the accumulator holding the row number, and the X chip register (56576/$DD00) that controls VIC-II chip memory
register holding the column number. banking is set to have the VIC-II see memory from its bank 0,
corresponding to addresses 0-16383/$0000-$3FFF in block 0
of system RAM (VIC-II banks are different from MMU banks;
49200 SC030 Unused see Chapter 8 for more details). Bit 1 of the processor I/O reg-
Three unused bytes filled with the value 255/$FR ister (l/$01) is set to %1 to make block 1 of color memory
(the block for 40-column text screen color) visible at
49203 8C033 SADDRTBL 55296/$D800. The Kernal CLRCH routine [$FFCC] is called to
Table of screen line starting addresses. reset normal I/O sources: input from the keyboard and output
Locations 49203-49227/$C033-$C04B hold the low bytes of to the screen. The SID chip volume register (54296/$D418) is
the address in 40-column screen memory for the column 0 po- set to zero to silence any sound output (a step not present in
sition in each of the 25 screen lines. Locations 49228-49252/ the Commodore 64's CINT routine). Screen editor RAM vari-
$C04C-$C064 hold the high bytes for the line addresses for ables and constants are initialized as follows:
the default 40-column screen position (at 1024/S0400). These Location Value Meaning
table values are used in conjunction with the screen base ad- 208/$D0 0 Keyboard buffer empty
dresses, 2619/$0A3B for the 40-column screen or $2606/$0A2E 2O9/$D1 0 No function key pending
for the 80-column screen, to calculate the actual starting ad- 214/$D6 0 Input from the keyboard
dress for each line of screen and attribute memory. 216/$D8 0 40-column display set for text mode
217/SD9 0 CHAREN shadow cleared
49253 $C065 SCNVCTRS 2592/$0A20 10/SOA Maximum of 10 keys in buffer
2593/$0A21 0 Printing pause flag cleared
Table of default screen editor indirect vectors. 2594/$0A22 128/$80 All keys repeat if held down
The five two-byte values here are copied to the screen editor 2595/$0A23 4/$04 Delay between repeats initialized
indirect vector table at 820-829/$0334-$033D when the system 2596/$0A24 10/$0A Delay before repeats initialized
is reset. In each case, the default indirect vector merely returns 2598/$0A26 0 40-column cursor will blink
control to the location immediately following the indirect jump, 2599/$0A27 10/$0A Cursor blink switch initialized
2600/$OA28 10/$0A Cursor blink countdown initialized
49263 8C06F KEYPTRS 2603/$0A2B 96/$60 80-column cursor set for blinking block
Table of default keyboard decoding table pointers. 2604/$0A2C 20/$14 40-column text screen and character base
initialized (screen at 1024/$0400, character
The six two-byte values here, the addresses of the ROM key- set seen at 4096/$1000)
board decoding tables, are copied to the keyboard decode 2605/$0A2D 120/$78 40-column bitmap and matrix base initial-
pointer table at 830-841/$033E-$0349 when the system is ized {matrix at 7168/$1COO, bitmap at
reset 8192/$2000)
2606/$OA2E 0 Base page for screen memory in 8563
RAM (screen at 0/$0000)

276 277
49275 $C07B SC15E 49502

2607/$0A2F 8/$08 Base page for attribute memory in 8563 49474 SC142 CLEAR
RAM (attributes begin at 2048/$0800) Clears the current window and homes the cursor.
2612/$0A34 208/$DO Default raster line for split screen (text por- Also handles clear screen character, CHR$(147).
tion starts at line 20)
2619/$0A3B 4/$04 Base page for 40-column screen memory Sets the cursor to the home position and clears rows until the
(value read from 49228/$C04C) bottom of the window is reached, then falls through into the
following routines to return the cursor to the home position
Also during this setup, the active screen flag (215/$D7) is and set pointers.
set for 40-column mode, and bit 7 of the MMU mode configu-
ration register (54533/$D505) is set to %1 to enable reading of
the 40/80 DISPLAY key. While the 40-column display is ac- 49488 $C15O HOME
tive, default tab stops are set and default screen editor vari- Moves the cursor to the home position of the current window.
ables are copied from the table at 52852/$CE74 into 224-249/ Sets the cursor row (235/$EB) and starting row for input
$E0-$F9. At the same time, default variables for the 80-col- (232/$E8) to the top row of the current window (229/$E5),
umn display are copied from the table at 52878/$CE8E into and the cursor column (236/SEC) and starting column for in-
2624-2649/$0A40-$0A59. However, there is a bug in this put (233/$E9) to the left margin of the current window
portion of the routine: The copy loop uses an index of 26/$lA (230/$E6), then falls through into the next routine to set
instead of the proper value 25/$19, so the byte following the pointers to that line.
40-column table is also copied to 250/$FA, and the byte fol-
lowing the 80-column table is also copied to 2650/$0A5A. 49500 $C15C SETLINE
The screen editor indirect vectors (820-829/$0334-$033D) are Sets starting address pointers for the current line.
initialized from the table at 49253/$C065. Loads the line number where the cursor currently resides
Next, bit 6 of the initialization status flag (2564/$0A04) is (235/$EB) into the X register, then falls through into the next
checked. If the bit is set to % 1 , the following steps to load routine to set pointers to that line.
keyboard table pointers and key definition strings are skipped.
If the bit is clear, the keyboard decoding table pointers 49502 $C15E SETADDR
(830-841/$033E-$0349) are initialized from the table at Sets starting address pointers for a specified line.
4926/$C06F, and the default programmable key definitions Calculates the screen memory address corresponding to the
are copied to the definition area at 4096/$1000 from the table leftmost column of the screen line specified in the X register
at 52904/$CEA8. After the values are copied, bit 6 of the flag and places the address in the pointer at 224-225/$EO-$E1.
is set to %1 to indicate that these steps have been performed. The low byte of the address comes from the table at 49203/
The flag is cleared before this routine is called by the reset $C033 (multiplied by 2 if the 80-column display is active). The
routine [$EOO0], so these steps will always be performed dur- high byte is calculated by taking a value from the table at
ing a reset. However, the RUN/STOP-RESTORE sequence 49228/$C04C, masking off all but the lowest two bits (and
[$FA53] does not affect the flag, so any changes to pro- multiplying the result by 2 if the 80-column screen is active),
grammable key definitions or keyboard decoding table point- then ORing the result with the starring page value for the ac-
ers will remain intact after RUN/STOP-RESTORE. tive screen—2619/$0A3B for the 40-column display or
Default tab stops are then established for the 80-column 2606/$0A2E for the 80-column display.
screen, and the 80-column window is reset to full screen size Next {at 49532/$C17C), the attribute memory address
and cleared. The 40-column window is also reset to full screen corresponding to the leftmost column of the specified screen
size and cleared. Finally, the position of the 40/80 DISPLAY line is calculated and placed in the pointer at 226-227/
key is read (by checking bit 7 of 54533/$D505), and the se- $E2-$E3. The low byte of the address is taken directly from
lected display will become the active screen upon exit. the low byte of the screen memory pointer (224/$E0). For the

278 279
49556 $C194
SC234 49716

40-column screen, the high byte is calculated by masking off


screen is established. If a split screen is in use, the scan line
all but the lowest two bits of the screen memory pointer high
value for the split, stored in 2612/$0A34, is loaded into the
byte (225/$El), then ORing the result with the value 216/$D8
VIC-II's raster compare register (53266/SD012). The processor
(40-column color memory always starts at $D80O). For the 80-
column screen, the high byte is calculated by masking off all I/O register (l/$01) is set to make block 0 of color memory—
but the lowest three bits of the screen memory pointer high the block for multicolor source 3—visible at 55296/SD800,
byte (225/$El), then ORing the result with the attribute mem- and the VIC memory control register (53272/$D018) is loaded
ory starting page value (2607/$0A2F). with the bitmap base address, stored in 2605/$0A2D. Bit 5 of
VIC control register 1 (53265/$D011) is set to %1 to enable
the bitmapped display. If the mode flag indicates that multi-
49556 $C194 SCNIRQ color bitmapped mode was selected, bit 4 of VIC control regis-
Performs screen and keyboard portion of IRQ functions.
(This routine has a jump table entry at 49188/$C024.) ter 2 (53270/SD016) is also set to %1 to enable that feature.
At 49631/$C1DF, the 40-column text screen (or the text
Begins by checking whether the current IRQ is the result of a area of a split screen) is established. The VIC-II's raster com-
raster interrupt (see Appendix A for a discussion of interrupts). pare register (53266/$D012) is loaded with 255/$FF to trigger
If it's not, then this can't be a normal jiffy IRQ, so the routine the offscreen raster interrupt. The processor I/O register
skips the screen setup steps and just scans the keyboard and (l/$01) is set to make block 1 of color memory—the block for
blinks the cursor before exiting. If it is a raster interrupt, the 40-column text color—visible at 55296/$D800, and the VIC
routine checks whether the screen mode flag (216/$D8) con- memory control register (53272/$D018) is loaded with the
tains the value 255/$FF. If so, the routine again skips ahead to screen and character memory base value, stored in $2604/
scan the keyboard, blink the cursor, and exit. The 128 itself $0A2C. The VIC control register bits for bitmapped and multi-
never puts that value into the flag, but you can use this fea- color are cleared to disable those display modes. Finally, a
ture when you set up your own custom screen mode or raster short delay loop is executed if the text portion of a split screen
interrupt (see the entry for location 216/$D8 for details). is being established. This is to insure that the switch from bit-
The routine then checks whether the raster is currently on mapped to text modes occurs while the raster is off the right
scan line 256 or higher. If so, the interrupt occurred while the edge of the visible screen area, which prevents the flicker that
raster was beyond the visible portion of the screen. This off- would occur if the change occurred in the middle of scanning
screen raster interrupt is the normal jiffy IRQ source for the a line.
128—quite a different technique from the CIA timer-driven If the IRQ source is a raster interrupt which occurred on
jiffy IRQ for the Commodore 64. (The interrupt is actually the visible screen (to set up the text portion of a split screen),
triggered at line 255, but the raster will have moved to the the routine exits at this point with the status register carry bit
next scan line by the time its position is checked here.) For an clear. In all other cases, the routines to scan the keyboard for a
offscreen interrupt, the VIC-II chip registers will be set accord- keypress [$C55D] and handle 40-column cursor blinking
ing to the screen mode flag value, using the step at 49631/ [$C6E7] are called, and the carry bit will be set upon exit.
$C1DF for mode 0 (a full text screen) or the one at 49587/
$C1B3 for a bitmapped or split-screen mode. 49716 3C234 KEYIN
If the interrupt occurred above scan line 255, bit 6 of the Performs GETIN from keyboard.
screen mode flag is tested. If that bit is set to % 1 , a split (This routine has a jump table entry at 49158/$C006.)
screen mode is in use, so a branch is taken to 49631/$C1DF Checks 2O9/$D1 to see whether any characters remain to be
to set VIC-II registers for the text portion of the display. read from the definition string for the most recently pressed
Otherwise, the registers are merely reset for whichever mode programmable key. If so, a character is read from the defini-
is currently in use, which produces no obvious effect. tion area, with the value in 210/$D2 used as an offset from
At 49587/$ClB3, the bitmapped or multicolor bitmapped the start of the definition area (4106/$100A). The count of re-
280
281
49752 $C258 $C29B 49819

maining characters is decremented and the offset into the defi- pointers to the input screen line and jumps to 49852/$C2BC
nition area is incremented; then the routine exits with the in the following routine to exit with the accumulator holding
character in the accumulator, the status register carry bit clear, the first character of the input—unless no other characters
and IRQ interrupts reenabled. were typed before RETURN, in which case the routine
If no programmable key string characters are pending, the branches to 49829/$C2A5 in the following routine to exit with
character at location 842/$034A, the first character in the key- the RETURN character code in the accumulator.
board buffer, is returned in the accumulator. Any remaining
characters in the buffer are shifted one position to the left to 49819 8C29B GETSCRN
remove the retrieved character from the buffer; then the count Performs BASIN from screen or keyboard.
of characters in the buffer (208/$D0) is decremented. Upon (This routine has a jump table entry at 49161/$C009.)
exit, the status register carry bit will be clear and IRQ inter-
Stashes the contents of the X and Y registers on the stack for
rupts will be reenabled.
later restoration, then checks the input source flag (214/$D6).
Unlike other major screen editor routines with jump table If the flag value is zero, indicating input from the keyboard,
entries, you should avoid calling this one directly. To retrieve the preceding routine is used to accept a line of input from the
keypresses, call the Kernal GETIN routine via its jump table keyboard. If the flag is nonzero, but with bit 7 clear (%0), the
entry (65508/$FFE4) with the current input device (153/$99) routine branches ahead to 49852/$C2BC to retrieve a charac-
set to zero to indicate keyboard input. The Kernal GETIN rou- ter from a screen line. If bit 7 is set (%1), the end of the input
tine [$EEEB] verifies that a character is waiting to be read from line has been reached, so (at 49829/$C2A5) the input source
either a programmable key string or the keyboard buffer flag is reset to zero and a RETURN character is printed unless
before it calls this routine. If you call this routine with no output is to a device other than the screen. The routine then
characters available (with 208/$D0 and 2O9/$D1 both con- exits with the RETURN character code, 13/$0D, in the accu-
taining zero), you'll cause serious problems. The contents of mulator (the X and Y registers will be restored to their original
all page 3 locations above the keyboard buffer (and part of 40-
column screen memory in page 4) will be garbled. This area values).
includes the vital indirect fetch and store routines; you'll have At 49852/$C2BC, the screen code at the current cursor
to reset the computer to recover. position is retrieved and converted into the corresponding
character code (disassemble $C2C2-$C2D8 to see the conver-
49752 8C258 KEYLIN sion process). The routine then checks whether the end of in-
Accepts a line of keyboard input and returns the first character. put has been reached. If so, bit 7 of the input flag is set to %1
(The normal entry point for this routine is 49755/$C25B.) to indicate that all characters have been read from the current
input line.
Turns on the cursor, then waits until a character is available in
the keyboard buffer or from a programmable key definition The cursor is then moved right to the next character posi-
string. The routine above is called to retrieve the character, tion in the line. If the calculated character code is 222/$DE,
and unless it's a RETURN character, code 13/$0D, the routine the pi (K) character, it's replaced with 255/$FF, an alternative
loops to display the character on the screen at the current value (and BASIC token) for that character. Before exiting, the
cursor position (using the PRINT routine [$C72D]), move the original X and Y register values placed on the stack at the start
cursor to the next position, and wait for another character to of the routine are restored, and retrieved character code is
become available. When RETURN is encountered, the routine loaded into the accumulator. The status register carry bit will
falls out of this loop and stores the RETURN code in the input be clear upon exit.
source flag (214/$D6) so that subsequent calls to the keyboard Although there are no bugs in this routine, its calling
BASIN routine will retrieve characters from the line of input Kernal routine (BASIN [$EF06]) will not correctly retrieve a
that has been displayed on the screen. The routine then sets line of input from the screen (keyboard input functions prop-
erly). The screen input setup portion of BASIN has two major
282 283
49919 8C2FF SC320 49952

flaws: It does not set the ending row for input (2608/$0A30), and X and Y registers with the values stored on the stack
and it resets the input source flag (214/$D6) before each char- when the BSOUT routine was entered [$C72D], so all register
acter is retrieved (so that the setting of bit 7 is lost). Together, values are preserved during BSOUT. The status register carry
these bugs make it impossible to determine when the end of bit will be clear upon exit.
the input is reached. The following is an example of the Because the address of this routine is pushed onto the
proper technique for retrieving a line of input from the screen: stack at the start of the screen BSOUT routine [$C72D], all
LDA $EB ;Set ending row for input screen printing subroutines will return to the calling routine
STA $0A30 ; (same as starting row) via this routine.
LDA $E7 ;Set ending column for input
STA $EA ; (to right window margin) 49952 $C320 SETCHAR
LDA #$03 ;Set screen as input source Handles character printing for screen BSOUT.
STA $D6 ; (any nonzero value will do) Handles all character display functions for the screen BSOUT
LDX #$00 ;Initialize storage offset routine [$C72D], including quote, reverse, and autoinsert
LOOP JSR $C009 ;Read character from the screen modes. The routine has several entry points, depending on the
CMP #$0D ;Is it RETURN?
BEQ EXIT ;Exit if so desired effect. For any of these entry points, the code to be
STA $0C00,X ;Stash character from screen printed should be in the accumulator upon entry:
INX increment the offset 49952/$C320: Entry point for printing character codes
BNE LOOP ;Loop for another character 160-254/$A0-$FE. Prior to entry, bit 7 of the code will have
EXIT RTS been cleared to %0. This step forces bit 6 to % 1 , so character
codes 160-191/$A0-$BF become screen codes 96-127/
49919 $C2FF QUOTECK $60-$7F, and character codes 192-254/$C0-$FE become
Handles quote mode flag. screen codes 64-126/$40-$7F.
Checks whether character value in the accumulator is 34/$22, 49954/$C322: Entry point for printing character codes
the quote (") character. If so, bit 1 of the quote mode flag 3 2-12 7/$ 20-$ 7F. Prior to entry, the character code will have
(244/$F4) is toggled, turning quote mode on if it was previ- been converted to a screen code by the screen BSOUT control
ously off or off if it was previously on. The character value routine [$C72D]. This step checks whether reverse mode is ac-
will still be in the accumulator upon exit. tive (indicated by a nonzero value in 243/$F3). If that mode is
not active, the next step is skipped.
49932 $C30C PRNTEXIT 49958/$C326: Entry point for printing characters in reverse
Provides common exit for screen BSOUT subroutines. video; also used for character codes less than 32 and for codes
128-159 when those characters are printed in quote mode or
Stores the current character code (239/SEF) as the previous
at a pending insert. For codes 1-31/$O1-$1F, the character
character code (240/SFO). The subroutine to move the cursor
code is used unchanged, so those characters are represented
on the 80-column screen [$CD57] is called to actually move
by the reverse images of screen codes 1-31/$O1-$1F. For char-
the cursor if that display is active. This is necessary because
acters 128-159/$80-$9F, bit 7 will have been cleared to %0,
the 80-column screen's cursor is controlled by hardware (not
and bit 6 set to %1 prior to entry, so those characters are rep-
by software, like the 40-column screen's cursor), so it doesn't
resented by the reverse images of screen codes 64-95/$40-$5F.
automatically move when its corresponding row and column
If autoinsert mode is active (indicated by bit 7 of 246/$F6
pointers are updated. The pending insert count (245/$F5) is
set to %1), a space is inserted at the current cursor position
checked. If it's nonzero, the quote mode flag is cleared. As a
before the character is printed. (The count of inserts pending is
result, you won't go into quote mode if you type the quote
also cleared; you can't have inserts pending in autoinsert
character for a pending insert unless the quote is typed for the
mode.) The subroutine at 52271/$CC2F is used to place the
last insert. Before exiting, the routine reloads the accumulator
284 285
49982 8C33E SC445 50341

character on the screen at the current cursor position using the


current attribute value from 241/$F1; then the routine falls
50086 $C3A6 SCROLL
through into the following one to move the cursor to the next Scrolls the window up one line.
position. Copies all lines in the window up one row. The top line will
be lost and the bottom line will be cleared. If the new top line
49982 $C33E UDCRSR was originally linked to the line scrolled off the window, it
Updates the cursor position. will be unlinked.
Compares the current cursor column (in the Y register upon 50140 $C3DC SCRLUP
entry) against the right window margin (231/$E7). If the
Copies lines up one row and clears bottom line.
cursor is at the right edge of the window, the routine checks
whether the cursor is also already on the bottom line of the Copies all lines in the window below the one specified in the
window. If so, the scrolling enable flag (248/SF8) is checked. X register up one row. The specified line will be overwritten,
The cursor will not be moved if scrolling is not allowed when and the bottom line will be cleared and unlinked. The line
the cursor reaches the lower right corner of the window. Oth- link bits for each line are also copied to the new positions so
erwise, the cursor is moved right one position. If the cursor that the links will be maintained intact.
moves beyond the right window margin, a new blank line is This routine also checks column 7 of the keyboard matrix
inserted and linked to the one above, and the cursor is moved (see the entry at 50525/$C55D) to test the Commodore key. If
to the left margin of this new line. However, linking can be that key is found to be pressed, a delay loop is executed. Since
disallowed by setting bit 6 of 248/$F8 to % 1 . In this case, the this is the subroutine used to open new lines at the bottom of
cursor will simply wrap around to the left margin without in- the window while printing, this feature allows the Commo-
serting a new line. This link-disable feature is not directly sup- dore key to slow screen scrolling. There is no simple way to
ported on the 128—there's no character or ESC sequence to defeat this feature.
disable linking—so you must set or clear the bit directly. See
the entry for location 248/$F8 for details. 50189 $C40D MOVLINE
Copies a line.
50019 8C363 NEXTLIN Copies characters from the line specified in the X register to
Moves the cursor down one line. the one pointed to in 224-225/$E0-$El, and copies the attri-
butes for the line to the attribute line pointed to in 226-227/
Moves the cursor down to the next row in the window. If the
cursor is already on the bottom row of the window, the scroll- $E2-$E3. The copying begins at the column specified in the Y
ing enable flag (248/$F8) is tested. If scrolling is allowed, the register and extends to the left window margin. The copy is
window contents are scrolled upward by one row, and the performed on whichever display, 40- or 80-column, is cur-
bottom row (where the cursor now resides) is cleared. If scroll- rently active. The X register will still contain the source line
ing is disabled, the cursor is wrapped to the top row of the number upon exit.
window.
50341 $C4A5 CLRLINE
Clears a line.
50044 $C37C OPENLIN
Inserts a new line linked to the one above. Writes a space character with the current attribute (from
241/SF1) at every character position between the left and right
Copies all lines in the window below the one on which the window margins of the line specified in the X register. The op-
cursor currently resides down one row (the bottom line will be eration is performed on whichever display, 40- or 80-column,
lost). The line on which the cursor resides is then cleared and is currently active. The link bit for the line is also cleared, un-
linked to the one above. linking the line. Upon exit, the X register will still contain the

286 287
50492 6C53C SC55D 50525

line number and the Y register will hold the column number the key at row 0 of column 0 (INST/DEL), to 87, for the key
of the right window margin. at row 7 of column 10 (NO SCROLL).
Several keys on the 128 keyboard are not included in the
50492 $C53C keyscan matrix. The CAPS LOCK key (read at bit 6 of location
Fills or copies a block of 8563 RAM. l/$01) is tested at the start of this routine. The 40/80 DIS-
Uses the hardware fill/copy feature of the 8563 chip to fill or PLAY key (read at bit 7 of location 54533/$D505) is tested
copy a block of the 8563's private 16K of RAM. The block during the screen initialization routine [$C07B]. The SHIFT
starts at the address currently in 8563 registers 18-19/$12-$13 LOCK key is a switch that has the effect of holding down the
and ends at the address in 2620-262 l/$0A3C-$0A3D. The op- left SHIFT key. The RESTORE key isn't read at all; it's con-
eration is determined by the state of bit 7 of 8563 register nected to circuitry which generates an NMI interrupt signal to
24/$18. If the bit is %0, the block is filled with the value in the processor when the key is pressed (see the NMI handling
8563 register 31/$1F. If the bit is % 1 , the contents of locations routine [$FA40]).
starting at the address in registers 32-33/$20-$21 are copied If the key at the intersection of the row and the column
to the block. being tested is pressed, the row bit will be %0; otherwise, it
will be % 1 . If a key is found to be pressed, the character code
50525 $C55D SCNKEY for the key is read from the default decode table. Unless the
Scans keyboard matrix for keypress. character code read from the table is 8, 4, 2, or 1, the keyscan
(This routine has a screen editor jump table entry at 49170/SC012 code (not the character code) for the key is stored in 212/$D4,
and a Kernal jump table entry at 65439/$FF9F.) and the routine goes on to scan the next position. However, if
Begins by checking bit 6 of location l/$01 to determine the the character code has one of these values, that value is ORed
position of the CAPS LOCK key. If that key is down, the shift with the shift key flag to set a bit in the flag value.
key flag (211/$D3) will be set to 16/$10 (bit 4 set to %1); Note that it's the keyboard decode table, not the physical
otherwise, it will be cleared to zero. Next, the keyscan code keyboard layout, that determines which keys are treated as
(212/$D4) is initialized to 88/$58, the value for no key shift keys. In the default ROM keyboard decode table at
pressed. The keyboard matrix is checked to see whether any 64128/$FA80, the ALT key (keyscan code 80) decodes as
keys are pressed. If not, the routine jumps to 50839/$C697 in character code 8, the CONTROL key position (keyscan code
the next routine to set 88 as the matrix code value. If a key 58) holds character code 4, the Commodore logo key position
has been pressed, the routine loads the keyboard decode table (keyscan code 61) holds character code 2, and the left and
pointer (204-205/$CC-$CD) from 830-831/$033E-$033F, right SHIFT key positions (keyscan codes 15 and 52, respec-
which holds the address of the default table, and begins the tively) both hold character code 1. Thus, pressing either SHIFT
process of determining which key is being pressed. key normally sets bit 0 of 211/$D3 to % 1 , and the Commo-
The keyboard is arranged electrically as a matrix of 11 dore, CONTROL, and ALT keys set bits 1, 2, and 3, respec-
columns and eight rows (Figure 7-1). To scan for a keypress, tively. (You can change this by modifying the default
the CIA or VIC port bit for one of the 11 columns is set to %0, keyboard table. See the entry at 830-831/$033E-$033F for
while the bits for all other columns are held at % 1 . While the more information.) Since the matrix code isn't stored when
column bit is %0, the CIA port for the eight rows (56321/ these shift keys are processed, 212/$D4 will never contain 15,
$DC01) is read, and, one by one, the bits corresponding to the 52, 58, 61, or 80 while the standard decode table is being
rows are tested. The count of scanned keys is incremented used. So the SHIFT, ALT, Commodore, and CONTROL keys
after each row bit is tested, so each key in the matrix has a can't normally be detected by checking 212/&D4. Their states
keyscan code corresponding to the number of keys scanned must be determined from 211/$D3.
when that key's position is tested. The codes range from 0, for

288 289
50525 $C55D $C55D 50525

All eight rows in each of the 11 columns are scanned,


whether keypresses are detected or not. Since there's only one
location (212/$D4) for storing the matrix code, only the key
with the highest code value will be recorded if more than one
key is detected during the scan. However, because of the way
the keyboard is wired, a false value may be returned if three
or more keys are held down simultaneously. For example, if
you hold down the J, K, and L keys simultaneously, the matrix
code returned will be 45, the code for the colon (:) key. The
special shift keys are an exception: 211/$D3 will show the
state of all five (SHIFT, Commodore, CONTROL, ALT, and
CAPS LOCK) on every keyscan.
Once the keyscan is complete, the matrix code of the
keypress is loaded into the accumulator. At this point, the rou-
tine takes an indirect jump through the KEYVEC indirect vec-
tor (826-827/$033A-$033B). Normally, this vector points to
5O657/$C5E1—the address immediately following the indirect
jump. However, if you wish to manipulate the keyscan in any
way, you can redirect the vector to your own routine in RAM.
See the KEYVEC entry for details.
Next, the routine checks whether the matrix code was
87/$57, the code for the NO SCROLL key. If so, the routine
checks bit 6 of the flag at 247/$F7 to determine if pausing is
allowed. If the bit is set, printing cannot be paused. This
enable/disable feature isn't directly supported—there's no
character or ESC sequence to set or clear bit 6 of the flag loca-
tion—so yOU must change the location directly (see the entry
for location 247/$F7 for details). If pausing is allowed, the
pause flag (2593/S0A21) is toggled; so pressing NO SCROLL
will alternately halt and resume printing to the screen.
NO SCROLL is a misnomer. The key doesn't stop scroll-
ing; it halts printing. PAUSE would have been a better name
for this key. The pause feature is implemented in the screen
BSOUT routine [$C72D].
The shift key flag (211/$D3) is tested to determine
whether the Commodore and SHIFT keys are both pressed. If
so, bit 7 of the case switching flag (247/$F7) is tested to deter-
mine whether this combination is allowed to switch character
sets If so, the character set in use is switched, either by tog-
gling bit 7 of the attribute flag (241/$F1) if the 80-column dis~
play is active, or by toggling bit 1 of the character set base
address (2604/$0A2C) if the 40-column display is active.

290 291
50769 8C651 50769
SC651

If the shift key flag indicates that the CONTROL key is


pressed, the routine checks whether the current matrix code is peat (the default setting for the 128). If bit 6 is set to % 1 , no
13/$0D, indicating that CONTROL and the S key have been keys repeat, so the routine exits. If bits 6 and 7 of the repeat
pressed simultaneously. The CONTROL-S combination pro- enable flag are both %0, only the cursor, space, and INST/DEL
vides a printing pause similar to NO SCROLL. Bit 6 of the flag keys repeat, so the routine exits if the character is not one of
at 247/$F7 is checked before the pause flag value is set so these.
pausing with CONTROL-S can be disabled as well. If pausing To keep repeats from happening too fast, a countdown lo-
is allowed, the pause flag (2593/$0A21) is loaded with the S cation (2596/$0A24) is decremented once per call to this rou-
key's matrix code value, 13/$0D. tine. The countdown, initialized to 16, must reach zero before
A keyboard decoding table is then selected from the table repeating begins, so a key must be held down long enough for
of addresses at 830-841/$033E-$0349, based on the value in 16 IRQ keyscans to pass before repeat processing begins. After
the shift key flag (211/$D3). The table address is loaded into the initial delay expires, a second countdown (2595/$0A23),
the pointer at 204-205/$CC-$CD before falling through into initialized to 4 between each repeat, must also expire before
the next routine. Since only one table can be used, the follow- the keypress is counted a second time. Thus, the delay before
ing order of precedence applies if more than one shift key has repeating begins is (16 + 4)/60 = 1/3 second, and the delay
been pressed: CONTROL has the highest priority; when it is between subsequent repeats is 4/60 = 1/15 second. These
pressed, the CONTROL decoding table is selected regardless values are fixed in the ROM routine and can't be changed as
of which other shift keys are pressed. For example, ALT- long as the standard keyscan is used. For repeating keypresses,
SHIFT-CONTROL-W is the same as CONTROL-W. CAPS the character code is added to the keyboard buffer only if the
LOCK and ALT are effective only if pressed when no other buffer is currently empty—a feature that prevents repeats from
shift keys are pressed. For example, ALT-SHIFT-S is the same filling up the buffer.
as SHIFT-S. If ALT is pressed while CAPS LOCK is down, At 50839/$C697, a special countdown flag (2597/$0A25)
both are ignored and the unshifted table is used. Likewise, if used to debounce NO SCROLL, CONTROL-S, and SH1FT-
the SHIFT and Commodore keys are pressed simultaneously Commodore keypresses is decremented. Then the current ma-
while case switching is disabled, both are ignored and the trix code (212/$D4) is stored as the previous matrix code
unshifted table is selected. (213/$D5). If the value read from the keyboard decoding table
is 255/$FF, the routine exits at this point, since that value sig-
50769 SC651 REPEAT nals that there was not a valid character code for the key.
Otherwise, the pause flag (2593/$0A21) is cleared to zero, so
Decodes key matrix value into character value and handles key printing will resume upon completion of this IRQ if it was pre-
repeating. viously halted.
(This routine has a jump table entry at 49173/$C015.) The character code is then loaded into the accumulator,
Uses the keyscan matrix code in 212/$D4 as an offset into the and the value in the shift key flag (211/SD3) is loaded into
keyboard decode table pointed to by 204-205/$CC-$CD to the X register. Then the routine takes an indirect jump through
find the character code for the current keypress. The current the KEYCHK indirect vector (828-829/$033C-$033D). Nor-
matrix code is then tested against the previous matrix code. If mally, this vector points to 50861/$C6AD, the address imme-
they are not the same, the countdown before repeating begins diately following the indirect jump. However, if you wish to
(2596/$0A24) is reset to 16/$10 and the following test for re- manipulate the character code in any way, you can redirect
peating keys is skipped. the vector to your own routine in RAM. See the KEYCHK en-
If the current code is the same as the previous one, it try for details.
means that the key is being held down. In this case, the repeat Next, the routine checks whether one of the programma-
enable flag (2594/$0A22) is tested to see whether any key re- ble keys has been pressed by comparing the character code in
peats are allowed. If bit 7 of the flag is set to % 1 , all keys re- the accumulator values from the table at 50909/$C6DD. If a
292
293
50909 8C6DD SC72D 50989

match is found, the count of pending programmable key string 50919 6C6E7 CRSR40
characters (2O9/$D1) is loaded with the length of the cor- Handles cursor blinking for 40-column screen.
responding definition string from the table at 4096-4105/ Begins by checking the active screen flag (215/$D7), exiting
$1000-$ 1009, and the offset into the definition area at immediately if the 80-column display is active. The routine
4106/$ 100A for the string is calculated and stored in also exits if the cursor blink switch (2599/$0A27) holds a non-
210/$D2. (A simple way to defeat this feature and make the zero value. Then, the cursor blink countdown value (2600/
function keys simply generate character codes as they do in $0A28) is decremented. The countdown is necessary because
the Commodore 64 is to change the KEYCHJC vector to point the cursor can't be blinked during every interrupt—that would
to 50871/$C6B7 so that this portion of the routine is skipped,) result in blinking too fast to see. If the cursor countdown
If the character isn't one of the programmable keys, the doesn't reach zero, the routine exits. If the count does reach
number of characters currently in the keyboard buffer (208/ zero, the cursor flag (2598/$0A26) is tested. If that flag indi-
$D0) is compared against the maximum number the buffer can cates that the solid cursor is selected and the cursor is re-
hold (2592/$0A20). If the buffer is full, the current keypress is versed, the routine exits (the solid cursor just stays reversed).
ignored. Otherwise, the character code is stored in the next Otherwise, it's time to switch the cursor's phase.
available position in the buffer at 842-851/$034A-$0353. The first step in switching phases is to reset the count-
From there, it can be retrieved by the Kernal GETIN and BA- down to its starting value—20/$14. That value will result in
SIN routines. the cursor changing phase every 20/60 second. Because it
Before exiting, the value 127/$7F is stored in the CIA I/O takes two phase changes (on-to-off and off-to-on) to blink the
port register for keyboard columns. This value (%01111111) cursor, the cursor blinks every 40/60, or 2/3, second. Since
sets the line for column 7 of the matrix low, while all other this value is part of this ROM routine, it's not possible to
lines are high, so that the keys in that column can be detected change the cursor blink rate while using the standard screen
by reading the row register (56321/$DC01). This feature is IRQ routine.
provided to allow testing for the RUN/STOP and Commodore If the cursor is currently in its reversed phase, the position
keys, but other keys on that row can also be detected outside is restored to its original color and screen code. If the cursor is
the normal keyscan. See the routine at 63037/$F63D and the in its normal phase, the screen code and color for the position
entry for location 145/$91 for more information. are stashed (in 2601/$0A29 and 2602/$0A2A, respectively).
Then the high bit of the screen code is toggled, and the re-
50909 $C6DD PFKCHRS versed screen code is written back to the current cursor posi-
Table of programmable key character values. tion using the current cursor color (in 241/$F1). Finally, the
This table is used to identify programmable keys and to deter- cursor phase bit (bit 6) in the cursor flag (2598/$0A26) is
mine the offset into the definition length table at 4096/$1000 toggled.
for the length of the corresponding string. This routine is part of the normal IRQ sequence. There is
Offset Character Code Key no corresponding routine to blink the cursor on the 80-column
0 133/$85 Fl screen because the 8563 80-column chip handles that opera-
1 137/$89 F2 tion automatically.
2 134/$86 F3
3 138/S8A F4 50989 8C72D PRINT
4 135/$87 F5 Handles BSOUT to the screen.
5 139/$8B F6 (This routine has a jump table entry at 49164/$C00C.)
6 136/$88 F7
7 140/$8C F8 Begins by storing the current character code (in the accumu-
131/$83 SHIFT-KUN/STOP lator upon entry) in 239/$EF. The current accumulator and X
9 132/$84 HELP and Y register values are then stashed on the stack for restora-
tion upon exit.
294
50989 8C72D 3C78C 51084

The next portion of the routine implements the pause is called to handle the quote (") character. Then the routine
printing feature. If the pause flag (2593/$0A21) contains a jumps to 49954/$C322 to display the calculated screen code at
nonzero value, the routine immediately loops to check the flag the current cursor position using the current attribute (241/$F1).
again. It remains in the flag testing loop until the flag value is Remember that the address pushed onto the stack causes
reset to zero. If you're wondering how the routine ever breaks the final printing or character handling subroutine called by
out of this loop, remember that normal processing is sus- this routine to return to 49932/$C30C. That routine restores
pended during interrupts. The flag value is set during the IRQ- the accumulator and X and Y registers from the stack, so they
driven SCNKEY routine. This means that if you ever call contain the same values upon exit that they did upon entry.
BSOUT while interrupts are disabled, you must be sure that
the pause flag contains a zero. Otherwise, the flag value will 51055 8C76F RTRN
never change, and the routine will be stuck in the loop until Handles RETURN and SHIFT-RETURN characters, CHR$<13> and
you reset the computer. It also means that, as long as the nor- CHR$(141).
mal IRQ is enabled, NO SCROLL and CONTROL-S can be Finds the position of the last nonspace character in the logical
used to pause screen printing in any program that calls line; then clears the link bit for the physical line just below
BSOUT—even in your own machine language programs. Re- that position, making the line following the current logical line
member, however, that since the pause loop is implemented the start of a new logical line. The cursor position is set to the
only in this routine, NO SCROLL and CONTROL-S can halt left margin of that line, and the screen line pointers are up-
printing to the screen only. dated to reflect the new cursor position. The routine then falls
Next, the input source flag (214/$D6) is reset to zero, through into the following one.
making the keyboard the input source. The value 49931/
$C30B is pushed onto the stack. This will cause the RTS at the 51069 $C77D MODESOFF
end of the printing subroutine—or at the end of the special Cancels quote and reverse modes and clears pending inserts
handling subroutine in the case of screen and color control (ESC-O and ESC-ESC).
characters—to jump to 49932/$C30C, the common exit rou- Bits 4 and 5 of the current attribute value (241/$F1) are cleared,
tine for all screen BSOUT subroutines. canceling flashing or underlined modes for subsequent charac-
If the code to be printed is 13/$0D (RETURN) or 141/ ters on the 80-column display. The pending insert (245/$F5),
$8D (SHIFT-RETURN), a branch is taken to 51055/$C76F to reverse mode (243/$F3), and quote mode (244/$F4) flags are
handle these special cases. Otherwise, 240/$F0 is checked to all reset to zero, canceling any pending inserts and turning off
see whether the last character printed is the ESC (escape) reverse and quote modes.
character, 27/$lB. If so, the code is the second character of an
ESC sequence, so a jump is taken to the ESC sequence han- 51084 $C78C
dler at 51646/$C9BE. Character codes greater than 127/$7F Tables of screen control codes and dispatch addresses.
are sent to a special handling routine at 51202/SC802, and Locations 51084-51097/$C78C-$C799 comprise a table of all
codes less than 32/$20 are sent to 51126/$C7B6. the character codes less than 32 which have a special function
Remaining characters, those with codes in the range (except for RETURN and ESC, codes 13 and 27, which are de-
32-127/$20-$7F, are converted to screen codes as follows: If tected in the main screen BSOUT routine [$C72D]). The sub-
the code is less than 96/$60, bit 6 is cleared. Character codes routine to handle codes less than 32 [$C7B6] compares the
32-63/$20-$3F are unchanged, becoming screen codes 32-63/ current character against these values. If a match is found, the
$20-$3F, while character codes 64-95/$40-$5F become screen corresponding dispatch address from the table at 51098-51125/
codes 0-31/$00-$1R If the code is 96 or greater, only bit 5 is $C79A-$C7B5 is placed on the stack to be called by the next
cleared, so character codes 96-127/$60-$7F become screen RTS. Because of the way the RTS opcode behaves, adding 1 to
codes 64-95/$40-$5F. Next, the subroutine at 49919/$C2FF the address placed on the stack, the address table values are 1
296 297
51126 SC7B6 $C802 51202

less than the actual address of the target routine. The table If quote mode is active, the routine clears the character
shows the characters handled and the actual addresses of the storage location (239/$EF) and branches to 49958/SC326 in
handling routines: the character printing routine to display the character code
Handling
Character Handling (0-31) as a screen code in reverse mode. If quote mode is not
Offset Code Routine Description active, the accumulator contents are compared against the 14
0 2/$02 51399/$C8C7 Turns on underline mode control character codes in the table at 51084/$C78C. If a
1 7/$07 51598/$C9BE Generates bell tone match is found, the dispatch routine [$C7F6] is used to execute
2 9/$09 51535/$C94F Moves cursor to next tab stop the corresponding subroutine. Otherwise, the routine falls
3 10/$0A 51633/$C9B1 Performs linefeed through into the next routine to check whether the character is
4 11/$OB 51366/$C8A6 Disables case switching a color change code.
5 12/$0C 51372/$C8AC Enables case switching
6 14/$0E 51328/$C880 Switches to lowercase set
15/$0F 51413/IC8D5 Turns on flashing mode 51162 $C7DA COLORSET
7
8 17/$11 51290/$C85A Moves cursor down one line Handles color change characters.
9 18/$12 51394/$C8C2 Turns on reverse mode Compares the character code in the accumulator with the table
10 I9/$13 51379/$C8B3 Moves cursor to home position of color character codes at 52812/$CE4C. If no match is
11 20/$14 51483/$C91B Deletes a character found, the routine exits. If the accumulator value matches a ta-
12 24/$18 51553/$C961 Sets or clears a tab stop ble entry, the X register will contain the table offset for the
13 29/$lD 51284/$C854 Moves cursor right one column match, a value in the range 0-15. For the 40-column display,
this value is placed in the current attribute flag value
51126 6C7B6 (241/SF1). For the 80-column display, the offset value is used
Interprets character codes less than 32. as an index into the table at 52828/$CE5C to retrieve the cor-
Jumps indirectly through the CTLVEC vector (820-821/ responding 8563 color code. That value is then placed in the
$0334-$0335), which is initialized on system reset to point to lower four bits of the attribute flag.
51129/10769, the location immediately following the indirect
jump. However, the vector can be redirected to your own rou- 51190 8C7F6
tine in RAM, allowing you to modify the effects of printing Calls control code execution routines.
any of the characters with codes less than 32. See the entry at Uses the control code index, in the X register upon entry, as
CTLVEC for details. an offset into the dispatch table at 51098/$C79A. The cor-
If the value in the accumulator is the ESC character, responding subroutine address is retrieved from the table and
27/$lB, the routine exits without performing any other check- pushed onto the stack, so the RTS at the end of this routine
ing. Otherwise, the routine checks whether an insert is pend- will transfer control to the subroutine.
ing. If so, the routine branches to handle the character just as
it would if quote mode were active. If no inserts are pending, 51202 SC802
the code is compared with the delete character value 20/$14, Interprets character codes greater than 127.
If the code matches, the routine branches past the following
Jumps indirectly through the SHFVEC vector (822-823/
test for quote mode. Because delete character handling is sand-
$0336-$0337), which is initialized on system reset to point to
wiched between the test for pending inserts and the test for
quote mode, it's possible to type deferred deletes when inserts 51205/$C805, the location immediately following the indirect
are pending, but not during quote mode. Delete is the only jump. However, the vector can be redirected to your own rou-
character singled out for this treatment: All other control char- tine in RAM, allowing you to modify the effects of printing
acters (except RETURN and ESC) are deferred when printed any of the characters with codes greater than 127. See the en-
while quote mode is active. try at SHFVEC for details.
Next, the high bit of the character code (in the accumu-
298 299
51220 $C814 $C875 51317

lator upon entry) is masked off, and the resulting value is If the code is not among this group, bit 7 of the accumulator is
compared against 32. If the value is less, indicating that the reset to %1 to restore the character to its original value. Then
original character code was in the range 128-159, a branch is the routine branches to 51162/SC7DA to test whether this is a
taken to the following routine to handle those characters. Oth- color change character.
erwise, the routine tests whether the result was 127, indicating
that the original code was 255, the pi (rc) character. If not, the 51284 $C854
routine jumps to 49952/$C320 in the character printing rou-
Handles cursor right character, CHR$(29).
tine to display the character corresponding to the specified
code. However, if the code was pi, it's changed to 94/$5E, the Calls the subroutine to move the cursor one position to the
screen code for the pi character, before jumping to the printing right [$CBED], then tests whether the cursor is wrapped to the
routine. left margin of a new line. If so, a branch is taken to the rou-
tine which determines whether the cursor has moved down
onto a new logical line.
51220 $C814
Handles character codes 128-159.
51290 $C85A
Checks whether quote mode is in effect and, if so, sets bit 6 of Handles cursor down character, CHR$(17).
the character value in the accumulator (converting the ad-
Calls the subroutine to move the cursor down one row
justed character code value 0-31 into a screen code value in
[$C363]. Upon return, the routine falls through into the next
the range 64-95), then jumps to 49958/$C326 in the character
routine to see whether the cursor has moved onto a new logi-
printing routine to display the control code as a reverse character.
cal line.
If quote mode is not in effect, the code tests against the
value 20/$14 to determine if it was originally the insert char-
acter— CHR$(148). If so, the routine jumps to 51427/$C8E3 to
51293 $C85D
Checks whether cursor moved onto a new logical line.
handle the insert. Otherwise, the count of pending inserts is
checked. If inserts are pending, the character is treated as if Checks whether the link bit for the current physical line is set
quote mode were in effect—it's converted to a screen code and to % 1 , indicating that the cursor is still on the same logical
printed in reverse video. Performing this test after checking for line. If not, bit 7 of 232/SE8 is set to %1 to indicate that the
the insert character allows multiple insertions to be made. input begins on the first line in a logical chain,
If no insert is pending, the accumulator value is compared
against a series of character values, branching or jumping to 51303 $C867
the appropriate handling routine if a match is found. The table Handles cursor up character, CHR$(145).
shows the address of the routine to which control is trans- Exits without moving if the cursor is already on the top line of
ferred if a match is found. (The table shows the original char- the window. Otherwise, the previous routine is used to deter-
acter code value before the high bit is masked off; the value mine if the cursor has moved onto a new logical line. Then
actually tested for in this routine will be 128 less): the row (235/$EB) is decremented, and screen line pointers
Character Handling are updated to reflect the change.
Code Routine Description
145/$9l 51303/$C867 Moves cursor up one line 51317 $C875
157/$9D 51317/$C875 Moves cursor left one position Handles cursor left character, CHR$(157).
142/$8E 51346/$C892 Switches to uppercase/graphics set Calls the subroutine to move the cursor one position to the
146/$92 51391/$C8BF Turns off reverse mode left [$CC00]. Upon return, the routine exits with the status
130/$82 51406/$C8CE Turns off underlining register carry bit set if the cursor is already at the upper left
143/$8F 51420/$C8DC Turns off flashing characters
147/$93 49474/$C142 Clears the window corner of the window (the cursor will not be moved in this
300 301
51328 $C880 $C8B3 51379

case). Otherwise, the routine exits immediately with carry flag (241/$F1) to %0. This bit, which has no effect on 40-
clear, unless the move wrapped the cursor to the right margin column printing, determines which character set will be used
of the line above. In that case, a test of whether the cursor for any characters subsequently printed on the 80-column
moved onto a new logical line must be performed, and the screen using this attribute value. Characters already on the
cursor row value (235/$EB) and screen line pointers must be screen are not affected, so it's possible to mix character sets on
updated. the 80-column display.

51328 $C880 51366 $C8A6


Handles switch-to-lowercase character, CHR$(14). Handles case switching disable character, CHR$(11).
Sets bit 1 of the character base address shadow register (2604/ Sets bit 7 of the case switching flag (247/$F7) to % 1 , This flag
$0A2C) to %1 if the 40-column screen is active. This value is checked during the keyscan routine [$C55D] to determine
will be copied into the VIC-II chip register at 53272/$D018 whether the character set should be changed when the SHIFT
during the next IRQ interrupt (see the screen IRQ routine and Commodore keys are held down simultaneously. If bit 7
[$C194]). If the bit has previously been cleared, this has the ef- of the flag is % 1 , case switching is not allowed. Note that this
fect of adding 2048/$0800 to the character base address. disables case switching only via the SHIFT-Commodore key
When the default register value is being used (standard ROM- combination. There is no provision for preventing case switch-
based characters), this selects the lowercase/uppercase charac- ing by printing characters 14 or 142.
ter set at 55296/$D800. Everything currently displayed on the
40-column text screen will be affected. If the 80-column screen 51372 $C8AC
is active, the routine instead sets bit 7 of the current attribute Handles case switching enable character, CHR$(12).
Hag <241/$F1) to % 1 . This bit, which has no effect on 40- Clears bit 7 of the case switching flag (247/$F7) to %0. This
column printing, determines which character set will be used allows case switching via the SHIFT-Commodore key
for any characters subsequently printed on the 80-column dis- combination.
play using this attribute value. Characters already on the
screen are not affected, so it's possible to mix character sets on 51379 $C8B3
the 80-column display.
Handles cursor home character, CHR$(19).
Checks the previous character code value (stored in 240/$F0).
51346 $C892 If that character is also 19/$13, the window is reset to full
Handles switch-to-uppercase character, CHR$(142). screen size before moving the cursor home. The routine at
Clears bit 1 of the character base address shadow register 49488/$C150 is called to set the cursor to the home position.
(2604/$0A2C) to %0 if the 40-column screen is active. This The special effect of HOME-HOME, resetting the window
value will be copied into the VIC-II register at 53272/$D018 to full screen size, is a feature you must keep in mind if your
during the next IRQ interrupt (see the screen IRQ routine programs use resized screen windows. If a program uses the
[$C194]). If the bit has been previously set to % 1 , this has the BSOUT routine to display characters in the window, you
effect of subtracting 2048/$0800 from the character base ad- should avoid printing the {HOME} character twice in a row. If
dress. When the default register value is being used (standard the program accepts user input and displays it on the screen,
ROM-based characters), this selects the uppercase/graphics you must guard against the chance of having your window
character set at 53248/SD000. Everything currently displayed boundaries reset. See the entry for the CTLVEC indirect vector
on the 40-column text screen will be affected. If the 80-column (820-821/$334-$335) for information on disabling this
display is active, the routine instead clears bit 7 of the attribute feature.

302 303
51391 $C8BF $C93D 51517

51391 $C8BF 51427 $C8E3


Handles reverse off character, CHR$(146). Handles insert character, CHR$(148).
Loads the accumulator with 0/$00, then uses a BIT opcode to Stashes the current cursor position. The routine then moves to
fall through into the following routine and store the value in the last nonspace character in the logical line and copies all
the reverse video flag (243/$F3). characters between there and the original cursor position one
position to the right. It then places a space character at the
51394 $C8C2 original cursor position. The pending insert flag is incre-
Handles reverse on character, CHR$(18), mented, then tested to see if it rolled over from 255/$FF to
Stores the value 128/$80 in the reverse video flag (243/$F3). 0/$00. If so, the flag is reset to 255/$FF; so that value is the
As long as this flag contains a nonzero value, all characters maximum number of pending inserts allowed. The cursor is
printed to the screen using the BSOUT printing subroutine restored to its original position upon exit.
[$C320] will be displayed in reverse video. When autoinsert mode is active, the screen printing sub-
routine [$C320] calls this routine before each character is
51399 $C8C7 printed to insert a space in which to print the character.
Handles underline on character, CHR$(2).
Sets bit 5 of the current attribute (241/$F1) to % 1 . This affects 51483 $C91B
only the 80-column screen; the upper four bits of the value are Handles delete character, CHRSUO).
meaningless for the 40-column screen. Any characters subse- Moves the cursor one position to the left, then checks to see
quently printed on the 80-column screen with this attribute whether the move wrapped the cursor to the right margin of a
will appear underlined. new logical line. If so, the routine exits, since no characters
need be moved in this case. Next (at 51491/$C923), the rou-
51406 $C8CE tine enters a recursive loop with the routine at 51517/$C93D
Handles underline off character, CHR$(130). to copy all characters to the end of the logical line one posi-
Clears bit 5 of the current attribute (241/$F1) to %0. This af- tion to the left, overwriting the character to the left of the orig-
fects subsequent printing only. Any underlined characters al- inal cursor position,
ready on the screen will remain underlined.
51506 $C932 RSTRPOS
51413 8C8D5 Restores the cursor row and column positions.
Handles flash on character, CHR$(15). Loads the cursor column position (236/SEC) from temporary
Sets bit 4 of the current attribute (241/$F1) to % 1 . This affects storage in 222/$DE and the current cursor row (235/$EB)
only the 80-column screen; the upper four bits of the value are from 223/$DF, then jumps to the routine at 49500/$C15C to
meaningless for the 40-column screen. Any characters subse- set pointers to the new cursor position. The corresponding
quently printed on the 80-column screen with this attribute routine to stash the cursor row and column values is at
will flash at the same rate as cursor blinking. 52254/$CClE.

51420 SC8DC 51517 $C93D DELCHAR


Handles flash off character, CHR$(143). Deletes a character in a logical line.
Clears bit 4 of the current attribute (241/$F1) to %0. This af- Copies the character and attribute to the right of the current
fects subsequent printing only. Any flashing characters already cursor position into the current position, then moves the cursor
on the screen will continue to flash. right and jumps back to the subroutine at 51491/$C923, which
calls this routine recursively until the end of the logical line is
reached.
304
305
51535 $C94F 8C9BE 51646

51535 $C94F 51587 $C983


Handles tab character, CHR$(9). Sets default tab stops (ESC Y).
Checks whether the tab stop bit for the position to the right of Loads the accumulator with the value 128/$80, then uses a
the current cursor column is set to % 1 , or whether the posi- loop to write the value to all ten bytes of the tab stop bitmap
tion is beyond the right window margin. If neither, the routine (852-861/$0354-$035D). Since a bit set to %1 indicates a tab
continues checking columns to the right until either a tab stop stop, filling the bitmap with this value (%10000000) has the
is found or the right margin is reached. The cursor position is effect of setting a tab stop every eighth character position.
then reset to the column where the tab stop is found, or to the
right margin if none is found. Thus, it's impossible to tab past 51598 $C98E
the right edge of the window. Handles bell character, CHR$(7).
Checks the bell disable flag (249/$F9) and exits immediately if
51553 $C961 bit 7 is set to % 1 . If the tone is enabled, SID chip registers are
Handles clear/set tab stop character, CHR$(24). set to produce a sawtooth waveform tone of approximately
Toggles the bit in the tab stop bitmap (852-861 /$0354-$035D) 750 hertz, using a moderately low volume setting (5). The du-
corresponding to the current cursor position. If the bit is %0, it ration of the tone is controlled by judicious selection of the
will be set to % 1 , setting a tab stop at the current position. If ADSR envelope values. The sound is never turned off, but it
the bit is % 1 , it will be cleared to %0, clearing the tab stop quickly decays to an inaudible level.
previously set at the position.
51633 $C9B1
51564 8C96C TESTTAB Handles linefeed character, CHR$(10).
Tests tab stop bit for current cursor position. Finds the position of the last character in the current logical
Calculates the byte offset and bit mask into the tab stop bit- line and moves the cursor to the row below that character po-
map (851-861/$0354-$035D) for the cursor column specified sition at the same column it previously occupied. If the logical
in the Y register, then checks the corresponding bit position in line extends onto the last physical line in the window, a new
the bitmap. If the bit is set to % 1 , indicating that a tab stop is blank line will be scrolled onto the bottom of the window, and
set at the specified cursor column, the status register Z bit will the cursor will be moved onto the blank line (or, if scrolling is
be clear upon exit. If the bitmap bit is %0, the Z status bit will disabled, the cursor will wrap to the top line of the window).
be set. In either case, the Y register will still contain the speci- Remember that linefeed moves the cursor to the next logical
fied column value upon exit. line, not the next physical line (that's what cursor down does).

51584 $C980 51646 $C9BE ESCAPE


Clears all tab stops (ESC Z). Handles ESC sequences.
Loads the accumulator with the value 0/$00, then uses a BIT Jumps indirectly through the ESCVEC vector (824-825/
instruction to fall through into the next routine and write $0338-$0339), which is initialized to point to the JESCAPE
the value to all ten bytes of the tab stop bitmap (852-861/ jump table entry [$C01E]. This in turn returns control to
$0354-$035D). This eliminates any set bits in the bitmap, thus 51649/$C9C1, the address immediately following the indirect
clearing all tab stops. jump. Thus, the jump normally has no effect; however, the
vector can be redirected to point to your own routine in RAM,
allowing you to add your own ESC sequences or to modify
the action's existing sequences. See the entry at ESCVEC for
more information.

306 307
51678 SC9DE $CA1B 51739

Next, the routine checks whether the character code (in ESC E 51979/$CB0B Sets nonblinking cursor mode
the accumulator upon entry) is also ESC. If so, the current ESC F 52001/$CB21 Sets blinking cursor mode
ESC G 52023/$CB37 Enables bell tone for CHR$(7)
character is shifted right one bit. This changes the character ESC H 52026/$CB3A Disables bell tone for CHR$(7)
from 27/$lB to 13/$0D, the RETURN character, so that dual ESC I 51773/$CA3D Inserts a blank screen line
ESCs are not read repeatedly. The routine then jumps to the ESC 52145/$CBB1 Moves cursor to start of logical line
routine to cancel quote mode. This is an undocumented fea- I
ESC K 52050/$CB52 Moves cursor to end of logical line
ture of the ESC sequences: ESC ESC is a handy shortcut for ESC L 51938/ICAE2 Enables screen scrolling
ESC O. ESC M 51941/$CAE5 Disables screen scrolling
If the character is not ESC, bit 7 is masked off. This ESC N 52040/$CB48 Sets normal 80-column screen
means that shifted letters are treated the same as unshifted ESC 0 51069/$C77D Cancels quote mode
ones. ESC SHIFT-A has the same effect as ESC A, for ex- ESC P 51851/$CA8B Erases to start of logical line
ample. (Remember, however, that only the alphabetic letter ESC Q 51830/$CA76 Erases to end of logical line
keys have this relationship. ESC SHIFT-@ is not the same as ESC R 52031/$CB3F Reverses 80-column screen
ESC @.) ESC S 51954/$CAF2 Sets block cursor (80-column)
ESC T 51732/$CA14 Sets top left corner of window
Next, 64/$40 is subtracted from the character values. This ESC U 51966/SCAFE Sets underline cursor (80-column)
will translate the character codes for @ and A-Z into an index ESC V 51900/$CABC Scrolls screen up one line
in the range 0-26. If the result is outside this range, there is ESC 51914/$CACA Scrolls screen down one line
no standard ESC sequence for the specified character, so the ESC
w
X 52524/$CD2C Switches active displays
routine exits without taking further action. If the character is ESC Y 51587/$C983 Sets default tab stops
within the valid range, the address of the subroutine to per- ESC 51584/$C980 Clears all tab stops
form the corresponding sequence is loaded from the table at z
51678/$C9DE. It is pushed onto the stack so that the subrou- 51732 $CA14 SETTOP
tine will be called when the RTS opcode at the end of this
routine is executed. Defines the upper left corner of the window (ESC T>.
Clears the carry bit, then uses a BIT opcode to fall through
into the following routine to load the current cursor position
51678 $C9DE ESCTBL and set the window boundary.
Table of ESC key dispatch addresses.
Each two-byte entry in this table consists of the address minus 51734 $CA16 SETBTM
1 of the subroutine to perform the corresponding ESC key se- Defines the lower right corner of the window (ESC B).
quence. The routine to handle ESC sequences [$C9BE] pushes Sets the carry bit, loads current cursor position, then falls
a table entry on the stack so that the RTS at the routine causes through into the following routine to set the window
a jump to the subroutine. Each entry is one less than the ac- boundary.
tual address because of the way RTS behaves: When RTS
pulls an address from the stack, the address value is incre- 51739 $CA1B WINDOW
mented before being placed in the 8502's program counter. Sets window boundaries.
The actual execution addresses for each of the subroutines are (This routine has a jump table entry at 49197/$C02D.)
as follows: Establishes a window boundary according to the values in the
ESC @ 51871/$CA9F Clears to end of screen accumulator and X register and the setting of the status regis-
ESC A 51949/$CAED Enters autoinsert mode ter carry bit. If entered with carry clear, the accumulator value
ESC B 51734/$CA16 Sets bottom right corner of window defines the new top row of the window, and the X register
ESC C 51946/$CAEA Cancels autoinsert mode
ESC D 51794/$CA52 value defines the new left margin. If entered with carry set,
Deletes an entire logical line
309
308
51748 SCA24 $CACA 51914

the accumulator value defines the new bottom row, and the X row of the next logical line upward to overwrite the current
register value defines the new right margin. The newly de-
fined window is not cleared, but the routine does fall through
t line (blank lines will be added at the bottom of the window).
The cursor is then moved to the left margin of the original top
to the portion of the following routine that clears the line link row of the deleted logical line. Bit 7 of the input starting line
bitmap, so all lines in the window will initially be unlinked. value (232/SE8) is set to % 1 , indicating that the cursor is at
When using this routine, remember that row and column the start of a logical line.
numbering begins with zero (column 0 of row 0 is the upper
left corner of the screen). Thus, SYS 51739,9,19,0,0 would set 51830 $CA76
the upper left corner at the twentieth column over on the Erases to the end of the current logical line (ESC Q).
tenth line down. The routine does not check the validity of Clears to the end of the current row, then checks whether the
your entries; you are responsible for making sure that the next row is linked to the current one. If so, that line is cleared
lower right corner values are at least equal to the upper left as well. This continues until the last row of the logical chain is
corner values. If you set a lower right corner that is above or reached. The cursor is restored to its original position upon
to the left of the upper left corner, the screen display will be exit.
garbled.
51851 $CA8B
51748 $CA24 FULLW Erases to the start of the current logical line (ESC P).
Resets the window to full screen size. Prints a space at the current cursor position, then checks
Sets the bottom right corner of the window to the maximum whether the cursor is at the left margin of the first row in a
row and column settings, held in 237/$ED and 238/SEE, re- logical chain. If not, the cursor is moved left and another
spectively; then sets row 0, column 0 as the upper left corner. space is printed, repeating until the start of the logical line is
Finally, the routine clears all bytes in the line link bitmap, ef- reached. The cursor is then restored to its original position.
fectively unlinking all screen lines.
51871 $CA9F
51773 $CA3D Erases to the end of the window (ESC @).
Inserts a blank line (ESC I). Clears to the right margin of the current row, then moves
Copies all lines in the window starring at the row on which down to the next row and clears the remainder of the window
the cursor currently resides one row lower (the bottom row one logical line at a time until the bottom of the window is
will be lost); then clears the row where the cursor resides and reached. The cursor is then restored to its original position.
moves the cursor to the left margin of the cleared line. The
link bit for the line below the new one (the line that originally 51900 $CABC
occupied the new line's position) is tested. If the link bit is set Scrolls the display up one line (ESC V).
to % 1 , the new line has been inserted within an existing logi- Copies all lines in the window up one row (the top row will
cal line, so the link bit for the new line will also be set to add be lost) and clears the bottom row. The cursor is then restored
it to the logical chain. If the new line is not linked to a previ- to its original position,
ous line, bit 7 of the input starting line value (232/$E8) is set
to %1 to indicate that the cursor is at the start of a logical line. 51914 $CACA
Scrolls the display down one line (ESC W).
51794 $CA52 Copies all lines in the window down one row (the bottom row
Deletes the current logical line (ESC D). will be lost) and clears the top row. The cursor is then restored
Determines which row is the first of the current logical line, to its original position.
then scrolls all lines in the window beginning with the first
310 311
51938 $CAE2 $CB3F 52031

51938 $CAE2 then copies the flag value to the 8563 chip cursor register
Enables screen scrolling (ESC L). (RIO). This causes the cursor to begin on raster line 7 of the
Loads the accumulator with 0/$00, then uses a BIT opcode to screen line, the scan line below the character patterns.
fall through into the following routine and store this value in
the scrolling enable flag (248/$F8). 51979 $CB0B
Disables cursor blinking (ESC E).
51941 $CAE5 Begins by checking which display is currently active. If the 80-
Disables screen scrolling (ESC M). column display is active, bits 5 and 6 of the 80-column cursor
Stores the value 128/$80 in the scrolling enable flag (248/ flag (2603/$0A2B) are cleared to %0. Then the flag value is
$F8), setting bit 7 to % 1 . As long as bit 7 of that flag is set, copied to the 8563 chip cursor register (RIO). This halts the
the printing routines will not scroll new lines onto the win- blinking of the cursor on the 80-column screen. If the 40-
dow, and the cursor will wrap at window margins. column display is active, bit 6 of the 40-column cursor flag
(2598/$0A26) is set to %1 to disable cursor blinking.
51946 $CAEA
Cancels autoinsert mode (ESC C). 52001 $CB21
Loads the accumulator with 0/S00, then uses a BIT opcode to Enables cursor blinking (ESC F).
fall through into the following routine and store this value in Begins by checking which display is currently active. If the 80-
the autoinsert enable flag (246/SF6). column display is active, bits 5 and 6 of the 80-column cursor
flag (2603/$0A2B) are set to % 1 . Then the flag value is copied
51949 SCAED to the 8563 chip cursor register (RIO). This causes the cursor
Enables autoinsert mode (ESC A), on the 80-column screen to blink. If the 40-column display is
Stores the value 128/$80 in the autoinsert enable flag (246/ active, bit 6 of the 40-column cursor flag (2598/$0A26) is
$F6). As long as that flag contains a nonzero value, the print- cleared to %0 to enable cursor blinking.
ing routines will insert a space before each character is
printed. 52023 $CB37
Enables tone for bell character (ESC G).
51954 $CAF2 Loads the accumulator with 0/$00, then uses a BIT opcode to
Changes 80-column cursor to solid block (ESC S). fall through into the following routine and store this value in
Checks the active screen flag, exiting immediately if the 80- the bell disable flag (249/$F9).
column display is not active. If it's active, the routine clears
bits 0-4 of the 80-column cursor flag (2603/$0A2B) to %00000, 52026 8CB3A
then copies the flag value to the 8563 chip cursor register Disables tone for bell character (ESC H).
(RIO). This causes the cursor to begin on raster line 0 of the Stores the value 128/$80 in the bell disable flag (249/$F9),
screen line, making the cursor block the same height as the setting bit 7 to % 1 . As long as bit 7 of that flag is set to % 1 ,
character patterns. no tone will be sounded when character code 7 is printed.

51966 $CAFE 52031 $CB3F


Changes 80-column cursor to underline (ESC U). Switches 80-column screen to reverse mode (ESC R).
Checks the active screen flag, exiting immediately if the 80- Sets bit 6 in 8563 register 24 (R24) to % 1 . This sets the 80-
column display is not active. If it's active, the routine sets bits column screen to reverse mode: Characters appear in the back-
0-4 of the 80-column cursor flag (2603/$0A2B) to %00111, ground color specified in the lower four bits of R26, and the

312 313
52040 $CB48 $CBC3 52163

screen background for each character position takes the color


specified in the corresponding attribute memory position.
52097 SCB81 SETLINK
Links or unlinks the current screen line.
Loads the X register with the current row number (235/$EB),
52040 $CB48
then enters one of the two following routines depending on
Switches 80-column screen to normal mode (ESC N).
the status of the carry bit. If carry is set, a branch is taken to
Clears bit 6 in 8563 register 24 (R24) to %0. This sets the 80- 52115/SCB93 to link the current screen line to the one above.
column screen to normal mode: Characters appear with the If carry is clear, this routine falls through to the next one to
attribute specified in the corresponding attribute memory posi- unlink the current line.
tion, and the screen background takes the background color
specified in the lower four bits of R26. 52101 $CB85 UNLINK
Unlinks a screen line.
52050 $CB52 Clears the bit in the line link bitmap corresponding to the line
Moves the cursor past the last character on the current logical
line (ESC K). specified in the X register. The line number is preserved in the
X register upon exit,
Finds the position of the last nonspace character in a logical
line, then sets the cursor pointers to the column to the right of 52115 $CB93 LINK
that position. If the existing logical line completely fills its last
Links a screen line.
physical line, a new blank line will be inserted (scrolling all
lines below the current one down one line), and the cursor Sets the bit in the line link bitmap corresponding to the line
will move to the left margin of the new line. However, if the specified in the X register. The line number is preserved in the
logical line in question completely fills the last physical line in X register upon exit.
the window, all lines in the window will instead be scrolled
up one line to open a new blank line at the bottom, unless 52127 $CB9F FINDLINK
scrolling is disabled. In this case, the cursor will simply be Calculates offsets into the line link bitmap.
moved to the bottom right corner of the window. Calculates the position of the bit in the line link bitmap cor-
responding to the line specified in the X register upon entry,
52056 $CB58 READCHR returning the byte offset into the line link bitmap in the X reg-
Reads character and attribute at current cursor position. ister and the mask for the corresponding link bit within that
byte in the accumulator.
Stores the attribute at the current cursor position in 242/$F2
and returns the screen code at the current cursor position in
the accumulator. 52145 $CBB1
Moves the cursor to the start of logical line (ESC J).
52084 $CB74 TESTLINK Sets all cursor position pointers to the left margin in the first
Tests whether a line is linked. row of the current logical line.
Checks the bit in the line link bitmap (862-865/$035E-$0361)
corresponding to the line specified in the X register. If the line
52163 $CBC3 FINDEND
is linked to the one above, the carry bit will be set upon exit; Finds the position of the last character in a line.
if not, it will be clear. The line number is preserved in the X Calculates the position of the last nonspace character in the
register upon exit. current logical line and returns the column value of that posi-
tion in 234/$EA and the row value in 235/$EB.

315
52205 8CBED $CC5B 52315

52205 8CBED FORWARD then allow the routine to fall through to 52276/$CC34 to dis-
Moves the cursor one position to the right. play the space.
Checks whether the move would place the cursor beyond the
right margin of the window. If not, the new position value is 52271 $CC2F DISPLY1
set in 236/$EC. If the cursor is already at the right window Displays a character using the current attribute.
margin, the subroutine at 50019/$C363 is called to move the Loads the X register with the current character color from the
cursor to the left margin of the next line, scrolling the window attribute flag (241/SF1), then uses a BIT opcode to allow the
if the cursor is on the bottom line (or wrapping the cursor to routine to fall through to 52276/$CC34 to display the screen
the top of the window if scrolling is not allowed). Upon exit, code in the accumulator.
the carry bit will be set if the move caused the screen to scroll
(or the cursor to wrap). The accumulator contents are pre- 52274 $CC32 DISPLY2
served unchanged during this routine; the cursor column will Displays a character using the previous attribute.
be in the Y register upon exit.
Loads the X register with the current character color from the
previous attribute flag (242/$F2), then falls through to display
52224 $CC00 RETREAT the screen code in the accumulator.
Moves the cursor one position to the left.
Checks whether the move would place the cursor beyond the 52276 $CC34 DISPLY
left margin of the window. If not the new position value is set Displays a character at the current cursor position.
in 236/$EC, and the carry bit is cleared. If the cursor is al- {This routine has a jump table entry at 49155/$C003.)
ready at the left window margin, the routine checks whether Places a character on the screen by putting the screen code
the cursor is on the top row of the window. If so—if the value (in the accumulator) into the screen memory location
cursor is currently in the home position of the window—the corresponding to the current cursor position. The attribute
routine exits with the carry bit set and without moving the value (in the X register) is then stored into the attribute mem-
cursor. Otherwise, the cursor position is set to the right margin ory location corresponding to the current cursor position.
of the screen line above the current one. In this case, the Z bit (Note that the accumulator should contain a screen code, not a
in the status register will be set upon exit. The accumulator
character code.) The screen memory address is determined by
contents are preserved unchanged during this routine; the
using the current cursor column (236/$EC) as an offset from
cursor column will be in the Y register upon exit.
the first screen memory position for the screen line
(224-225/$E0-$El), and the attribute memory address is de-
52254 $CC1E SAVEPOS termined by using the current column value as an offset from
Stores the cursor position for later restoration. the first attribute memory position for the screen line
Stashes the current cursor column value in temporary storage (226-227/$E2-$E3). For the 40-column screen, the screen
at 222/SDE and the current cursor row value at 223/$DF. The code and attribute values are stored directly into the memory
corresponding routine to retrieve these values and restore the locations. For the 80-column screen, the values must be stored
cursor to the saved position is at 51506/$C932. in the 8563 chip's private 16K of RAM indirectly, via the 8563
registers.
52263 $CC27 SPACE
Prints a space. 52315 $CC5B SCRORG
Loads the X register with the current character color from the Returns height and width of current screen window.
attribute flag (241/$F1), masking out bits 4-6, and loads the (This routine has a screen editor jump table entry at 49167/$C00F
accumulator with 32, the screen code for a space. BIT opcodes and a Kernal jump table entry at 65517/$FFED.)

316 317
52330 6CC6A 8CCA2 52386

Calculates the screen height by subtracting the top margin of the screen display. This makes no difference as long as the
(229/$E5) from the bottom margin (228/$E4); this value is re- window is set for full screen size, but it is significant when
turned in the Y register. The screen width is calculated by- you are using a reduced-size window. For example, if the
subtracting the left margin (230/$E6) from the right margin cursor is on the eighth row down from the top of the screen
(231/$E7); this value is returned in the X register. The accu- and the tenth column across from the left edge of the screen,
mulator is loaded with the maximum column number for the the row and column values returned by this routine will be 7
screen in use (238/$EE)—39/$27 for the 40-column screen or and 9, respectively, if the window is full screen size. However,
79/$4F for the 80-column screen. if the top left corner of the window is moved to the sixth col-
Note that the height and width values calculated by this umn of the sixth row, the row and column values returned for
routine will be one less that the actual number of rows and the same cursor position will be 1 and 3, respectively.
columns in the window. For example, with the 40-column When setting the cursor position, the routine first checks
screen set for a full-size window (40 columns X 25 rows), this whether the specified position would be beyond either the
routine will return X and Y register values of 39 and 24, re- right or bottom margin of the window. If the position would
spectively. To return the proper values, the routine should be outside the window, the routine exits with the carry bit set
have added 1 to the subtraction results. By comparison, this and without changing the current cursor position. Thus, you
routine in Commodore 64 ROM, where is it called SCREEN, can check the carry bit after calling this routine to determine
returns the values 40 and 25 for the standard screen (also 40 whether the cursor was successfully moved (indicated by a
columns X 25 rows). clear carry bit).
This routine has an idiosyncrasy that will trip you up if
52330 $CC6A PLOT you're not careful. Keep in mind that the value in the X regis-
Reads or sets the current cursor position. ter contains the vertical (row) position, and the value in the Y
(This routine has a screen editOT jump table entry at 49176/$C018 register contains the horizontal (column) position. This is op-
and a Kernal jump table entry at 6552O/$FFF0.) posite from the way you normally think of x and y coordinates
Returns the row and column numbers corresponding to the in geometry: x is usually horizontal and y vertical. Some other
current cursor position or establishes new row and column routines, such as SCRORG [$CC5B], use X to hold the hori-
values, depending on the status of the carry bit upon entry. To zontal value and Y for the vertical value, so don't get
set the cursor position, enter the routine with the desired row confused.
number (0-24) in the X register, the desired column number
(0-39 for the 40-column screen or 0-79 for the 80-column 52386 $CCA2 KEYSET
screen) in the Y register, and the carry bit clear. To read the Defines a programmable function key.
cursor position, enter the routine with the carry bit set; the (This routine has a screen editor jump table entry at 49185/$CO21
current row number will be in the X register upon return, and and a Kemal jump table entry at 65381/$FF65.)
the current column number will be in the Y register (and also Replaces the existing definition string for one of the ten pro-
in the accumulator). grammable keys, F1-F8, SHIFT-RUN/STOP, and HELP, with
It's important to remember that coordinate numbering be- a new string. The routine first converts the key number (1-10),
gins with 0, not 1. Thus, setting the cursor position with X and in the X register upon entry, to a key index (0-9), which is
Y containing 5 and 3, respectively, will place the cursor on the stored in 220/SDC. The length of the definition string should
sixth row down at the fourth column across. When reading co- be in the Y register upon entry, and the address of the zero-
ordinates, remember that the cursor will actually be one posi- page pointer to the definition string should be in the accumu-
tion beyond the last character printed. The coordinates you set lator upon entry. The number of the memory bank where the
or read are relative to the home position and left margin of the definition string resides is read from the zero-page location im-
current window, not the absolute home position and left edge mediately following the two-byte pointer to the string. If the

318 319
52512 $CD20 $CD57 52567

length of the new definition string is the same as the length of 52524 $CD2C
the existing definition string for the specified key, no special Changes screen displays (ESC X).
handling is required; the new definition string is simply copied Stores the current character code in 240/$F0, then falls
over the old one. If the new definition is shorter, all the defi- through into the next routine to switch active displays.
nitions above the existing one are moved down. If the new
definition is longer, all characters must be moved upward. 52526 $CD2E SWAPPER
Before anything is actually moved, the routine checks to make
sure that adding the extra characters will not exceed the 246 Switches active screen displays.
bytes available for string definitions (4106-4351/$100A-$10FF). (This routine has a screen editor jump table entry at 49194/SC02A
and a Kernal jump table entry at 65375/SFF5R)
If the new definition will not fit, the routine exits with the sta- Swaps the active and inactive screen variables by exchanging
tus register carry bit set and without changing the existing def- the contents of 224-250/$E0-$FA with the contents of
inition string. 2624-2650/$0A40-$0A5A. (This duplicates the bug in the ini-
To add a new definition string, the length of the string is tialization routine [$C07B] which copies 27 values, when only
placed in the proper position in the string length table in bank 26 are actually valid.) The routine then swaps the active and
0 (4096-4105/$1000-$1009). Then characters are loaded from inactive tab stop and line link bitmaps by exchanging the
the new string in whatever bank it is located in by using the contents of 852-865/$0354-$0361 with the contents of
INDFET routine [$02A2]. They are stored at the proper posi- 2656-2669/$0A60-$0A6D. Finally, bit 7 of the active screen
tion in the definition string table (4106-4351/$100A-$10FF). flag (215/$D7) is toggled, switching the active and inactive
The status register carry bit is cleared before exit to indicate screen displays.
that the new definition string has been successfully added to Note that this doesn't physically turn either video chip on
the table. or off. Both video sources remain on at all times. The active
display is merely the one to which all printing is currently
directed.
52512 8CD20 52567 $CD57 CRSR80
Calculates the offset to the start of key definition string. Sets cursor position on 80-cohimn screen.
Adds the length table entries for all key definition strings with (This routine has a jump table entry at 49179/$C01B.)
an index lower than the one specified in the X register upon Checks active screen flag and exits immediately if the 40-
entry. (X should contain a key index, 0-9, not a key number, column screen is active. The screen memory address for the
1—10.) The total will be in the accumulator upon exit, and carry cursor position is calculated by adding the current cursor col-
will be set. Because there are no separator characters between umn (236/$EC) to the starting address for the screen line
definition strings in the table, the only way to determine the (224-225/$E0-$El), This address is then written to the 8563
starting position of a particular string is to add the lengths of chip's cursor position registers (R14-R15) using the routine at
all the preceding strings. This implies that an incorrect length 52684/$CDCC
value in the string length table (4096-4105/$1000-$1009) will This routine is normally called by the BSOUT exit routine
result in incorrect strings being returned for all keys with a [$C30E] after a character has been printed. The routine is nec-
higher index. Thus, you should use caution when changing essary because the 80-column cursor is managed in hardware,
string length tables directly. not software. So, unlike the 40-column display's cursor, it
doesn't move automatically when cursor row and column
pointers are changed.

320 321
52591 $CD6F $CDD8 52696

52591 $CD6F CRSRON sequential addresses. The routine works by loading X with
Turns cursor on. 31/$1F, the number of the 8563's data r e a d / w r i t e register.
Begins by checking the active screen flag. If the 40-column Then it falls through into the following routine to store the ac-
display is active, the routine merely clears the cursor enable cumulator contents in that register. Writing to register 31
flag (2599/$0A27) and exits. For the 80-column display, the causes the value written to be stored in the 80-column RAM
attribute of the current cursor position is read and stored in location addressed in registers 18-19.
2611/$0A33. The upper four bits (containing the printing style The following example shows h o w to use this routine to
information) are stored in 219/$DB. Then this style infor- copy the contents of the first 256 bytes of 40-column screen
mation is combined with the current cursor color (the lower memory (locations 1024-1279/$0400-$04FF) to 80-column
four bits of 241/$F1) to determine the new attribute for the screen memory:
cursor position. Finally, the cursor is enabled by writing the
current cursor style (stored in 2603/$0A2B) to the 8563 chip's 0B00 LDX #$12 ; Load registers 18 and 19
cursor control register (RIO). 0B02 LDA #$00 ; with low and high bytes of
OB04 JSR $CDCC ; 80-column screen starting
0B07 INX ; address ($0000).
52639 $CD9F CRSROFF 0B08 JSR $CDCC
Turns cursor off. 0B0B LDY #$00 ; Initialize loop offset.
Begins by checking the active screen flag. If the 80-column 0B0D LDA $0400,Y ; Read byte from 40-column screen,
display is active, this routine sets the update location registers 0B10 JSR $CDCA ; Store in 80-column RAM.
(R18-R19) to the address of the attribute for the current cursor 0B13 INY
0B14 BNE $0B0D ; Loop for 256 bytes.
position, then restores the cursor position to its original 0B16 RTS
attribute (stored in 2611/S0A33), Finally, the cursor is dis-
abled by writing the value 32/$20 to the 8563 chip's cursor 52684 $CDCC WRITEREG
control register (RIO). For the 40-column display, the cursor is
disabled by clearing the cursor enable flag (2599/$0A27). Writes to an 80-column chip register.
Then the blink phase flag (2598/$0A26) is checked to see Stores the accumulator contents in the 8563 register specified
whether the character under the cursor is in the normal or re- in the X register (see Chapter 8 for a description of the 8563's
versed portion of the blink sequence. If the character is in its registers). The accumulator and X register contents will not be
normal state, no further action is necessary. However, if the changed, and the Y register is unaffected. No error checking is
character is reversed, the blink phase flag is reset and the performed; when you use this routine you are responsible for
cursor position is restored to its original character and color making sure that X contains a valid register number (0-36/
(stored in 2601/S0A29 and 2602/$0A2A, respectively). $00-$24). This routine illustrates the proper procedure for
writing to an 8563 register: The desired register number is
52682 $CDCA WRITE80 stored in 54784/$D600. Then the routine waits until bit 7 of
that location is set to % 1 , after which the new register value is
Writes a byte value to 80-column chip memory. stored in location 54785/$D601.
Stores the value in the accumulator into a location in the 8563
chip's private 16K of RAM. The target memory address is 52696 $CDD8 READ80
specified by the current contents of the 8563's update location
registers (R18-R19). The contents of the X register will be Reads a byte value from 80-column chip memory.
changed, but the contents of the accumulator and Y register Reads the contents of a location in the 8563 chip's private 16K
are unaffected. The address in R18-R19 is automatically incre- of RAM. The target memory address is specified by the current
mented after a byte is written, so it is not necessary to update contents of the 8563's update location registers (R18-R19).
those registers before every byte when writing to a series of The location's contents will be in the accumulator upon exit
322
323
52698 SCDDA 52748
ecEoc

from this routine. The contents of the X register will be 52710 $CDE6 SCNPOS
changed, but the Y register is unaffected. The address in
R18-R19 is automatically incremented after a byte is read, so Sets the current address in 80-column screen memory.
it is not necessary to update those registers before every byte Loads the 8563 update location registers (R18-R19) with the
when reading a series of sequential addresses. The routine address of the screen memory location that corresponds to the
works by loading X with 31/$IF, the number of the 8563's current cursor position. Upon entry, the Y register should con-
data read/write register. Then it falls through into the follow- tain the offset to the current column. To calculate the memory
ing routine to load the accumulator with the contents of that address, this offset is added to the address of the first screen
register. Reading from register 31 returns the contents of the memory location for the current screen line (224-225/
80-column RAM location addressed in registers 18-19. $E0-$El). The registers are loaded by using the subroutine at
52684/$CDCC. Once the address is loaded into R18-R19, the
The following example shows how to use this routine to next value placed in the read/write register (R31) will be
copy the contents of the first 256 bytes of 80-column screen stored in the specified screen memory location.
memory to 40-column screen memory locations 1024-1279/
$0400-$04FF: 52729 $CDF9 ATTRPOS
0B00 LDX #$12 Load registers 18 and 19 Sets the current address in 80-column attribute memory.
0B02 LDA #$00 with low and high bytes of
0B04 JSR Loads the 8563 update location registers (R18-R19) with the
$CDCC 80-column screen starting
0B07 INX address ($0000). address of the attribute memory location that corresponds to
0B08 JSR $CDCC the current cursor position. Upon entry, the Y register should
0B0B LDY #$00 Initialize loop offset. contain the offset to the current column. To calculate the
0B0D JSR $CDD8 Read a byte from 80-column RAM. memory address, this offset is added to the address of the first
0B1O STA $0400,Y Store in 40-column screen memory. attribute memory location for the current screen line
0B13 INY (226-227/$E2-$E3), The registers are loaded by using the
0B14 BNE $0B0D Loop for 256 bytes. routine at 52684/$CDCC. Once the address is loaded into
0B16 RTS
la R18-R19, the next value placed in the read/write register
(R31) will be stored in the attribute memory location.
52698 $CDDA READREG
Reads from an 80-column chip register. 52748 SCEOC INIT80
Reads the current contents of the 8563 register specified in the Initializes character definitions for 80-column screen.
X register. The register value will be in the accumulator upon (This routine has a screen editor jump table entry at 49191/SC027
exit from this routine. See Chapter 8 for a description of the and a Kernal jump table entry at 65378/$FF62.)
8563's registers. The X register contents will not be changed, Copies the contents of the character generator ROM (at
and the Y register is unaffected. No error checking is per- 53248-57343/$D000-$DFFF in bank 14) to the character defi-
formed; when you use this routine you are responsible for nition area at 8l92-16383/$2000-$3FFF in the 80-column
making sure that X contains a valid register number (0-36/ video chip's private block of RAM (which is not part of the
$00-$24). This routine illustrates the proper procedure for 8502 microprocessor's address space). This is necessary be-
reading an 8563 register: The desired register number is stored cause the 8563 chip has no character ROM of its own. Because
in 54784/SD600. Then the routine waits until bit 7 of that lo- the 8563 uses 16-byte character definitions, each 8-byre char-
cation is set to % 1 , after which the register value can be read acter definition from ROM is padded with eight zeros when
from location 54785/$D601. copied to 8563 RAM. See Chapter 8 for information on how
the 80-column characters can be redefined.
In the 128's ROM, this routine is called only by the
Kernal IOIN1T routine [$E109], which is part of both the reset
324 325
52812
$CE4C SCE5C 52828

and RUN/STOP-RESTORE sequences. However, the call is


preceded by a test of the initialization status flag (2564/$0A04). Table Entry Table Offset
If bit 7 of that flag is set to % 1 , the step to download 80- (character code) (color number) Color
column character definitions is skipped. The reset routine 152/$98 12/$0C medium gray
[$E000] clears the status flag before calling this routine, so 153/$99 13/$0D light green
character definitions are initialized when the 128 is reset (in- 154/$9A 14/$0E light blue
155/$9B 15/$0F light gray
cluding when it is first turned on). Then it sets bit 7 afterward
to indicate that this step has been performed. The RUN/ 52828 $CE5C COLOR80
STOP-RESTORE sequence [$FA53] does not affect the initial- Table of 8563 color code translation values.
ization status flag, so the character definitions will not usually
The character codes which change printing colors are initially
be recopied when IOINIT is called during that sequence. Thus,
translated into color numbers for the 40-column (VIC-II) chip.
if you redefine (or, worse, accidentally garble) the character
The 8563 80-column video chip can produce most of the
definitions in the 8563's RAM, RUN/STOP-RESTORE won't
same colors as the 40-column chip, but its color memory and
return them to normal as it does for the 40-column screen.
color registers require different color numbers. This table is
You can restore the normal 80-column character shapes by
used to translate VIC-II color values into 8563 color values.
pressing the RESET button or, less dramatically, by calling this
For example, storing 6 in the VIC-II chip register at
routine (with SYS 52748, for example). You can clear bit 7 of
53281/SD021 changes the 40-column background to dark
2564/$0A04 to %0 and call IOINIT.
blue, but storing 6 in the 8563's background register (the
lower nybble of R26) will result in a dark cyan 80-column
52812 $CE4C COLORTBL background. The proper 80-column chip color number can be
Table of color character translation values. found by using the VIC-II color number as an offset into this
There is no direct mathematical relationship between the char- table. For example, the 80-column color value for dark blue, 2,
acter codes which change printing colors and the actual VIC-II is found at an offset of 6 from 52828/$CE5C,
chip color numbers for the selected hues, so this table is used
to translate the character codes into values for VIC-II chip Offset
color settings. For example, the character code which, when (VIC-II 8563 Chip
printed, changes character color to dark blue is 31/$ IF. This color number) (color number) Color
0/$00 0/$00 black
value is found at an offset of 6 into the table, and 6 is the
l/$01 15/$0F white
VIC-II's color number for dark blue.
2/$02 8/$08 dark red
Table Entry Table Offset 3/$03 7/$07 light cyan
(character code) (color number) Color 4/$04 ll/$0B light purple
144/$90 0/$00 black 5/$05 4/$04 dark green
5/$05 l/$01 white 6/$06 2/$02 dark blue
28/$1C 2/$02 red 7/$ 07 13/$0D light yellow
159/$9F 3/$03 cyan 8/$08 10/$0A dark purple
156/$9C 4/$04 purple 9/$09 12/$0C dark yellow
3O/$1E 5/$05 green 10/$0A 9/$09 light red
31/$1F 6/$06 blue ll/$0B 6/$06 dark cyan
158/$9E 7/$07 yellow 12/$0C 1/S01 dark gray (light black)
129/$81 8/$08 orange 13/$0D 5/$05 light green
149/$95 9/$09 brown 14/$0E 3/$03 light blue
150/$96 10/$OA light red 15/$0F 14/$0E light gray (dark white)
151/197 ll/$0B dark gray
326
327
52844 $CE6C $CEF5-$CFFF 52981-53247

As an example of how you would use this table to trans- 52904 $CEA8 KEYDEFS
late color numbers, suppose you had a 40-column color num-
ber in the accumulator and needed to know the equivalent 80- Table of standard function key definitions.
column color number. All that's needed is The first ten bytes here hold the lengths of the following ten
key definition strings. The screen editor initialization routine
TAX [SC07B] copies these lengths and strings to the definition area
LDA $CE5C,X
at 4096/$1000. The text for the standard definitions is as
52844 $CE6C follows:
MASKTBL Key Definition
Table of bit mask values.
Fl GRAPHIC
Each of the eight bytes in this table has only one bit set to F2 DLOAD"
% 1 . The mask values are used to decode bitmapped tables F3 DIRECTORY {RETURN}
such as the ones for tab stops and line links. The binary F4 SCNCLRjRETURN}
equivalents of the table bytes, in order, are as follows: F5 DSAVE"
%10000000 F6 RUN {RETURN}
%01000000 F7 LIST{RETURN}
%00100000 F8 MONITOR {RETURN}
%00010000 SHIFT-RUN/STOP DL"*{RETURN}RUN{RETURN}
%00001000 HELP HELP {RETURN}
%00000100 If you ever need to restore the standard key definitions, you
%0 0000010
%00000001 can recopy the contents of this table into the definition area.
In BASIC, the required program line would have this form:
BANK 15: FOR 1=0 TO 76: POKE 4096+I,PEEK(52904+I): NEXT I
52852 $CE74 VARTBL
Tables of default screen editor variables. 52981-53247 $CEF5-$CFFF Unused
Locations 52852-52877/$CE74-$CE8D hold the default
screen editor variable settings for the 40-column screen. Loca- All locations in this unused area of ROM are filled with the
tions 52878-52903/$CE8E-$CEA7 hold the default settings value 255/$FF, except for the final two, which are $00 $C3.
for the 80-column screen. The screen editor initialization rou- Ideally, the keyboard decoding tables would have been placed
tine [$C07B] copies the values for the default screen—deter- here following the screen editor routines so that the screen
mined by the position of the keyboard 40/80 DISPLAY key— editor package could be fully self-contained in this block of
into the active screen variable table at 224-249/$E0-$F9, and ROM. However, there's not sufficient room here for the five
the values for the other screen into the inactive screen table at 89-byte keyboard tables, so they were placed at the end of
2624-2649/$0A40-$0A59. Thus, the values in these tables de- Kernal ROM (64128-64572/$FA80-$FC3C).
termine the variable settings after power-on, reset, or
RUN/STOP-RESTORE.
Actually, due to a bug in the initialization routine, one
byte too many is copied when the tables are transferred to
RAM. Thus, the byte following the active screen default value
table will be copied to 250/SFA, and the byte following the
inactive screen default table will be copied to 2650/$0A5A.

328
329
I/O Chip Registers,
Color RAM, and
Character ROM
Bits 0 and 4-5 of the MMU configuration register (65280/
$FF00) determine what is visible in the area between addresses
53248-57343/$DO00-$DFFF of the 128's memory space. If bit
0 of the configuration register is %0, the collection of hard-
ware registers and 40-column color RAM known as the I/O
block is visible, regardless of the setting of bits 4 and 5 of the
register. The I/O block includes the following elements:
53248-53296/$D00O-$D030 VIC (40-column) video chip registers
54272-54300/$D400-$D41C SID sound chip registers
54528-54539/$D500-$D50B MMU chip registers
54784-54785/$D600-$D601 VDC {80-cohimn) video chip registers
55296-56319/$D800-$DBFF Color RAM for VIC chip
56320-56335/$DC00-$DC0F CIA chip registers (CIA #1)
56576-56591/$DD00-$DD0F CIA chip registers (CIA #2)
57088-57098/$DF0O-$DFOA REC expansion controller chip regis-
ters (if memory-expansion module
connected)
If bit 0 of the configuration register is set to % 1 , the set-
ting of bits 4 and 5 will determine what is visible in this area.
(Actually, these bits control what is seen in the entire area
from 49152-65535/$C000-$FFFF.) The four possible selec-
tions for 53248-57343/$D000-$DFFF are as follows:
Bits Block contents
5 4
0 0 Character ROM
0 1 Internal function ROM
1 0 External function ROM
1 1 RAM
Character ROM contains the bit patterns to define the shape
of the letters, numbers, and symbols for the video displays.
When RAM is selected, the RAM block from which the mem-
ory is seen is determined by the setting of bits 6 and 7 of the

333
configuration register. The I/O block is visible in all standard
bank configurations except banks 0-3, which are all RAM, and Video Fundamentals
bank 14, where character ROM is seen. The output signals from the VIC chip tell the video device
A bit of 128 hardware trivia: Since the MMU configura- (monitor or television) how to draw the screen display. To un-
tion register setting in bits 4-5 for character ROM is also the derstand the operation of the VIC chip, you need to under-
one which selects screen editor ROM at 49152-53247/ stand a few of the fundamentals of video displays. The display
$C000-$CFFF and Kemal ROM at 57344-65535/$E000-$FFFF, is drawn on the monitor or television picture tube by a "gun"
you might expect that character patterns are stored between that shoots a beam of electrons at the screen. Where the beam
the screen editor and Kernal routines in the 16K ROM chip strikes the face of the screen, a spot on the screen's phospho-
designated U35. However, this is not the case. Character pat- rescent coating glows briefly. The electron gun doesn't just
terns are stored in a separate 4K ROM chip, designated U18. spray electrons at random; the beam is moved in a precisely
So what's between 53248-57343/$D000-$DFFF in the ROM controlled pattern. Beginning in the upper left corner of the
chip containing the screen editor and Kernal? That's where the screen, the beam is scanned (moved) horizontally across to the
ROM routines for CP/M mode are stored. The memory-shuf- right edge of the screen, drawing a very thin line of dots. It is
fling capabilities of the MMU and PLA allow this area of ROM then blanked while it is moved back to the left edge, but just
to appear at addresses 0-4095/$0000-$0FFF when CP/M below the top line. The beam is then scanned horizontally
mode is selected. Because this section of ROM is always invisi- across the screen again, and the process is repeated until the
ble to 128 mode, it is not covered further in this book. stack of thin lines fills the screen display.
Actually, for a color display there are three separate
beams working in conjunction to draw each line—one each
VIC (Video Interface Controller) Chip for the colors red, green, and blue. Each dot in the thin screen
line consists of red, green, and blue points. When the relative
53248-53296/$D000-$D030 intensities of the red, green, and blue points are varied, the
The chip whose registers appear in this area of the I/O block dot can take on a variety of hues. The VIC chip can produce
is referred to in Commodore literature as the VIC, even 16 different colors. Whenever a memory location or VIC regis-
though it is not exactly the same as the chip with that des- ter calls for a color value, the color is specified by a value in
ignation in the Commodore 64. However, the chip does pro- the range 0-15. Table 8-1 lists the standard designations for
vide the same 40-column video display features as its the VIC chip colors.
Commodore 64 predecessor. The differences are in the chip's
less familiar, but equally vital function of providing all the Table 8-1. Standard VIC Color Values
basic riming signals required by the system. The 128's version
of the VIC chip also supports the scanning of the additional 24 Value Color Value Color
keys on the 128's keyboard. For these new features, the 128 0/$00 black 8/$08 orange
version of the VIC has two more registers than its Commodore l/$01 white 9/$09 brown
2/$02 red 10/$OA light red
64 counterpart (49 instead of 47). There are actually two dif-
3/$03 cyan ll/$0B dark gray
ferent versions of the 128 VIC chip, depending on the video 12/$0C medium gray
4/$04 purple
system required in the country where the computer is sold. green 13/$0D light green
For NTSC (North American) video, the version is officially 5/$05
6/$06 blue 14/$0E light blue
designated the 8564 chip, while the PAL (European) model is 7/$07 yellow 15/$0F light gray
designated the 8566. All the registers described below operate
the same on both chips; only the video signal format is different. The stack of horizontal video lines is called the raster
(from the Latin word for rake—the pattern of evenly spaced
parallel lines is similar to that produced by pulling a rake
through soil). The individual lines are called raster scan lines.
334
335
The number of lines required for a full screen depends on the is in the degree of control over individual pixels. The bitmapped
video system in use. The North American (NTSC) version of (high-resolution) modes allow you to determine the color of
the VIC chip draws a raster of 264 scan lines, while the Euro- each pixel individually, while the character (low-resolution)
pean (PAL) version draws 313. Since the screen phosphor modes only allow control of groups of pixels. The tradeoff is
glows only briefly when struck by the raster beam, the screen that the character display modes use much less memory.
must be constantly redrawn. The rate of redrawing also de-
pends on the video system: 60 times per second for NTSC sys- Video Banks
tems or 50 times per second for PAL systems. Not all of these Before you read a discussion of the display modes, it's impor-
raster lines are used for the active video display. Most televi- tant to understand how the VIC chip sees memory. The VIC
sions and monitors overscan. That is, some raster lines at the uses the same RAM as the 8502 microprocessor, but it views
top, bottom, or both are actually drawn off the screen. The the memory very differently. The VIC chip has only 14 ad-
VIC compensates by restricting the active portion of the dis- dress lines compared to the processor's 16. This means that
play, the area where characters and graphics can be displayed, the VIC can, at any given time, address only 16K (16384
to 200 lines in the middle of the raster for both NTSC and bytes) out of the 64K of RAM in a block. The 16K area seen
PAL systems. (This can be reduced to 192 lines. For details, by the VIC chip is referred to as a video bank, not to be con-
see the entry for 53265/$D011.) The inactive lines form the fused with one of the processor's bank configurations—there
top and bottom portions of the border, a solid-color frame is no relationship. All of the information for the VIC screen
around the active screen. display must be visible within the same video bank. There are
The horizontal dots that make up each scan line are called four possible video banks per 64K block, or a total of eight
pixels (short for picture elements). The number of pixels in a possible video banks in the two RAM blocks in the 128. Bits
scan line depends on the screen mode, and is limited by the 0-1 of the CIA #2 register at 56576/$DD00 select one of the
speed at which the VIC chip can read data from memory. In four banks, and bit 6 of the MMU register at 54534/$D506 se-
the standard two-color modes, where a single bit determines lects which 64K-RAM block the video bank will be seen in.
the pixel color, the VIC chip draws 320 active pixels per scan Refer to the entries for those locations later in this chapter for
line. In the four-color (multicolor) modes, two bits are required more details. The base (starting) addresses for the banks are as
to specify the color of each pixel. Since the VIC must read follows:
twice as much data per pixel, only half as many pixels can be Bank Base address
drawn in the time allotted for a single scan line. As a result, 0 0/$0000
the multicolor modes have only 160 active pixels per scan line. 1 16384/S4000
The display is still the same size; the pixels are twice as wide. 2 32768/$8000
{The screen width can also be reduced to 304 standard pixels 3 49152/$C000
or 152 multicolor pixels. For details, see the entry for 53270/
$D016.) Just as the VIC draws extra lines above and below the Character Display Modes
active ones, it also draws extra pixels to the left and right of The VIC provides three character display modes: standard,
the active ones. The inactive pixels form the sides of the solid- multicolor, and extended background color. The standard
color border. character display mode is the default system for the VIC—the
The VIC chip supports two major classes of display one which is active when no other mode is selected. The other
modes—character and bitmapped. These are also referred to two modes are not directly supported by the 128 operating
as low resolution and high resolution, but that's somewhat system (there's no GRAPHIC statement to select these modes),
misleading, since both provide the same active screen areas— so you must enable them by directly setting the appropriate
320 pixels X 200 lines for standard modes or 160 pixels X 200 bits in VIC registers. As a result, those modes are a bit more
lines for multicolor modes. The difference between the classes difficult to use effectively.
336 337
For a standard (GRAPHIC 0) character display, the 320- acter position on the screen. Unlike the case of screen and
pixel X 200-line active screen area is divided into 1000 8-pixel character memory, however, the location of VIC color memory
X 8-line character positions, arranged as 25 rows with 40 is fixed and does not have to be within the current video bank.
character positions per row. The contents of the character po- It always appears to the processor at locations 55296-56319/
sitions are determined by values stored in a 1000-byte area of $D800-$DBFF in the 1/0 block. Refer to the section on color
screen memory (sometimes referred to as the video matrix). memory later in this chapter for details.
Each location in screen memory corresponds to a single char- The procedure for displaying the character A in blue at
acter position on the screen. The value in a screen memory lo- the upper left corner of the screen would be something like
cation selects one of 256 standard character-pattern definitions this: The VIC looks to the first location of screen memory to
to be drawn in the corresponding character position. The determine which character pattern to display in that position.
screen memory values are referred to as screen codes, and The screen code for A is 1, so this value is used as an index to
they are not the same as character codes. See Appendix C for the eight-byte pattern definition in character memory. The VIC
a list of screen codes and corresponding character patterns. then looks to the first location of color memory and proceeds
The location of screen memory within the current video bank to draw pixels in the color specified there (6 for blue) for all
is controlled by bits 4-7 of the VIC register at 53272/$D018. %1 bits in the pattern. For all %0 bits, pixels are drawn in the
See the entry for that register for details. color specified in the background color register. Figure 8-1
The pattern definitions come from another area of mem- illustrates the process.
ory known as character memory. As mentioned above, each
character position consists of eight scan lines with eight pixels Figure 8-1. Standard Character Display Mode
per line—a total of 64 pixels per position. In standard charac-
ter mode, a pixel can be one of two colors, so only one bit
(which can be either %0 or %1) is required per pixel. Thus, a
character-pattern definition requires 64 bits, or eight bytes.
The pixels represented by %0 bits in the pattern definition are
drawn in what is referred to as the background color, which is
common to all screen positions. The pixels represented by %1
bits are drawn in what is referred to as the foreground color,
which can be independently selected for each character posi-
tion. The location of character-pattern memory within the cur-
rent video bank is controlled by bits 1-3 of the VIC register at
53272/SD018. See the entry for that register for more details.
Standard character definitions for the 128 come from the char-
acter ROM. This ROM is located beginning at address 53248/
$D000 in the system's address space, but can be made visible
in any video bank. See the section on character ROM later in
this chapter for more information.
The background color for %0 bits in all character posi-
tions is determined by the value in the VIC register at
53281/$D02I. The foreground color for the %1 bits in each
character position is determined by values in another 1000-
byte area of memory known as color memory. As in screen
memory, each location in color memory corresponds to a char-
339
Custom Characters 600 FOR 1 = 0 TO 7
You are not limited just to the character patterns provided in 610 READ A
the ROM. It is relatively simple to design your own characters. 620 POKE 8192 + (8 * 28) + I,A
However, using custom characters is an all-or-nothing affair. 630 NEXT
Once you switch off the standard ROM-based character set, 640 DATA 24,60,102,96,102,60,24,0
you must provide definitions for every character you wish to This example assumes that character memory has previously
use. You must begin by selecting the area of RAM where you been relocated to address 8192/$2000.
will place the new character set. See the entry for the register
at 53272/$D018 for details. If you only want to use a few cus- Figure 8-2. Custom Character Design Grid
tom characters while retaining the majority of the standard
% D0011000 = 24/$18
character set, the next step is to copy the standard character
% 00111100 = 60/$3C
patterns from ROM to the selected RAM area. If you do this,
% 01100110 = 102/$66
you'll only have to provide custom pattern information for
% 01100000 = 96/$60
those characters you wish to redefine.
"A011001IO = 102/S66
To calculate the proper byte values for a custom character % 00111100 = 60/S3C
definition, use an 8 X 8 grid as shown in Figure 8-2. Fill in % 00011000 = 24/S1B
the grid squares for those pixels you wish to have displayed in % 00000000 = 0/$00
the foreground color. Unless you are designing patterns that
will connect with adjacent patterns (such as the line segments
in the standard character set), it is customary to leave at least Multicolor Character Mode
one row and one column of the pattern blank to provide some Multicolor character mode is similar in operation to standard
horizontal and vertical separation between characters. The character mode. The difference is that each multicolor charac-
ROM patterns for the standard letters and numbers don't fill ter position consists of 4 pixels X 8 lines (instead of 8 X 8).
in any pixels in the leftmost column, and only lowercase char- The number of positions remains the same (25 rows X 40 col-
acters with descenders (g, j, p, q, and y) use the bottom row. umns) and the positions are the same size, but now each pixel
To calculate the binary bit pattern for each row of the pat- is twice as wide (there are only 160 pixels per raster line).
tern, use a %0 for each blank (background) pixel and a %1 for However, each pixel can be one of four colors instead of just
each filled (foreground) pixel. Next, convert the binary bit pat- one of two colors. Screen memory still holds pointers to pat-
tern to a number (use the machine language monitor's number- tern definitions in character memory, but the pattern infor-
conversion feature if you're not handy with binary). The final mation is interpreted differently. It now takes two bits per
step is to store the resulting eight values in the character pixel to select the color instead of just one, but since there are
memory locations for the pattern you are changing. The sim- only half as many pixels per pattern, the number of bits re-
ple formula for finding the starting address in character mem- quired for each definition remains the same (2 bits per pixel *
ory of the pattern for any character is: 4 pixels * 8 lines = 64 bits).
pattern address = character base address + (8 * screen code) To select multicolor character mode, you must set bit 4 of
the VIC register at location 53270/$D016. However, there's a
The character base address is the starting address of character problem here because the screen editor IRQ routine always re-
memory (see the entry for 53272/$D018). For example, to re- sets this bit to %0 when setting up the text screen (see the sec-
place the British pound symbol (£, screen code 28/$lC) with tion below on the screen editor IRQ routine). To prevent this,
the pattern shown in Figure 8-2, you could use statements like you must turn off the screen-setup portion of the IRQ by stor-
the following: ing the value 255/$FF in location 216/SD8. Setting the VIC
register bit makes it possible to enable multicolor character

340 341
mode for any or all screen positions, but it doesn't actually
switch any screen positions to multicolor mode. Multicolor Desired %11 bit color Value to store in color memory
mode must be enabled individually for each character position black 8/$08
white 9/$09
on the screen. The controlling factor is bit 3 of the color mem- red
ory location for each character position. When that bit is %0 10/$0A
cyan ll/$0B
in a color memory position, the corresponding character posi- purple 12/$0C
tion on the screen remains in standard character mode, so it is green 13/$0D
possible to intermix standard and multicolor character modes blue 14/$0E
on the same screen display. However, only bits 0-2 of the yellow 15/$0F
color memory location are now available to hold color values,
so the foreground color for standard mode positions in a mul- Because the standard character sets were not designed to
ticolor display is limited to the first eight values in Table 8-1— be displayed in multicolor character mode, any text printed to
black-yellow, values 1-7. To select multicolor character mode the screen in this mode will be at best barely legible. As a re-
for a screen position, you must set bit 3 of the corresponding sult, multicolor mode is practical only when you are using cus-
color memory location to % 1 . That is, you must store a value tom characters designed specifically for this mode. The rules
of 8 or greater in the location. for designing custom characters for multicolor mode are the
When a multicolor character is drawn, all pixels in the same as for the standard character mode, except that you de-
pattern represented by %00 bit pairs will be drawn in the sign the characters in a 4 X 8 grid, as shown in Figure 8-3.
background color specified in the VIC register at 53281/
$D021. All pixels represented by %01 bit pairs will be drawn
in the color specified by the value in the register at 53282/ Figure 8-3. Multicolor Character Design Grid
$D022, and all pixels for %10 bit pairs will be drawn in the
color specified in the register at 53283/$D023. All of these
registers can take any of the 16 standard colors listed in Table = %00 Dl 01 00 = 20/S14
8-1, but since the registers are common to all positions, the
color for pixels with %00, %01, and %10 patterns will be the = %00 10 10 00 = 40/$28
same for all characters. However, the color for pixels with
%11 bit patterns can be specified individually for each screen - %01 10 10 01 = 105/$69
position in the corresponding color memory location. Since bit
3 of the color memory location is used to specify multicolor = <ftl0 11 11 10 = 190/SBE
mode, only bits 0-2 are available to hold color values. As a re-
sult, only the first eight colors are available. But since bit 3 - 1410 11 11 10 = 190/SBE
must be set to % 1 , the values you store in color memory to
achieve these colors are different from the standard values. For = %01 10 10 01 = 105/$69
multicolor character mode, the values to store in color memory
to select the available colors for %11 bits are as follows: « %00 10 10 00 = 40/$28

= %00 01 01 00 = 20/$14

342
343
Each grid position can hold one of four two-bit values unique screen code values (0-63), so only the first 64 eight-bit
representing the four color choices: pattern definitions in character memory are used in this mode.
%00 Background color 0 (common to all characters) For example, screen memory values of l/$01, 65/$41, 129/$81,
%01 Background color 1 (common to all characters) and 193/$C1 all produce the same character (screen code 1,
%10 Background color 2 (common to all characters) the letter A in the standard character set), but each provides a
%11 Foreground color {independently selectable for all characters, different background color for that character.
but only eight colors are available)
Once the design is completed, the byte values for the charac- Bitmapped Display Modes
ter-pattern definition are calculated just as for standard charac- The VIC provides for two bitmapped modes: standard and
ter mode. multicolor. In these modes, the state of each pixel in the
screen display can be controlled independently. The standard
Extended Background Color Mode bitmapped mode allows you to select one of two colors for
The third character mode, extended background color mode, is each pixel, while the multicolor mode allows you to chose
selected by setting bit 6 of the VIC register at 53265/$D011 to from among four colors. Both modes are supported by the op-
% 1 . It also uses the same fundamental elements as standard erating system: standard bitmapped mode as GRAPHIC 1 (or,
character mode: screen memory, character memory, and color with a text window, as GRAPHIC 2) and multicolor bit-
memory. As in standard character mode, the extended back- mapped mode as GRAPHIC 3 (or, with a text window, as
ground color mode screen is divided into a 25-row X 40-column GRAPHIC 4).
grid of 8-pixel X 8-line character positions. As in standard Standard bitmapped mode is selected when bit 5 of the
character mode, each position has a corresponding screen VIC register at 53271/$D017 is set to %1 (but see the section
memory location that holds a value indicating which pattern below on the screen editor IRQ for information about the
from character memory is to be drawn in the position. And, as shadow for this bit). This mode provides for 320 horizontal
in standard character mode, each character position on the pixels per line, each of which can be one of two colors. A sin-
screen takes its foreground color (the color for pixels repre- gle bit is required to specify the color of each pixel, so 320 *
sented by % 1 bits in the character pattern) from the value in a 200, or 64,000 bits, are required to "map" the entire display
corresponding color memory location. The difference is that area. At 8 bits per byte, 8000 bytes are required for the bit-
extended background color mode allows you to select from map. This is half of the available space in the 16K video bank.
among four different background colors for the pixels repre- The starting address of the bitmap is specified in bit 3 of the
sented by %0 bits in the character patterns. register at 53272/$D018.
The background color for each position is specified by bits The VIC's scheme for mapping the screen is simple for
6-7 of the screen code for the position. These bits select which the chip (it's a variation of character mode), but it's rather
of the four background color registers will specify the back- complicated for the programmer. As you would expect, the
ground color for the position: first eight pixels on the screen, starting in the upper left corner
Bits Background color source of the first vertical line, are controlled by the eight bits of the
7 6 first byte of the bitmap. However, the next eight pixels are
0 0 background color register 0 (53281/$D021) controlled by the bits of the ninth byte. The bits of the second
0 1 background color register 1 (53282/$D022) through eighth bytes in the bitmap control the leftmost eight
1 0 background color register 2 (53283/SD023) pixels of the second through eighth vertical lines. This scheme
1 1 background color register 3 (53284/$D024) is repeated across the screen. Figure 8-4 illustrates the offsets
Since the highest two bits of each screen memory location from the bitmap starting address for the bytes which control
are used to specify background color, only bits 0-5 are avail- the pixels in the upper left corner of the screen.
able to hold screen code data. Thus, there are only 64 different
344 345
Figure 8-4. Byte Offsets for Bitmapped Screen where x will have a value in the range 0-319 and y will have
a value in the range 0-199.
0 B 16 Each bit in the bitmap can be either %0 or % 1 , so each
1 9 17 corresponding pixel on the screen can be one of two colors. By
2 10 18 convention, the color specified by a %0 bit is referred to as the
3 11 19 background color and the color specified by a %1 bit is re-
4 12 20 ferred to as the foreground color. The values for both colors
5 13 21 come from the video matrix, the area used as screen memory
6 14 22 in the character display modes. (Color memory and the back-
7 IS 23 ground color registers are not used in standard bitmapped
320 328 336 mode.) The low nybble (bits 0-3) of a video matrix location
321 329 337 holds the background color value and the high nybble (bits
322 330 338 4-7) holds the foreground color value. Either foreground or
323 331 339 background can take any of the 16 colors listed in Table 8-1.
324 332 340 However, since there are only 1000 video matrix positions, the
325 333 341 foreground and background color cannot be specified individ-
326 334 342 ually for each of the 64,000 pixels on the screen. All 64 pixels
327 335 | 343 within an 8-pixel X 8-line area will share foreground and
640 648 656 background colors. The common areas are arranged in the
641 649 657 same fashion as screen memory: 25 rows X 40 coiumns.^ To
642 650 658 determine the video matrix location that holds the color infor-
643 651 659 mation for a particular x,y coordinate, use the following
644 652 660 formula:
645 653 661 color byte = 40 * INT(y / 8) + INT(x / 8) + screen base address
646 654 662
647 |_ 655 663 Multicolor Bitmapped Mode
960 968 976 Multicolor bitmapped mode is similar to bitmapped mode, but
the number of possible colors per common color area is in-
creased to four. To select among four different colors, two bits
This obviously isn't very convenient. Most programmers are required for each pixel. Since twice as many bits are re-
prefer to use a more familiar ^-coordinate system, as shown quired to specify the color of each horizontal pixel, only half
in Figure 8-5. In this system, the horizontal (x) pixel position as many pixels can be displayed per line; horizontal resolution
will be in the range 0-319 and the vertical {y) position will be is reduced to 160 pixels per line. The display will still be the
in the range 0-199. In x,y format, the upper left corner of the same size, but each pixel will now be twice as wide. To deter-
screen is position 0,0 and the lower right corner is position mine the byte offset (0-7999) within the bitmap and the bit
319,199. This is also the format used to specify screen posi- pair (0-3) within that byte which correspond to a particular
tions in BASIC statements such as BOX, CIRCLE, and DRAW, ^-coordinate pair, use the following formulae:
To determine the byte offset (0-7999) within the bitmap and byte offset = 40 * (y AND 248) + 2 * (x AND 252) + (y AND 7)
the bit (0-7) within that byte which corresponds to a particu- bit pair = 3 - (x AND 3)
lar ^-coordinate pair, use the following formulae: where x will have a value in the range 0-159 and y will have
byte offset = 40 * (y AND 248) + (x AND 504) + (y AND 7) a value in the range 0-199.
bit = 7 - (x AND 7)
346 347
Of the four color sources in multicolor mode, one is com- wide. Sprites can also be doubled in size horizontally or verti-
mon to all pixels on the screen and the other three can be se- cally (see the registers at 53271/$D017 and 53277/$D01D).
lected independently for each common color area. Common The rules for defining sprite bit patterns are the same as
color areas correspond in size {4 pixels X 8 lines) and layout for custom characters in the corresponding screen modes. Each
(40 X 25) to multicolor character positions. All pixels repre- standard sprite pixel is represented by one bit in a pattern bit-
sented by %00 bit patterns in the bitmap will take the color map, while each multicolor sprite pixel requires two bits.
specified in the VIC background color register at 53281/ Thus, three bytes are required to define each scan line of the
$D021. As in standard bitmapped mode, the video matrix pattern, and each sprite pattern definition requires 3 * 21, or
(screen memory) area holds color information. In this case, the 63 bytes. The rules for calculating byte values are the same as
lower nybble (bits 0-3) of each video matrix location specifies for custom character patterns. Figure 8-5 shows a sprite design
the color for all %10 bit patterns within the corresponding grid.
common color area, while the upper nybble (bits 4-7) specifies
the color for alt %01 bit patterns in the common color area. Figure 8-5. Sprite Design Grid
The color for any %11 bit patterns in each common color area
is determined by the value in the corresponding color memory
location (55296-56295/$D800-$DBE7). Any of these color
sources can take any of the 16 color values listed in Table 8-1.

Sprites
Sprites, which Commodore officially calls movable object
blocks (MOBs), are a special feature of the VIC. As their offi-
cial name implies, sprites are images that can be easily moved
about on the screen. Sprites are completely independent of the
background display, and can be made to appear either in front
of or behind screen foreground objects. They can move with
equal ease over character and bitmapped screens. The manipu-
lation of sprites consumes a substantial portion of the VIC
chip's internal hardware. You'll notice in the discussion of VIC
registers that 34 of the chip's 49 registers are used for some
sort of sprite manipulation. This section uses the standard VIC
number designations, 0-7, for the eight sprites. BASIC, on the
other hand, uses sprite numbers 1-8. Add 1 to the VIC sprite
number to get the corresponding BASIC sprite number, or
subtract 1 to convert the BASIC sprite number to a VIC sprite
number.
Sprites have the same two basic modes as screen displays:
standard and multicolor. Standard sprites are 24 pixels wide X For standard sprites, all pixels represented by %0 bits in
21 scan lines tall, and can have only one color. Multicolor the definition pattern will be transparent. That is, whatever is
sprites are 12 pixels wide X 21 scan lines tall, and can have on the screen behind the sprite will show through. Pixels rep-
three colors. However, multicolor sprites are the same size as resented by %1 bits take the color specified in the color regis-
standard sprites because the multicolor pixels are twice as ter for that sprite (53287-53294/$D027-$D02E), so each sprite
can take a different sprite foreground color. For multicolor
348 349
sprites, pixels represented by %00 bit patterns are transparent. ters at 53248-53264/$D000-$D010. Refer to the discussion of
Pixels represented by %01 and %11 patterns take the colors those registers for details.
specified in the sprite multicolor registers (53285/$D025 and When two sprites positions' overlap, one will appear in
53286/$D026, respectively). These colors are common to all front of the other. The one that appears in front is said to
eight sprites. Multicolor pixels represented by %10 bit patterns have higher priority. The priority of the sprites in relation to
take the color specified in the sprite foreground color registers. each other is fixed. Sprite 0 has the highest priority, and will
The 63 data bytes for the sprite pattern can't be placed appear in front of any other sprites it may overlap. Sprite 1
just anywhere in memory. The definitions must be located has the next highest priority; it can appear in front of any
within the current VIC video bank, and must begin at an ad- sprite except sprite 0. The priority decreases with increasing
dress which is an exact multiple of 64. A 16K VIC video bank sprite number, down to sprite 7, which appears behind any
other sprite it may overlap. The priority of sprites in relation-
has room for 16384 / 64, or 256 sprite patterns. The pattern
ship to screen foreground objects is programmable; sprites can
for each of the eight sprites is determined by the value in a
appear to pass either in front of or behind screen foreground
corresponding sprite pointer. The sprite pointers don't occupy pixels. See the discussion of the register at 53275/$D01B for
any fixed locations. Rather, they are found at the highest eight details.
locations of the current screen memory (video matrix) area, at
offsets of 1016-1023 bytes from the start of the area. The When two sprites overlap, or when a sprite overlaps
screen foreground pixels, a collision is said to occur. The VIC
pointer value (0-255) selects one of the 256 sprite pattern
records these collisions automatically, and can generate inter-
areas. The relationship between pointer values and definition
rupts as a result. See the discussion of the registers at
pattern area starting addresses is as follows: 53278-53279/$D01E-$D01F.
pointer value = pattern starting address / 64
or: Screen IRQ Routines
pattern starting address = pointer value * 64 The 128 introduces a feature that may be unfamiliar to those
with previous Commodore experience: shadow registers. A
The 128 reserves locations 3584-4095/$0E00-$OFFF in shadow register is a RAM memory location that is copied into
block 0 RAM to hold sprite pattern data. This 512-byte area a hardware register at regular intervals. Shadow registers are a
provides room for eight patterns, one for each of the eight feature of the system's software, not its hardware. The system
sprites. The sprite pointers are initialized to point to patterns IRQ interrupt sequence, the collection of routines executed ev-
in this area as follows: ery 1/60 second (1/50 second in PAL systems), includes two
Sprite Pointer value Pattern address separate sections which affect the VIC chip. The screen editor
0 56/$38 3584-3647/$0E00-$0E3F IRQ routine [$C194] controls the screen mode and raster inter-
1 57/$39 3648-371l/$0E40-$0E7F rupt, and the BASIC IRQ routine [$A84D] controls sprite
2 58/$3A 3712-3775/$0E80-$0EBF movement, detects sprite collisions, and reads the light pen.
3 59/$3B 3776-3839/$0ECO-$0EFF Because these routines maintain shadows of some VIC regis-
4 60/$3C 384O-3903/$0F0O-$0F3F ters, the registers cannot be changed directly while the normal
5 61/$3D 3904-3967/$0F40-$0F7F interrupt sequence is active. If you try to store a new value in
6 62/$3E 3968-403l/$0F80-$0FBF a register that has a shadow, the interrupt will replace your
7 63/$3F 4032-4095/$0FC0-$0FFF value with the shadow register contents at the next system
Even after a sprite is assigned a pattern, it will not appear IRQ interrupt—within 1/60 second. The discussion of the VIC
on the screen until it is enabled and moved into the visible registers below notes which registers have shadows and ex-
area of the screen display. Sprites are enabled by setting the plains how to go about changing such registers. Refer to the
appropriate bits in the register at 53269/$D0l5. The position appropriate ROM routine entry for more information on the
of each sprite on the screen is specified by values in the regis- interrupt routines.

350 351
53248 $D000 SD010 53264

VIC Registers Address Function


Table 8-2 is a summary of the VIC chip's registers. A detailed 53286/$D026 Sprite multicolor (source 1) register
description of each register follows. 53287/$D027 Sprite 0 color register
53288/$D028 Sprite 1 color register
53289/$D029 Sprite 2 color register
Table 8-2. VIC Chip Registers 53290/ID02A Sprite 3 color register
53291/$D02B Sprite 4 color register
Address Function 53292/$D02C Sprite 5 color register
53248/ID000 Sprite 0 horizontal position register 33293/$D02D Sprite 6 color register
53249/$D001 Sprite 0 vertical position register 53294/$D02E Sprite 7 color register
53250/$D002 Sprite 1 horizontal position register 53295/$D02F Extended keyboard scan register
53251/$D003 Sprite 1 vertical position register 53296/$D030 Processor clock rate control register
53252/$D004 Sprite 2 horizontal position register
53253/$D005 Sprite 2 vertical position register
53254/$D006 Sprite 3 horizontal position register
53255/$D007 Sprite 3 vertical position register
53256/$D008 Sprite 4 horizontal position register 53248 $D000 SPOX
53257/$D009 Sprite 4 vertical position register 53249 $DOO1 SPOY
53258/$D00A Sprite 5 horizontal position register 53250 $D002 SP1X
53259/$D00B Sprite 5 vertical position register 53251 $D003 SP1Y
53260/$D00C Sprite 6 horizontal position register 53252 $D004 SP2X
53261/$D00D Sprite 6 vertical position register 53253 $DOO5 SP2Y
53262/$D00E Sprite 7 horizontal position register
53263/$D00F Sprite 7 vertical position register 53254 $D006 SP3X
53264/SD010 Sprites 0-7 horizontal position (most significant bits) 53255 $D007 SP3Y
53265/$D011 Control/vertical fine scrolling register 53256 $D008 SP4X
53266/$D012 Raster scan-line register 53257 $D009 SP4Y
53267/$D013 Light pen horizontal position 53258 $D00A SP5X
53268/SD014 Light pen vertical position 53259 $D00B SP5Y
53269/$D015 Sprite enable register 53260 $D00C SP6X
53270/$D016 Control/horizontal fine scrolling register 53261 $D00D SP6Y
53271/$D017 Sprite vertical expansion register 53262 $D00E SP7X
53272/$D018 Memory control register 53263 $D00F SP7Y
53273/$D019 Interrupt flag register 53264 $D01O MSIGX
53 2 74/$ DO 1A Interrupt mask register Sprite horizontal and vertical position registers
53275/$D01B Sprite-to-foreground priority register
53276/$D01C Sprite multicolor mode register The position of each sprite is controlled by a pair of these reg-
53277/$D0ID Sprite horizontal expansion register isters plus a bit in the register at 53264/$D010. The extra bit
53278/$D01E Sprite-sprite collision register is required because the horizontal position value can exceed
53279/$D01F Sprite-foreground collision register 255. The extra bit is effectively the ninth (most significant) bit
53280/$D020 Border color register of the horizontal position register. The relationship of registers
53281/$D021 Background color (source 0) register to sprites is as follows:
53282/$D022 Background color (source 1) register
53283/$D023 Background color (source 2) register
53284/$D024 Background color (source 3) register
53285/SD025 Sprite multicolor (source 0) register
353
352
53264 $DO1O 9D011 53265

Sprite Horizontal Bit in Vertical greater than 255, which is the largest value that can be stored
register $D010 register in a horizontal position register. To move a sprite to horizontal
0 53248/$DO00 0 53249/$D001 position 256, you must set the horizontal position register to
1 53250/$D002 1 53251/$D003 0/$00 and set the most significant horizontal bit for that sprite
2 53252/$D004 2 53253/$D005
3 53254/$D006 3
(in the register at 53264/$D010) to % 1 . The most significant
53255/$D007 bit must remain set for all positions greater than 255. Because
4 53256/$D008 4 53257/$D009
5 53258/$DO0A 5 53259/$D00B
of the extra programming required to move the sprite to this
6 53260/$DOOC 6 53261/$D00D right portion of the screen, the vertical column at horizontal
7 53262/SDOOE 7 53263/SD00F position 256 is frequently referred to as the seam.
The values in these registers specify a sprite's position on The values in these registers cannot be changed directly
the screen. (Actually, the values set the position of the upper while the normal BASIC IRQ routine [$A84D] is in use. That
left corner of the 24 X 21-pixel sprite pattern.) The coordinate routine copies the contents of the shadow sprite position loca-
system used is slightly different from the one used for bit- tions (4566-4582/$llD6-$llE6) into these registers during
mapped graphics, as illustrated in Figure 8-6. Note that the each system IRQ interrupt. (See the discussion of the BASIC
sprite coordinate system remains the same regardless of the IRQ routine in Chapter 5 for more details.) There are two
current screen mode (character or bitmapped) or sprite mode ways to deal with this. The simplest solution is to store the
(standard or multicolor). desired sprite position values in the proper shadow location
(see the entry for the shadow locations in Chapter 3). If you
wish to use the true registers, you can prevent the execution of
Figure 8-6. Sprite Position Values the BASIC portion of the IRQ interrupt. This will disable most
BASIC sprite and sound commands, but that shouldn't be a
problem for machine language programmers. To prevent exe-
cution of the BASIC IRQ routine, you can either set bit 0 of
the initialization status flag at 2564/$0A04 to %0 (which tells
the Kernal that BASIC is not initialized), or you can store any
nonzero value in the BASIC IRQ status flag at 4861/S12FD.

53265 SD011 SCROLY


Vertical smooth scrolling and control register
Bits 0-2: These bits control the VlC's vertical fine scrolling
feature. The value here specifies how many scan lines down-
ward the display should be shifted. The available three bits
allow the screen to be scrolled up to seven scan lines. The
IOINIT routine [$E109] initializes these bits to %011 = 3, so
the default display will be scrolled down three scan lines from
its highest possible position.
The display scrolls without wrapping; blank scan lines are
The horizontal position range includes both the active moved in from the top and scan lines on the bottom move off
screen area and the inactive left and right borders, in units the visible screen. Pixels in scan lines scrolled off the bottom
that equal standard screen pixel widths. The vertical position of the display are not erased. They become visible again if the
range also includes the top and bottom borders in addition to display is scrolled back upward by reducing the value in these
the active screen area. Note that the horizontal position can be bits. The 24-row feature is useful with scrolling because it cre-
354
355
53265 $D011 I $D012 53266

ates hidden scan lines at the top and bottom of the screen that editor IRQ routine [$C194] sets this bit according to the screen
can be scrolled onto the visible area. mode flag (location 216/$D8). To change the setting of this
Bit 3: This bit determines the vertical height of the active por- bit, you can either store the appropriate value in the flag loca-
tion of the screen display. Setting this bit to %1 selects a 25- tion, or you can disable the screen-setup portion of the IRQ
row (200 scan-line) active screen. The bit is initialized to this routine and change this bit directly. To use the flag location,
setting during the IOINIT routine [$E109], and neither the op- set bit 5 of location 216/$D8 to the desired setting (%0 or %1)
erating system nor BASIC changes this value. Setting this bit for the register bit. To turn off the screen-setup portion of the
to %0 reduces the height of the active portion of the display interrupt routine, store the value 255/SFF in location 216/$D8.
to 24 rows (192 scan lines) by blanking the top four and bot- Bit 6: This bit controls extended background color mode,
tom four scan lines of the display. The pixels in the blanked which offers a choice of four different background colors for
columns aren't erased; they'll still be intact when the screen is each character position. For details about this mode, refer to
switched back to 25 rows. The 24-row feature is useful in con- the introduction for this section. Extended background color
junction with the vertical scrolling feature described in bits 0-2. mode is enabled when this bit is set to % 1 . The mode works
Bit 4: This bit enables or disables the VIC screen display. only in conjunction with character mode. You should not se-
While the bit is % 1 , the VIC provides its normal screen out- lect extended background color mode while bit 5 is set to %1
put. The bit is initialized to this setting during the IOINIT rou- to select bitmapped mode.
tine [$E109]. When the bit is set to %0, the VIC suspends the Bit 7: This bit is effectively the ninth bit of the raster register
active portion of the display and provides a solid screen in the at 53266/$D011. Refer to the discussion of that register for
border color specified in the register at 53280/$D020. The details. The extra bit is necessary because a full screen con-
screen is not erased, just blanked. Any text or graphics will tains more than 256 scan lines.
still be intact if the screen is again enabled. With the display
blanked, the VIC doesn't have to steal timing cycles from the 53266 $D012 RASTER
processor as it normally does. As a result, the 128 actually Raster compare register
runs about 7 percent faster with the VIC display off. This register has two different functions, depending on
There are several uses for this blanking feature. For ex- whether it is being read from or written to. As explained in
ample, you could blank the display while drawing a complex the introduction for this section, the video screen display con-
bitmapped graphics screen, then dramatically unveil the com- sists of a stack of thin horizontal lines of dots called a raster.
pleted picture by reenabling the display. Since the VIC cannot When the register is read, the value returned is the number of
provide a proper display at the 2-MHz clock rate, the VIC dis- the raster scan line currently being drawn. The range of scan-
play is normally blanked when the system is switched to fast line numbers depends on the video system in use. For NTSC
mode. One step in the BASIC statement FAST involves setting (North American) systems, values can be in the range 0-262,
this bit to %0. The SLOW statement returns it to % 1 . This bit while PAL (European) systems have a maximum count of over
is also set to %0 to blank the screen during tape operations, 300. In either case, the active portion of the screen consists of
and restored to %1 upon completion of the operations. scan lines 50-249.
Bit 5: This bit selects whether the VDC will generate a charac- The maximum scan-line number in either system is larger
ter mode display or a bitmapped mode display. (See the intro- than can be held in a single eight-bit register, so bit 7 of the
duction to this section for a discussion of the display modes.) register at 53265/$D011 is used to hold the ninth bit of the
Setting this bit to %0 selects character mode, while setting it value. When bit 7 of 53265/$D011 is % 1 , you should add
to %1 selects bitmapped mode. 256/ $100 to the value in this register to get the true scan-line
This bit cannot be directly modified while the normal sys- number. For scan line 262, for example, bit 7 of 53265/$D011
tem interrupt sequence is active because a step in the screen will be %1 and the value in this register will be 6/$06. Be-

356 357
53267 $D013 $D014 53268

cause the value in this register changes so rapidly (over 15,000 scan line are latched into these registers. The register at
times per second), it can't be read usefully from BASIC. By the 53267/SD013 will hold the horizontal position value, and the
time you PEEKed the value into a variable, the raster scan line one at 53268/$D014 will hold the vertical position value. To
would have moved far beyond the line recorded in the vari- signal that a new value has been latched, bits 7 and 3 of the
able value. interrupt register at 53273/SD019 will be set to % 1 . These
When you write to this register or to bit 7 of 53265/ registers are read-only; writing to them has no effect. The reg-
$D011, the value written is stored in an internal nine-bit raster isters are not cleared when read; the latched values will be re-
compare latch register. Whenever the current scan-line count tained until the LP line is again brought low.
equals the value in this register, bit 0 of the interrupt register The range of scan-line values in the register at 53268/
at 53273/$D019 will be set to % 1 . If bit 0 of the interrupt $D014 is the same as the range of sprite vertical positions
mask register at 53274/$D01A was previously set to % 1 , this shown in Figure 8-6. For example, the top scan line of the ac-
will also trigger an external interrupt request to the processor. tive screen area is 50, In that figure, you'll note that the range
The value you store in this register represents the scan line at of horizontal positions extends to 343, which is greater than
which you wish the interrupt to occur. For scan-line values can be represented in a single eight-bit register. To compen-
less than 256, you must also set bit 7 of 53265/$D011 to %0. sate, the range of horizontal values in the register at 53267/
For scan-line values of 256 or greater, you must set bit 7 of $D013 is the equivalent of one-half the range of horizontal
53265/$D011 to %1 and store the line number minus 256 in values shown in Figure 8-6. For example, the horizontal-position
this register. To calculate the top scan line corresponding to value for the center of the screen is 184, so the corresponding
any row of character positions, use the following formula: light pen position will be about 92.
scan line = (row * 8) + 50 The LP line is connected to pin 6 of control port 1 (con-
where the row value is in the range 0-24. trol port 2 does not support a light pen). A light pen has at its
Raster interrupts can be used to program a variety of spe- tip an electronic device known as a phototransistor, which is
cial video effects, including split screens like those in the connected so as to cause a low pulse whenever the video
GRAPHIC 2 and GRAPHIC 4 modes. The 128 also uses a ras- beam moves past the pen. These registers can be tricked into
ter interrupt off the visible screen (at scan line 255) to drive reading false values. Pin 6 of control port 1 is also used for
the system IRQ sequence. Because of this, you cannot write a light pen input for the VDC chip, so a light pen signal gener-
new value directly to this register while the the normal system ated on the 80-column screen will latch meaningless values in
interrupt sequence is in use. The screen-setup portion of the these registers. In lieu of a light pen, several other events can
screen editor IRQ routine [$C194] will write the value 255/$FF cause a pulse on the LP line. That control port pin is also used
to this register on every pass, except when setting up the bit- for the joystick fire button, so pressing the button of a joystick
plugged into port 1 will also latch values in these registers. Be-
mapped portion of a split bitmapped/text screen. In that case, cause of this joystick button function, the port line is also con-
the value in location 2612/$0A34 will be copied into the reg- nected to the line from row 4 of the keyboard matrix. This has
ister. In either case, bit 7 of the register at 53265/$D011 will two consequences. First, pressing any of the following keys
be set to %0. To use a raster interrupt for your own purposes, with no light pen connected will latch meaningless values: Fl,
you must write a new interrupt routine. Refer to Appendix A Z, C, B, M, period, right SHIFT, space, the 2 and ENTER keys
for more information. on the numeric keypad, and the ^ key in the cursor group.
More significantly, while a light pen is connected, all of these
53267 $D013 LPENX keys will be "dead," and cannot be typed.
53268 SD014 LPENY
Light pen horizontal and vertical positions
Whenever the VIC's LP input line is brought to a low (0 volts)
state, the raster beam's horizontal dot position and vertical
358 359
53269 $D015 $D016 53270

53269 $D015 SPENA screen. Pixels scrolled off the right are not erased, just hidden.
Sprite enable register They will become visible again if the display is scrolled back
This register controls which sprites are enabled. Only enabled to the left by reducing the value in these bits. The 38-column
sprites can be visible, and only enabled sprites can be in- feature is useful with scrolling because it creates a hidden left
volved in collisions. Setting a bit in this register to %1 enables column that can hold pixels to be scrolled onto the visible area.
the corresponding sprite. However, an enabled sprite won't be Bit 3: This bit determines the horizontal width of the screen.
visible unless it is also positioned within the visible screen Setting this bit to %1 selects a 40-column (320-pixel) screen.
area, has a pattern definition that includes some nonzero bits, The bit is initialized to this setting during the IOINIT routine
and is set to a color different from the screen background [$E109], and neither the operating system nor BASIC ever
color. Setting a bit in this register to %0 turns off the cor- change this value. Changing this bit to %0 reduces the width
responding sprite, but does not change the setting of any other of the active portion of the display to 38 columns (304 pixels)
parameters. When reenabled, the sprite will still have the by blanking the leftmost and rightmost columns. (Actually, 7
same position, color, and pattern (unless those were changed pixels on the left and 9 on the right are blanked.) The contents
while the sprite was turned off). The sprites are controlled as of the blanked columns aren't erased; they'll still be intact
follows: when the screen is switched back to 40 columns. The 38-column
Bit Bit value Sprite controlled feature is useful in conjunction with the horizontal scrolling
0 l/$01 ' 0 feature in bits 0-2. Scrolling the 38-column screen the maxi-
1 2/$02 1 mum 7 pixels to the right will make the contents of the previ-
2 4/$04 2 ously hidden leftmost column visible.
3 8/$08 3
4 16/S10 4 Bit 4: This bit controls multicolor mode for both the character
5 32/$20 5 and bitmapped screens. While this bit is %0, foreground pixels
6 64/$40 6 will be limited to one color (although the color can be differ-
7 128/$80 7 ent for every character position). Setting this bit to %1 enables
multicolor mode, which allows a choice of three different col-
This register is initialized to 0/$00 (all sprites disabled) by ors for each foreground pixel. However, selecting multicolor
the IOINIT routine [$E109], part of the reset and RUN/ mode also cuts horizontal resolution for the screen in half. Se-
STOP-RESTORE sequences. Sprites are normally disabled lecting multicolor mode for the screen has no effect on any
during tape and serial bus operations to prevent timing prob- sprites that might be displayed on that screen. Sprite multi-
lems. In this case, the contents of the register are stored in lo- color mode is controlled by the register at 53276/$D01C.
cation 2616/$0A38 for the duration of the operation, then
restored to the register when the operation is completed. You This bit cannot be directly modified while the normal sys-
can prevent this and keep sprites enabled by setting bit 7 of tem interrupt sequence is active because a step in the screen
the custom mode flag (2618/$0A3A) to % 1 . editor IRQ routine [$C194] sets this bit according to the screen
mode flag (location 216/$D8). To change the setting of this bit
for bitmapped mode, you can either store the appropriate
53270 $D016 SCROLX value in the flag location, or you can disable the screen-setup
Horizontal smooth scrolling and control register
portion of the IRQ routine and change this bit directly. To use
Bits 0-2: These bits control the VIC's horizontal smooth scroll- the flag location, set bit 7 of location 216/$D8 to the desired
ing feature. The value here specifies the number of pixels the setting (%0 or %1) for the register bit. To turn off the screen-
display is to be shifted to the right. The available three bits setup portion of the interrupt routine, store the value 255/$FF
allow the screen to be shifted as many as seven pixels. The in location 216/SD8. To select multicolor character mode, you
display scrolls without wrapping; blank pixels are moved in must use the option to disable the screen setup, since the text
from the left and pixels on the right move off the visible mode-setup subroutine always sets this bit to %0.
361
53271 $D017 SD018 53272

Bit 5: This bit is referred to in Commodore literature as the re- setup portion of the screen editor IRQ routine to gain direct
set bit, but its intended usage is unclear. The value here has access to the register. To disable the screen-setup step, store
no apparent affect on any VIC operations. the value 255/$FF in location 216/$D8.
Bits 6-7: These bits are unused. Writing to them has no effect, Bit 0: This bit is unused. Writing to it has no effect, and it
and they always return %1 when read. always returns %1 when read. Thus, the value read from this
register will always be odd.
53271 $D017 YXPAND Bits 1-3: The value in these bits determines the location of char-
Sprite vertical expansion register acter memory (for character mode) or of the bitmap (for bit-
Each bit in this register controls the vertical expansion feature mapped modes). For character mode, a complete 256-character
for one of the eight sprites. The relationship of sprites to regis- set requires 2048 (2K) bytes, and the character set must start
ter bits is the same as for the sprite enable register (53269/ on an even 2K memory address boundary. Possible selections
$D015). Setting a bit here to %1 will double the vertical are as follows:
height of the corresponding sprite. Each sprite can be ex- Bits Offset for
panded independently, with regard for the background screen 3 2 1 character set
on which the sprite is displayed. The resolution of the sprite is 0 0 0 0/$00
not increased—it will still be 21 pixels tall—but the height of 0 0 1 2048/$0800
the pixels will be doubled. Vertical expansion can be selected 0 1 0 4096/$1000
in conjunction with horizontal expansion to double the size of 0 1 1 6144/$1800
a sprite. (Horizontal expansion is controlled by the register at 1 0 0 8192/$2000
53277/SD01D.) The default value in this register, established 1 0 1 10240/$2800
by the IOINIT routine [$E109], is 0/$00, so no sprites are ini- 1 1 0 12288/$3000
tially expanded. 1 1 1 14336/S3800
These bits do not determine the absolute address of the char-
53272 $D018 VMCSB acter set, but rather the offset from the starting address of the
Screen and character base address register current video bank. For example, video bank 2 begins at ad-
The value in this register determines the location within the dress 32768/$8000, so a bit setting of %100 in that case
current 16K VIC video bank of the two movable components would place the character set at 32768 + 8192 = 40960/$A000.
of video memory: the screen memory/video matrix and char- However, the default video bank (bank 0) begins at location
acter memory/bitmap areas. (There is no provision for moving 0/$0000, so in that case the offset is equal to the actual address.
color memory; that area always appears at 55296-56319/ The 128 normally provides a pair of character sets and al-
$D800-$DBFF.) The contents of this register cannot be changed lows you to switch between them by pressing the SHIFT -
directly while the normal system IRQ interrupt sequence is in Commodore key combination. If you are setting up a single
use. The screen editor IRQ routine [$C194] copies the contents custom character set, you should disable this character
of a shadow location into this register during each interrupt. set-switching feature by setting bit 7 of location 247/$F7 to
The shadow location depends on the screen mode in use. For % 1. If you wish to retain the character set-switching feature,
text mode, or for the text portion of a split screen, the contents you must provide two character sets, one at an "even" posi-
of location 2604/$0A2C will be copied here. For bitmapped tion (one for which bit 1 of this register is %0), and the other
modes, the value in location 2605/S0A2D will be copied into at the next higher ("odd") position.
the register. You have two choices for changing the value in The CINT screen editor initialization routine [$C07B] sets
this register. You can either store the desired value in the ap- bits 1-3 to %010 in location 2604/$0A2C, the shadow for this
propriate shadow location, or you can turn off the screen- register in text mode. This places the default character memory
at an offset of 4096/$1000 from the starting address of the
362 363
53272 $D018 SD018 53272

video bank (and implies that the alternate character set will be be protected from BASIC, and any character memory slot in
located at an offset of 6144/$1800), This may seem strange, that area can be used to hold the new character set.
since there is certainly no character pattern data stored in Since the bitmap for a high-resolution display requires
RAM at addresses 4096-8191/$1000-$lFFF/ and since the 8000 bytes of memory and must begin at an even 8K memory
128's memory map shows that the character ROM is actually address boundary, there are only two possible positions for
located at addresses 53248-57343/$D000-$DFFF. However, the bitmap within the 16K video bank. When you are specify-
the 128 has the capability to make the VIC chip see character ing the location of the bitmap, only the setting of bit 3 is sig-
ROM at addresses 4096-6143/$1000-$17FF (for the uppercase/ nificant. When that bit is %0, the bitmap will begin at an
graphics set) and addresses 6144-8191/$1800-$lFFF (for the offset of 0/$0000 from the start of the video bank. When bit 3
lowercase/uppercase set) in any video bank. (Note that this is is % 1 , the bitmap begins at an offset of 8192/$2000 from the
a change from the Commodore 64, which could only see char- start of the video bank. The CINT screen editor initialization
acter ROM in video banks 0 and 2.) Only the VIC will see the routine [$C07B] sets bits 1-3 to %100 in location 2605/$0A2D,
character ROM at those addresses. To the processor, those lo- the shadow for this register in bitmapped mode, so the default
cations will still be RAM. location of the bitmap is 8192/$2000 bytes beyond the start of
This feature is controlled by bit 2 of the 8502's built-in the video bank (address 8192/$2000 for the default video bank).
I/O port, at location l/$01. When bit 2 of the register at
l/$01 is %0, the VIC chip will see character ROM in the char- Bits 4-7: These bits determine the location of the video matrix
acter memory areas beginning at addresses 4096/$1000 and area, which is used as screen memory in character mode and
6144/$1800. No other character memory slots are affected. to hold color information in bitmapped mode. The video ma-
When the I/O port bit is set to % 1 , the VIC will instead see trix requires 1000 bytes of memory and must start on an even
the true contents of RAM at those addresses rather than im- IK address boundary. Possible selections are as follows:
ages of the character ROM. Like other screen control locations, Bits Offset for
the I/O port bit has a shadow location. Bit 2 of location 7 6 5 4 video matrix
217/SD9 is copied into bit 2 of location l/$01 during each 0 0 0 0 0/$0000
pass through the text screen-setup portion of the screen editor 0 0 0 1 1024/$0400
IRQ routine. To switch out character ROM, you must set bit 2 0 0 10 2048/$0800
of the shadow location to %1 (store the value 4/$04 in loca- 0 0 11 3072/$OC00
tion 217/$D9). Alternatively, you can disable the screen-setup 0 10 0 4096/$1000
portion of the screen editor IRQ routine by storing the value 0 10 1 5120/$1400
0 1 1 0 6144/$1800
255/$FF in location 216/$D8; then you change bit 2 of loca- 0 1 1 1 7168/$1COO
tion l/$01 directly. 10 0 0 8192/$2000
Finding free space for a custom character set can be a chal- 0 0 1 9216/$2400
lenge. If you are using machine language exclusively, any of 0 1 0 10240/$2800
the character set slots above address 4864/$1300 can be used, 0 1 1 11264/$2C00
but none of the address slots are completely free in the stan- 1 0 0 12288/$3000
dard configuration with BASIC. If you disable character ROM, 1 0 1 13312/$3400
there is free memory at 6144-7167/$ 18OO-$1BFF for half a char- 1 1 0 14336/S3800
acter set (128 character patterns). If your program doesn't use 1 1 1 15360/$3CO0
a bitmapped screen, you can allocate a bitmap area and then These bits do not determine the absolute address of the video
use the reserved space for custom character sets. For example, matrix, but rather the offset from the starting address of the
if your BASIC program includes the statements GRAPHIC current video bank. For example, video bank 3 begins at ad-
1:GRAPHIC 0, the area from 7168-16383/ $1COO-$3FFF will dress 49152/$C000, so a bit setting of %0010 in that case
would place the character set at 49152 + 2048 = 51200/
364 365
53273 $D019 $D01A 53274

$C800. However, the default video bank (bank 0) begins at lo- quest for the event. Once a bit here is set to % 1 , it will retain
cation 0/$0000, so in that case the offset is equal to the actual that value until the register is read, at which time all func-
address. tional bits are reset to %0.
The C1NT screen editor initialization routine [$C07B] sets Bit 0: This bit will be set to %1 whenever the raster scan-line
bits 4-7 to %0001 in location 2604/$0A2C, the shadow for count equals the value in the raster compare register 53266/
this register in text mode. This places the default character $D012 (plus bit 7 of 53265/$D011).
memory at an offset of 1024/$0400 from the starting address
of the video bank. You can't change this register directly while Bit 1: This bit will be set to %1 whenever a nontransparent
the normal system interrupt sequence is active. To move the portion of a sprite overlaps any screen foreground pixels. (Re-
video matrix for the text screen, you can either change the member, however, that for multicolor character or multicolor
value in location 2604/$0A2C, or you can turn off the screen- bitmapped screens, no collision can be detected between
setup portion of the interrupt sequence by storing the value sprites and foreground pixels represented by %01 bit patterns.)
255/$FF in location 216/$D8. After that, you can change the The register at 53279/$D01F records which sprites are in-
register directly. Even if you change the value in this register, volved in collisions with foreground data.
all printed characters will continue to go to the former screen Bit 2: This bit will be set to %1 whenever two or more sprites
memory range until you change the value in location 2619/ overlap. Collisions can only be detected between the fore-
$0A3B to reflect the new starting page for screen memory. ground portion of the sprites, those pixels represented by non-
Because the bitmap for a high-resolution display requires zero bit patterns. No collision is detected when the over-
half of the memory available in a 16K video bank, only half of lapping portions of the sprites are transparent (when the pixels
the possible addresses are really useful. When setting up a bit- are represented by %0 or %00 bit patterns). The register at lo-
mapped display, you should select a video matrix area in the cation 53278/$D01E records which sprites are involved in col-
portion of the video bank not occupied by the bitmap. The lisions with other sprites.
CINT screen editor initialization routine [$C07B] sets bits 4-7 Bit 3: This bit will be set to %1 whenever a new value is
to %0111 in location 2605/$0A2D, the shadow for this regis- latched into the light pen registers at 53267-53268/
ter in bitmapped mode, so the default location of the video $D013-$D014.
matrix in that mode is 7168/$1COO bytes from the start of the
video bank (address 7168/$1COO for the default video bank). Bits 4-6: The bits are not used, and always return %1 when
Thus, the bitmapped mode video matrix will not disturb char- read.
acter mode screen memory. Bit 7: Whenever any internal interrupt source sets one of the
To move the video matrix for the bitmapped screen, you other bits in this register to % 1 , this bit will also be set to %1
can either change the value in location 2605/$0A2D, or you to indicate that an internal interrupt has been recorded. Thus,
can turn off the screen-setup portion of the interrupt sequence you need to test only this bit to determine whether an internal
by storing the value 255/$FF in location 216/SD8. After that, interrupt has occurred. Note that this register is automatically
you can change the register directly. cleared after it is read, so you'll need to save the register value
before testing this bit if you want to be able to subsequently
53273 $D019 VICIRQ read any of the other bits.
Interrupt register
This register is read-only; writing to this location has no effect. 53274 $D01A IRQMSK
Bits 0-3 indicate the status of the four interrupt sources for the Interrupt enable register
VIC chip. These bits will always reflect the status of their cor- Certain events such as sprite-sprite collisions always generate
responding events, regardless of whether or not register internal VIC interrupts, recorded in the register at 53273/
53274/$D01A has been set to trigger an external interrupt re-
366 367
SD01B $D01D 53277
53275

$D019. The VIC chip has the capability to generate an exter- ground color on the text or bitmapped screens. When a bit
nal interrupt request to the processor as a result of any of here is set to % 1 , the corresponding sprite will have lower pri-
these conditions. In the 128, the VIC's interrupt request output ority than the screen foreground, and will thus appear to pass
line is connected to the processor's IRQ line, so internal VIC behind anything displayed in the foreground color. For multi-
events can trigger processor IRQ interrupts. See Appendix A color character or multicolor bitmapped screen modes, the
for more information on IRQ interrupts. low-priority sprite will appear to pass behind screen pixels
Bit 0: Setting this bit to %1 enables an external interrupt re- represented by %10 and %11 bit patterns, but will still pass in
quest when the raster count match is recorded in the flag at front of pixels represented by %01 bit patterns. (The sprite al-
bit 0 of the register at 53273/$D019. Because raster interrupts ways appears in front of pixels with the %00 background bit
are the normal source of the system jiffy interrupt that drives pattern.) The default value for this register, established by the
keyboard scanning and other important housekeeping fea- IOINIT routine [$E109], is 0/$00, so all sprites initially have
tures, this bit is initialized to %1 by the Kernal IOINIT routine higher priority than the screen foreground.
[$E109]. Changing this bit to %0 will completely disable the
system interrupt. 53276 8D01C SPMC
Sprite multicolor mode register
Bit 1: Setting this bit to %1 enables an external interrupt re-
Each bit in this register controls the multicolor feature for one
quest when a sprite-foreground collision is recorded in the flag
of the eight sprites. The relationship of sprites to register bits
at bit 1 of the register at 53273/$D019, as when a sprite
is the same as for the sprite enable register (53269/$D015).
passes over a character on the text screen.
Setting a bit here to %1 selects multicolor mode for the cor-
Bit 2: Setting this bit to %1 enables an external interrupt re- responding sprite. Multicolor mode can be selected indepen-
quest when a sprite-sprite collision is recorded in the flag at dently for each sprite, and standard and multicolor sprites can
bit 2 of the register at 53273/$D019. be mixed freely on the same screen. Multicolor sprites are not
Bit 3: Setting this bit to %1 enables an external interrupt re- restricted to multicolor screen modes; they can be used freely
quest when a new value is recorded in the flag at bit 3 of the in standard screen modes as well. The default value for this
register at 53273/$D019. It is risky to use this interrupt register, established during the IOINIT routine [$E109], is
source, because a number of events other than the light pen 0/$00, so no sprites are initially in multicolor mode.
can trigger the latching of values into these registers. See the Selecting multicolor mode for a sprite reduces the number
entry for the light pen registers for details. of horizontal pixels for the sprite from 24 to 12. However, the
sprite remains the same size; the multicolor sprite pixels are
Bits 4-7: These bits are unused; writing to them has no effect,
twice as wide. Two bits of the pattern definition are required
and they always return %1 when read. Thus, the value seen
for each pixel. All pixels represented by %00 are transparent;
when this register is read will always be at least 240/$F0. To
whatever is behind the sprite will show through. Pixels with
mask off these unused bits and see the valid interrupt settings,
%01 and %11 bit patterns take their color values from the reg-
use AND 15 in BASIC or AND #$0F in machine language.
isters at 53285/$D025 and 53286/$D026, respectively, which
are common to all multicolor sprites. Pixels with %10 bit pat-
53275 8D01B SPBGPR terns take the color specified in the color register for the par-
Sprite-to-foreground priority register ticular sprite (53287-53294/$D027-$D02E).
Each bit in this register controls the sprite-to-foreground prior-
ity for one of the eight sprites. The relationship of sprites to 53277 $D01D XXPAND
bits is the same as for the sprite enable register (53269/ Sprite horizontal expansion register
$D015). While a bit here is %0, the corresponding sprite will Each bit in this register controls the horizontal expansion fea-
have higher priority than the screen foreground, and will thus ture for one of the eight sprites. The relationship of sprites to
appear to pass in front of anything displayed in the fore-
368
369
53278 $D01E $D020 53280

register bits is the same as for the sprite enable register from the object. Also, sprite-sprite collisions can occur even
(53269/$D015). Setting a bit here to %1 will double the hori- when the sprites are located completely outside the visible
zontal width of the corresponding sprite. Each sprite can be screen area.
expanded independently, without regard for the background
screen on which the sprite is displayed. The resolution of the 53279 $D01F SPFGCL
sprite is not increased (it will still be 24 pixels wide) but the Sprite-foreground collision register
width of the pixels will be doubled. Horizontal expansion can This register records collisions between sprites and the screen
be selected in conjunction with vertical expansion to double foreground. This register is read-only; storing values here has
the size of a sprite. (Vertical expansion is controlled by the no effect. A collision occurs whenever any pixel in a sprite
register at 53271/$D017.) The default value in this register, represented by a nonzero bit pattern overlaps any foreground
established by the IOINIT routine [$E109], is 0/$00, so no pixel on the screen, as when a sprite passes over a character
sprites are initially expanded. on the text screen. Background or transparent pixels are not
involved in collisions. For the purposes of collision detection,
53278 8D01E SPSPCL multicolor screen pixels represented by %01 bit patterns are
not considered foreground, and no collision will be detected
Sprite-to-sprite collision register
when a sprite pixel overlaps a multicolor screen %01 pixel.
This register records collisions between two or more sprites. When a sprite collides with a foreground pixel, the bit in this
This register is read-only; storing values here has no effect. A register corresponding to that sprite is set to %1 (the cor-
collision occurs whenever any nontransparent portions of the respondence between sprites and bits is the same as for the
sprites overlap. Transparent pixels (pixels with bit patterns of sprite enable register). The register is automatically cleared to
%0 or %00) are not involved in collisions. When sprites col- 0/$00 after each time it is read, so you'll need to store the
lide, the bits in this register corresponding to those sprites are value you read if you wish to perform multiple tests. Bit 1 of
set to %1 (the correspondence between sprites and bits is the the interrupt register at 53273/$D019 will also be set to %1
same as for the sprite enable register). Since a minimum of whenever any sprite-foreground collision occurs.
two sprites are involved in any sprite-sprite collision, at least
This register indicates only that a sprite has collided with
two bits will be set. The register is automatically cleared to
some portion of the screen foreground. It does not tell you ex-
0/$00 after each time it is read, so you'll need to store the
actly what the sprite is overlapping. To determine that, you
value you read if you wish to perform multiple tests. Bit 2 of must determine which sprite or sprites are involved in colli-
the interrupt register at 53273/$D019 will also be set to %1 sions, then read the horizontal and vertical position registers
whenever any sprite-sprite collision occurs. for the involved sprites and determine what screen-foreground
This register indicates only that sprites have collided. It object is located in that vicinity. Remember that the sprite po-
does not necessarily tell you which sprites are involved in a sition registers return the position of the upper left corner of
particular collision. If only two bits are set, then those sprites the sprite, which may not be the point of the sprite that is col-
obviously must have hit each other. However, if you find that liding with the foreground.
three or more bits are set, you must read the horizontal and
One thing to beware of when reading this register is that
vertical position registers for the involved sprites and deter- after a sprite overlaps a foreground object, the register will
mine which sprites are in contact with each other. Remember continue to record collisions until the sprite is moved away
that the sprite position registers return the position of the up- from the object.
per left corner of the sprite, which may not be the point of the
sprite that is colliding with the foreground. 53280 $D020 EXTCOL
One thing to beware of when reading this register is that Border color register
after a sprite overlaps a foreground object, the register will The value in this register determines the color of the screen
continue to record collisions until the sprite is moved away border, the area of the screen surrounding the active portion

370 371
53281 SD021 $D024 53284

of the display. When the screen is blanked by setting bit 4 of ways return %1 when read. Thus, the value in this register
the register at 53265/$D011 to %0, the entire display area will will always be at least 240/$F0. To mask off these bits and
be filled with the color specified here. Since the VIC can pro- read the true color value you should use AND 15 in BASIC or
duce only 16 different colors, only four bits are required to AND #$0F in machine language. See Table 8-1 for a list of
hold all possible color values. Thus, only bits 0-3 of this loca- standard VIC color values. This register is initialized to
tion hold meaningful values. Bits 4-7 are unused; writing to ll/$0B (dark gray) by the IOINIT routine [$E109], part of
those bits has no effect, and the bits always return % 1 when both the reset and RUN/STOP-RESTORE sequences. From
read. Thus, the value in this register will always be at least BASIC, the value here can be changed using the statement
240/$F0. To mask off these bits and read the true color value COLOR 0,n (where n is the desired BASIC color number;
you should use AND 15 in BASIC or AND #$0F in machine BASIC color numbers are equal to VIC color values plus one.)
language. See Table 8-1 for a list of standard VIC color values.
The default setting for this register, established by the IOINIT 53282 $D022 BGCOL1
routine [$E1O9], is 13/$0D (light green). From BASIC, the 53283 $D023 BGCOL2
value here can be changed using the statement COLOR 4,rc 53284 $D024 BGCOL3
(where n is the desired BASIC color number; BASIC color Background color registers 1-3
numbers are equal to VIC color values plus one). These three registers are used only when multicolor character
mode or extended background color mode is enabled. For
53281 $DO21 BGCOLO multicolor character mode, the value in 53282/SD022 deter-
Background color register 0 mines the color of any pixels in a screen position represented
In standard character mode, the value here determines the by %01 bit pairs in the character pattern, and the value in
color of all pixels in a screen position which are represented 53283/SD023 determines the color of all pixels with %10
by %0 bits in the character pattern. This background color is pairs. Since there is only one set of registers for all screen po-
common to all screen positions. Clearing the screen fills all po- sitions, the colors of pixels with %01 and %10 bit pairs will be
sitions with the screen code for the space character, which has common to all characters on the screen. The color of pixels
a pattern that is all %0 bits. Thus, a cleared screen will be filled with %00 bit pairs is determined by the value in
with the color specified here. The color of pixels with %1 bits in 53281/SD021, and the color of pixels with %11 bit pairs is se-
the character pattern (the foreground color) is determined by lected individually for each character position by the value in
the value in the color memory location for the position. the corresponding color memory location (55296-56319/
This register is also used in both of the other character $D800-$DBFF). The register at 53284/$D024 is unused in mul-
modes. In multicolor character mode, the value here deter- ticolor character mode,
mines the color of all pixels in all screen positions represented For extended background color mode, these registers de-
by %00 bit pairs in the character pattern. In extended back- termine the background color for the character position for the
ground color mode, the value here determines the background character, depending on the setting of bits 6-7 of the screen
color in any screen positions for which bits 6-7 of the screen code in the screen memory location for the position. The se-
code in the corresponding screen memory location are %00. lections are as follows:
This register is unused in standard bitmapped mode, but for Bits Background color source register
multicolor bitmapped mode the value here determines the 7 6
color for all pixels represented in the bitmap by %00 bit pairs. 0 0 53281/SD021
Since the VIC can produce only 16 different colors, only 0 1 53282/$D022
four bits are required to hold all possible color values. Thus, 1 0 53283/$D023
only bits 0-3 of this location hold meaningful values. Bits 4-7 1 1 53284/$D024
are unused; writing to those bits has no effect, and the bits al-

372 373
53235 $D025 SD02E 53294

Since the VIC can produce only 16 different colors, only IOINIT routine [$E109], are 1 (white) for 53285/$D025 and 2
four bits are required to hold all possible color values. Thus, (red) for 53286/$D026. From BASIC, these settings can be
only bits 0-3 of these locations hold meaningful values. Bits changed using the SPRCOLOR statement.
4-7 in any of these locations are unused. Writing to those bits
has no effect, and the bits always return % 1 when read. Thus, 53287 SD027 SPOCOL
the value in any of these locations will always be at least 53288 SD028 SP1COL
240/$F0. To mask off these bits and read the true color value 53289 SD029 SP2COL
you should use AND 15 in BASIC or AND #$0F in machine 53290 $D02A SP3COL
language. See Table 8-1 for a list of standard VIC color values. 53291 8D02B SP4COL
These registers are initialized during the IOINIT routine 53292 $D02C SP5COL
[$E019], part of the reset and RUN/STOP-RE STORE se- 53293 $D02D SP6COL
quences. The default values are 1 (white) for 53282/$D022, 2 53294 $D02E SP7COL
(red) for 53283/$D023, and 3 (cyan) for 53284/$D024. There Sprite color registers
is no BASIC statement specifically for changing the settings of Each of these registers holds color information for one of the
these registers. eight sprites. For standard sprites, the value here determines
the color of all %1 bits in the sprite pattern (%0 bit positions
53285 $D025 SPMCO will be transparent). For multicolor sprites, the value here de-
53286 $D026 SPMC1 termines the color of all %10 bit groups in the pattern.
Sprite multicolor registers Since the VIC can produce only 16 different colors, only
The values in these registers determine two of the colors for four bits are required to hold all possible color values. Thus,
multicolor sprites. (A sprite can be switched to multicolor only bits 0-3 of these locations hold meaningful values. Bits
mode by setting the appropriate bit in the register at 53276/ 4-7 in any of these locations are unused. Writing to those bits
$D01C.) The value in the register at 53285/$D025 determines has no effect, and the bits always return %1 when read. Thus,
the color for all pixels in the sprite represented by %01 bit the value in any of these locations will always be at least
pairs in the pattern. The value in 53286/$D026 determines the 240/$F0. To mask off these bits and read the true color value
color for all pixels represented by %11 bit pairs. Since there you should use AND 15 in BASIC or AND #$0F in machine
are only these two registers for all eight sprites, the colors of language. See Table 8-1 for a list of standard VIC color values.
pixels with %01 and %11 bit pairs will be common to all The following table shows the default colors for each sprite,
sprites. The color of pixels represented by %10 bit pairs can be established by the IOINIT routine [$E109], part of both the re-
selected individually for each sprite using the registers at set and RUN/STOP-RESTORE sequences.
53287-53294/$D027-$D02E. Pixels with %00 bit pairs in the
pattern will be transparent. Register Sprite Default color
Since the VIC can produce only 16 different colors, only 53287/$D027 0 0 (black)
four bits are required to hold all possible color values. Thus, 53288/$D028 1 1 (white)
only bits 0-3 of these locations hold meaningful values. Bits 53289/$D029 2 2 (red)
4-7 in any of these locations are unused. Writing to those bits 53290/$D02A 3 3 (cyan)
has no effect, and the bits always return %1 when read. Thus, 53291/$D02B 4 4 (pmple)
the value in any of these locations will always be at least 53292/$D02C 5 5 (green)
240/$F0. To mask off these bits and read the true color value 53293/$D02D 6 6 (blue)
53294/$D02E 7 7 (yellow)
you should use AND 15 in BASIC or AND #$0F in machine
language. See Table 8-1 for a list of standard VIC color values.
The default settings of these registers, established by the

374 375
53295 $D02F $D031-$D03F 53297-53311

53295 $D02F XSCAN screen becomes a colorful pattern of rapidly flashing squares.
Extended keyboard scan-line control register It is common practice to set bit 4 of the VIC register at 53265/
Bits 0-2: Each of these bits controls the state of one of the $D011 to %0 to blank the 40-column screen display while op-
three output lines from the VIC chip, K0-K2. Setting a register erating in 2-MHz mode. For example, the BASIC routine for
bit to %0 causes the corresponding output line to go to a low the FAST statement [$77B3] includes this step. The VDC pro-
(0 volts) state, while setting a register bit to %1 causes the vides an alternative to the VIC for fast mode, but other I/O
output line to go to a high ( + 5 volts) state. Reading these bits chips have no substitutes. In these cases, the system employs
returns the current state of the corresponding output lines. In an elaborate technique known as clock stretching, where the
the 128, the three output lines are used to scan the three key- clock period is extended to create an effective 1-MHz rate for
board columns containing the 24 keys in the numeric keypad the portion of the clock cycle when the I/O chip is being
and top row of control keys. See Figure 7-1 and the discussion accessed.
of the keyboard scanning routine [$C55D] in Chapter 7 for Because some serial bus and tape communications
more information. routines depend on software loops for timing functions, the
Unless you are writing a custom keyboard scanning rou- system is usually switched to the slower clock frequency when
tine, there's rarely a need to tinker with this register. The out- serial bus or tape operations are being performed. The con-
put lines are connected only to the keyboard, and are not tents of this register are stored in location 2615/$0A37 during
available externally. the operation, and restored to the register when the operation
is completed. You can prevent this by setting bit 7 of the cus-
Bits 3-7: These bits are unused. Writing to them has no effect, tom mode flag (location 2618/$0A3A) to % 1 . In this case, the
and they always return %1 when read. Thus, the value in this clock rate will not be changed during tape and serial
location will always be at least 248/$F8. To mask off these ir- operations.
relevant bits, use AND 7 in BASIC or AND #$07 in machine
language. Bit 1: This bit is described in Commodore literature as a test
bit. The IOINIT routine [$E019] sets the bit to %0, and no
53296 $D030 CLKRATE other 128 ROM routine changes that setting. Some program-
Processor clock rate control register mers have discovered that setting this bit to %1 will blank the
40-column screen display, and have even used this as an alter-
Bit 0: This bit controls the processor clock speed. (Remember, native to clearing bit 4 of location 53265/$D011 when switch-
the VIC chip is the source of most of the system's timing sig- ing the processor to fast mode. While this does appear to work
nals.) When the bit is set to %0, the processor operates at its without side effects, such undocumented "features" are best
normal 1-MHz rate. To be precise, the clock frequency is avoided.
1.02273 MHz for NTSC (North American) systems and 0.98525
MHz for PAL (European) systems. Setting this bit to %1 dou- Bits 2-7: These bits are unused. Writing to them has no effect,
bles the clock rate, providing what is commonly referred to as and they always return %1 when read. Thus, the value in this
2-megahertz (MHz) mode. This is also known as fast mode, register will always be at least 252/$FC. To mask off these
the old standard speed being disparagingly referred to as slow bits, use AND 3 in BASIC or AND #$03 in machine language.
mode. During the reset and RUN/STOP-RESTORE sequences,
the IOINIT routine [$E109] sets this bit to %0 for slow mode. 53297-53311 $D031-$D03F Unused
Fast mode does have a few limitations. While the 8502 These unused register addresses always return the value
microprocessor and the VDC 80-column video chip have no 255/$FF when read. Writing to these locations has no effect.
problems operating at the higher clock rate, most of the other
I/O chips cannot keep up at this speed. The VIC chip itself
cannot maintain its video display at this speed—the 40-column

376 377
53312-54271 $D040-$D3FF $D400-$D41C 54272-54300

53312-54271 $D040-$D3FF
VIC chip register images In the common musical scale, every note is assigned a
particular frequency (see Appendix D). But you don't have to
Due to incomplete address decoding, images of the VIC chip know much about music to know that a C note played on a
registers repeat every 64 bytes through the remainder of this guitar sounds different from one played on a piano or flute or
page of memory. That is, storing a value in any location in
this range which has an address that is an exact multiple of 64 organ. Obviously, there is more to sound than just frequency.
greater than one of the base register locations has the same ef- The next important characteristic is waveform. The sound
fect as storing that same value at the base register location. For wave for a "pure" tone will have a sinusoidal waveform, as
example, storing a value at 53312/$D040 or 54208/$D3C0 shown in Figure 8-7. However, a sine waveform is relatively
has the same effect as storing a value in 53248/$DOOO. How- difficult to synthesize digitally, so it is fortunate that pure
ever, it's better programming practice to use the officially des- tones are relatively rare.
ignated register addresses. Figure 8-7. Sinusoidal Waveform

SID (Sound Interface Device) Chip Registers


S4272-54300/$D400-$D41C
The SID (Sound Interface Device) chip, officially designated
the 6581, was a remarkable breakthrough when it was first
introduced in the Commodore 64. It remains the most sophis-
ticated piece of standard audio hardware in any currently
available home computer. The SID incorporates most of the
features of a complete sound synthesizer in a single chip, and
it has been a key to the Commodore 64's success as a music
machine.
Some sound fundamentals: Most sounds we hear are
transmitted in the form of pressure waves through the air. The
sounds humans usually consider pleasant have regularly re-
peating patterns. To duplicate (synthesize) these sounds, an
electronic device such as the SID chip generates patterns of
electrical signals that are passed through an amplifier to a
speaker, which translates the signals into corresponding sound
waves. The most rudimentary characteristic of a sound wave is Most sounds, including the sounds of almost all musical
its frequency, the measure of how many times per second the instruments, contain harmonics in addition to the fundamental
bask sound pattern repeats. In music, frequency is expressed frequency. Harmonics are components of complex sound
as pitch. The higher the frequency of a sound wave, the waveforms which are exact multiples of the fundamental fre-
higher its pitch. Frequency is measured in units of cycles per quency. For example, the first harmonic of a 120-hertz wave
second, called hertz (Hz). The generally accepted range of fre- will have a frequency of 120 Hz (the fundamental frequency).
quencies audible to humans is 20 Hz to 20,000 Hz. Any com- The second harmonic will have a frequency of 240 Hz, and
puter that provides for sound output will allow you to control the third harmonic will have a frequency of 360 Hz. Any
the frequency of the sound. For those computers like the IBM wave shape can be expressed in terms of a fundamental sine
and Apple that have only rudimentary sound capabilities, fre- wave and additional harmonics. The SID can generate three
quency is the only component you can control. different wave shapes: the triangle, which corresponds to a
378
379
54272-54300 $D400-$D41C $D400-$D41C 54272-54300

Figure 8-8. SID Waveforms fundamental frequency plus odd harmonics in diminishing
proportions; the sawtooth waveform, which corresponds to a
fundamental frequency plus both odd and even harmonics in
diminishing proportions; and the pulse waveform, which has a
varying mix of harmonics depending on the width of the
pulse. Figure 8-8 illustrates these waveforms. The triangle
waveform corresponds to mellow sounds like those of the xy-
lophone. The sawtooth waveform corresponds to the slightly
harsher sound of instruments like the guitar or accordion. Be-
cause the harmonic content of the pulse waveform is variable,
it can be used for a variety of sounds ranging from piano to
trumpet.
Note that Figure 8-8 includes a fourth waveform not pre-
viously mentioned. In addition to the "orderly" waveforms,
the SID can also produce a waveform that varies constantly
with no discernible frequency. Such a pattern (or lack of pat-
tern) is characteristic of the class of sounds we call noise. De-
pending on how fast the wave changes levels, it can range
from a low buzz to a high hiss like radio station static.
The final component of sound that can be controlled by
the SID is the envelope. If you visualize the sound waveforms
as shown in Figure 8-8, the volume of the sound corresponds
to the height of the waveform, technically called the ampli-
tude of the wave. While some instruments like the organ can
start a note playing at a constant amplitude (volume) and turn
it off almost immediately, most instruments take a certain
amount of time to bring a note to full amplitude, and in some
instruments a note will linger for a brief period after it has
been played. This rise and fall of amplitude is called the enve-
lope of the waveform, and is usually described in terms of at-
tack, decay, sustain, and release (ADSR), as illustrated in
Figure 8-9, Each class of instrument has a characteristic ADSR
envelope.
The attack is the time required for the note to rise from si-
lence to maximum volume after it is begun—for example, after
a string is picked or bowed or struck. Decay is the time re-
quired for the note to drop from maximum volume to its sus-
tain level, where it remains until it begins to die away to
silence again (the release phase). Not every sound will exhibit
every phase of the ADSR envelope. For example, the envelope
for instruments like the guitar or piano which have plucked or
struck strings will have almost no attack time; the envelope for

380 381
$D400-$D41C 54272-54300
54272-54300 $D400-$D41C

Figure 8-9. ADSR Envelope Figure 8-10. Sound Characteristics:


Frequency, Waveform, and Envelope

instruments like the flute, where the player must start a col-
umn of air vibrating, have a significant attack time. The dis-
cussion of the ENVELOPE statement in the System Guide that
came with your 128 shows the relative ADSR parameters of a
variety of instrument types. If you are confused about the rela-
tionship between frequency, waveform, and envelope, Figure
8-10 should help clear up some of the confusion.
Table 8-3 lists the available registers of the SID chip. A
detailed description of each follows. The SID's 29 registers fall
into two distinct classes. The first 25 are write-only; reading
from them returns zeros or meaningless values. The final 4 are
read-only; writing to them has no effect. All 128 SID registers
appear in the same locations and have the same functions as
the Commodore 64's SID chip. Thus, any Commodore 64
sound routine should also work in Commodore 128 mode. In
addition to being loaded directly, some of these registers can
also be loaded indirectly from shadow registers as part of the
BASIC IRQ service routine.

383
382
54272 $D400 6D401 54273

T a b l e 8-3. SID Chip R e g i s t e r s clock rate depends on which video system the 128 uses. For
54272/$D400 Frequency register for voice 1 {low byte) NTSC (North American) systems, the clock value is 1022730
54273/$D401 Frequency register for voice 1 (high byte) Hz, while for PAL (European) systems it is 985250 Hz. Thus,
54274/$D402 Pulsewidth for voice 1 (low byte) you can use the following expressions to calculate the fre-
54275/$D403 Pulsewidth for voice 1 {high byte) quency produced by any given register setting:
54276/$D404 Control register for voice 1 frequency = register value * 0.06096 (for NTSC systems)
54277/$D405 Attack/decay register for voice 1 frequency = register value * 0.05873 (for PAL systems)
54278/$D406 Sustain/release register for voice 1
54279/SD407 Frequency register for voice 2 (low byte) Since the register pair can hold values from 0-65535/
54280/$D408 Frequency register for voice 2 (high byte) $0000-$FFFF, the range of possible output frequencies for an
54281/$D409 Pulsewidth for voice 2 {low byte) NTSC system is 0-3995 Hz. A register value of zero corre-
54282/$D40A Pulsewidth for voice 2 {high byte) sponds to no frequency, hence no sound. The upper limit of
54283/$D40B Control register for voice 2 human hearing is about 20,000 Hz, but the fact that the SID
54284/$D40C Attack/decay register for voice 2 can't generate frequencies above 4000 Hz isn't really a serious
54285/$D40D Sustain/release register for voice 2 handicap. The frequencies between 4000 and 20,000 Hz are
54286/$D40E Frequency register for voice 3 (low byte) not often used in music. For example, the highest note on a
54287/$D40F Frequency register for voice 3 (high byte) piano (a C four octaves above middle C) has a frequency of
54288/$D410 Pulsewidth for voice 3 {low byte) 4186 Hz, just slightly beyond the SID's range. The SID can
54289/$D411 Pulsewidth for voice 3 (high byte) produce notes corresponding to those for any of the 88 keys
54290/$D412 Control register for voice 3 on a piano keyboard except the very rightmost one. The lower
54291/$D413 Attack/decay register for voice 3 limit of human hearing is about 20 Hz, so register values less
54292/$D414 Sustain/release register for voice 3 than about 320/$0140 should result in inaudible output re-
54293/SD415 Filter cutoff frequency {low byte)
54294/$D416 Filter cutoff frequency (high byte) gardless of the volume setting. Actually, this is true only for
54295/$D417 Resonance/filter control register the triangle waveform. The sudden transitions in output am-
54296/$D418 Volume/filter mode register plitude during sawtooth and pulse waveforms will produce a
54297/$D419 Potentiometer (paddle) x position clicking or buzzing output at these supposedly inaudible low
54298/$D41A Potentiometer (paddle) y position frequencies.
54299/$D41B Voice 3 oscillator output If you know the frequency (in hertz) that you wish to
54300/$D4lC Voice 3 envelope generator output generate, you can calculate the corresponding register setting
using the following formulae:
54272 $D400 FRELO1 register value = desired frequency * 16.40 (for NTSC systems)
54273 $D401 FREHI1 register value = desired frequency * 17.03 (for PAL systems)
Frequency control registers
The value in this pair of registers determines the frequency of See Appendix D for a list of the standard frequencies for musi-
the sound generated for voice 1. The higher the frequency, the cal notes and the register values required to produce those fre-
higher the pitch of the sound. For triangle, sawtooth, and quencies. It is permissible to change the frequency of a sound
pulse waveforms, the relationship between the value in these while it is playing. The change will take effect immediately,
registers and the voice 1 sound frequency in hertz (cycles per and will not affect the envelope. Changing the frequency of an
second) is: active sound can produce interesting effects. See the entry for
the register at 54299/$D41B for an example.
frequency = register value * clock rate / 16777216 The noise waveform doesn't have a regularly repeating
The first register (54272/$D400) holds the low byte of the pattern like the triangle, sawtooth, and pulse waveforms. The
value and the second (54273/$D401) holds the high byte. The output jumps erratically from one amplitude level to another,

384 385
54274 $D402 $D403 54275

so noise doesn't really have a frequency in the same sense Figure 8-11. Pulse Waveform Duty Cycles
that the other waveforms do. For noise, the value in these reg-
isters determines how rapidly the amplitude level changes.
The number of changes per second is approximately equal to
the register value. For example, a register value of 1000/$03E8
will cause the noise output level to change about 1000 times
per second, or approximately one change every 1/1000 sec-
ond. The faster the output level changes, the higher the per-
ceived pitch of the generated noise.
Remember that these are write-only registers; they will al-
ways return 0/$00 when read, regardless of the values you
have stored in them.

54274 $D402 PWLO1


54275 SD403 PWHI1
Pulsewidth control registers
This register pair controls the waveform shape when pulse
output is selected for voice 1. The value here has no effect on
any other waveform. The pulse waveform is binary; that is, it
has two states: maximum amplitude and off {no amplitude).
Unlike the ideal sine waveform, which has a smooth transition
between maximum and minimum amplitudes, the pulse wave-
form switches almost instantly. The duration of each cycle of
the waveform is controlled by the registers at 54272-54273/
$D400-$D401. What the registers here control is how much of
each cycle the waveform spends in the zero-amplitude state.
Pulse waveforms are often described in terms of their duty
cycles, the percentage of the total waveform cycle spent in the
maximum amplitude state. A pulse waveform with a 0-percent
duty cycle is always off, while a pulse waveform with a 100-
percent duty cycle is always at maximum amplitude. A wave-
form with a 50-percent duty cycle is at maximum amplitude
for half of the cycle and off for the remaining half, resulting in
a square wave. Figure 8-11 illustrates various duty cycles.
This register pair controls the duty cycle (expressed as a
percentage of the total duration of one cycle of the waveform)
according to the following formula:
duty cycle = 100 — (register value / 40.95)
Only 12 of the 16 bits in the register pair are used. The lower
8 bits come from the register at 54274/$D402 and the higher
4 bits come from bits 0-3 of the register at 54275/$D403. Bits

386 387
54275 $D403 $D404 54276

4-7 of 54275/$D403 are unused; any value written to these It is permissible to change the value in these registers, and
bits has no effect. The available 12 bits allow register values of hence the width of a pulse waveform, while the voice is gen-
0-4095/$000-$EFF, Thus, you can specify duty cycles in the erating output. This will affect only the waveform, not the en-
full range 0-100 percent. If you know the duty cycle you velope. Remember that these are write-only registers; they will
want, you can calculate the proper register value with: always return 0/$00 when read, regardless of the values you
register value = (100 — desired duty cycle) * 40.95 have stored in them.
In the expression above, the duty cycle is expressed as a per- 54276 8D404 VCREG1
centage. For example, the required register value for a 50-percent
duty cycle—a square wave—would be (100 — 50) * 40.95 = Voice 1 control register
2048/$0800. For this, you would store the low byte (0/$00) in Each bit of this register controls some aspect of the output
54274/$D402 and the high byte (8/$08) in 54275/$D403. sound for the voice. Remember that this is a write-only regis-
There's one phemomenon you need to be aware of when ter. All of the following bits return %0 when read.
selecting duty cycles. The relative percentage of the pulse Bit 0: This bit, called the gate flag, is used to initiate output for
waveform cycle spent in each state, rather than the actual this voice and to trigger the release portion of the defined
state, determines how the resulting output will sound. Notice sound envelope for the voice. (See the introduction of this sec-
in Figure 8-11 that both the 25-percent and 75-percent duty tion for more information on sound envelopes.) Writing a %1
cycles have waveforms that are in one state for 25 percent of here starts the attack portion of the envelope. This is some-
the cycle and the other state for 75 percent of the cycle. In times referred to as gating the voice. For audible output, the
either case, the ratio of time spent in each state is 3 to 1. A frequency registers for this voice and the overall volume regis-
pulse wave with a 75-percent duty cycle will sound exactly ter for the chip must contain nonzero values. The attack por-
the same as one with a 25-percent duty cycle. For every pulse tion of the envelope will normally be followed by the decay
waveform duty cycle less than 50 percent, there is a duty cycle phase, after which the sound amplitude will remain at the
greater than 50 percent that will produce the same sound. For specified sustain level until a %0 is written to this register.
example, a waveform with a 10-percent duty cycle (on for 10 After the %0 is written, the release phase begins and the
percent of the cycle and off for the remaining 90 percent) will sound output level will fade away to silence at the specified
sound the same as a waveform with a 90-percent duty cycle release rate. (Release does not occur unless a %0 is specifically
(on for 90 percent of the cycle and off for the remaining 10 written to this bit.)
percent), since for either waveform the cycle is divided be- Note that writing a %0 here triggers the release phase re-
tween the two states in a 9-to-l ratio. gardless of the current state of the envelope. For example, if
The closer the register value is to 2048/$0800—the value you write a %1 here and then immediately write a %0 before
for a square wave (50-percent duty cycle, 1-to-l ratio of time the attack phase is completed, the attack will be aborted and
in each state)—the richer the resulting output will sound. As release will begin from the current amplitude level. Likewise,
the register value approaches 4095 or 0, for 0- or 100-percent writing a %1 here initiates the attack phase, regardless of the
duty cycles, respectively, the ratio approaches its maximum of current state of the envelope. For example, if a %1 is written
1 to 4095 and the resulting sound output becomes increasingly here while the envelope for the voice is in the decay phase,
thin. Very low or very high duty cycles result in nearly inau- the decay phase will be aborted and another attack phase will
dible output. Duty cycles of exactly 0 or 100 percent result in begin from the current amplitude level.
constant output levels. Since some variation in the output is Bit 1: This bit, called the sync flag, controls a special effect
required to produce sound, register values of 0/$000 or 4095/ known as synchronization, which changes the frequency of
$FFF produce no audible output. and adds extra harmonics to the voice 1 output. When this bit
is set to % 1 , the waveform of voice 1 will be synchronized

388
54276 $D404 SD404 54276

with the waveform of voice 3. That is, whenever the waveform Ring modulation is rather difficult to explain simply.
of voice 3 starts a new cycle, voice 1 will also start a new cy- When you ring modulate voice 1 at the frequency of voice 3,
cle, regardless of its point in its current waveform. Figure 8-12 the resulting waveform is the equivalent to the sum of two
illustrates the effect on the voice 1 waveform. waveforms of different frequencies. However, the resulting fre-
Figure 8-12. Voice 1 Synchronized with Voice 3 quencies are different from both the frequency of voice 1 and
that of voice 3. Figure 8-13 is an example of one observed
ring-modulated output.
Figure 8-13. Voice 1 Ring Modulated by Voice 3
voice I

voice 1

voice 3
frequency
voice 3
frequency

resulting
output
resulting
output

Only the frequency specified for voice 3 is significant for The ring modulated waveform will have a complex mix of
synchronization. In fact, it doesn't matter whether voice 3 is harmonics. This is useful for simulating the sounds of bells,
turned on or not, so long as a frequency value is stored in the gongs, and similar instruments whose waveforms don't closely
frequency control registers for the voice. (Synchronization has resemble the triangle, sawtooth, or pulse.
no effect if the frequency for the synchronizing voice is zero.) Only the frequency specified for voice 3 is significant for
Ideally, the frequency for voice 3 should be less than that ring modulation, (Voice 1 must be set for a triangle waveform,
specified for voice 1. but the waveform of voice 3 is irrelevant.) It doesn't even mat-
Synchronization also works for voices 2 and 3. Setting ter whether voice 3 is turned on or not, as long as a frequency
this bit in the control register for voice 2 (54283/$D40B) al- value is stored in the frequency control registers for the voice.
lows voice 2 to be synchronized with voice 1, and setting this (Ring modulation has no audible effect if the frequency for the
bit in the control register for voice 3 (54290/$D412) allows modulating voice is zero.)
voice 3 to be synchronized with voice 2. It is possible to have Ring modulation also works for voices 2 and 3. Setting
two or all three voices synchronized simultaneously. this bit in the control register for voice 2 (54283/$D40B) al-
lows voice 2 to be ring modulated by voice 1. (Voice 2 must
Bit 2: This bit, called the ring mod flag, controls a special effect be set for a triangle waveform.) Setting this bit in the control
known as ring modulation. When this bit is set to %1 and a register for voice 3 (54290/$D412) allows voice 3 to be ring
triangle waveform is selected for the voice, the triangle wave- modulated by voice 2, (Voice 3 must be set for a triangle
form will be ring modulated at the frequency of voice 3. (Ring waveform.) It is possible for two or all three voices to be
modulation works only when the triangle waveform is selected.) simultaneously ring modulated.
390 391
54276 SD404 $D405 54277

Bit 3: This bit, called the test flag, can be used to reset the in- 54277 $D405 ATDCY1
ternal oscillator for the voice. When this bit is set to % 1 , the
internal-oscillator register is reset to zero, halting sound output Attack and decay control register
for the voice. The oscillator remains stopped until a %0 is This register controls the behavior of the attack and decay
written to this bit. You can use this bit to precisely control phases of the envelope for the voice.
when the voice oscillator turns off or on. You must also use Bits 0-3: These bits control the decay rate, the amount of time
this bit to unfreeze the noise output if you accidentally turn on required for the voice to drop from the peak amplitude at-
noise while another waveform is active. tained during the attack phase to the specified sustain level.
Bits 4-7: These bits control the behavior of the internal oscil- For decay to have any audible effect, the sustain level must be
lator for the voice, and hence the resulting waveform of the less than %1111/$F. There is no simple formula relating the
sound output for the voice. (See the introduction to this sec- bit value to the corresponding time. The following table shows
tion for more information on waveforms.) Each bit controls the relationship:
one of the standard waveforms, as follows: Bits Value Time required for
32 10 decay phase (in seconds)
Bit Value Waveform
4 16/$10 triangle 00 00 0/$00 0.006
5 32/$20 sawtooth 0 0 01 l/$01 0.024
6 64/$40 pulse 0 0 10 2/$02 0.048
7 128/$80 noise 0 0 11 3/$03 0.072
0 10 0 4/$04 0.114
Setting one of these bits to %1 tells the oscillator to produce 0 10 1 5/$05 0.168
the corresponding waveform. Setting the bit to %0 turns off 0 110 6/$06 0.204
that waveform. One of the waveforms must be selected for the 0 111 7/$07 0.240
voice to produce any output. 10 0 0 8/$08 0.300
Since the waveforms can be independently selected, you 10 0 1 9/$09 0.750
might be tempted to simultaneously enable more than one 10 10 10/$0A 1.50
10 11 11/S0B 2.40
waveform for the voice. This won't hurt the SID chip, but 110 0 12/$0C 3.00
you'll probably be disappointed with the results. When you 110 1 13/$0D 9.00
select more than one waveform, the resulting output is not the 1110 14/$0E 15.0
simple combination of the selected waveforms. Commodore 1111 15/$0F 24.0
literature continues to claim that the result will be a logical You can change the decay rate while a sound is being played.
ANDing of the selected waveforms, but the SID's designer has However, unless the envelope is currently in the attack or de-
stated that this is not the case. In any event, mixed waveforms cay phase, the change won't have any effect until the next
tend to produce a rather erratic sound, so the technique isn't time the envelope is started by writing a %1 to the gate bit for
really useful. Furthermore, you'll cause a problem if one of the the voice (bit 0 of the control register).
waveforms in the combination is noise. When the noise wave-
form is selected while any other waveform is also selected, the Bits 4-7: These bits control the attack rate, the amount of time
noise generator for the voice will cease to function. To restart required for the sound output of the voice to rise from silence
it you'll have to write a %1 and then a %0 to the TEST flag (zero amplitude) to peak amplitude. The attack phase begins
(bit 3 of this register) or reset the computer. when a %1 is written to the gate bit for the voice (bit 0 of the
control register). There is no simple formula relating bit values
to the corresponding attack rates. The following table shows
the relationship. Note that attack rates are three times faster

392 393
54278 SD406 $D406 54278

than corresponding decay or release rates. This is because the Bits Value Time required for
attack phase tends to be shorter than decay or release for most 3210 release phase (in seconds)
naturally occurring sounds. 0000 0/$00 0.006
Bits
000 1 l/$01 0.024
Value Time required for 00 10 2/$02 0.048
7654 attack phase (in seconds)
00 11 3/$03 0.072
0000 0/$00 0.002 4/$04 0.114
000 1 16/$10 0.008 oioo
010 1 5/$05 0.168
00 10 32/$20 0,016 oiio 6/$06 0.204
00 11 48/$30 0.024 0111 7/S07 0.240
0 100 64/$40 0.038 1000 8/$08 0.300
0 10 1 80/$50 0.056 1001 9/$09 0.750
0 110 96/560 0.068 1010 10/$0A 1.50
0 111 112/$70 0.080 10 11 ll/$0B 2.40
1000 128/$80 0.100 1100 12/$0C 3.00
100 1 144/$90 0.250 110 1 13/$0D 9.00
10 10 160/$A0 0.500 1110 14/$0E 15.0
10 11 176/$B0 0.800 1111 15/$0F 24,0
1100 192/$C0 1,00
110 1 208/$D0 3.00 It is possible to change the release rate while a sound is
1110 224/$E0 5.00 being played. The new rate will supersede the old one, even if
1111 240/$F0 8.00 the envelope is currently in the release phase.
Yot i can change the attack rate while a sound is being Bits 4-7: These registers specify the volume level at which the
played. However, unless the envelope is currently in the at- voice output will be maintained during the sustain level of the
tack phase, the change won't have any effect until the next envelope. Note that this is different from the attack, decay,
time the1 gate bit for the voice (bit 0 of the control register) is and release values, which specify periods of time instead of
set to %1 to restart the envelope. levels. Once the attack and decay phases are completed, the

54278 SD406 SUREL1 Bits Value Percentage of


76 5 4 peak output
Sustain and release control register 000 0 0/$00 0 (no output)
This register controls the behavior of the sustain and release 000 1 16/$10 7
phases of the envelope. 00 1 0 32/$20 13
Bits 0-3: The value in these bits determines the amount of 00 1 1 48/$30 20
010 0 64/$40 27
time required for the volume level for the voice to drop to
010 1 80/$50 33
zero (silence) during the release phase of the envelope. The re- 0110 96/$60 40
lease phase doesn't begin until it is triggered by writing a %0 011 1 112/$70 47
to bit 0 of the control register for the voice. Note that release 1 00 0 128/$80 53
will have no audible effect if the specified sustain level is zero. 1 00 1 144/$90 60
There's no simple formula relating the value in these bits to 1010 160/SAO 67
the corresponding release times. The following table lists the 1011 176/$B0 73
relationships: 1100 192/$C0 80
1 101 2O8/$D0 87
111 0 224/$E0 93
111 1 240/SFO 100 (peak output)
394 395
54279 $D407 SD416 54294

voice will remain at the level specified here until the release 54286 SD40E FRELO3
phase is specifically triggered by writing a %0 to the control 54287 $D40F FREHI3
register for the voice. The sustain level can be considered a Frequency control register
percentage of the peak volume level of the output, as shown 54288 $D410 PWLO3
in the following table. (The overall peak output level is con- 54289 $D411 PWHI3
trolled by bits 0-3 of the register at 54296/$D418.) Pulsewidth control register
If 0 is specified for the sustain level, the voice will die
away to silence at the end of the decay period. You can 54290 $D412 VCREG3
change the value in these bits to reduce the sustain level (and Waveform control register
hence the output volume) while a sound is being played. 54291 $D413 ATDCY3
However, if you try to increase the sustain level above its cur- Attack and decay control register
rent value while a voice is in the sustain phase, the voice will 54292 $D414 SUREL3
be turned off.
Sustain and release control register
Voice 2 Control Registers 54293 $D415 FCLO
The following seven registers (54279-54285/$D407-$D40D) 54294 SD416 FCHI
provide the same control functions for voice 2 that the regis- Filter cutoff frequency registers
ters at 54272-54278/$D400-$D406 provide for voice 1. Refer
to the entries for the voice 1 registers for details of how these The value in these registers specifies the cutoff frequency for
registers are used. the filter. See the entry for bits 4-6 of the register at
54296/$D418 for more information on the effect of filtering.
54279 $D407 FRELO2 Only 11 of the 16 bits in this register pair are used. The lower
54280 $D408 FREHI2 3 bits of the value come from bits 0-2 of the register at
Frequency control registers 54293/SD415 and the upper 8 bits come from the register at
54281 $D409 PWLO2 54294/$D416. Bits 3-7 of 54293/$D415 are not used, and
54282 $D40A PWHI2 writing to those bits has no effect. Remember that these are
Pulsewidth control registers write-only registers; they will always return 0/$00 when read,
regardless of the values you have stored in them.
54283 $D40B VCREG2 The available 11 bits allow you to specify values in the
Waveform control register range 0-2047/$0000-$07FF. However, there is a great deal of
54284 $D40C ATDCY2 confusion about the exact relationship between the value in
Attack and decay control register these registers and the corresponding cutoff frequency. Sup-
54285 $D40D SUREL2 posedly, the value here specifies the cutoff frequency in linear
Sustain and release control register steps between a minimum of about 30 Hz and a maximum de-
termined by two external capacitors connected to the SID chip.
Voice 3 Control Registers Commodore's formal specifications for the SID chip state that
The following seven registers (54286-54292/$D40E-$D414) the equation for maximum cutoff frequency is:
provide the same control functions for voice 3 that the regis- frequency = 2.6 X 10"5 / capacitance
ters at 54272-54278/$D400-$D406 provide for voice 1. Refer Other official literature, including the 128 Programmer's Refer-
to the entries for the voice 1 registers for details of how these ence Guide, states that the maximum cutoff frequency is about
registers are used. 12,000 Hz, a calculation based on filtering capacitors of 2200
picofarads (2200 X 10"12). There are a number of problems

396 397
54295 $D417 $D41S 54296

here. First of all, the capacitors used in the 128 (and, by the Bit 2: This bit provides the same filter control function for
way, also in later versions of the Commodore 64) are instead voice 3 that bit 0 provides for voice 1.
actually 470 picofarads, not 2200, If the stated equations were
correct, this would give a maximum cutoff value of over Bit 3: This bit controls the handling of any external audio in-
55,000 Hz, implying that the majority of register values would put to the SID. As with bits 0-3, setting this bit to %0 con-
produce cutoff frequencies beyond the audible range. Simple nects the external input directly to the combined output, while
experimentation shows that this is not the case. This isn't sur- setting the bit to %1 routes the external input through the fil-
prising, since the SID's designer, Bob Yannes, stated in an in- ter before output. These two functions—adding directly to the
terview in the March 1985 issue of IEEE Spectrum magazine output or adding to the filtered output—are the only process-
that filtering doesn't work according to the specified equation ing the SID can perform on the input signal from an external
anyway. source. The SID's external input line is connected to pin 5 of
So how do you go about selecting a cutoff frequency? Our the composite (40-column) video port. To avoid damage to the
experience suggests that, while filtering does work after a SID, you should not use highly amplified signals such as the
fashion for any given 128, a value that produces a particular final output of a home stereo system for the external input
cutoff frequency on one computer may produce a slightly dif- source.
ferent cutoff frequency on another system. Although it's not a Bits 4-7: These bits control an effect of filtering known as res-
particularly scientific approach, the best way to discover the onance. The four bits provide for 16 evenly spaced steps from
proper register value for a given cutoff frequency is simply to no resonance (%0000) to full resonance (%1111). Resonance
try different values until the desired effect is achieved. accentuates frequencies near the cutoff frequency for the filter.
The higher the resonance, the more pronounced the effect of
54295 $D417 RES/FILT the selected filter.
Filter selection and resonance control register
The bits of this chip select whether the various audio sources 54296 $D418 SIGVOL
in the SID will be passed directly to the chip output or routed Volume and filter mode control register
through the filter stage. This register also controls a special fil- This register controls the overall volume of the SID output, as
tering effect known as resonance. Remember that this register well as the type of frequency attenuation provided by the fil-
is write-only; all bits will return %0 when read, regardless of ter. Remember that this register is write-only; reading any of
the values you write to them. the following bits will return %0, regardless of the values you
Bit 0: This bit controls whether or not the output for voice 1 write to the bits.
passes through the SID's filter stage. When the bit is %0, the
filter is bypassed and voice 1 output is routed directly to the Bits 0-3: These bits specify the peak volume for the combined
combined SID output. When the bit is % 1 , voice 1 output is output of all three voices plus any external input. The four bits
routed through the filter before being passed to the chip out- allow for 16 evenly spaced steps between no output (%0000)
put. The filter will modify the voice 1 output according to the and maximum output (%1111). Expressed as a percentage of
filter parameters specified in the registers at 54293-54294/ maximum possible output volume, the effects of the settings
$D415-$D416 and 54296/$D418. are roughly as follows:
Bit 1: This bit provides the same filter control function for
voice 2 that bit 0 provides for voice 1.

399
54296 $D418 $D418 54296

Bits Value Percentage of


Figure 8-14. Filter Types
3 2 10 maximum output
0000 0/$0 0 (no output)
0001 1/$1 7
0 0 10 2/$2 13
0 0 11 3/$3 20 (a) low-pass
0 10 0 4/$4 27
0 10 1 5/$5 33
0 110 6/$6 40
0 111 7/$7 47
1000 8/$8 53
100 1 9/$9 60
10 10 10/$A 67
10 11 11/$B 73
110 0 12/$C 80
110 1 13/$D 87
1110 14/$E 93 (b) high-pass
1111 15/$F 100 (maximum output)
These bits must be set to some value greater than zero for the
SID to produce any audible output. There's only one volume
control for the chip, but the relative output volume level of
each voice can be controlled by adjusting the sustain level of
the voice's envelope.
Bits 4-6: These bits control the operation of the SID's filter
stage. The SID has only one filter for all three voices (plus the
external input), so the filtering selections affect any source
passed through the filter. Any of the voices can also bypass
the filter and connect directly to the output. Bits 0-3 of the (c) band-pass
register at 54295/$D417 control which voices are routed
through the filter. Bits 4-7 of that register control resonance,
which can be used to emphasize the effects of filtering.
The SID provides three basic types of filtering, as illus-
trated in Figure 8-14(a-c). The first type, called a low-pass fil-
ter, allows frequencies below a specified cutoff frequency to
pass virtually unchanged, but sharply reduces (attenuates) the
volume of frequencies higher than the cutoff. The high-pass
filter provides the opposite effect, allowing frequencies above
the specified cutoff to pass while attenuating frequencies lower id) band-stop
than the cutoff. The third selection, the band-pass filter, allows
frequencies near the specified cutoff to pass while blocking
frequencies that are much above or below the cutoff. The fil-
tering types can also be combined. For example, selecting low-
pass and high-pass filters simultaneously provides a fourth
400 401
54297 $D419 SD41A 54298

type of filter known as the band-stop, or notch, filter (see Fig- called analog-to-digital (A/D) converters. The A/D converters
ure 8-14d). In this case, frequencies well above and below the generate a one-byte value based on the input voltage. These
cutoff are passed with little change, while frequencies near the read-only registers return the values generated by the convert-
cutoff are attenuated. The cutoff frequency is specified in the ers; writing to these locations has no effect. As connected in
registers at 54293-54294/$D415-$D416. the 128, the converters measure the voltage across capacitors
Bit 4 controls the low-pass filter, which is enabled when at the input pins. When a variable resistor (also called a poten-
the bit is %1 and disabled when the bit is %0. Bits 5 and 6 tiometer) is connected between a constant voltage source and
provide the control for the high-pass and band-pass filters, re- the capacitor, the converters can be used to read the input re-
spectively, in the same manner. Thus, standard filter selections sistance. The output values will be in the range 0-255, accord-
are as follows: ing to the resistor value. Minimum resistance (or a closed
circuit) produces a reading of 0/$00 and maximum resistance
Bits Value Filter type (or an open circuit, as when nothing is connected to the lines)
6 54 results in a reading of 255/SFF. The official SID chip specifica-
001 16/$10 Low-pass tions state that the relationship between the installed capacitor
0 10 32/$20 Band-pass values and the resistance for maximum output value is:
10 0 64/S40 High-pass
10 1 80/$50 Band-stop resistor value = 4.7 X 10~ 4 / capacitor value
Bit 7: This bit controls whether or not voice 3 can be con- The capacitors in the 128 are 1800 picofarads (1800 X 10"12),
nected directly to the combined output of the SID chip. While so any resistance greater than about 4.7 X lO"4 / 1800 X
the bit is %0, the voice 3 output will be added to the com- IO-12 = 261 X 103 ohms (261 Kfl) will result in a register
bined output unless it is routed through the filter. Setting this value of 255/$FF. (Actually, our experience indicates that a
bit to %1 will prevent the direct connection of voice 3 to the slightly higher value, 270-280 KQ or so, may be required.)
combined output. However, even when voice 3 is blocked The SID input lines can be connected to either of the two
from direct connection to the combined output, it's still possi- control ports on the right side of the 128. Bits 6-7 of the CIA
ble to route voice 3 output through the filter and hence to the #1 port A register at 56320/$DC00 determine which control
combined output. To prevent this and completely disconnect port is currently connected (for details, see the section on the
voice 3, make sure that bit 2 of the register at 54295/$D417 is CIA chip later in this chapter). The default setting connects
set to %0. control port 1, the front one. For either port, the SID register
Voice 3 is often used in conjunction with one of the other lines are connected to port pins 5 and 9. Location 54297/
voices to generate special audio effects, since the oscillator and $D419 will read the level at pin 9 and location 54298/$D41A
envelope generator output values for this voice can be read will read the level at pin 5. From BASIC, the POT function
from registers 54299/$D41B and 54300/$D41C, respectively. can be used to read these registers. POT(l) reads the register
While voice 3 is used to generate special envelopes or as a at 54297/$D419 connected to pin 9 of port 1 and POT(2)
random-number generator, it's desirable to insure that the reads the register at 54298/$D$lA connected to pin 5 of port
specified frequency and envelope for voice 3 don't cause any 1. POT(3) and POT(4) read the same registers when con-
disruption of the other voices. This bit provides that feature. nected, respectively, to pins 9 and 5 of port 2.
Voice 3 is the only voice which can be disconnected. The device most commonly connected to these inputs is
the game paddle controller. A paddle is an extremely simple
54297 SD419 POTX device, consisting of a variable resistor connected between a
54298 8D41A POTY + 5 volt source (pin 7 of the control port) and the SID A/D
converter input line. Turning the paddle knob changes the re-
Potentiometer (paddle) reading registers sistance, and hence the register value. The paddle tends to be
The SID chip has two special input lines, designated POTX more efficient than the joystick for games that require only
and POTY, which are connected to a pair of internal devices
402 403
54298 $D41A $D41B 54299

horizontal or only vertical movement, such as Pong-type consists of two variable resistors—one on the horizontal axis
games for which the paddle was originally developed. Since and one on the vertical axis.
the steps between output levels are so small (only about one
ohm), consecutive readings of the same paddle position can 54299 $D41B OSC3
vary by one or two register values. This "jitter" can be annoy- Voice 3 oscillator output register
ing. The recommended solution is to read the paddle several This register reflects the upper eight bits of the internal-oscillator
times, then calculate the average of the readings and use that register for voice 3. This is a read-only register; storing values
value. here has no effect. The output signal for each voice is gener-
One thing you should be aware of is that Commodore has ated by converting the digital bit pattern from the voice's os-
changed the values of the capacitors used with the converters cillator register into an analog voltage level, so the output
since the Commodore 64 was first introduced. The original 64 signal for the voice is directly proportional to the value in its
used 1000 picofarad capacitors, so a resistance of about 470 oscillator. However, voice 3 is the only voice for which the os-
KX2 was required for a maximum register value. Thus, most cillator contents can be read.
paddles currently available for Commodore computers use For triangle and sawtooth waveforms, the oscillator acts
potentiometers with a top resistance of 470 Kf2 or 500 KQ. as a repeating counter. For the triangle waveform, the oscil-
Such paddles can be used with the 128, but they will swing lator count starts at zero and increments upward to its maxi-
the full range of register values (0-255) in about the first half mum count, then decrements downward to zero again. Once
of the paddle's full turn. Thus, you probably won't be able to the count reaches zero, it immediately begins incrementing
select fine increments of intermediate values. Furthermore, again, and the process repeats over and over. The counting
paddles for Atari computers, which are much more widely rate depends on the value in the frequency control registers
available than Commodore paddles, use 1 M£l (1 million ohm) for the voice. For all but the lowest frequencies, the count
potentiometers. Again, these can be used with the 128, but in sweeps up and down so quickly that you won't read every in-
this case you'll see the full register value swing (0-255) in termediate value between 0/$00 and 255/$FF in this register.
about the first quarter of the paddle's ful] turn. Thus, Atari For the sawtooth waveform, the count also starts at zero and
paddles will give you only very coarse control of the resulting increments upward to maximum count, but in this case the
register values. count then returns immediately to zero and begins increment-
Most paddle controllers also have fire buttons like joy- ing again.
sticks. However, since paddles almost always come in pairs, Unlike the triangle and sawtooth waveforms, the pulse
and since there is only one fire button line per control port, waveform doesn't sweep smoothly from one output level to
the paddle fire buttons are connected to the lines normally the next. Instead, the it jumps back and forth between two
used for joystick direction. Standard Commodore paddles use discrete levels. When the pulse waveform is selected for voice
the lines connected to bits 2 and 3 of each CIA #1 data port 3, this register will contain one of two values: 0/$00 when the
(locations 56320-56321/$DCOO-$DC01), the lines for joystick waveform is at minimum (zero) amplitude and 255/$FF when
left and right. the waveform is at maximum amplitude. The portion of the
These A/D converters can also be used for other interfac- cycle spent in the zero-amplitude state is determined by the
ing projects. Any device which provides a variable resistance value in the pulsewidth registers for the voice, and the rate at
can be connected to the appropriate control port lines and which the off/on switching repeats is determined by the value
read via these registers. For example, most graphics tablets in the frequency control registers for the voice.
such as the popular KoalaPad effectively function as paddles, The noise waveform is different from the others in that it
with one resistance for the horizontal coordinate of the stylus exhibits no regularly repeating pattern. Rather, the oscillator
position and another for the vertical coordinate. You could will contain a series of random values. The rate at which the
also rig an interface for an Apple/IBM-style joystick, which value in the oscillator changes—and hence the rate at which

404 405
54300 $D41C $D41C 54300

the value in this register changes—-is determined by the value


in the frequency control registers for the voice. This feature The envelope generator regulates the amplitude (volume)
can be used to provide a random-number generator. If your of the output for the voice. When voice 3 is silent or turned
program needs random numbers in the range 0-255/$00-$FF, off, this register will contain 0/$00, indicating no output.
simply set the voice 3 frequency registers (54286-54287/ When the gate bit for the voice (bit 0 in the register at
$D40E-$D40F) for a high frequency; then set bits 0 and 7 of 54290/$D412) is set to % 1 , the value here will begin incre-
the voice 3 control register (54290/$D412) to %1 to start the menting to 255/$FF, indicating peak output amplitude. This
noise waveform. After that, just read this register whenever peak amplitude for the voice will be relative to the overall
you need a random value. peak volume level specified in bits 0-3 of the register at
In addition to its use as a random-number generator, this 54296/$D418.
register can be used for a number of special audio effects. The The rate at which the register increments depends on the
changing output of the oscillator can be used to modify the attack rate specified in bits 4-7 of the register at 54291/$D413.
frequency or pulsewidth of a voice or the filter parameters in Once the register reaches 255/$FF, it immediately begins
realtime. The following is a simple example: decrementing to the sustain level specified in bits 4-7 of the
register at 54292/$D414 (unless the specified sustain level is
1 BOO LDA #$F0 ;set sustain to maximum level 15/$F—in that case, the register value remains at 255/$FF fol-
1B02 STA $D406 lowing the attack phase).
1B0S LDA #$8F ;set maximum volume; disconnect voice 3 The rate at which the amplitude drops to the sustain level
1B07 STA $D418 depends on the decay rate specified in bits 0-3 of the register
1B0A LDA #$01 ;set frequency (high byte) for voice 3 54291/$D413. The register value while the voice is in the sus-
1B0C STA $D40F tain phase will be equal to the specified sustain-level value re-
1B0F LDA #$21 ;start sawtooth waveform on voice 3 peated in both nybbles. For example, if the sustain level is
1B11 STA $D412 %1001 = $9, then the value in this register while the voice is
1B14 LDA #$11 ;start triangle waveform on voice 1 in the sustain phase of the envelope will be $99/153. Once
1B16 STA $D404 the gate bit for the voice is set to %0, the value in this register
1B19 LDA $D41B ;change voice 1 frequency according to will decrease from the sustain level to 0/$00. The rate at
1B1C STA $D401 ;voice 3 oscillator output which the register value decrements is determined by the re-
1B1F JMP $1B19
Whenever voice 3 is used for special effects such as lease rate specified in bits 0-3 of the register at 54292/$D414.
random-number generation, it should be disconnected from The value in this register can be used to modify other SID
the combined SID output so that it doesn't distort any sounds parameters, such as the contents of one of the write-only reg-
produced by the other voices. To disconnect voice 3, set bit 7 isters, in realtime. For example, you could try continuously
to %1 in the register at 54296/$D418. Also, make sure that bit storing the value from this register in the filter cutoff-frequency
2 of the register at 54295/$D417 is %0. This will insure that register at 54294/$D416. This would cause the cutoff fre-
voice 3 output is not routed through the filter. quency to rise and fall in conjunction with the voice 3 enve-
lope. If you use the voice 3 envelope generator for special
54300 $D41C ENV3 effects, you may want to disconnect voice 3 from the com-
Envelope generator 3 output register bined SID output so that it doesn't distort any sounds pro-
The value in this register reflects the contents of the internal duced by the other voices. To disconnect voice 3, set bit 7 to
envelope generator for voice 3, This is a read-only register; %1 in the register at 54296/$D418. Also, make sure that bit 2
storing values here has no effect. Each voice has its own enve- of the register at 54295/$D417 is %0. This will insure that
lope generator which controls the peak amplitude of the out- voice 3 output is not routed through the filter.
put for that voice. However, voice 3 is the only one for which
the envelope-generator register contents can be read.
406 407
54301-54303 $D41D-$D41F $D500 54528

54301-54303 $D41D-$D41F Unused The 17 registers of the MMU are unusual in that they are
These unused register locations always return the value 0/$00 divided into two separate groups at different memory loca-
when read. Writing to these locations has no effect. tions. The first 12 appear in the I/O block at 54528-54539/
$D500-$D50B, while the other 5 appear at 65280-65284/
54304-54527 $D420-$D4FF $FF00-$FF04. This second set of MMU registers is special in
SID register images that it appears in all memory configurations. There is no way
Due to incomplete address decoding, images of the SID chip to make the processor see anything other than the MMU regis-
registers appear repeatedly every 32 locations throughout the ters at those locations while the 128 is in 128 mode. Table 8-4
remainder of this page of memory. That is, storing a value in lists the MMU registers. A detailed description of each register
any location with an address which is an exact multiple of 32 follows.
greater than one of the base address locations listed above has Table 8-4. MMU Chip Registers
the same effect as storing a value in the corresponding base
register. For example, storing a value in 54328/$D318 or Address Function
54520/$DF18 has the same effect as storing that same value 54528/$D500 Configuration register
in 54296/$D018. However, it's better programming practice to 54529/$D501 Preconfiguration register A
use the officially designated register addresses. 54530/$D502 Preconfiguration register B
54531/$D503 Preconfiguration register C
54532/$D504 Preconfiguration register D
MMU (Memory Management Unit) Chip 54533/SD505 Mode configuration register
54534/$D506 RAM configuration register
Registers 54535/$D507 Page 0 page pointer
54528~54539/$D500-$D50B and 54536/$D508 Page 0 block pointer
65280-65284/$FF00-$FF04 54537/$D509 Page 1 page pointer
54538/$D50A Page 1 block pointer
The MMU memory management chip, officially designated the MMU version register
54539/$D50B
8722, is the cornerstone of the 128 system. In fact, the MMU 65280/$FF00 Configuration register
is what makes most of the 128's special features possible. The 65281/$FF01 Load configuration register A
MMU was designed by Commodore's engineers specifically to 65282/$FF02 Load configuration register B
support the 128's multiple operating modes and elaborate 65283/$FF03 Load configuration register C
memory banking scheme. It is the MMU which determines 65284/$FF04 Load configuration register D
which microprocessor, 8502 or Z80, has control of the com-
puter. When the 8502 is in control, the MMU determines 54528 SD500 MMUCR1
whether the computer operates in 128 mode or 64 mode. As Configuration register
described in Chapter 1, the 128 hardware includes many times The value in the configuration register determines which of
more elements than can simultaneously fit in the 64K address the available memory resources will be visible to the
space of the 8502 or Z80 microprocessors. The MMU chip also microprocessor at any given time. However, this particular
determines which memory resources are visible to the register is only rarely used—-not at all in 128 ROM except dur-
processsor at any given time. ing MMU register initialization—because it has an identical
Most BASIC programming can be done without under- twin at address 65280/SFF00 which is more convenient. There
standing the inner workings of the MMU, simply by using the is really only one configuration register; it just appears at two
available standard bank configurations. However, a thorough different addresses. The register is accessible here only when
knowledge of the MMU is essential for taking full advantage the I/O block is visible, whereas it is always accessible at
of all the 128's features. 65280/$FF00, regardless of the memory configuration. As a
408 409
54529 $D501 SD505 54533

result, memory configuration is usually done with the higher


configuration register location. Refer to the entry (below) for In a number of instances in BASIC ROM you'll find instruc-
the other configuration register for details of the function of tions like STA $FF03, where BASIC is using this shortcut
the register bits. method of bank selection.
This register is initialized during the Kernal RESET rou- Because BASIC depends on standard values in the precon-
tine [$E000] to 0/$00, the setting for the bank 15 configura- figuration registers, it's generally best to avoid changing the
tion. However, that step of the routine is redundant because register settings in machine language programs which must
the same value has previously been stored in 65280/$FF00. work in conjunction with BASIC. To reset the preconfiguration
Reading this register returns the current configuration setting, registers to their default values without performing the entire
regardless of whether the setting has been established by writ- BASIC warm start or cold start sequence, call the BASIC ROM
ing to this register or to 65280/$FF00. subroutine at 16762/$417A. Of course, if BASIC is not being
used, you're free to use the preconfiguration registers to set up
54529 8D501 any memory configuration you desire.
PCRA
54530 8D502 PCRB
54531 8D503 PCRC 54533 $D505 MMUMCR
54532 SD504 PCRD Mode configuration register
Preconfiguration registers The primary function of this register is to select the current
These registers provide an indirect method of setting up a operating mode from the three possibilities—-128, 64, or CP/M.
memory configuration. Whenever a value—any value—is Bit 0: This bit determines which microprocessor is in control
stored in one of the four ]oad configuration registers at of the system. Writing a %0 here puts the Z80 in command,
65281-65284/$FF01-$FF04, the value in the corresponding while writing a %1 switches to the 8502. Since this bit is reset
preconfiguration register is transferred to the configuration to %0 when the system is reset or powered on, the Z80 al-
register. Thus, the preconfiguration registers allow you to set ways has control of the system before the 8502. The reset se-
up as many as four different memory configurations, each of quence in Z80 ROM is nearly identical to that in 128 mode
which can then be established with a single store operation. ROM, including checking for the presence of Commodore 64
The bit functions for preconfiguration register locations are the cartridges and testing whether the Commodore key is held
same as for the configuration register. For details, see the entry down for Commodore 64 mode. If the Z80 reset routine does
below for 65280/$FF00. not find a CP/M boot disk in the drive (or a Commodore 64
The Kernal RESET routine [SEOOO] initializes all the pre- cartridge or the Commodore key held down), it jumps to a
configuration registers to 0/$00, the setting for the bank 15 routine it has copied into 65504/$FFE0 in block 0 RAM. That
configuration. The preconfiguration/load configuration register routine ends by setting this bit to %1 to return control to the
memory management technique is not used by the operating 8502 for 128 mode.
system. However, BASIC ROM routines do make use of this Switching processors is not for the faint of heart. When
method. The BASIC cold start [$4023] and warm start [$4009] you activate the Z80, it will begin executing instructions at
routines both initialize the preconfiguration registers as follows: whatever address is currently in its program counter registers.
Register Setting Bank configuration The address in those internal processor registers can't be
54529/$D501 63/$3F 0 changed from 128 mode, so you're stuck with having the Z80
54530/$D502 127/$7F 1 take up wherever it left off when the system was switched to
54531/$D503 l/$01 14 128 mode. This address is usually 65518/$FFEE, the location
54532/$D504 65/$41 A custom setting with the same visible following the one where 128 mode was activated at the end of
ROM as bank 14, but with RAM from the Z80's reset routine. In block 0 RAM, that location is initial-
block 1 instead of block 0 ized with a Z80 instruction (RST1) to perform a warm start of
CP/M mode. If you don't have a valid Z80 machine language
410
411
54533 SD50S $D505 54533

instruction there when you activate the Z80—for example, if Bits 4-5: These bits are connected, respectively, to the MMU
the system is in a memory configuration such as bank 15 pins labeled GAME and EXROM, which in the 128 are con-
where 128 Kernal ROM is seen at that address—you'll proba- nected to the memory expansion port lines with the same
bly experience an immediate system lockup. names. These MMU lines are bidirectional, meaning that they
If you wish to use any routines in the CP/M BIOS (Basic can be both inputs and outputs. The 128 uses the lines only as
Input/Output System) ROM, you must make sure that bit 6 of inputs, to read the state of the memory expansion port lines
this register also is set to make 128 mode ROM visible. The (pins 8 and 9 of the port). Writing to one of the bits sets the
BIOS code is stored in the same ROM chip used to hold the corresponding line's output level. Writing a %0 to the bit pulls
128 mode screen editor and Kernal routines, so you'll have the line to a low (0 volts) state, while writing a %1 to the bit
problems if that ROM is not visible. Activating the Z80 makes allows the line to go to a high ( + 5 volts) state. When used for
the BIOS ROM visible at addresses 0-4095/$0000-$0FFF input, an external device connected to the line can pull the
(even though the ROM is physically located at 53248-57343/ line low if its output level is set high, but cannot bring the line
$DO00-$DFFF). Thus, the Z80 never disturbs the lowest 4K of high if its output level is set low, so writing a %0 to one of
block 0 RAM, so the 8502's zero page and stack (page 1) are these bits effectively blocks the use of the line as an input.
preserved while the Z80 is in control.
The Kernal RESET routine [$E000] initializes both of these
If you want to switch to full CP/M mode, there's more in- bits to %1 so that they can be used to read the state of the
volved than simply turning on the Z80. Most of the CP/M op- port lines. In 128 ROM, these bits are read during the reset se-
erating system must be loaded from disk, so you should instead quence by the routine which checks for the presence of a
use the BASIC BOOT statement or the Kernal BOOT_CALL Commodore 64 ROM cartridge [$E242], Almost all Commo-
routine [$FF53] with a CP/M boot disk in the drive. dore 64 cartridges ground one or both of these port lines, so
Bits 1-2: Unused. These bits always return %1 when read, the 128 will assume that a 64 cartridge is present if either of
and writing to these bits has no effect. these bits is found to be %0, and will respond by switching to
Bit 3: This bit is connected to the MMU pin labeled FSDIR. Commodore 64 mode.
This line is bidirectional, meaning that it can be both an input While the system is in 128 mode, you can use these bits
and an output. The 128 uses the line only as an output, to to control the corresponding expansion port pins as either in-
control the direction of data flow on the fast serial bus. The puts or outputs. Keep in mind, however, that the pins must be
lines of the slow serial bus are each controlled by a pair of high during reset or the system will enter Commodore 64 mode.
CIA chip lines, one for input and one for output, but the fast Bit 6: This bit controls which set of ROMs will be visible to
serial bus uses the same CIA chip lines for both input and out- the system. Writing a %0 here selects the 128 mode ROM set,
put. The 128's designers added additional circuitry which in- while writing a %1 selects the Commodore 64 mode ROM.
sures that the fast serial bus will ignore incoming data during The 128 mode RESET routine [$EOOOj, of course, initializes
fast serial output. The FSDIR (fast serial direction) line controls this bit to %0. However, simply writing a %1 here won't
that circuitry. Writing a %0 to the bit pulls the line to a low (0 cause a clean transfer to 64 mode; it's necessary to perform
volts) state, which sets the fast serial bus for input. Writing a the 64 mode reset sequence after the 64 mode ROM is se-
%1 to the bit allows the line to go to a high ( + 5 volts) state, lected. See the C64_MODE routine [$E24B] for details. This
which sets the fast serial bus for output. The IOINIT routine bit has one other effect—selecting 64 mode also makes all the
[$E109] leaves this bit set to %0 so that the system can detect MMU chip registers invisible, so once you make the jump to
fast serial input. The setting of this bit is controlled in Kernal 64 mode there is no way back to 128 mode short of resetting
ROM by the routines SPIN [$E5C3] and SPOUT [$E5D6]. the computer or turning it off and back on.

412 413
54534 3D506 SD506 54534

Bit 7: This bit is connected to the MMU pin labeled 40/80. There are a few exceptions to the common RAM rules.
This line is bidirectional meaning that it can be both an input First, locations 0-l/$00-$01, the 8502 on-chip I/O port, and
and an output. The 128 uses the line only as an input, to read locations 65280-65284/$FF00-$FFO4, the upper MMU regis-
the 40/80 DISPLAY switch on the 128's keyboard. Writing to ters, always appear in any configuration, regardless of the
the bit sets the state of the line output. Writing a %0 to the bit setting of these bits. That is, there is no way to make the pro-
pulls the line to a low (0 volts) state, while writing a %1 to cessor see anything other than the hardware registers in these
the bit allows the line to go to a high ( + 5 volts) state. The locations (at least not while the computer is operating in 128
switch connected to the line can pull the line low if its output mode). Second, the area where the two lowest pages of mem-
level is set high, but cannot bring the line high if its output ory are seen is also affected by the registers at 54535-54538/
level is set low. Thus, writing a %0 to this bit effectively $DF07-$DF0A. Even if you change the page pointers at
blocks the reading of the 40/80 DISPLAY switch. The CINT 54535/$D507 or 54537/SD509 to physically move zero page
screen editor initialization routine [SC07B], part of both the re- or page 1 somewhere in memory outside the common area,
set and RUN/STOP-RESTORE sequences, sets this bit to %1 the contents of those pages will still appear to be common as
to insure that the switch can be read. The bit returns a %0 long as a common area at the bottom of memory is selected. If
when read while the switch is down (80-column position), or you disable the common area at the bottom of memory, all
a %1 while the switch is up (40-column position). In 128 references to zero page and page 1 will continue to affect only
ROM, this bit is read only during the CINT routine, where its block 0 RAM unless you specifically change the block pointers
setting is used to determine which display to make active. for those pages in the registers at 54536/SDF08 and 54538/
$DF0A. Finally, you should be aware that the common area
54534 8D506 MMURCR setting does not affect the RAM block from which the VIC
RAM configuration register chip sees its video bank. The VIC's RAM block is determined
An important aspect of the MMU's memory configuration ca- by bits 6-7 of this register, and all RAM in the VIC bank is
pabilities is its ability to create common areas of RAM, areas seen in the block specified in those bits without regard for the
where the same RAM is seen regardless of the configuration common area specification. The VIC chip can see the memory
register selection. Kernal routines copied into the default com- that is hidden from the processor.
mon area allow the processor to jump from bank to bank, or The four possible selections for the size of the common
to manipulate data in other banks. This register controls the areas are as follows:
common RAM feature, and also specifies which RAM block Hits Size of
the VIC video banks are seen in. 1 0 common areas
Bits 0-3: These bits control the common RAM feature. Bits 0-1 0 0 IK
control the size of the common areas, and bits 2-3 control 0 1 4K
1 0 8K
whether the common areas will exist at the top, bottom, or 1 1 16K
both top and bottom of the RAM blocks. (No RAM will be
common if bits 2-3 are set to %00.) When common RAM is Figure 8-15 illustrates the address ranges of these selections.
specified, the RAM seen as common is always that from block The four possible selections for location of the common
0. As long as the common RAM feature is enabled, there is no areas are as follows:
way for the processor to access the RAM in block 1 which is
covered by the common area. When a common area at the top Location of
common areas
of memory is selected, it will be visible only when bits 4-5 of No common RAM
the configuration register are set to make RAM visible at the Common area at bottom of memory
top of memory. Common area at top of memory
Common areas at both top and bottom of memory
414 415
54534 $D506 $D506 54534

Figure 8-15. Common RAM Areas The default value in these bits, established during the Kernal
RESET routine [SEOOO], is %0100 = $4. This setting selects a
IK common area at the bottom of memory, addresses 0-1023/
$0000-$03FF. The proper functioning of both the operating
system and BASIC depends on the presence of this common
area, so you should change the setting of these bits with great
care. BASIC is almost certain to crash if the common area is
disabled altogether. The operating system will crash if an in-
terrupt occurs while the system is configured for block 1 RAM
with the common area disabled.
You can manipulate these bits to gain temporary access to
the IK of RAM from block 1 which is normally hidden by the
standard common area, but making any practical use of the
hidden area is more than a little complicated. The standard in-
terbank data transfer routines like INDFET and INDSTA can't
be used because they depend on the common area. Further-
more, the machine language routine you write to perform the
transfer can't use any zero-page locations, nor can it use jumps
to subroutines or other instructions which would affect the
stack (page 1). Interrupts must also be disabled while the com-
mon area is disabled. The following routine swaps the con-
tents of the hidden block 1 area with the contents of the next
higher IK area of block 1 (addresses 1024-2047/$0400-$07FF).
Note that this routine must be placed in block 1 RAM:
1FF60 SEI ;Disable interrupts
1FF61 LDA #$7E ;Make I/O block visible
1FF63 STA $FF0O
1FF66 LDA #$00 ;Disable common RAM
1FF68 STA $D506
1FF6B LDA #$01 ;Make pages 0 and 1 visible
1FF6D STA $D508 ; block 1 RAM
1FF70 STA $D50A
1FF73 LDA #$00
1FF75 STA $D507
1FF78 LDA #$01
1FF7A STA $D509
1FF7D LDA #$00 •Initialize source starting
1FF7F STA $FF91 ; address locations
1FF82 STA $FF98
1FF85 LDA #$04 initialize target starting
1FF87 STA $FF95 ; address locations
1FF8A STA $FF9C
1FF8D LDY #$02 initialize index for first page
1FF8F LDA $0000,Y ;Swap bytes
416
417
54534 $D506 $D5O8 54536

1FF92 TAX
1FF93 LDA $04O0,Y Bits RAM block for
1FF96 STA $000O,Y 7 6 VIC video bank
1FF99 TXA 0 0 0
1FF9A STA $O4O0,Y 0 1 1
1FF9D INY 1 0 2
;Repeat for 256 bytes per page
1FF9E BNE $FF8F 1 1 3
1FFA0 INC $FF91 i n c r e m e n t address high bytes Remember, however, the 128 actually has only two 64K
1FFA3 INC $FF95 blocks of RAM. Thus, the setting of bit 7 is meaningless, al-
1FFA6 INC SFF98 though that bit will retain whatever value you write to it.
1FFA9 INC $FF9C Only the setting of bit 6 matters, since the choice is between
1FFAC LDA $FF9C ;Check whether all four pages have blocks 0 and 1. The default setting for these bits is %00, since
1FFAF CMP #$08 ; been swapped the normal VIC text and bitmapped screens are located in
1FFB1 BCC $FF8F block 0 RAM.
1FFB3 LDA #$00 ;I( so, restore pages 0 and 1
1FFB5 STA $D508 You should note that the operating system and BASIC
; to block 0 RAM
1FFB8 STA $D50A will not support a VIC video bank in block 1, That is, all the
1FFBB STA $D507 screen editor ROM routines and BASIC bitmapped graphics
1FFBE LDA #$01 routines assume that the VIC screen is located in block 0
1FFCO STA $D509 RAM, and will continue to write data to block 0 even after
1FFC3 LDA #$04 ;Reenable common RAM you've changed these bits to switch the video bank into block
1FFC5 STA $D5O6 1 RAM. Thus, you must provide your own text and graphics
IFFC8 CLI ;Reenable interrupts routines for a display from block 1. For text displays, you can
1FFC9 RTS use the standard character sets because the character ROM is
To execute the routine, use J 1FF60 from the monitor or BANK still visible in a block 1 video bank.
1:SYS 65376 from BASIC. These bits actually determine the RAM block for all DMA
(direct memory access) operations, not just for the VIC chip,
but the VIC is the only built-in device in the 128 to use DMA.
Bits 4-5: These two bits are not used in the current version of
The only other commonly available DMA device for the 128 is
MMU. The design specifications for the chip indicate that in
the REC (RAM expansion controller) chip in the 1700 and
future versions these bits may be used in a "superbanking" 1750 Memory Expansion Modules. These bits, rather than bits
scheme to select one of four separate 256K blocks of RAM in a 6-7 of the configuration register, determine which block of
1M (one-megabyte, or 1024K) system. It's a tantalizing pros- 128 system RAM is affected by REC transfer operations.
pect, but there's no guarantee that a Commodore 1024 will
ever be produced. In the current MMU, the bits will retain 54535 8D507 MMUPOL
whatever value is written to them, but changing the bit 54536 $D508 MMUPOH
settings has no effect on the memory configuration. The bits Page 0 pointers
are initialized during the Kemal RESET routine [$E000] to %00.
Bits 6-7: These bits determine which 64K block of RAM the One unique feature provided by the MMU is the ability to re-
locate page 0 anywhere in memory. Zero page is the most
VIC video bank is located in. (See the section on the VIC chip
heavily used area of memory in any computer built around a
earlier in this chapter for more information on video banks.)
6502-family microprocessor like the 128's 8502, since the pro-
The formally defined selections for the bits are as follows:
cessor has many instructions that are designed to work only
with this page. Although neither the 128 operating system or
BASIC makes use of this page-relocation capability, it has sev-
418 419
54536 SD508 SD50A 54538

eral interesting applications. For example, you could have sev- rarely a need to change the value in 54536/$D508. If you se-
eral programs in memory simultaneously and give each its lect block 1 RAM while the bottom common area is enabled, a
own personal zero page, without having to worry about mem- strange effect results. Zero page is relocated to the page speci-
ory conflicts. fied in the page pointer, but that page is not swapped with
Location 54535/$DF07, the page pointer, selects the page zero page. That is, both pages will occupy the same area of
of memory to which zero page is to be relocated. The Kernal memory, and the true zero-page area remains untouched.
RESET routine [$E0O0] stores the value 0/$00 here to locate When choosing areas of memory for a relocated zero
zero page initially in the true zero page. To move zero page, page, you must avoid page 1 (or the area where you relocate
store the target page number here. {The page number is equiv- page 1), since that page is also vital to proper system opera-
alent to the high byte of the first address in the page.) Actu- tion. You should also avoid page 255/$FF, since attempting to
ally, the operation is more a swap than a relocation. When place zero page there will cause conflicts with the MMU regis-
you redirect zero page to another page of memory, all refer- ters. Because all references to the target page will affect true
ences to addresses in the target page are diverted to the true zero page, you should be careful to avoid using any locations
zero page. For example, if you store the value 19/$13 in this in the target page while zero page is relocated (unless you
register to move zero page to page 19, then all references to really want to change true zero page). After relocating zero
addresses in the range 2-255/$02-$FF will be redirected to page, you will probably want to call the Kernal routines
4866-5119/$1302-$13FF, and all references to 4864-5119/ RAMTAS [$FF87] and CINT [$FF81] to initialize important
$1300-$13FF will be redirected to 0-255/$00-$FF. Notice that zero-page locations. (If you switch to a zero page without
addresses 0-1 from zero page are not affected. These are the proper screen editor variables, you may find yourself looking
processor's on-chip I/O port registers—not RAM. Storing values at a garbled mess on the screen.)
in these locations always affects the registers rather than RAM.
Location 54536/$D508 selects the block of RAM in which 54537 $D509 MMUP1L
zero page will be seen. Only bit 0 of the block pointer is sig- 54538 SD50A MMUP1H
nificant. Setting that bit to %0 selects block 0 RAM, while set- Page 1 pointers
ting it to %1 selects block 1. The bit is set to %0 by the Kernal
RESET routine [$E000]. Bits 1-3 will retain whatever value is Just as the MMU can relocate zero page, it also has the ability
written to them, but changing these bits has no effect. The RE- to make page 1 appear anywhere in memory. Page 1 is vital in
SET routine sets these bits to %000, Bits 4-7 are also unused, any computer built around a 6502-family microprocessor like
but these bits always return %1 when read. As a result, the the 128's 8502, since that page is the processor stack. The
value in this register will always be at least 240/$F0. Values stack is the area of memory where the processor stores return
written to the page pointer take effect immediately, but values addresses while it is executing subroutines or handling inter-
written to the block pointer are actually effective only after the rupts. The stack is also used extensively for temporary data
next time a value is stored in the page pointer. Thus, if you storage. Although neither the 128 operating system or BASIC
are changing both registers it is important to remember to makes use of this page-relocation capability, it has several in-
store the value in the block pointer (54536/$DF08) before teresting applications. For example, you could have several
storing the value in the page pointer (54535/$DF07). programs in memory simultaneously and give each its own
However, the block pointer value is ineffective while the personal stack, without having to worry about memory conflicts.
RAM configuration register (54534/$D506) is set to provide a Location 54537/$DF09, the page pointer, selects the page
common area at the bottom of memory. With the bottom com- of memory to which page 1 is to be relocated. The Kernal RE-
mon area enabled, zero page is always seen in block 0 RAM, SET routine [$E000] stores the value 0/$01 here to locate page
although it can still be moved around freely within block 0. 1 initially in the true page 1. To move page 1, store the target
Since this is the default configuration for the 128, there is page number here. (The page number is equivalent to the high
byte of the first address in the page.) Actually, the operation is
420 421
54538 $D50A 6D50B 54539

more a swap than a relocation. When you redirect page 1 to serve the original stack pointer; otherwise, your program will
another page of memory, all references to addresses in the tar- crash when the memory moving subroutine tries to return to
get page are diverted to the true page 1. For example, if you its calling routine. The two routines below are alternate meth-
store the value 21/$ 15 in this register to move page 1 to page ods of filling the high-resolution screen area. The conventional
21, then all references to addresses in the range 256-511/ method (on the left) is shorter, but the relocated stack method
$0100-$01FF will be redirected to 5376-5631/$1500-$15FF, (on the right) is about 30 percent faster.
and all references to 5376-5631/$1500-$15FF will be re-
BOO LDA #$00 COO TSX
directed to 256-511/$0100-$01FF. STA $FB C01 STX $FB
B02
Location 54539/$D50A selects the block of RAM in B04 LDA #$20 C03 LDX #$FF
which page 1 will be seen. Only bit 0 of the block pointer is B06 STA $FC COS TXS
significant. Setting that bit to %0 selects block 0 RAM, while BOS LDA #$FF C06 LDA #20
setting it to %1 selects block 1. The Kernal RESET routine BOA LDX #$20 COS STA $D509
[$E000] sets this bit to %0 for block 0. Bits 1-3 will retain B0C LDY #$00 COB LDA #$FF
whatever value is written to them, but changing these bits has B0E STA ($FB),Y COD LDX #$20
no effect. The bits are set by the RESET routine to %000. Bits B10 INY C0F LDY #$00
4-7 are also unused, but these bits always return %1 when Bll BNE $B0E Cll PHA
read. As a result, the value in this register will always be at B13 INC $FC C12 INY
B15 DEX C13 BNE $C11
least 240/$F0. Values written to the page pointer take effect C15 INC $D509
B16 BNE $C11
immediately, but values written to the block pointer are actu- CIS DEX
B18 RTS
ally effective only after the next time a value is stored in the C19 BNE $C11
page pointer. Thus, if you are changing both registers it is im- C1B LDX SFB
portant to remember to store the value in the block pointer C1D TXS
(54538/$DF0A) before storing the value in the page pointer C1E LDA #$01
(54537/$DF09). C20 STA $D509
However, the block pointer value is ineffective while the C23 RTS
RAM configuration register (54534/$D506) is set to provide a
common area at the bottom of memory. With the bottom com- 54539 $D50B MMUVER
mon area enabled, page 1 is always seen in block 0 RAM—al- Version register
though it can still be moved around freely within block 0, This read-only register returns a constant value (much like a
Since this is the default configuration for the 128, there is ROM location) reflecting the amount of RAM in the system
rarely a need to change the value in 54538/$D50A. If you se- and the version of the MMU. If Commodore ever introduces
lect block 1 RAM while the bottom common area is enabled, a successors to the 128 built with similar system architecture (a
strange effect results. Page 1 is relocated to the page specified Commodore 256 or 1024, for example), this register will allow
in the page pointer, but that page is not swapped with page 1. software to identify the amount of memory available.
That is, both pages will occupy the same area of memory, and Bits 0-3: These four bits indicate the version of the MMU chip
the true page 1 area remains untouched. installed in the 128. In current 128s the value here is %0000
This mobile page 1 allows a tricky technique for filling = 0, indicating version 0 of the MMU, but this may change if
areas of memory. Instead of storing values in a series of loca- new versions of the chip are introduced.
tions, you can redirect page 1 to the desired area of memory Bits 4-7: These four bits indicate the number of 64K blocks of
and push values onto the relocated stack. The advantage of RAM present in the system. In the 128, the value here is
this is that the PHA instruction takes only half as long to exe- %0010 = 2, indicating 128K of RAM in two 64K blocks.
cute as the STA (address),Y instruction. Just be sure to pre-

422 423
54540-54783 $D50C-$D5FF 6FF00 65280

54540-54783 $D50C-$D5FF Unused cess to the configuration register to make the I/O block visi-
All the unused register addresses in this range return the value ble). Both registers will hold identical values, regardless of
255/SFF when read. Writing to these locations has no effect. which register is written to set the value.
There is an alternative to storing values directly in this
65280 $FF00 MMUCR register. You can store up to four configuration register
Configuration register settings in the preconfiguration registers at 54529-54532/
This is one of the most important locations in all of 128 mem- $D501-$D504, then transfer the values to the configuration
ory, since the value here determines what other memory ele- register by writing to the corresponding load configuration
ments will be visible to the processor. The entire design of the registers at 65281-65284/$FF01-$FF04. See the precon-
128 is contingent on the MMU's ability to make various selec- figuration and load configuration register entries for details.
tions of the system's memory resources visible at shared loca- Bit 0: This bit determines what is seen at addresses in the
tions within the processor's limited address space. The 16 range 53248-57343/$D000-$DFFF. When the bit is set to %0,
banks supported by the operating system are merely 16 pre- the I/O block (containing hardware chip registers and color
defined settings of this register—not 16 physical arrangements RAM) is visible. When the bit is set to % 1 , the contents of the
of memory. See Table 1-1 in Chapter 1 for details of the stan- address area is determined by the setting of bits 4-5.
dard bank configurations. Bit 1: This bit determines what is seen at addresses in the
Configurations other than the standard banks are certainly range 16384-32767/$4000-$7FFF. When the bit is set to %0,
possible. Since each of the eight bits of this register is assigned the lower portion of BASIC ROM appears there. When the bit
a function in the MMU specifications, there are theoretically is set to % 1 , the address area will contain RAM from the block
256 possible different memory configurations. Actually, there specified in bits 6-7.
are only 128 functional combinations because bit 7 of the reg-
ister in not implemented in the current version of the MMU. Bits 2-3: These bits determine what is seen at addresses in the
However, not all of these possible configurations are equally range 32768-49151/$8000-$BFFF. The four possible selections
useful. For example, none of the configurations which involve are as follows:
either internal or external function ROM are useful unless you Bits
have a function ROM installed. The only configuration regu- 3 2 Address range contents
larly employed by the system that doesn't correspond to a 0 0 Upper portion of BASIC ROM ($8000-$AFFF), plus monitor
standard bank is one used by BASIC, consisting of BASIC ROM ($BOOO-$BFFF)
ROM, screen editor ROM, character ROM, and Kernal ROM, 0 1 Internal function ROM
plus block 1 RAM (essentially the same as bank 14, but with 1 0 External function ROM
1 1 RAM
RAM from block 1 instead of block 0). Machine language pro-
grammers may find it useful to set up a configuration which Internal function ROM refers to ROM in the free ROM socket
switches out BASIC ROM while retaining the I/O block and on the 128 circuit board. External function ROM refers to
screen editor and Kernal ROM, Such a configuration leaves 4IK ROM in a cartridge plugged into the expansion port. If you se-
free for ML programs in the range 7168-49151/$1COO-$BFFF. lect either of these sources when no ROM is actually installed,
To set up this arrangement, use LDA #$0F:STA $FFOO. the area will appear to contain unpredictable changing values.
When RAM is selected in this area, the block from which the
This location has an identical twin at address 54528/
RAM will be seen is determined by the setting of bits 6-7.
$D500. Actually, there is only one configuration register, but it
can be accessed at two different addresses. The higher address Bits 4-5: These bits determine what is seen at addresses in the
is used almost exclusively because it is visible in all memory range 49l52-65535/$C000-$FFFF, with some exceptions. The
configurations, whereas the register is visible at 54528/$D500 MMU configuration and load configuration registers always
only when the I/O block is selected (and you must have ac- appear at 65280-65284/$FF00-$FF04, regardless of the
424 425
65280 $FF00 $FF04 65284

settings of these bits. Also, bit 0 of this register can override MMU. Bit 7 will retain whatever value you write to it, but
the specification for the contents of addresses in the range only bit 6 is significant.
53248-57343/$D000-$DFFF. As long as bit 0 is set to %0, the The block specification in these bits will be overridden for
I/O block will be seen in that portion of this area, regardless certain ranges of memory if any common RAM areas are spec-
of the setting of these bits. The four possible selections for this
area are as follows: ified by the RAM configuration register at 54534/$D506.
When common areas are enabled, any visible RAM in the
Bits common range will be seen from block 0, regardless of the set-
5 4 Address area contents ting of these bits.
0 0 Screen editor ROM ($COOO-$CFFF), character ROM
These bits specify the RAM block for the processor only;
($D00O-$DFFF), Kemal ROM ($EOOO-$FFFF) the block in which the VIC (40-column) chip's video RAM
Internal function ROM
External function ROM bank is seen can be selected independently. The VIC block is
RAM specified in bits 6-7 of the MMU's RAM configuration register
at 54534/$D506. The RAM configuration register bits, rather
Internal function ROM refers to ROM in the free ROM socket than the configuration register bits, also determine which
on the 128 circuit board. External function ROM refers to block will be affected by other DMA (direct memory access)
ROM in a cartridge plugged into the expansion port. If internal operations, such as data transfers by the REC (RAM expansion
or external function ROM is selected when no ROM is actually controller) chip in the RAM expansion modules.
present, the area will appear to contain unpredictable chang-
ing values. When RAM is selected, the area will contain RAM 65281 SFF01 LCRA
from the block specified in bits 6-7, unless the MMU's RAM 65282 $FF02 LCRB
configuration register at 54534/$D506 specifies a common 65283 $FF03 LCRC
area at the top of memory. When a common area is enabled, 65284 $FF04 LCRD
all RAM in the common area will come from block 0, regard- Load configuration registers
less of the block specified in bits 6-7.
Each of these registers has a corresponding preconfiguration
Bits 6-7: The memory configuration established by the 128 al- register at 54529-54532/$D501-$D504. Storing a value in a
ways includes RAM in the lowest 16K area (addresses load configuration register causes the value in the precon-
2-16383/$0002-$3FFF), and RAM may be selected in any of figuration register to be transferred to the configuration regis-
the other three 16K segments in the processor's 64K address ter. The value stored in the load configuration register is
space. These bits determine which 64K RAM block the RAM irrelevant; it is the store operation, rather than the value
in the selected configuration will be seen from. The formal stored, which causes the transfer. Reading any of the load
specifications for these bits are as follows: configuration register locations returns the value in the cor-
Bits responding preconfiguration register. Values stored in a load
7 6 RAM block selected configuration register location have no effect on the value re-
0 0 Block 0 turned when the register is read.
0 1 Block 1 The 128 operating system does not use the preconfigur-
1 0 Block 2 ation or load configuration registers, but BASIC does. See the
1 1 Block 3 entry above for the preconfiguration registers for details of the
Remember, however, that the 128 actually has only two 64K standard configuration settings.
blocks of RAM (blocks 0 and 1). Thus, the setting of bit 7 is
meaningless and has no effect in the current version of the

426 427
54784-54785 $D600-$D601 6D600-$D601 54784-54785

VDC (Video Display Controller) Chip Although the VDC does have a graphic mode (see the en-
Registers try for bit 7 of register 25/$19), it is primarily used for text
54784-54785/$D600-$D601 displays. In this mode, it uses the same basic elements as the
The VDC (video display controller), officially designated the VIC: screen memory, character memory, and attribute memory
8563, is a custom chip designed by Commodore's engineers (which corresponds to the VIC's color memory). However, all
especially to provide the 80-column display for the 128. The these elements for the VDC appear in a 16K block of memory
VDC provides a digital RGBI signal requiring a special moni- that is totally separate from the 128's system address space.
tor, but other than that the fundamentals of its video display This separate block is reserved solely for the VDC. Figure 8-16
are similar to those described for the VIC chip. The other illustrates the configuration of VDC memory.
thing that distinguishes the VDC from the VIC is the VDC's VDC screen memory holds screen code values identical to
high degree of programmability. Many of the features that are the screen codes for the VIC display. For each screen position,
fixed in the silicon of the VIC can be customized on the VDC the screen code serves as an index into character memory to
simply by storing a value in one of its registers. For example, select the pattern to be displayed in the position. All character
the VDC gives you complete control over the number of rows patterns are in RAM. The VDC has no character ROM of its
and columns in the screen display, and even over the number own, so the contents of the VIC's character ROM is copied
of pixels and scan lines in each character position. into VDC RAM during system initialization. Redefining char-
acters for the VDC is as simple as storing the new pattern in
Figure 8-16. VDC Memory Configuration the proper area of character memory. Each character definition
is 16 bytes long, but because the default character height is
S3FFF-
eight scan lines, only the first eight bytes are used to hold
character pattern information. The remaining eight bytes are
Lowerra se/uppercase generally padded with zeros. To determine the starting ad-
character set dress for the definition for any character, use the appropriate
formula from the following:
$3000-
for uppercase/graphics character set:
address = (screen code * 16) + 8192
Uppercase/graph ic
character set for lowercase/uppercase character set:
address = (screen code * 16) + 12288
$2000- The remaining memory area is attribute memory, which
determines the display characteristics for the character speci-
fied in screen memory. It is called attribute memory to distin-
Unused
guish it from simple color memory because each attribute
memory location specifies more than just the color. Figure 8-
$1000- 17 shows the use of each bit of attribute memory.
Attribute memory The lower four bits specify the foreground color for the
$0800- character in the corresponding screen position. Unlike the
VIC's color numbers, there is a strictly logical relationship be-
Screen memory tween the value in these bits and the resulting color. The RGBI
$0000- .
in Figure 8-17 stands for red, green, blue, and intensity. For ex-
ample, a value of %1000 in these bits selects only red, while

428
429
54784-54785 $D600-$D601 SD600 54784

Figure 8-17. VDC Character Attributes .^hich reverses the foreground and background pixels of the
character pattern. However, this attribute isn't used by the 128,
which instead has reversed character patterns as part of the stan-
R G B I dard character sets. Finally, bit 7 selects which of the two charac-
ter sets will be used. The VIC allows only one of the two
character sets to be used at any one time, but the VDC allows
color (see Table 8-5) ju to select the character set independently for each character
position.
character set
(0 «• uppercase/graphics) The register structure of the VDC chip is rather unusual. It
(1 = lowercase/uppercase) has only two registers visible in the normal system address
flash (0 = off, J = on) space. You must go through these registers to access any of the
internal functions of the VDC. Table 8-6 lists the VDC communi-
reverse cations registers visible to the processor. A detailed description of
(0 •" normal) underline (0 — off, 1 — on)
(1 = reverse) both locations follows.

%1011 selects red plus blue plus intensity, resulting in light Table 8-6. VDC External Communications Registers
purple. Table 8-5 shows the standard VDC color values. Note
that these values are different from the BASIC color numbers. 54784/$D600 VDC address/status register
54785/$D601 VDC data register
Table 8-5. Standard VDC Color Values
Value VDC color 54784 $D600 VDCADR
0/$00 black Address/status register
l/$01 dark gray (light black) The VDC actually has two different registers at this location: a
2/$02 dark blue write-only address register and a read-only status register. Any
3/$03 light blue value you store in this location goes to the address register.
4/$04 dark green The value specifies which one of the 37 internal VDC registers
5/$05 light green can be accessed via the data register at 54785/$D601. Since
6/$06 dark cyan only six bits are needed to specify all the valid register num-
7/$07 light cyan bers (0-36), bits 6 and 7 of the address register are unused
8/$08 dark red and have no effect when you are writing to this register.
9/$09 light red
10/$0A dark purple You can't read this location to determine which internal
ll/$0B light purple register is being accessed; reading always returns the status
12/$0C dark yellow register contents. The status register bits are defined as
13/$0D light yellow follows:
14/$0E light gray (dark white) Bits 0-2: These locations hold a constant number (like a ROM
15/$0F white location) indicating the version number of the VDC chip cur-
rently installed. There have been two versions of the VDC to
Bit 4 selects the flash attribute, causing the character in date. In early 128s, the value here will be %000 = 0, while in
the corresponding character position to blink at the rate speci- later models the value will be %001 = 1, The exact difference
fied in bit 5 of internal register 24/$18. Bit 5 selects the under- between the versions is not clear, but they do require slightly
line attribute, but the line can be moved to any scan line of different initialization. Specifically, internal register 25, the
the character position. Bit 6 controls the reverse attribute,
430 431
54784 $D600 &D601 54785

horizontal smooth scrolling register, requires different settings cation, a n d will return to %1 w h e n the specified register is
for the different versions. The IOINIT routine [$E109] checks ready for access. The s t a n d a r d procedure for reading from or
these VDC status register bits and performs the initialization writing to a VDC register is as follows;
accordingly. Reading: Writing:
LDX #register number LDX #register number
Bits 3-4: These bits are unused, and always return %0 when 5TX $D600
STX $D600
read. WAIT LDX $D600 WAIT LDX $D600
Bit 5: This bit, called the VBLANK flag, is used to indicate BPL WAIT BPL WAIT
when the VDC raster scan is in its vertical blank period. After LDA $D601 STA $D601
a full screen has been drawn and the electron beam has reached Refer to the entry below for information concerning the
the lower right corner of the display, the beam must be turned restrictions on accessing this location from BASIC.
off briefly while it is moved back to its home position in the
upper left corner to begin the next frame. Otherwise, moving 54785 SD601 VDCDAT
the beam would result in a diagonal line across the screen. Data register
The time while the beam is turned off for this repositioning is This register is the gateway to the internal registers of the
called the vertical blanking interval. This bit, normally %0, VDC. After you have set the desired internal register number
will be set to %1 during the vertical blanking period. by writing to the address register at 54784/$D600, the speci-
When you're programming special screen effects, it's fied register becomes visible at this location. Reading from this
handy to know when the blanking period is occurring. The location shows the internal register contents, and writing to
time when one frame has been completely drawn but another this location stores the value in the internal register. Once you
one has not yet been started is a good time to change screen specify an internal register, that register remains visible here
parameters without causing excessive flicker. The VIC chip can until you change registers by storing a new value in 54784/
generate a raster interrupt to signal when its vertical blanking $D600. Refer to the internal register descriptions below for
interval is beginning, but the VDC chip can't generate inter- more information on the effects of reading from and writing to
rupt requests, so this bit provides an alternate method of sig- the various registers.
naling that vertical blanking is in progress. Commodore's specifications for this chip state that when
Bit 6: This bit, known as the LP flag, is used to indicate when accessing the VDC, you should avoid machine language in-
new values have been latched in the internal light pen regis- structions that use the indirect addressing mode. That is, you
ters. Whenever a pulse is detected on the VDC chip's LP input should avoid using instructions like LDA ($CC),Y to read this
line, the row and column positions of the raster beam at that register because the VDC apparently responds improperly to
time are latched into internal registers 16—17/$10-$ll and such instructions. This imposes no particular hardship on ma-
this bit is set to % 1 . This bit will remain %1 until one or both chine language programmers, but has highly unfortunate con-
of the internal light pen registers are read, at which time it sequences for BASIC programmers. The 128's PEEK, POKE,
will be reset to %0. Thus, a %1 in this bit is a signal that a and WAIT instructions are implemented using the Kernal
new light pen position can be read from the internal registers, INDFET, INDSTA, and INDCMP routines, all of which use in-
while a %0 indicates that the register values have not changed direct-Y addressing to read or store values. As a result, you
since they were last read. See the entry for internal registers should not use PEEK, POKE, or WAIT statements to read or
16-17/$10-$ll for details of light pen reading. change the contents of this location or of location 54784/$D600.

Bit 7: This bit, known as the STATUS flag, is used to indicate This would seem to make the VDC inaccessible from
that the VDC is ready to read from or write to the internal BASIC. Fortunately, a pair of screen editor ROM routines pro-
vide a simple detour around this roadblock. In Chapter 7 they
'I register specified by writing to the external address register. are designated WRITEREG [$CDCC] and READREG [SCDDA],
The flag bit will be set to %0 when a value is stored in this Io-
432 433
54786-55039 $D602-$D6FF $D600-$D601 54784-54785

and they have the form shown above in the discussion of lo- VDC Internal Registers
cation 54784/$D600. To store a value in any VDC register Table 8-7 lists the various internal VDC registers which can be
from BASIC, use: accessed via the external communications register. A detailed
SYS DECCCDCC"), value, register description of each follows.
or
SYS 52684, value, register Table 8-7. VDC Internal Registers
where register is the number (0-36) of the internal VDC regis- 0/$00 Total number of horizontal character positions
ter you wish to access, and value is the value (0-255) you l/$01 Number of visible horizontal character positions
wish to place in that register. If you have used any other 2/$02 Horizontal sync position
BANK statements in your program, it would be wise to add a 3/$03 Horizontal and vertical sync width
BANK 15 statement before these SYS statements to insure the 4/$04 Total number of screen rows
proper memory configuration. 5/$05 Vertical fine adjustment
To read the contents of an internal VDC register from 6/$06 Number of visible screen rows
BASIC, use a statement of the form: 7/$07 Vertical sync position
8/$08 Interlace mode control register
SYS DECC'CDDA"),, register : RREG A 9/$09 Number of scan lines per character
or 10/$OA Cursor mode control
SYS 52698,, register : RREG A ll/$0B Ending scan line foT cursor
12/$0C Screen memory starting address (high byte)
Be sure you have two commas between the SYS address and 13/$0D Screen memory starting address (low byte)
the register number. After this statement has been executed, 14/$0E Cursor position address (high byte)
the variable A will contain the value read from the specified 15/$0F Cursor position address (low byte)
register. Again, if you change bank configurations elsewhere 16/$10 Light pen vertical position
in your program, it would be wise to add a BANK 15 before 17/$11 Light pen horizontal position
the SYS statement. 18/$12 Current memory address (high byte)
19/$13 Current memory address (low byte)
20/$14 Attribute memory starting address (high byte)
54786-55039 $D602-SD6FF 21/$15 Attribute memory starting address {low byte)
VDC chip register images 22/$ 16 Character horizontal size control register
Due to incomplete address decoding, images of the VDC chip 23/$17 Character vertical size control register
registers appear repeatedly through the remainder of this page 24/$18 Vertical smooth scrolling and control register
of memory. That is, storing a value in any even-numbered lo- 25/$19 Horizontal smooth scrolling and control register
cation in this range has the same effect as storing a value in 26/$lA Fore ground/background color register
54784/$D600, and storing a value in any location in this 27/$lB Address increment per row
range having an odd address has the same effect as storing a 28/$lC Character set address and memory type register
value in 54785/$D601. It might be easier to remember the ad- 29/$lD Underline scan-line-position register
30/$lE Number of bytes for block write or copy
dress of one of the image locations, such as 55000 in place of 31/$1F Memory read/write register
54784. Nevertheless, it's better programming practice to use 32/$20 Block copy source address (high byte)
the officially designated register addresses. 33/$21 Block copy source address (low byte)
34/$22 Beginning position for horizontal blanking
35/$23 Ending position for horizontal blanking
36/$24 Number of memory refresh cycles per scan line

434 435
54784-54785 SD600-SD601 AP600-$D601 54784-54785

0 $00 support a display wider than 80 columns, so you'll have to


Total number of horizontal character positions write your own text handling routines if you want to use a
The value in this register determines the total width (in char- wider display.
acter positions) of each horizontal line of the display. The
value stored here should be one less than the desired number 2 $02
of horizontal character positions. This total includes the active Horizontal sync position
portion of the display (where characters can be displayed), the The value in this register determines the character position at
left and right borders, and the horizontal sync width. The total which the vertical sync pulse begins. The value here also de-
number of horizontal pixels is given by multiplying the value termines the horizontal position of the active portion of the
here (plus 1) by the total number of pixels per character posi- screen within the total display. The default value here is
tion (the value in bits 4-7 of register 22/$16 plus 1). 102/$66. Increasing this value moves the active screen area to
The default value for this register, established during the the left; decreasing it moves the active area to the right.
IO1NIT routine [$E109], is 126/$7E, This provides 127 hori-
zontal character positions. You'll need to reduce this by half if 3 $03
you enable the pixel double feature (see the entry for bit 4 of Horizontal and vertical sync width
register 25/$19). You may need to increase the value here Bits 0-3: These bits specify the width of the horizontal sync
slightly if you use one of the interlaced modes. pulse. The value here should be one greater than the desired
number of character positions for the pulse. The default value
1 $01 for these bits is 9/$9, for a pulse eight character positions wide.
Number of active horizontal character positions Bits 4-7: These bits specify the width of the vertical sync
The value in this register determines how many of the hori- pulse. The bit value here should be equal to the desired num-
zontal character positions specified in register 0/$00 can actu- ber of scan lines for the pulse, unless the interlaced sync and
ally be used to display characters. The value stored here video mode is being used (in that case, use a value that is
should be the desired number of columns for the display. The twice the desired number of scan lines). The default value for
value here must be less than the value in register 0/$00. The these bits is 4/$4, for a pulse four scan lines wide.
default value for this register is 80/$50, since the default VDC
display is an 80-column text screen. The value here also deter- 4 $04
mines the width of the bitmap when the VDC is set for graphic Total number of screen rows
mode. The bitmap width is given by multiplying the number This register specifies the total height (in character positions)
of character positions by the character-position width specified of the VDC display. The value stored here should be one less
in bits 0-3 of register 22/$16. than the desired number of vertical character positions. The
The screen editor routines that support printing to the 80- total includes the rows for the active display, the top and bot-
column screen assume that each screen line occupies 80 screen tom portions of the border, and the vertical sync width. To de-
memory locations. If you want the screen printing routines to termine the height of the raster in scan lines, multiply the
continue to function properly after you reduce the number of value in this register (plus 1) by the number of scan lines per
active character positions in this register, you should increase character position (the value in register 9/S09 plus 1) and add
the value in register 27/$lB so that the sum of the value in any additional scan lines specified in register 5/$05.
that register plus the value in this register remains equal to 80. The proper number of scan lines for the display is a func-
Reducing the value here removes characters from the right of tion of the video system being used; it's different for NTSC
the display area. To center the active display area after reduc- (North American) and PAL (European) systems. During the
ing the number of character positions, you must reduce the IOINIT routine [$E109], the 128 checks the VIC chip to deter-
value in register 2/$02. The screen editor routines will not

436 437
54784-54785 $D600-$D601 6D600-$D601 54784-54785

mine which system is being used (since the VIC isn't pro- 6 $06
grammable like the VDC, there is a different version of the Number of visible screen rows
VIC for each of the two video systems). This register is then The value in this register determines how many of the vertical
initialized accordingly: to 32/$20 for NTSC systems or 39/$27 character positions specified in register 4/S04 can actually be
for PAL systems, selecting 33 or 40 rows, respectively. Since used to display characters. The value here must be less than
the default character-position height is eight scan lines, the re- the total number specified in register 4/$04. The default value
spective total heights are 33 * 8, or 264 lines, for NTSC, and established for this register by the Kernal IOINIT routine
40 * 8, or 320 scan lines, for PAL. These scan-line totals [$E109] is 25/$19, which sets up the standard 25-row display.
should remain constant, so if you increase the character height One obstacle to selecting other numbers of rows is that the
you must decrease the total number of rows, and vice versa. screen editor ROM routines will, by default, assume a 25-line
screen. When decreasing the number of rows, you can make
5 $05 the screen editor use the reduced number by storing a value
Vertical fine adjustment equal to the new number of rows minus 1 in location 237/
Bits 0-4: The total number of scan lines in the VDC's video $ED, then resetting the output window to full screen size (by
display should be 264 for an NTSC (North American) system printing two cursor-home characters, for example). The screen
or 320 for a PAL (European) system. The number of scan lines editor routines will not support a display with more than 25
used in the VDC display is given by the total number of verti- rows, so you'll have to provide your own character manipula-
cal positions (specified in register 4/S04) multiplied by the tion routines to use such a screen.
number of scan lines per character position (specified in regis-
ter 9/$09). If the result doesn't come out exactly equal to the 7 $07
required 264 or 320, the VDC can add a few extra scan lines at Vertical sync position
the end to achieve the proper result. The value in this register The value in this register determines the vertical character po-
specifies the number of extra scan lines to add. The available sition at which the vertical sync signal will be generated. This
five bits allow up to % 11111 = 3 1 / $ i F additional scan lines. register can be used to adjust the vertical location of the active
The default character height of eight scan lines is an exact display area within the screen. The default value for this regis-
multiple of both 264 and 320 (33 * 8 = 264 and 40 * 8 = ter, established by the IOINIT routine [$E109], is 29/S1D for
320). Thus, no extra scan lines are required, so this register is NTSC (North American) systems or 32/S20 for PAL (Euro-
initialized to 0/$00 by the Kernal IOINIT routine [$E109]. As pean) systems. Decreasing the value here will move the active
an example of the use of this register, assume that you in- display area down the screen, while increasing the value will
creased the character height to nine scan lines. For an NTSC move the active display area upwards. However, you should
system, 264 / 9 = 29 with a remainder of 3. Thus, for this not increase the value here above the maximum number of
case you should specify 29 for the total number of vertical rows specified in register 4/$04.
character positions and store a 3 in this register to provide the
required additional scan lines. 8 $08
Bits 5-7: These bits are unused; writing to them has no effect, Interlace mode control
and they always return %1 when read. Thus, the value you Bits 0-1: The value in these bits controls the interlace mode of
read from this register will always be at least 224/$E0. To the screen. The complete standard for NTSC video calls for a
mask off these bits and see only the valid bits of the register, frame (raster) of 525 lines to be redrawn 30 times per second,
use AND 31 in BASIC or AND #$1F in machine language. while the PAL standard calls for 625 lines redrawn 25 times
per second. The full screen isn't drawn all at once; instead, it's
drawn in two passes with half the lines for the frame drawn
on each pass. The lines for the second pass of the frame are
439
54784-54785 $D600-$D601
$D600-$D601 54784-54785

drawn between the lines for the first. Like most computer dis-
plays, the VDC normally takes a shortcut and draws half the screen will not support a display longer than 25 lines, so
full number of lines at twice the rate. This noninterlaced dis- you'll have to write your own text manipulation routines to
play provides sufficiently sharp output for most uses. How- handle the extra 25. Nevertheless, this mode has interesting
ever, the VDC is also capable of producing two interlaced possibilities.
display modes. The modes are selected as follows: Bits 2-7: These bits are unused; writing to them has no effect,
Bits and they always return %1 when read. Thus, the value you
I 0 Value Interlace mode read from this register will always be at least 252/$FC. To
x 0 0 or 2 noninterlaced mask off these bits and see only the valid bits of the register,
0 1 1 interlaced sync use AND 3 in BASIC or AND #$03 in machine language,
II 3 interlaced sync and video
The default value is 0/$00, which selects the standard 9 $09
noninterlaced mode. The system never uses any other mode. Total number of scan lines per character
In the interlaced sync mode, the number of scan lines is dou- Bits 0-4: These bits determine the total vertical height (in scan
bled. Each horizontal scan line is drawn twice, once on the lines) of each character position. The value stored here should
first pass and very slightly lower on the second pass. The re- be one less than the desired number of scan lines. The total
sult should be greatly improved vertical resolution, but you'll vertical height value includes the scan lines for the active por-
probably be disappointed. Remember that each tiny dot on the tion of each character position, plus any desired number of
screen glows only very briefly after being struck by the raster blank scan lines for intercharacter vertical spacing. The height
video beam. Since this mode must draw twice as many lines, of the active portion of the character position is determined by
it draws each line only half as often. On most video monitors, the value in register 23/$17.
the first set of lines will have started to fade before the second The default value for this register, established during the
set is completely drawn. As a result, the screen will appear to IOINIT routine [SE109], is 7/$07, for a total character-position
jitter annoyingly in this mode. height of eight scan lines. In this case, there will be no vertical
The remaining choice is interlaced sync and video mode. intercharacter spacing because this is less than the active char-
In this case, the VDC also draws twice as many lines as non- acter height. (In the default character set, intercharacter spacing
interlaced mode, but the alternating half-frames are indepen- is achieved by leaving the bottom row of the character pattern
dent, so you can use twice as many horizontal lines per frame blank.) The five available bits allow values up to %11111 =
(the maximum screen height in scan lines is double that of the 31/$IF, for character-position heights of up to 32 scan lines.
noninterlaced mode). This creates the tantalizing prospect of However, when changing this value to allow for greater verti-
an 80-column X 50-line text screen. The following routine cal resolution, you must keep in mind that the value here mul-
sets up such a display: tiplied by the total number of rows specified in register 4/$04
(and plus the number of extra scan lines specified in register
10 WR=DEC("CDCC") 5/$05) determines the number of scan lines in the display.
20 SYS W R , 3 , 8 This total should always be 264 lines for NTSC (North Ameri-
30 SYS WR,64,4 can) systems or 320 lines for PAL (European) systems.
40 SYS W R , 5 0 , 6 The value here also determines how much memory is re-
50 SYS WR,58,7 quired for character pattern memory. While the value here is
60 SYS W R , 1 2 8 , 0
less than or equal to 15 (while the character height is 16 or
fewer scan lines), each character pattern is allocated 16 bytes.
However, this setup does have limitations. It suffers from the
Since the VDC supports two complete 256-character sets, a to-
same jitter problems as the other interlaced mode. Further-
tal of 512 * 16, or 8192 bytes, are required for character mem-
more, the screen editor routines that control printing to the
ory' However, if the character height exceeds 16 scan lines (if
440
441
54784-54785 $D600-$D601 $D600-$D601 54784-54785

the value here is greater than 15), then 32 bytes are allocated
for each character pattern. In this case, 512 * 32, or 16,384 Bit values Cursor mode
bytes, are required for character memory. Note that this is all 0/$00 solid {nonblinking) cursor
the memory available to the VDC. 32/S20 no cursor
Bits 5-7: These bits are unused; writing to them has no effect, 64/$40 blinking at 1/16 screen refresh rate
and they always return %1 when read. Thus, the value you 96/$60 blinking at 1/32 screen refresh rate
read from this register will always be at least 224/$E0. To
mask off these bits and see only the valid bits of the register, The default setting for these bits is %11, specifying a cursor
use AND 31 in BASIC or AND #$1F in machine language. blinking at the slower of the two rates. The operating system
also supports a nonblinking cursor, selected by printing ESC E
10 $0A [$CB0B]. In this case, the bits are changed to %00. To rum the
Cursor mode control cursor off when the system is not accepting input (as when a
program is running), these bits are reset to %01 [$CD9F].
The value in this register cannot be changed directly while the
standard screen editor ROM routines are used for printing. Bit 7: This bit is unused; writing to it has no effect, and it al-
The contents of a shadow location at 2603/$OA2B are copied ways returns %1 when read. Thus, the value you read from
to this register each time the cursor position is updated. Thus, this register will always be at least 128/$80. To mask off this
to change the value in this register, you must store the desired bit and see only the valid bits of the register, use AND 127 in
value in the shadow location rather than in the register. BASIC or AND #$7F in machine language,
Bits 0-4: The value in these bits determines the scan line
within each character position for the top of the cursor. Scan 11 $0B
lines within character positions are numbered beginning with Bottom scan line for cursor
0 for the top line of the position. Bits 0-4 of register ll/$0B Bits 0-4: These bits determine the scan line within a character
determine the bottom line, and together these registers deter- position for the bottom of the cursor. Together with bits 0-4
mine the height of the cursor. The available five bits allow of register 10/$0A, this serves to determine the height of the
starting row numbers as large as %11111 = 31/$1F. The de- cursor. The value here should be one greater than the desired
fault value for these bits is %00000, to start the cursor at char- bottom scan line (scan-line numbering starts with 0 for the top
acter scan line 0, the top line of the character, for the standard scan line of the character position). The five available bits
full-height block cursor. The operating system also supports allow values up to % 11111 = 31/$1F, so the cursor can go as
an underline cursor, selected by printing ESC U [$CAFE], In low as scan line 30, However, the actual displayed cursor
this case, the value here is changed to %00111 (7) to start the height will never be greater than the character-position height
cursor on the bottom line of the standard character position. specified in register 9/$09. The default value for this register,
The value for the top scan line should be no greater than the established by the IOINIT routine [$E109], is 7/$07, so the
maximum number of scan lines specified in register 9/$09, or normal bottom scan line of the cursor is scan line 6 of the
else the cursor will not be visible. character position.
Bits 5-7: These bits are unused; writing to them has no effect,
Bits 5-6: These bits control the type of cursor provided. Unlike and they always return %1 when read. Thus, the value you
the VIC, where the cursor is an effect maintained by software,
the VDC has hardware to generate a cursor automatically. The read from this register will always be at least 224/$E0, To
possible modes are as follows: mask off these bits and see only the valid bits of the register,
use AND 31 in BASIC or AND #$1F in machine language.

442
443
54784-54785 $D600-$D601 _ _ _

12 $0C The value in these registers cannot be changed directly


13 $0D while the normal screen editor 80-column printing routines are
Starting address for screen memory in use. The printing routines update the cursor position after
For standard text mode, the value in this register pair deter- each character is printed so that these registers always hold
mines the starting address for screen memory, the area which the address of the next available character position.
holds screen codes specifying which character will be displayed
in each screen position. The size of the screen memory area is 16 $10
determined by the number of active horizontal positions (spec- 17 Sll
ified in register l/$01) multiplied by the number of active rows Light pen vertical and horizontal positions
(specified in register 6/$06) and the address increment per Whenever the LP input line to the VDC chip is brought to a
row (specified in register 27/$lB). The order of bytes for the low (0 volts) state, the row and column values for the current
pair is opposite that normally used in the 128 system: The first position of the raster beam are latched into these registers. The
register (12/$0C) holds the high byte and the second (13/$0D) vertical (row) number will be latched into register 16/$10, and
holds the low byte. Unlike VIC screen memory, which must the horizontal (column) number will be latched into register
begin on an even IK address boundary, VDC screen memory 17/$11. To signal that a value has been latched, the LP flag
can begin at any address in the VDC's address space. See Fig- (bit 6 of the external register at 54784/SD600) will be set to
ure 8-16 for a diagram of the VDC's memory configuration. % 1 . That bit will remain at %1 until either of these registers is
For graphic mode, the value in this register pair deter- read, at which time it will be reset to %0. However, reading
mines the starting address for the bitmap of the graphic these registers does not clear them; the latched values will be
screen. The amount of memory required for the bitmap is retained until the LP line is brought low again.
found by multiplying the number of horizontal character posi- The VDC's LP line is connected to pin 6 of control port 1
tions (from register l/$01) by the number of vertical character (control port 2 does not support a light pen). A light pen has
positions (in register 6/$06) times the total height of each at its tip an electronic device known as a phototransistor,
character position (from register 9/$09 plus 1). The bitmap which is connected so as to cause a low pulse whenever the
can be started at any address in the VDC address space. video beam moves past the pen. Note that the pen will not be
Even if you change the value here, the screen editor ROM triggered if the screen position is black or one of the other
routines will continue to assume that screen memory is located dark colors. Only positions which have bright characters can
in its default position unless you also change the value in the be read. The ideal character to read with a light pen is a white
screen memory starting-page pointer at 2606/$0A2E. re verse-video space.
When a light pen is used, the range of values in these
14 $0E registers depends on the screen width and height selected by
15 SOF other VDC registers. Unlike the VIC chip, whose light pen
Address of current cursor position registers return scan line and dot position values, these regis-
For the VIC chip's display, the cursor is an effect laboriously ters return row and column numbers corresponding to the
maintained by software. The VDC, by contrast, has hardware light pen position. This makes the results much easier to inter-
to maintain the cursor for its display automatically. The cursor pret, but does not allow precise positioning, so it is unlikely
will appear at the character position with the screen memory that you'll see any 80-column drawing programs using the
location specified in this register pair. If the address specified light pen as an input device. For the standard 80-column X
here is outside the area of VDC memory currently being used 25-line screen, the value in register 16/$ 10 corresponds very
for screen memory, no cursor will be visible. Other characteris- closely to the row number: ranging from l/$01 at the top of
tics of the cursor such as its blinking status and position within the screen to 25/$19 at the bottom. Actually, you may find
the character are specified in registers 10/$OA and 11/$OB.

444 445
54784-54785 $D600-$D601 $D600-$D601 54784-54785

that if you position the pen slightly below the bottom screen
line you can get a reading of 26/S1A. 18 §J2
While the vertical resolution is good, the horizontal reso- 19 $13
lution is quite poor. The horizontal reading won't correspond Current memory address
to the row number (1-80). Instead, it corresponds approxi- This register pair specifies which address in the VDC's private
mately to the absolute horizontal character position, which in- block of RAM will be referenced by the next read or store op-
cludes the border areas on the left and right edges of the eration involving register 31/S1F. As with the other VDC ad-
screen. You should find that when the pen is pointed at the dress register pairs, the first register (18/$12) holds the high
leftmost character position, you get a reading of about 27-29 byte of the address and the second (19/$13) holds the low
in register 17/$11. This implies that the rightmost character byte. A value stored in register 31/$1F is transferred to the
position should give readings of about 106-108. Actually, you VDC memory location specified in this register pair. Reading
may get higher readings—120 or more. In fact, even if you register 31/$1F returns the value in the location in VDC mem-
hold the pen perfectly stil] you may see the character position ory with the address specified in this register pair. For copy or
vary up or down by 4 or 5. The moral is that the light pen is fill operations, the value in these registers determines the des-
much better at reading vertical than horizontal positions. tination address for the operation. These registers are auto-
You'll have better luck if you limit yourself to checking incrementing, meaning that the address value here is auto-
whether the pen is within a range of horizontal positions. For matically increased by 1 after each read or store to register
example, if you read the horizontal position and store the re- 31/S1F. Thus, when you wish to read or load a continuous se-
sult in the variable H, then an expression such as H = INT({H ries of VDC memory locations you only need to set the mem-
— 30) / 8) will return a range of values 0-9 indicating ory address in these registers before the first read or store.
roughly which one of ten eight-column horizontal areas the After that, you can just read from or write to register 31/$1F
pen is pointing to. and the address will be handled automatically.
You should be aware that these registers can be tricked 20 $14
into reading false values. Pin 6 of control port 1 is also used 21 $15
for light pen input for the VIC chip, and a light pen signal Starting address for attribute memory
generated on the 40-column screen will latch meaningless val-
When attributes are activated, this register pair determines the
ues in these registers. In lieu of a light pen, several other
starting address for attribute memory, the area which holds
events can cause a pulse on the LP line. That control port pin
attribute values for each active character position on the
is also used for the joystick fire button, so pressing the button
screen. (Attributes can be turned on and off by setting bit 6 of
of a joystick plugged into port 1 will also latch values in these
register 25/$19.) The size of the attribute memory area de-
registers. Because of this joystick button function, the port line
pends on the number of active rows and columns specified in
is also connected to the line from row 4 of the keyboard matrix.
registers 2/$02 and 6/$06, and will be the same as the size of
This has two consequences. First, pressing any of the follow-
the screen memory area. See the discussion of attributes in the
ing keys with no light pen connected will latch meaningless
introduction to this section for more information.
values: Fl, Z, C, B, M, period, right SHIFT, space, the 2 and
These locations are initialized to 2048/S0800, the default
ENTER keys on the numeric keypad, and the ^ key in the
starting address for attribute memory. Like the other address
cursor group. More significantly, while a light pen is con-
pairs in the VDC, the first register (20/$14) holds the high
nected, all of these keys will be "dead," and cannot be typed.
byte and the second (21/$15) holds the low byte. Attribute
memory can start at any address within the VDC's address
space. Even if you change the value here, the screen editor
ROM routines will continue to assume that attribute memory

446 447
_
54784-54785 $D600-$D601 SP600-$D601 54784-54785

is in its default position unless you also change the value in available five bits allow you to specify values up to % 11111
the attribute starting-page pointer at 2607/$0A2F. = 31/$1F. If the value here is less than the total number of
scan lines for the character position, the extra lines will be
22 $16 blank for intercharacter spacing. If the value here is greater
Character horizontal size control than the total number of scan lines, only the total number of
Bits 0-3: The value in these bits determines how many of the scan lines will be displayed. For graphic mode, the value here
total horizontal pixels in the character position will be used to should be at least equal to the total number of scan lines (the
display character pattern data. (The total number is specified value in register 9/$09 plus 1); otherwise there will be gaps in
in bits 4-7 of this register.) If the number of active pixels is the display.
less than the total number of pixels, the extra pixels will be The default value stored in this register is 8/$08, for eight
blank for intercharacter spacing. If you specify a value here active scan lines per character position. This is equal to the de-
that is greater than the total number of pixels available for the fault total number of scan lines for the position, so there will
position, only the specified total number of pixels will be visi- be no intercharacter spacing. (For the standard character set,
ble. However, the value here should not exceed 8, since a intercharacter spacing is achieved by leaving the bottom row
maximum of eight bits are available per byte of character pat- of most character definition patterns blank.)
tern data. Even for values greater than 8, no more than eight Bits 5-7: These bits are unused; writing to them has no effect,
pixels will be active per horizontal scan line within the charac- and they always return %1 when read. Thus, the value you
ter position. For graphic mode, the value here should be equal read from this register will always be at least 224/$E0. To
to the total number of pixels; otherwise there will be gaps in mask off these bits and see only the valid bits of the register,
the display. use AND 31 in BASIC or AND #$1F in machine language.
The default value for these bits is 8, for eight active hori-
zontal pixels per character-position scan line. This is the same 24 $18
as the total number of pixels per position, so there will be no Vertical smooth scrolling and control
intercharacter spacing. (For the default character set, the Bits 0-4; These bits can be used to smoothly scroll the screen
rightmost column of each character pattern is left blank to pro- vertically upward. The value here specifies the number of scan
vide the effect of intercharacter spacing,) lines the display should be shifted upward. Although five bits
Bits 4-7: The value in these bits determines the width of each are available, the value here should not exceed the value in
character position (in pixels). The value stored here should be register 9/$09.
one less than the desired total number of pixels. If the total is Bit 5: This bit controls the blinking rate for all characters on
greater than the number of active pixels specified in bits 0-3 the screen with the flash attribute. A character position has the
of this register, the extra pixels will be blank for intercharacter flash attribute when bit 4 of its corresponding attribute mem-
spacing. The default value for these bits is 7, for eight total ory is set to % 1 . The two available blinking rates are once
pixels per character position. The total number of horizontal each 16 times the screen is refreshed (selected when this bit is
pixels is determined by multiplying the value here (plus 1) by set to %0) or once each 32 times (selected when this bit is set
the total number of character positions (from register 0/$00). to %l). For NTSC (North American) systems, the screen is re-
drawn 60 times per second, so the corresponding blinking
23 $17 rates are about four times per second when the bit is %0 and
Character vertical size control about twice per second when the bit is % 1 .
Bits 0-4: The value in these bits determines how many of the The default setting for this bit is % 1 , for the slower blink-
total scan lines for each character position (specified in register ing rate. This is established during the IOINIT routine [$E109],
9/$09) will be used to display character pattern data. The

448 449
54784-54785 $D600-$D601 $D600-$D601 54784-54785

part of both the reset and RUN/STOP-RE STORE sequences. each pixel is twice as large, there will be room for only half as
This setting is not changed by any other ROM routine. many on the screen. Thus, you must reduce the values in the
Bit 6: This bit controls a special VDC feature known as reverse horizontal screen width registers (0-2/$00-$02) to half their
mode. While this bit is %0, all pixels on the screen repre- normal values. The following routine sets up a VDC 40-column
sented by %0 bits in character patterns or the graphic screen display that will be very similar to the VTC's 40-column display:
bitmap take the background color specified in bits 0-3 of reg-
ister 26/$lA, and all pixels represented by %1 bits take the 10 WR=DEC("CDCC"):RR=DEC("CDDA")
foreground color specified in a corresponding attribute mem- 20 SYS WR,63,0:SYS WR,40,1:SYS WR,55,2
30 SYS RR,,25:RREG A:SYS WR,(A OR 16),25
ory location (or in bits 4-7 of register 26/$lA if attributes are 40 SYS WR,(8*16)+9,22
disabled). Setting this bit to %1 reverses the color sources, so 50 SYS WR,40,27
that all pixels for %0 bits take the foreground color and all 60 POKE 238,39
pixels for %1 bits take the background color. 70 PRINT"{2 HOMEllCLR}"
This bit is initialized to %0 for a normal screen display.
Bit 5: This bit controls a special VDC feature called
The screen editor ROM supports escape sequences to change
semigraphic mode. When semigraphic mode is activated
this bit. The ESC R sequence will set the bit to % 1 , reversing
(when this bit is %1), the rightmost active pixel will be re-
the screen display. The ESC N sequence will clear the bit to
peated through the intercharacter spacing pixels. For this
%0, returning the display to normal.
mode to have any visible effect, there must be some
Bit 7: This bit determines whether the next block operation intercharacter spacing (the value in bits 0-3 of register 22/$16
initiated by writing to register 3O/$1E will be a copy or a fill. must be less than the total number of pixels specified in bits
Setting this bit to %0 specifies a fill operation, while setting it 4-7 of that register). This mode has no effect in graphic mode.
to %1 specifies a copy operation. See the entry for register One use of this mode is to create a simple "digital" character
3O/$1E for more information on VDC block operations. This effect. Try these lines:
bit is set to %0 when the register is initialized during the SYS 52684,118,22
IOINIT routine [$E109]. SYS 52698,,25: RREG A: SYS 52684,(A OR 32),25
25 $19 Bit 6: The VDC has two methods of supplying foreground
information for its display. When this attribute enable bit is set
Horizontal smooth scrolling and control
to % 1 , each character position will have a corresponding
Bits 0-3: These bits can be used to smoothly scroll the screen attribute memory location. Refer to the introduction to this
horizontally. The use of these bits depends on the version of section for details on attributes. The starting address of attribute
the VDC in your 128. (The version number can be determined memory is determined by the value in registers 20-21/$14-
by reading bits 0-2 of the external communications register at $15, When this bit is %0, attribute memory is not used. In-
54784/$D600.) For version 1 of the VDC, which includes most stead, all character positions take the foreground color specified
128s, this register should be initialized to the maximum char- in bits 4-7 of register 26/$lA. In this case, the character posi-
acter width (in bits 4-7 of register 22/$16). Each decrement of tions cannot have the flash, underline, or reverse attributes,
this register shifts the display one pixel to the left. For the and only the first of the two character sets will be available.
older version 0 of the VDC, these bits should be initialized to
%0000. In this case, each increment of these bits shifts the dis- Bit 7: This bit determines whether the VDC will operate as a
play one pixel to the right. text or graphics display. Text mode, selected when the bit is
Bit 4: This bit controls the VDC's pixel double feature. While set to %0, is the only one supported by the 128 operating sys-
this bit is %0, pixels will be their normal size. Setting this bit tem (%0 is the default value for this bit). In that mode, each
to %1 will double the size of all horizontal screen pixels. Since screen memory position holds a screen code which serves as

450 451
54784-54785 $D600-$D601 $D600-$D601 54784-54785

an index into character memory to specify the pattern to be program 8-1. 80-Column Sketchpad
displayed in that position.
When this bit is set to % 1 , graphics mode is selected. In 100 GRAPHIC 0:FAST
that mode, screen memory is replaced with a bitmap. (There is 110 WR=DEC("CDCC"):RR=DEC("CDDA")
no cursor on the graphic display.) Each bit in the bitmap con- 120 SYS RR,,25:RREG A:SYS WR,(A AND 63)OR 128,25
trols the state of one pixel in the display. The layout of the 130 SYS RR,,24:RREG A:SYS WR,A AND 127,24
bitmap is much simpler than that for'the VIC screen. Each 140 SYS WR,0,13:SYS WR,0,19:SYS WR,0,31
150 FOR 1=0 TO 63:SYS WR,255,30:NEXT 1
horizontal scan line is controlled by a sequential series of 160 X=320:Y=100:BC=0:FC=15
bytes. The size of the bitmap (in bytes) is determined by the 170 GET KS:ON INSTR( "BF{HOME HCLR j " , KS ) GOTO 180,1
number of active horizontal positions times the number of ver- 80,160,140:GOTO 190
tical positions times the number of scan lines per vertical posi- 180 BC={BC-(K?="B"))AND 15:FC=(FC-(K$="F"))AND 15:
tion. For the standard screen setup, this means that 80 * 25 * SYS WR,FC*16+BC,26
8, or 16,000 bytes, are required—almost all of the available 190 D=JOY(2) AND 15:IF D=0 THEN 170
200 Y=Y+(D<3 OR D=8)-(D>3 AND D<7);IF Y<0 THEN Y=l
VDC memory. At eight pixels per byte, there are 128,000 indi- 99:ELSE IF Y>199 THEN Y=0
vidual pixels on the graphic display. 210 X=X-(D>1 AND D<5)+{D>5):IF X<0 THEN X=639:ELSE
The graphic display can use attribute memory for color IF X>639 THEN X=0
information. In this case, the relationship of attribute locations 220 AD=(Y*80)+INT(X/8):AH=INT(AD/256):AL=AD-(AH*25
to bitmap positions is similar to that for the VIC screen. Each 6)
attribute memory location controls the color for all pixeis 230 SYS WR, AH ,18:SYS WR,AL,19
240 SYS RR,,31:RREG A
within a character-position area on the screen. However, there 250 SYS WR,AH,18:SYS WR,AL,19
isn't enough free memory available for a full bitmap and a full 260 SYS WR,A OR 2T(7-(X AND 7)),31
attribute memory area. One solution is to turn off attributes 270 GOTO 170
(set bit 6 of register 25/$19 to %0). This limits all screen posi-
tions to the same foreground and background colors (as speci- the same foreground and background colors). The CLR/
fied in register 26/$lA). The other solution is to reduce the HOME key can be used to move the drawing point back to its
size of the active screen area to free up enough memory for an home position in the center of the screen, and SHIFT -
attribute area. For example, if you reduce the number of active CLR/HOME will clear the display.
rows to 22, then 80 * 22 * 8, or 14,080 bytes, will be required
for the bitmap, and 80 * 22, or 1760 bytes, will be required for 26 $1A
attribute memory, so there will be enough room within VDC Background and foreground colors
memory for both bitmap and attributes. Bits 0-3: The value in these bits determines the background
When attribute memory is enabled for a graphic display, color of the display. For text mode, this is the color of all
the lower four bits of each attribute memory location deter- pixels represented by %0 bits in the pattern definition for the
mine the color of all foreground (%1) pixels in the correspond- character in each screen position. For graphic mode with
ing character-position area, and the upper four bits determine attribute memory disabled, the value here determines the color
the color of all background (%0) pixels in the character °f all pixels represented by %0 bits in the bitmap. The cor-
position. respondence between register value and background color is
as shown in Table 8-5. For graphic mode with attribute mem-
Program 8-1 is a very simple example of a bitmapped ory enabled, the value here determines the color of the screen
drawing program for the VDC. Use a joystick in port 2 to border only.
sketch. Pressing the B key will change the background color
and pressing the F key will change the foreground color The default background color value, 0/$00 (black), is es-
(attribute memory is turned off, so all character positions use tablished by the Kernal IOINIT routine [$E109], part of both
the reset and RUN/STOP-RESTORE sequences. From BASIC,
452 453
54784-54785 $D600-$D601 $D600-$D601 54784-54785

the background color can be changed using the statement Bit 4: This bit specifies the type of RAM chip used for VDC
COLOR 6, color number. However, the values for the color num- video memory. When the bit is %0, the VDC is configured for
ber parameter are not the same as the color values shown in 4416 chips (16K X 4 bits). When the bit is % 1 , the VDC is
Table 8-5. Refer to the description of the COLOR statement in configured for 4164 chips (64K X 1 bit). Since the 16K VDC
the System Guide that came with your 128 for more information. video memory space in the 128 is provided by two 4416 chips,
this bit is initialized to %0 by the Kernal IO1NIT routine
Bits 4-7: When attributes are disabled (by setting bit 6 of reg- [$E109]. It is theoretically possible to replace the existing chips
ister 25/$19 to %0), the value in these bits specifies the fore- with the 64K variety to quadruple the amount of available
ground color for the display. For text mode, this is the color VDC RAM. However, the swap involves unsoldering the exist-
for all pixels represented by %1 bits in the pattern definitions ing chips from the circuit board and soldering the new ones in
for all screen positions. For graphic mode, the value here de- their place. This is not a task for the inexperienced, and will
termines the color of all pixels represented by %1 bits in the most certainly void any warranty on your 128.
bitmap. For either mode, if the screen is switched to reverse Bits 5-7: These bits determine where within VDC memory the
mode (by setting bit 6 of register 24/S18), the value here will character pattern definitions will be located. The amount of
instead determine the color for all pixels represented by %0 memory required for the character set depends on the value in
bits in the character pattern or bitmap. The correspondence register 9/$09. If the character height is 16 or fewer scan lines,
between bit values and colors is as shown in Table 8-5. each character set requires 4K (4096 bytes). Character heights
of 17-32 scan lines require 8K (8192-b'yte) character sets. The
27 $1B VDC normally supports a pair of character sets, using bit 7 of
Address increment per row of characters the attribute memory location to select between them for each
The value in this register will be added to the value in register character position. Thus, 8K is normally used for character sets
1/S01 to determine the amount by which to increase the screen when the character height is 16 or fewer scan lines, and 16K is
memory address for each new row of the display. This allows used when the character height is greater than 16 scan lines.
you to set up a virtual screen wider than the actual screen. In the latter case, bit 5 is not used in the address selection.
You can scroll back and forth across the virtual screen by ad- The possible starting addresses for character patterns are as
justing the screen starting address in registers 12-13/$0C-$0D. follows (the asterisks indicate valid selections for 16K-character
The default value for this register is 0/$00, since no extra set pairs):
columns are used with the 80-column text display. The screen Bits Character memory
editor routines that support printing to the VDC screen all as- 7 6 5 starting address
sume an 80-column screen line. If you reduce the number of 0 0 0 0/$0000 *
active columns in register l/$01, you should increase the value 0 0 1 8192/$2000
in this register correspondingly so that the total remains 80. 0 1 0 16384/$4000 *
0 1 1 24576/$6000
28 $1C 1 0 0 32768/$8000 *
Character pattern address and memory type 1 0 1 40960/SAOOO
110 39152/SC0O0 *
Bits 0-3: These bits are unused; writing to them has no effect, 1 1 1 57344/$E000
and they always return %1 when read. Thus, the value you
read from this register will always be at least 15/SOF. To mask Since the 128 has only 16K of RAM for the VDC, only the
off these bits and see only the valid bits of the register, use first two settings are currently valid. (Note that there is insuffi-
AND 240 in BASIC or AND #$F0 in machine language. cient room in the 128's 16K of VDC video memory for a 16K
character set plus screen and attribute memory.) These bits are
initialized to %001 by the IOINIT routine [$E109], part of the

454 455
6n600-$P601 54784-54785
54784-54785 $D600-$D601

reset and RUN/STOP-RESTORE sequences, so the default or a fill. The operations require different preparatory steps, as
character set starting address is 8192/$2000. Since this area is outlined below:
RAM, not ROM, it is necessary to copy character patterns into For a fill operation:
this area of memory if the VDC is to display recognizable 1. Set bit 7 of register 24/S18 to %0 to indicate a fill
characters. This step is performed during the IOINIT routine operation.
by calling the screen editor INIT80 routine [$CE0C]. 2. Load registers 18-19/$12-$13 with the starting address of
the area to be filled (the destination area).
29 $1D 3. Store the value with which the area is to be filled in register
Underline scan-line control ' 31/$1F. This will fill the first location.
Bits 0-4: The value in these bits determines which scan line 4. Store the number of bytes to be filled, minus one because of
within the character position will be filled for any characters the store performed in step 3, in register 3O/$1E. This will
with the underline attribute. (A character position has the un- initiate the block fill operation.
derline attribute when the corresponding attribute memory po- For a copy operation:
sition has bit 5 set to %1.) Since the line can appear on any 1. Set bit 7 of register 24/$18 to %0 to indicate a fill operation.
horizontal scan line of the character position, it's not strictly
2. Load registers 18-19/$12-$13 with the starting address of the
correct to call it an underline. For example, you could move
the line to the top line of the position to be an overbar, or to area to be filled (the destination area).
the middle line of the position to serve as an overstrike. Scan 3. Store the value with which the area is to be filled in register
line 0 is the top line of the character position. The available 31/$1F. This will fill the first location.
five bits allow a maximum scan-line value of %11111 = 3 1 / 4. Store the number of bytes to be filled, minus one because of
$1F. However, the underline will not be visible if the value is the store performed in step 3, in register 3O/$1E. This will ini-
greater than the maximum character-position height in bits tiate the block copy operation.
4-7 of register 22/$16.
Either operation can be performed repeatedly to copy or
Bits 5-7: These bits are unused; writing to them has no effect, fill areas larger than 255 bytes. The destination address regis-
and they always return %1 when read. Thus, the value you ters (18-19/$12-$13) and, for copy operations, the source ad-
read from this register will always be at least 224/$E0. To dress registers (32-33/$20-$21) increment automatically each
mask off these bits and see only the valid bits of the register, time a location is copied or filled, so upon completion of one
use AND 31 in BASIC or AND #$1F in machine language. copy or fill operation they will hold the address of the first
byte beyond the area affected by the copy or fill. Thus, it is
30 $1E not necessary to reload the address registers to copy or fill
Number of bytes to copy or fill more subsequent memory locations, nor is it necessary to set
The VDC has the capability to copy blocks of data up to 255 the operation flag or to load the data register after the first
characters long from one area of VDC memory to another, and block. (For multiple fill operations, the instruction above to
to fill areas up to 255 bytes long with a specified value. The subtract 1 from the desired number of bytes to fill applies only
value in this register determines the number of bytes to be for the first block.)
copied or filled. The copy or fill operation begins immediately
after the count value is stored here. The setting of bit 7 of reg- 31 $ 1 F
ister 24/$18 determines whether the operation will be a copy Memory read/write
This register is the gateway between the VDC's private block
of RAM and the rest of the 128 system. When read, this

457
456
54784-54785 $D600-$D601 fiP600-$D601 54784-54785

location reflects the contents of the VDC memory location ad- The value in register 34/$22 must be less than the value
dressed in registers IS—19/$12—$13. Writing a value to this in register 0/$00; otherwise, the entire display will be
register will cause the value to be transferred to the location blanked. The value in 34/$22 here must also be greater than
addressed in registers 18—19/$12—13. For both reading and the value in register 35/$23 to prevent an entirely blank dis-
writing, the address in registers 18-19/$12-$13 will automati- play. The default values for these locations are 125/S7D and
cally be incremented after this register is accessed. Thus, to 100/$64, respectively. This positions the blanking interval en-
read or write a sequential series of locations you need only tirely outside the active screen area. For purposes of blanking
load the starting address of the series into registers 18—19/ an area of the screen, a value of 6/$06 in these registers corre-
$12—$13. You can then read or write repeatedly to register sponds to the leftmost column of the standard screen and a
31/$1F; the destination address will automatically increment value of 85/$55 corresponds to the rightmost column.
after each read or write.

32 $20 36 $24
Number of memory refresh cycles per scan line
33 $21 Bits 0-3: The value in these bits determines the number of
Source address for block copy memory refresh cycles per scan line. The RAM chip used for
The VDC has the capability to copy blocks of data up to 255 the VDC's video memory is a type known as dynamic RAM.
bytes long from one area of memory to another (see the entry A dynamic RAM can hold data only briefly without external
for register 3O/$1E for details). The value in this register pair support. Just as the image on the video screen must be con-
determines the source address for copy operations, the address stantly redrawn to keep it from fading away, dynamic RAM
from which data will be copied. Like all other address register must be constantly refreshed to keep it from losing its con-
pairs in the VDC, the first register (32/$20) holds the high tents. The VDC handles this refresh function automatically for
byte of the address and the second (33/$21) holds the low its video RAM, just as the VIC automatically handles the re-
byte—the opposite of the normal 8502 address format. The freshing of system RAM. However, for the VDC, the number
registers should be loaded with the desired source starting ad- of refresh cycles provided during each scan line is programma-
dress before the copy operation is initiated. Upon completion ble. The IOINIT routine [SE109] initializes these bits to %0101
of the operation, the registers will hold the address of the next for five refresh cycles per scan line, and there's no reason to
location beyond the last one involved in the operation. Thus, change that setting.
it is possible to copy blocks of more than 255 successive bytes
by using repeated copy operations without reloading these Bits 4-7: These bits are unused; writing to them has no effect,
registers. and they always return %1 when read. Thus, the value you
read from this register will always be at least 240/SFO. To
34 $22 mask off these bits and see only the valid bits of the register,
35 $23 use AND 15 in BASIC or AND #$0F in machine language.
Horizontal blanking positions
37-63 $25-83F Unused
The VDC can adjust its horizontal blanking interval to blank a
portion of the screen. These locations control the horizontal Since the external address register at 54784/$D600 allows a
width and position of the blanked area. If the blanked area ex- six-bit register number, these register addresses can also be
tends onto the active portion of the screen, any text under the specified. However, none of these internal registers are used,
blanked area is only covered, not erased. The value in register and writing to them has no effect. All register numbers in this
34/$22 determines the rightmost blanked column, and the range return the value 255/$FF when read.
value in register 35/$23 determines the leftmost blanked col-
umn. The blanked area extends the entire height of the screen.
458
459
55040-55295 $D700-$D7FF fen800-$DBFF 55296-56319

Unused I/O Area Value Color


55040-55295/$D700-$D7FF 0/$00 black
This area is described in Commodore literature as a reserved l/$01 white
I/O expansion slot, but no currently available devices use 2/$02 red
3/$03 cyan
these locations. All locations in this area of the I/O block re- 4/$04 purple
turn unpredictable changing values, and storing values here 5/$05 green
has no effect. 6/$06 blue
7/$07 yellow
8/$08 orange
VIC Color RAM 9/$09 brown
5S296-56319/$D800-$DBFF 10/$0A light red
11/$OB dark gray
When the I/O block is selected, this IK area holds color infor- 12/$0C medium gray
mation for the VIC 40-column video chip. Unlike the other 13/$0D light green
portions of the I/O block, this area is RAM memory, not hard- 14/$0E light blue
ware chip registers. Since the VIC chip can generate only 16 15/$0F light gray
different colors, all possible color values can be specified in The standard screen editor ROM routines for printing text
just four bits (0-15 - %0000-%llll). Thus, the RAM in this to the 40-column display also set the color memory location
area does not consist of the usual eight-bit bytes, but rather of for each character displayed. The color to be used is specified
four-bit half-bytes, also called nybbles. When you read a loca- in location 241/$F1, the current foreground color. Whenever
tion in this area, the upper four bits of the location's contents the output window is cleared—as when you print the {CLR}
are meaningless, random values which may be different each character, CHR$(147)—all locations in this area which corre-
time the location is read. Those bits should be masked off to spond to character positions in the window will be filled with
determine the true color value (use AND 15 in BASIC or the color specified in the lower four bits of location 241/$F1.
AND #$0F in machine language). When you store values in Since the output window is reset to full screen size and
these locations, only the lower four bits of the stored values cleared by the CINT routine [$C07B], part of both the reset
are significant (POKE 55300,1 and POKE 55300,241 have the and RUN/STOP-RESTORE sequences, either of those events
same effect). will fill the first 1000 locations in this area, addresses
In the standard character display mode (GRAPHIC 0), 55296-56295/$D800-$DBE7, with the default foreground
each character position in screen memory has a corresponding color value, 13/SOD (light green). The highest 24 addresses in
location in this area which determines the color of the screen this area are not affected.
dots drawn for any %1 bits in the character pattern specified
for that position. Since the screen background color shows in Multicolor Character Mode Usage
any %0 bits in the character pattern, the color specified in For multicolor character mode, each screen position has a cor-
color memory is referred to as the foreground color for the responding location in this area which serves two functions.
character position. The colors resulting from the possible val- Multicolor character mode is selected by setting bit 4 of the
ues in these nybbles are as follows: VIC register at 53270/$D016 to % 1 . In multicolor mode, each
character is four dots wide by eight lines tall, and the dots can
have one of four colors. However, simply enabling multicolor
mode does not automatically specify multicolor mode for all

460 461
55296-56319 $D800-$DBFF anH00-$DBFF 55296-56319

character positions. Multicolor mode must be selected on a po- multicolor bitmapped screen can be thought of as a grid of 4
sition-by-position basis. For each position, bit 3 of the color X 8-pixel blocks that is 40 blocks across and 25 blocks tall.
memory location for that position specifies whether the position Each block of dots in the grid has a corresponding color mem-
will behave like standard character mode or multicolor mode. ory location. The color of dots within the block which have
Setting bit 3 of a color memory location to %0 will make the same bit pattern is not independently selectable—all dots
the position behave as if standard character mode were still with %11 bit patterns within the same 4-dot X 8-line block
active for that position, except that only bits 0-2 of the color take the same color, the one specified in the color memory lo-
memory location are then available to hold foreground color cation for that block. The color memory locations can hold
information. Such positions are therefore limited to only 8 any of the 16 standard color values.
choices for foreground color instead of the usual 16. Only the When the multicolor screen area is cleared with the
first 8 of the colors listed above are available, since using a BASIC statements GRAPHIC 3,1 or SCNCLR 3, all color
color value greater than 7 would put the position into multi- memory locations are filled with the value from location
color mode. 133/$85, the multicolor source 2 location. The default value
Setting bit 3 of a color location to %1 selects multicolor for that location is 2, but that can be changed with the
mode for that position. In that case, bits 0-2 of the color mem- COLOR statement. The GRAPHIC 4,1 or SCNCLR 4 state-
ory location specify the color of any %11 bit pairs in the char- ments should have the same effect, but they do not. The con-
acter pattern specified for the position. Since only three bits tents of color memory are not affected by either of those
are available, only eight different colors can be selected. The statements. Due to a bug in the SCNCLR routine [$6A79],
first eight of the standard colors (black-yellow) are the only color memory is filled for GRAPHIC modes 2 and 3 rather
ones available, but since bit 3 must be set to %1 for multicolor than 3 and 4. However, the fact that SCNCLR 2 unnecessarily
mode, the value you must store in color memory to get these fills color memory has no obvious effect, since the standard
colors is different from that used for standard character mode. bitmapped mode doesn't use color memory.
You must add 8 to the normal color value. For example, to
make all %11 bit pairs in a character position white, you must Color Banks
store the value 9 (8 + 1, the normal value for white). Com- The 128 actually has two separate IK blocks of RAM available
modore's Programmer's Reference Guide states that the color for this address area—a new feature not available in the Com-
values still produce the standard colors, but this is not correct. modore 64 (or in the 128's Commodore 64 mode). Normally,
For a multicolor mode position, storing a 9 in its color memory the 128 uses one block for character color and the other for
location makes the %11 bit pairs white, not brown. multicolor bitmapped mode. This is why GRAPHIC 4 mode
Since the operating system does not specifically support (split multicolor bitmapped and text) doesn't cause the con-
multicolor character mode, clearing the output window when flicts you might otherwise expect. That is, printing on the text
this mode is active has the same effect it does in standard screen doesn't disturb colors on the multicolor bitmapped
character mode—color memory is filled with the value from screen, and drawing on the multicolor bitmapped screen
the current foreground color location (241/SF1). doesn't disturb the colors on the text screen, even though both
appear to use the same color RAM.
Bitmapped Mode Usage The banking of color RAM is handled by the screen editor
This area of memory is not used by the standard bitmapped portion of the IRQ service routine [$C194j. Bits 0-1 of the
mode (GRAPHIC 1). That mode gets all of its color infor- 8502's on-chip I/O port at location l/$01 determine which
mation from video matrix locations. For multicolor bitmapped block of color RAM is visible in this address area (see the en-
mode (GRAPHIC 3), values stored in this area control the try for location l/$01 in Chapter 2 for details). Block 0 is nor-
color of those dots defined by %11 bit patterns in the bitmap. mally used for the multicolor bitmapped screen and block 1
For the purposes of controlling color, the 160-dot X 200-line for the text screen. If you disable the screen handling portion

462 463
55296-56319 $D800-$DBFF fcnnO0-$DD0F 56576-56591

of the interrupt service routine, you can use this feature for 220 FOR I = 0 T0 3 9 ! P O K E 1024+1,81 sPOKE 1984+1,81 -.NE
other effects. For example, you can maintain two separate XT I
color displays for the text screen, or two separate text screens— 230 FOR 1=0 TO 22:POKE 1064+(1*40),81:POKE 1103+(I
each with its own color memory—or two separate sets of %11 *40),81:NEXT I
pixel color patterns for the multicolor bitmapped screen. 240 REM ** ALTERNATE COLOR RAM BLOCKS
250 POKE 1,PEEK(1) AND 253
Program 8-2 shows one effect you can create with multiple 260 FOR 1=1 TO 65JNEXT I
color memory blocks for a single text screen. Line 110 selects 270 GET A$:IF A$<>"" THEN 310
the BANK 15 configuration (so that the I/O block, including 280 POKE 1,PEEK(1} OR 2
color RAM, will be visible) and stores the value 255 in the 290 FOR 1=1 TO 65:NEXT I
screen mode flag to disable the screen handling portion of the 300 GET A$:IF A$="" THEN 250
interrupt service routine. Remember that split screen modes 310 END
like GRAPHIC 2 and GRAPHIC 4 will not work while this por-
tion of the interrupt service routine is disabled. Lines 130-150
set up block 0 of color RAM, filling the screen borders with an CIA (Complex Interface Adapter) Chip
alternating pattern of black and white positions. Lines 170-190 Registers
perform a similar setup for block 1, but using an alternating 56320-56335/$DC00-$DC0F and
pattern of white and black. Lines 210-230 set up screen mem- 56576-56591/$DD00-$DD0F
ory, drawing a border of ball characters around the screen. The CIA (complex interface adapter) chips perform the major-
Lines 250-310 then switch between the two color blocks, pro- ity of the 128's input and output functions. Between them, the
ducing a marquee effect as the border colors alternate. CIAs are responsible for handling communications with the
keyboard, joysticks, the serial bus (where disk drives and
Program 8-2. Color Bank Switching Demo printers are connected), the RS-232 port (where modems are
connected), and the user port. In fact—with the exception of
100 REM ** COLOR SWITCHING DEMONSTRATION video output provided by the VIC and VDC chips and the au-
110 BANK 15:POKE 216,255:REM DISABLE SCREEN INTERR dio output provided by the SID chip—the list of I/O functions
UPTS performed by devices other than the CIAs is quite short: the
120 REM ** SET UP BLOCK 0 OF COLOR RAM VIC and VDC chips handle light pen input for their respective
130 POKE 1,PEEK(1) AND 254:PRINT"[CLR}" displays, the SID chip reads paddle controllers (although a
140 FOR 1=0 TO 39 STEP 2:POKE 55296+1,0:POKE 55297 CIA reads paddle buttons and selects which pair of paddles is
+I,1:POKE 56256+1,0:POKE 56257+1,1:NEXT I
150 FOR 1=0 TO lliPOKE 55336+(1*80),1:POKE 55375+{
to be read), the processor's on-chip I/O port is used to control
I*S0),0:POKE 55376+(I*80),0:POKE 55415+(1*80),1 some aspects of tape data storage and to read the CAPS LOCK
:NEXT I key, and an MMU register line is used to read the 40/80 DIS-
160 REM ** SET UP BLOCK 1 OF COLOR RAM PLAY key.
170 POKE 1,PEEK(1) OR 1:PRINT"ICLRJ"
180 FOR 1=0 TO 39 STEP 2:POKE 55296+1,1:POKE 55297
All CIA registers are set to zero when the system RESET
+I,0:POKE 56256+1,1:POKE 56257+1,0:NEXT I line is pulled low, as when the reset button is pushed. Most of
190 FOR 1=0 TO 11:POKE 55336+(1*80),0:POKE 55375+( the CIA registers are initialized during the IOINIT routine
I*80),1:POKE 55376+(I*80),l:POKE 55415+(1*80),0 [$E1O9]. Table 8-8 lists the functions of the various CIA regis-
:NEXT I ters. A detailed description of the use of each follows.
200 REM ** SET UP SCREEN MEMORY
210 PRINT"{HOME}[3 DOWNJtRIGHT}tRVSJ PRESS ANY KEY
TO HALT DEMONSTRATION^ SPACES J "

464 465
56320 SDC00 SDC01 56321

Table 8-8. CIA Chip Registers "float" in a high state, and the corresponding data register bit
yn\\ hold a % 1 . Writing to a data register bit for an input line
CIA #1 CIA #2 has no effect on the state of the line, or on the value returned
56320/$DC00 56576/$DD00 Port A data I/O register when the bit is read. However, the value written to the bit will
56321/$DC01 56577/$DD01 Port B data I/O register be retained internally, and will determine the state of the line
56322/$DC02 56578/$DD02 Port A data direction register
56323/$DC03 56579/$DD03 Port B data direction register if the line is changed to an output.
56324/$DC04 56580/$DD04 Timer A latch/counter (low byte) When a port line is set for output, its corresponding data
56325/$DC05 56581/$DD05 Timer A latch/counter (high byte) register bit will control the state of the line. Setting the bit to
56326/$DC06 56582/$DD06 Timer B latch/counter (low byte) %0 will pull the line to a low (0 volts) state, and setting the
56327/$DC07 56583/$DD07 Timer B latch/counter (high byte) bit to %1 will allow the line to go to a high state (+5 volts).
56328/$DC08 56584/$DD08 Time-of-day dock (1/10 seconds) Note that string the bit to %1 doesn't guarantee that the out-
56329/$DC09 56585/$DD09 Time-of-day clock (seconds) put line will be set to a high state. The data CIA can force an
56330/$DC0A 56586/$DD0A Time-of-day dock (minutes) output line low when an external device connected to the line
56331/$DC0B 56587/$DD0B Time-of-day dock (hours) is trying to hold the line high, but it cannot bring an output
56332/$DC0C 56588/$DD0C Serial data register line high when an external device is holding the line low.
56333/$DC0D 56589/$DD0D Interrupt control register Reading the data register bit for an output line returns the cur-
56334/$DC0E 56590/$DD0E Control register A rent state of the line (%0 if the line is low, or %1 if the line is
56335/$DC0F 56591/$DD0F Control register B high). Thus, a line set for output can still be used for a limited
form of input. If the data register bit for the output line is set
CIA #1 Registers to % 1 , then reading that bit will return %1 while the output
This CIA is used to read the keyboard, joysticks, and other de- line is high and %0 when an external device pulls the line
vices connected to the control ports, such as the 128 mouse. It low. This explains how a joystick can be read from port A de-
also selects which pair of paddles will be read. The timers and spite the fact that the lines of that port are normally config-
FLAG input line are used in reading from and writing to tape. ured as outputs.
The chip's serial data communications hardware is used for
fast serial bus I/O. Port B has a feature not available with port A. A special
handshaking output line (from the CIA) designated PC, nor-
56320 SDC00 D1PRA mally high, will go low for one system clock cycle each time
data is read from or written to port B. This can be used to sig-
56321 $DC01 D1PRB nal an external device that data has been written or accepted
I/O port data registers at the port. The PC line from CIA #1 is not connected to any-
The CIA chip has two eight-line data ports, designated A and thing in the 128, but the PC line from CIA #2 is available at
B. Each bit in the data registers is connected to one of the port pin 8 of the user port.
lines (PA0-PA7 for port A and PB0-PB7 for port B). The lines For CIA #1, all port A lines are normally configured as
can be either inputs or outputs, depending on the setting of outputs and all port B lines are normally configured as inputs.
the data direction registers (56322-56323/$DC02-$DC03). For This is to set up the lines for their primary function—reading
port B, bits 6-7 (lines PB6-PB7) can also have special timer the keyboard. Refer to Figure 7-1 and the discussion of the
output functions. See the discussion of the control registers at keyboard-scanning routine [$C55D] in Chapter 7 for more de-
56334-56335/$DC0E-$DC0F for more information. tails on how these lines are used for that purpose.
When a port line is set for input, its corresponding data The second major function of these ports is to read the
register bit will reflect the state of the line. The bit will hold status of digital controllers connected to the two control ports
%0 when the line is pulled low (0 volts), or %1 when the line °n the side of the 128. Each control port is connected to five
is high ( + 5 volts). An unconnected input line, or one con- lines of one of the CIA #1 ports. Port B is connected to control
nected to a device that isn't actively pulling the line low, will
466 467
56321 $DC01 $DC01. 56321

port 1 {the front one) and port A to control port 2 (the back ortl Control port 2 Joystick
one), which is the opposite of what you might expect. The SDC01) CIA port A. ($DC00) direction
connections are as follows: $11111111 255/SFF %oiinm 127/$7P not pressed
fciiiiino 254/SFE %01111110 126/S7E up
CIA port bit Controller port pin Joystick function %11111101 253/$FD %01111101 125/$7D down
0 1 ftllUlOll 251/SFB %01111011 123/$7B left
up £11111010 250/$FA %01111010 122/S7A up + left
1 2 down £11111001 249/$F9 %01111001 121/579 down + left
2 3 left %iinom 247/$F7 %omom 119/$77 right
3 4 #11110110 246/$F6 %01110110 118/$76 up + right
right
4 6 %11110101 245/$F5 %onioioi 117/$75 up + left
button
If the fire button is pressed, bit 4 of the data register will also
The control port pins are usually described in terms of be set to %0, and the values listed above will be reduced by
their joystick functions, since the joystick is the device most
commonly connected to the ports. A joystick is a very simple 16/$10.
device consisting of five switches, one for each of the four pri- If you'd prefer to read %1 bits instead, try the following
mary directions and one for the fire button. The switches are code:
normally open, meaning that no connection is made when the Control port 1 Control port 2
joystick is not being pressed. Remember that unconnected CIA LDA $DC01 LDA $DC00
port lines float to a high state ( + 5 volts), so the corresponding AND#$1F AND #$1F
EOR #$1F EOR #$1F
CIA port bits will be % 1 . Pressing the stick in one of the eight
possible directions (four primary directions and four diagonals) Using this method, the accumulator will hold one of the fol-
closes one or two of the switches, grounding the CIA port lowing values after the port is read:
lines and forcing the corresponding bit or bits to %0. Pressing
the fire button grounds that line, so it is possible to have as Value Joystick direction
many as three lines simultaneously grounded. 0/$00 not pressed
l/$01 up
For reading the joysticks, BASIC provides the JOY func- 2/$02 down
tion [$8203], which returns a value from 1-7, depending on 4/$04 left
the direction the stick is pressed (the value is 0 if it is not be- 5/$05 up + left
ing pressed), with 128 added if the fire button is pressed. To 6/$06 down + left
read the joystick from machine language, you simply read the 8/$08 right
corresponding CIA port data register and check for %0 bits. 9/$09 up + right
Even though the port A lines are normally set up as outputs, 10/$00 down + right
you can still read the joystick without switching the lines to Pressing the fire button will add 16/$10 to any of the values
inputs. The keyboard scan routine leaves all port A bits except listed above.
bit 7 set to % 1 , so it is still possible for external devices like You should be aware, however, that using control port 1
the joystick to pull the lines low (bit 7 of that port will nor- (CIA port B) for joystick input can have an undesirable side ef-
mally always be %0). The possible port readings are as follows: fect. Since the input lines of that port are also used for reading
the keyboard, the keyscan routine [$C55D] has no way to tell
whether the port lines are being grounded by keypresses or

468 469
56321 $DC01 SDCO3 56323

joystick presses. As a result, moving a joystick effectively gen-


erates a keypress, and certain keypresses produce the same ef- Control port selected
fect as moving the joystick:
Joystick conflicts Keyboard conflicts
Direction Effective keypress Keypress Effective direction The other combinations result in either both or neither ports
up ALT 1 up
down SHIFT-INST/DEL - down
being selected. The port A lines are always outputs, so there is
left RETURN CONTROL left no problem with using them for this purpose. The default
right cursor left 2 right value in port A (except during the IRQ, when it is being used
fire SHIFT-F7 space fire to scan the keyboard) is 127/$7F. This has the bits set to %01,
Many programs avoid this problem by using only port A selecting control port 1. Unless you really need four paddles,
(control port 2), which is the simplest solution. Because the it's best to use this port. To write any value other than
port A lines are outputs, the joystick is never mistaken for the 127/S7F into port A, you must disable interrupts, since the
keyboard in control port 2. You can prevent the keyboard con- keyboard-scanning routine always leaves the port set to that
flicts by disabling interrupts and forcing all keyboard column value.
lines high before reading the port (add SEI:LDA #$FF:5TA Another bit of 128 hardware trivia: Our experience
$DC00:STA $D02F before the LDA $DC01 instruction, and indicates that a CIA #1 failure is one of the most common
CLI after it). The joystick conflicts are more difficult to pre- hardware problems the 128 owner is likely to experience. Inte-
vent—there is no way to disable the joystick. If your program grated circuit chips like the CIA are very sensitive to electric
doesn't require keyboard input, a rather inelegant solution is discharges such as the static electric spark you see when you
to simply zero the count of keys in the buffer and pending touch a doorknob after shuffling across a carpet. Since the
function key characters (locations 208/$D0 and 2O9/$D1) control port lines lead directly to the pins of CIA #1, touching
before exiting from the program. a control port pin when your body carries a static charge is
like a lightning strike to the chip. Unfortunately, since the
Any device which behaves like a joystick can be read in
control ports lie so close to the reset and power switches, it's
the same manner. This includes trackballs and the new mouse
very easy to touch them unintentionally, especially control
controllers (which are more or less upside-down trackballs).
port 2. Of the five 128s we have had at COMPUTE! Publica-
Devices such as paddles or graphics tablets are analog, not
tions to date, three have experienced "blown" CIAs. Bit 1 of
digital, devices, and are read by the SID chip. (See the entry port A seems to be particularly susceptible. This is in keeping
for the SID registers at 54297-54298/$D419-$D41A.) How- with our experience with Commodore 64s over the past sev-
ever, any buttons on these devices are read as if they were eral years, where we have lost approximately a dozen CIA
joystick lines. For example, the two buttons on a standard pair chips out of about 30 computers. If one joystick direction or a
of Commodore paddles are read exactly like the joystick left- group of keys suddenly becomes impossible to read, a blown
and right-direction lines for the corresponding control ports. CIA is the likely source. To prevent this, some users resort to
Since the CIA ports are bidirectional, you could also use the covering the control ports with masking or electrical tape
control port lines in interfacing projects. Together they provide when the port is not in use. Another solution is to leave the
ten lines which can be either inputs or outputs. joystick plugged in at all times.
The final function of these CIA ports is that bits 6-7 (lines
PA6-PA7) of port A control which control port will be con-
nected to the SID lines for reading paddles. Since paddles 56322 8DC02 D1DDRA
come in pairs and the 128 has two control ports, you can con- 56323 SDC03 D1DDRB
nect up to four paddles. However, the SID has only two pad- Data direction registers
dle inputs. As a result, you can read paddles from only one Each of the eight lines in the CIA's two data ports can be indi-
port at a time. Valid selections are as follows: vidually configured as either an input or an output. These data

470 471
56324 $DC04
6PC07 56327

direction registers (DDRs) specify the direction of data flow on


the port lines. Each register bit corresponds to one port line Instead, the values are held in an internal latch register. The
(PA0-PA7 for port A and PB0-PB7 for port B). Setting a regis- latch contents are transferred into the counter whenever the
ter bit to %0 makes the corresponding port line an input timer underflows. Alternatively, a bit in the control register
while setting the bit to %1 makes the line an output. The lines can force an immediate transfer of the latched value into the
are read and controlled by the data registers at 56320-56321/ counter.
$DCOO-$DC01. For lines PB6-PB7 of port B, the settings of One special function of timer A is to control the rate of
bits 6-7 of 56323/$DC03 can be superseded when those lines data output over the CIA's serial port (SP) line. In this case,
are used for their special timer output functions. See the dis- timer A generates a clock signal that is provided as an output
cussion of the control registers at 56334-56335/$DC0E-$DC0F on the CNT line. Since timer A must underflow twice to pro-
for more information. duce the full clock cycle on the CNT line required for each bit,
For CIA #1, the IOINIT routine [$E109]—part of both the you should load timer A with a value which will produce an
reset and RUN/STOP-RESTORE sequences—initializes the underflow in half the time desired for each bit. In other words,
port A DDR (56322/$DC02) to 255/$FF, making all port A the duration of each bit transmitted on the serial line will be
lines outputs, and the port B DDR (56323/$DC03) to 0/$00, twice the time required to count down the value specified in
making all port B lines inputs. These settings are not changed the timer A latch. See the entry for the CIA serial data register
by any other ROM routines. You can change these settings (56332/$DC0C) for more information on the CIA's serial data
briefly for special I/O functions involving the control ports, I/O capabilities.
but leaving any port A lines set as inputs or port B lines set as For CIA #1, timer A can be a source of IRQ interrupts to
outputs will disable normal keyboard functioning. See the dis- the processor. This feature is used during tape I/O to generate
cussion of the data registers above for more information on the IRQ interrupts which drive the reading and writing of
the uses of the port lines. data. CIA #1 timer A also controls the transmission rate for
data sent over the fast serial bus. Thus, if you use the timer
56324 $DC04 D1T1L for your own timing applications, you should be aware that
56325 $DC05 D1T1H both tape and fast serial operations will change the settings of
Timer A latch/counter registers the timer. (The timer will be stopped upon completion of any
Timer A is a programmable counter that can provide a variety tape or fast serial operation.) The IOINIT routine [$E109] calls
of timing functions. It is a countdown timer, meaning that it the Kernal fast serial output setup routine, which starts the
repeatedly decrements the counter contents until the value is timer counting down from $0004, but then immediately calls
decremented below zero, a condition known as underflow. the fast serial input setup routine, which halts timer A. Thus,
When Timer A underflow causes an internal CIA interrupt, bit upon completion of the reset or RUN/STOP-RESTORE se-
0 of the CIA interrupt register at 56333/$DC0D will be set to quence, the timer will contain some very low value: usually
% 1 . The timer can be set to count down repeatedly or just either $0001 or $0002. Unlike the Commodore 64, CIA #1
once. The timer countdown can be driven by either of two timer A is not the source of the 128's normal jiffy IRQ inter-
sources: the system clock frequency or a signal provided on rupts. That task is instead performed by raster interrupts from
the CNT line by an external device. The operating conditions the VIC chip.
of the timer are specified in the CIA control register A
(56334/$DC0E). 56326 $DC06 D1T2L
When read, the registers here return the current value in 56327 $DC07 D1T2H
the 16-bit counter (low byte in 56324/SDC04 and high byte in Timer B latch/counter registers
56325/$DC05), Data written to these registers does not go di- The operation of timer B is quite similar to that described
rectly into the counter unless the timer is currently stopped. above for timer A, but is a bit more flexible. In addition to
c
°unting system clock and CNT pulses, timer B can also count
472
473
56328 $DC08 SDCOB 56331

timer A underflows. This effectively ties the two timers to- 56329/$DC09: Bits 0-3 hold the ones digit for seconds. Bits
gether to form a 32-bit countdown value, allowing countdown 4_6 of this register hold the tens digit (only three bits are
intervals of up to 70 minutes. The operation of timer B is con- needed, since this digit will never be greater than %101 =
trolled by the register at 56335/$DC0F. 5 the seconds count rolls over to $00 after reaching $59.) Bit
For CIA #1, the IOINIT routine [$E109], part of both the 7 is unused. Writing to that bit has no effect, and it always re-
reset and RUN/STOP-RESTORE sequences, loads the latch turns a %0 when read.
for this timer with 65535/$FFFF and starts the timer running
in continuous mode. There is no obvious reason for this step. 56330/$DC0A: Bits 0-3 hold the ones digit for minutes. Bits
The only use of timer B by 128 ROM routines is during tape 4-6 hold the tens digit. Bit 7 is unused. Writing to that bit has
I/O, where it is used to generate IRQ interrupts to drive the no effect, and it always returns a %0 when read.
reading and writing of data. Upon completion of a tape opera- 56331/$DC0B: Bits 0-3 of this register hold the ones digit for
tion, the timer will be left halted and set for one-shot mode. hours. Bit 4 holds the tens digit for hours (only one bit is
needed, since this digit will always be either 0 or 1). Bits 5-6
56328 SDC08 D1TOD1 are unused. Writing to these bits has no effect, and they al-
56329 $DC09 D1TODS ways return %0 when read. Bit 7 is the AM/PM flag. The 12-
56330 $DC0A D1TODM hour format time value is taken to represent AM (midnight-
56331 $DC0B D1TODH noon) when this bit is %0 and PM (noon-midnight) when the
Time-of-day clock registers bit is % 1 . Be sure to remember this bit when setting an alarm
The time-of-day (TOD) clock is a special feature of the CIA. It time.
keeps time in hours, minutes, seconds, and tenths of sec- The order in which you read and write these registers is
onds—units more useful to humans than the jiffies of the sys- important. When reading the clock, the registers latch (remain
tem software clock or the fractional microseconds of timer A constant) after you read the hours register until you read from
or B. There are actually two sets of registers at these locations, the 1/10-seconds register. The clock continues to count inter-
the time and the alarm. By storing an alarm value here, you nally; only the register values remain constant. Thus, each
can trigger an internal interrupt (and, optionally, an external read of the hours register must be followed by a read of the
IRQ request) when a specified time is reached. When you read 1/10-seconds register, even if you don't care about the 1/10-
the registers, you always see the time value (the alarm setting second value. Likewise, the clock stops whenever a value is
is never visible). When you're writing to the register, bit 7 of written to the hours register, and does not start again until a
control register B (56335/SDCOF) determines whether the value is written to the 1/10-seconds register. Thus, for both
value being written will set the time or the alarm. reading and writing you should start with the hours register
and end with the 1/10-seconds register.
The time is kept in 12-hour format, with bit 7 of the
hours register used as a flag to indicate AM or PM. The time The following routine illustrates the use of the time-of-
data in the registers is in binary coded decimal (BCD) format. day clock by displaying the current time in the upper left cor-
In this format, each half-byte (nybble) contains a value which ner of the screen:
represents one decimal digit. For example, if the minutes regis- D00 LDA #$89 ;Load clock registers with desired
ter contains the value %00100110, equivalent to 38/$26, the D02 STA $DC0B ; initial time. (This example uses
minutes digits should be interpreted as 2 and 6—26 minutes D05 LDA #$05 ; 9:05:00.0 PM)
past the hour, rather than 38 minutes. The register bits should D07 STA $DC0A
be interpreted as follows: D0A LDA #$00
DOC STA $DC09
56328/$DC08: Bits 0-3 hold the 1/10-seconds digit. Bits 4-7 DflF
i LDA #$00
are unused. Writing to those bits has no effect, and they al-
ways return %0 when read.
474
475
56331 56332
$DCOB $DCOC

Dll STA $DC08 ;Gock starts when this register is written routine. Thus, both are free for your own programming. All
D14 LDA $DC0B ;Read hours byte (this latches the time value)
D17 BMI $OD1D clock registers are reset to %0 when the system is reset.
;Add either an A or a P to the time string,
D19 LDX #$41 ; depending on the state of the AM/PM bit
DIB BNE $0DlF 56332 8DC0C D1SDR
DID LDX #$50 Serial data register
D1F STX $0D70 The CIA supports serial (bit-by-bit) data transfers in hardware.
D22 AND #$7F ,Mask off the AM/PM bit This register holds the byte of data to be sent over the CIA's
D24 JSR $0D54 ;Convert the hours byte to two characters SP (serial port) line, or the byte read from the line. At any
D27 CMP #$30 ;RepIace leading zero with a space given time, the CIA serial line must be configured for either
D29 BNE $0D2D input or output. This is controlled by the setting of bit 6 of
D2B LDA #$20
D2D
control register A (56334/$DC0E).
STA $0D67 ;Add hours-digit characters to string
D30 STX S0D6S When the line is set for input, the state of the SP line is
D33 LDA $DC0A ;Read minutes byte read as a data bit each time there is a low-to-high (0 to +5
D36 JSR $0D54 ;Convert to two characters volts) transition on the CNT input line. (CNT must be driven
D39 STA $0D6A ;Add minutes-digit characters to string by the external device which is sending data.) As each bit is
D3C STX $0D6B read, it is transferred into an internal serial shift register.
D3F LDA $DC09 ;Read seconds byte When an entire byte has been read (after eight pulses of the
D42 JSR $0D54 ;Convert to two characters CNT line), the value in the internal shift register is transferred
D45 STA $0D6D ;Add seconds-digit characters to string to this register and an interrupt will be indicated in bit 3 of the
D48 STX $0D6E CIA interrupt register (56333/$DC0D). At this point, the re-
D4B LDA $DCO8 ;Read 1/10-seconds byte (to unlatch time) ceived byte can be read from the register.
D4E JSR $0D62 ;Print time string
D51
When the line is set to be an output, data written to this
JMP $0D14 ;Repeat indefinitely register will be transferred into the internal shift register and
;Convert BCD byte to two ASCII characters then sent out a bit at a time over the SP line. Timer A deter-
TJ S4 PHA ;Stash the byte mines the rate at which bits will be sent. The transmission will
D55 AND #$0F ;Mask off all but the lower four bits begin immediately if timer A is running; otherwise, it begins
D57 ORA #$30 ;Add base ASCII numeral value
D59 TAX
when the timer is started. Bits will be written on the serial line
;Leave low digit in X register at one-half the countdown rate of timer A. That is, timer A
D5A PLA ;Retrieve original value
D5B LSR must underflow twice for each bit sent. This clock signal ap-
;Move high four bits into low nybble pears as output on the CNT line. After all eight bits are sent,
D5C LSR
D5D LSR an interrupt will be indicated in bit 3 of the CIA interrupt reg-
D5E LSR ister (56333/$DC0D) to indicate that another byte can be sent.
D5F ORA #$30 ;Add base ASCII numeral value This hardware serial data communications feature went
D61 RTS unused in the Commodore 64, but in the 128 it is used to sup-
D62 JSR $FF7D ;Print time string using Kernal PRIMM port the fast serial bus. The only fast serial peripheral device
> D 6 5 13 12 30 30 3A 30 30 3A ;String characters: currently in widespread distribution is the 1571 disk drive, but
>D6D 30 30 20 41 4D 20 00 ; {HOME}{RVS}00:00:00 AM others may appear in the future. For CIA #1, the SP line is
D74 RTS
connected to the serial bus DATA line (with additional cir-
Neither CIA's time-of-day clock is used by 128 mode, al- cuitry to prevent conflicts with slow serial communications)
though CP/M does make use of the CIA #1 dock for time- and the CNT line is connected to the SRQIN line. The CIA #1
keeping. None of these registers is initialized by any 128 ROM SP and CNT lines are also available from the user port, at pins
5 and 4, respectively.
476 477
56333 $DCOD 56333
SDCOD

56333 SDCOD D1ICR Bit 7 controls the interrupt mask register function. When
Interrupt control register vou're writing to this register, bit 7 determines which mask
The CIA chip has five internal interrupt sources: timer A bits will be set or cleared. If bit 7 is set to %1 in a value writ-
underflow, timer B underflow, time-of-day clock alarm, serial ten to this register and any of bits 0-4 in the value are also set
data buffer full or empty, and FLAG signal. The CIA can also to %1/ then the corresponding interrupt mask bits will be set
generate an interrupt request output signal as a result of any and the specified interrupt or interrupts will generate an exter-
of these conditions. The location actually has two different nal interrupt request output. The mask bits correspond to the
functions, depending on whether it is being read from or writ- sources listed above the data register. For example, to enable
ten to. When you read from this register, you see the contents timer B as an interrupt source you would write a value to the
of an internal interrupt data register that indicates which inter- register which has bits 1 and 7 set to % 1 — LDA #$82:STA
rupts, if any, have occurred. When you write to this register, $DC0D. (Bits in the value which are %0 are not significant.) If
the value goes to an internal interrupt mask register that speci- bit 7 in the value written to the register is set to %0 and any
fies which interrupts—if any—are to result in an external in- of bits 0-4 in the value are % 1 , then the corresponding mask
terrupt request being generated. The data register is read-only bits will be cleared and the specified interrupt or interrupts
{it can't be written to), and the mask register is write-only (it will be disabled. For example, you could use LDA #$0F:STA
can't be read from). $DC0D to clear all except FLAG interrupts. (Again, bits in the
When you're reading from the register, bits 0-4 indicate value which are %0 have no effect.)
which interrupts have occurred since the last time those bits When external interrupt requests are enabled, you can
were read. The bit is set to %1 when the corresponding inter- read bit 7 to determine whether any interrupts have occurred.
rupt occurs, regardless of whether or not the source is set to When read, bit 7 will be %0 if no CIA source has generated
trigger an external interrupt request output. All these bits are an interrupt request, or %1 if an interrupt request output has
automatically cleared to %0 after the register has been read. been generated as the result of one or more enabled internal
The interrupt type indicated by the individual bits is as follows: CIA interrupt conditions. Remember, however, that all the
Bit Interrupt source data bits in this register are cleared to %0 after the register is
0 Timer A underflow read. Thus, you must preserve the read register value if you
1 Timer B underflow wish to determine which source produced the interrupt re-
2 Time-of-day clock alarm quest. For example, you shouldn't test bit 7 with the machine
3 Serial data buffer full or empty language BIT instruction, since that will result in the loss of
4 High-to-low transition on FLAG input line the data register bit settings.
A timer underflow occurs when the timer counts down below For CIA #1, the interrupt request output is connected to
zero. A time-of-day clock alarm occurs when the time in the the processor's IRQ input line, so interrupt requests from CIA
clock registers matches the value in the alarm registers. The #1 result in IRQ interrupts to the processor. The IOINIT rou-
serial-buffer-empty condition occurs during output after all tine [SE109] clears all interrupt mask bits, so initially no inter-
eight bits for a byte have been written on the serial port (SP) rupts are enabled. Some operations enable interrupts for the
line, and a buffer-full condition occurs during input after eight duration of their activity. Tape I/O, which is interrupt-driven,
bits have been read from the SP line. The FLAG line is a spe- uses timer A, timer B, and FLAG interrupts as IRQ sources.
cial input provided on the CIA specifically for the purpose of Fast serial bus I/O uses internal serial data buffer interrupts,
generating interrupts. A FLAG interrupt occurs whenever the but does not trigger external IRQ requests. See the tape and
device connected to the FLAG line causes a high-to-low volt- fast serial routines in Chapter 9 for details. You are, of course,
age transition ( + 5 to 0 volts) on the line. ' r ee to set up your own CIA #1 interrupts, but you must write
your own interrupt service routine. The standard IRQ handler
Bits 5-6 are unused. Writing to them has no effect, and [5>FA65] merely reads this register to clear it, and ignores the
they always return %0 when read.
1
478
479
56334 $DCOE flpCOE 56334

value read. See Appendix A for more information on inter- tvveen high and low states. The output mode is controlled by
rupts. In Commodore 64 mode (and in the original Commo- bit
t
2 of this register. Writing a %0 here disables timer A out-
dore 64), timer A interrupts from CIA #1 were the source for put and restores PB6 to the state and function defined in the
the system's 1/60-second jiffy IRQ. However, 128 mode in- port B data and data direction registers.
stead uses raster interrupts from the VIC chip for that function. For CIA # 1 , this bit is set to %0 during the IOINIT rou-
tine [$E109], and is not changed by any 128 ROM routine.
56334 $DCOE D1CRA The PB6 output feature is not useful on CIA # 1 , since the PB6
Control register A line for that CIA is connected only to a keyboard row scan-
This register controls the operation of timer A, except for bits ning line, and is not available externally. However, the PB6
6-7, which control serial data port and time-of-day clock func- line from CIA #2 is available at pin K of the user port, so this
tions, respectively. See the entry at 56324-56325/$DC04-$DC05 feature could be used with timer A of that CIA.
for more information on timer A. Bit 2: When bit 1 of this register is set to allow timer A to gen-
Bit 0: This bit acts as the ignition switch for timer A. Writing a erate output on the PB6 line of port A, this bit controls the
%0 here stops the timer. If the timer is currently stopped, type of output. (This bit has no effect when bit 1 is %0.) The
writing a %1 here causes the counter to begin decrementing two selections for output type are pulse and toggle. For pulse
its current contents (unless the force load strobe, bit 4 of this output, selected when this bit is set to %0, the output line is
register, is also set to %1—in that case, the latch value is held low except for a very brief high pulse each time timer A
loaded into the counter before counting resumes). Writing a overflows. The line will be held high for one cycle of the O2
%1 here when the bit is already set to %1 has no effect. Set- clock rate. For the 128, that is equal to 0.978 microseconds in
ting the bit to %0 when it has previously been %1 halts the NTSC (North American) systems, or 1.01 microseconds on
timer, leaving the counter holding the value it has reached PAL (European) systems. For toggle output, selected when this
when stopped. When the timer is set for one-shot mode, this bit is set to % 1 , the PB6 line switches state—low-to-high or
bit will automatically be reset to %0 when the count under- high-to-low—each time the timer underflows, starting from a
flows. In this case, the counter will be reloaded with the latch high state.
value. For CIA # 1 , this bit is set to %0 during the IOINIT rou-
For CIA #1, the IOINIT routine sets this bit to %0, so tine [$E109], and is not changed by any 128 ROM routine.
timer A is initially stopped. The ROM routines for tape I/O
use this timer to generate IRQ interrupts for reading and writ- Bit 3: This bit controls whether timer A runs in continuous or
ing tape bits, but the bit is reset to %0 upon completion of one-shot mode. In continuous mode, selected when this bit is
any tape operation. The Kernal SPOUT routine [$E5D6], set to %0, the timer will perform repeated countdowns. After
which prepares the fast serial bus for output, starts the timer each underflow, the counter is reloaded with the latch value
and leaves it counting. (Timer A determines the rate at which and restarted. In one-shot mode, selected when this bit is set
data is sent over the fast serial lines.) The Kernal fast serial t° % 1 , the timer counts down to underflow only once, at
output routines end with calls to the SPIN routine [$E5C3], which time bit 0 of this register is reset to %0 to halt further
which resets this bit to %0, halting the timer. counting. However, the latch value is still transferred to the
counter when the underflow occurs.
Bit 1: This bit controls whether or not timer A generates out- For CIA # 1 , the IOINIT routine [$E109] initializes this bit
put on the PB6 line of port B. Writing a %1 here enables PB6 to % 1 , Tape I/O routines use this timer, but also in one-shot
output. When PB6 is selected for timer A output, the line wode, so the bit should still be set to %1 after any tape opera-
automatically becomes an output, regardless of the setting of tion is performed. The Kernal fast serial output routines will
the data direction register bit for that line. The output on PB6 change this bit to %0 to run the timer in continuous mode.
will be either short pulses or a regular toggling of the line be- However, upon completion of any fast serial output operation,

480 481
56334 $DCOE 56335
$DCOF

the port is reset for fast serial input, which includes resetting
this bit to %1 for one-shot mode. timer A. See the discussion of the serial data register for more
information.
Bit 4: Writing a %1 to this bit, called the force load strobe, For CIA #1, this bit is initialized during the IOINIT rou-
causes the contents of the timer A latch to be transferred to tine to %0. The 128 uses the CIA #1 serial data register for
the counter, regardless of whether the timer is currently run- fast serial bus communications, so the bit must be set to %1
ning or stopped. Using the strobe bit while the timer is run- whenever fast serial output is being performed. However, after
ning allows you to modify the counter contents in the middle the output has been completed the Kernal fast serial output
of a countdown. Writing a %0 to this bit has no effect. This bit routines reset the bus for input, which includes resetting this
is write-only; it always returns a %0 when read. bit to %0.
Bit 5: This bit controls which of two possible events will drive Bit 7: This bit controls a time-of-day clock function rather than
timer A. Two different input signals can be used to make the a timer A function. It determines the rate at which the time-of-
timer decrement. The timer will be decremented once for each day clock will be incremented. The clock is driven by the
cycle of the specified event, but only if bit 0 of this register is CIA's TOD input pin, which, in the 128, is connected to cir-
set to %1 to allow counting. When this bit is set to %0, the cuitry which produces a clock signal from the AC power sup-
timer will be driven by the system O2 clock, which provides ply. This signal will have the same frequency as the local
a "tick" every 0.978 microseconds in NTSC (North American) power supply, generally 60 hertz (60 cycles per second) in
systems, or 1.01 microseconds on PAL (European) systems. North America and 50 hertz in Europe. Setting this bit to %0
The maximum delay between underflows with this clock rate specifies that the 1/10-seconds digit of the clock time should
is in the neighborhood of 1/15 second. Setting the bit to %1 be incremented once for every 6 cycles of the TOD signal (for
makes the CIA's CNT line the clock source, so that an external a 60-hertz source), while setting it to %1 specifies that the
source can drive the count rate. In this case, the counter will digit should be incremented on every fifth cycle (for a 50-hertz
be decremented once each time the external device connected source). Specifying an incorrect rate will make the time-of-day
to CNT provides a low-to-high transition on the line. For CIA clocks in your system count either too fast or too slow.
#1, the CNT line is available at pin 4 of the user port. The For CIA #1, this bit is initialized to %0 during the IOINIT
CNT line is also used as the clock source for the fast serial routine [$E109], and that setting is not changed by any other
bus, and is connected to the SRQIN line of the serial port. 128 ROM routine. This is the proper setting for North Amer-
However, the line from SRQIN will be an input only when ica, but unless there is a different version of the ROM in Euro-
the FSDIR bit (bit 3) of the MMU mode configuration register pean 128s, overseas users will need to change this bit to get
at 54533/$D505 is set to %0. proper timekeeping.
For CIA #1, this bit is initialized to %0 during the IOINIT
routine [$E109], and that setting is not changed by any other 56335 $DC0F D1CRB
128 ROM routine. Timer A must be set to count system clock Control register B
pulses in order for tape operations to perform properly. This register controls the operation of timer B, except for bit 7,
Bit 6: This bit does not control a timer A function, but instead which controls a time-of-day clock function. See the entry at
specifies the direction of data flow on the CIA's serial port 56324-56325/$DC04-$DC05 for more information on timer B.
(SP) line. When this bit is set to %0, the SP line is an input. Bit 0: This bit acts as the ignition switch for timer B. While the
Data read on the line will be collected in the serial shift regis- bit is %0, the timer is stopped. If the timer is currently
ter until a full byte has been received; then an interrupt will stopped, writing a %1 here starts the counter. The countdown
be generated. When this bit is set to % 1 , the SP line is an out- will resume with the current counter contents unless bit 4 of
put, and data written to the serial data register at 56332/ this register is also set to %1 to force the latch value to be re-
$DC0C will be sent out on the SP line at a rate depending on loaded. Writing a %1 here when the bit is already set to %1
482
483
^
56335 $DCOF
$PCOF_ 56335

has no effect. Setting the bit to %0 when it has previously For CIA # 1 , this bit is set to %0 during the IOINIT rou-
been %1 halts the timer, leaving the counter holding whatever tine [$E109], and is not changed by any 128 ROM routine.
count value it has reached when stopped. When the timer is
set for one-shot mode, this bit is automatically reset to %0 Bit 3: This bit controls whether timer B runs in continuous or
when the count underflows. In this case, the counter is re- o ne-shot mode. In continuous mode, selected when this bit is
loaded with the latch value. set to %0, the timer will perform repeated countdowns. After
each underflow, the counter is reloaded with the latch value
For CIA #1, the IOINIT routine sets this bit to % 1 , so and restarted. In one-shot mode, selected when this bit is set
timer B is normally running (although there is no obvious rea- to %1/ the timer counts down to underflow only once, at
son for this). The timer is used in one-shot mode for tape I/O,
so this bit will be set to %0 (and the timer will be stopped) which time bit 0 of this register is reset to %0 to halt further
upon completion of any tape operation. counting. However, the latch value is still transferred to the
counter when the underflow occurs.
Bit 1: This bit controls whether or not timer B generates out- For CIA #1, the IOINIT routine [$E109] initializes this bit
put on the PB7 line of port B. Writing a %1 here enables PB7 to %0, so timer B starts running continuously. However, the tape
output. When PB7 is selected for timer B output, the line auto- I/O routines use this timer in one-shot mode, and this bit will
matically becomes an output, regardless of the setting of the be left set to %1 after any tape operation has been performed.
data direction register bit for that line. The output on PB7 will
be either short pulses or a regular toggling of the line between Bit 4: Writing a %1 to this bit, called the force load strobe,
high and low states. The output mode is controlled by bit 2 of causes the contents of the timer B latch to be transferred to the
this register. Writing a %0 here disables timer B output and re- counter, regardless of whether the timer is currently running
stores PB7 to the state and function defined in the port B data or stopped. Using the strobe bit while the timer is running al-
and data direction registers. lows you to modify the counter contents in the middle of a
For CIA #1, this bit is set to %0 during the IOINIT rou- countdown. Writing a %0 to this bit has no effect. This bit is
tine [$E109], and is not changed by any 128 ROM routine. write-only; it always returns a %0 when read.
The PB7 output feature is not useful on CIA #1, since the PB7 Bits 5-6: These bits control which of four possible events will
line for that CIA is connected only to a keyboard row scan- drive timer B. That is, four different input signals can be used
ning line, and is not available externally. However, the PB7 to make the timer decrement. The timer will be decremented
line from CIA #2 is available at pin L of the user port, so this once for each specified event, but only if bit 0 of this register
feature could be used with timer B of that CIA. is set to %1 to allow counting. The four possible selections are
Bit 2: When bit 1 of this register is set to allow timer B to gen- as follows:
erate output on the PB7 line of port B, this bit controls the Bits
type of output. (This bit has no effect when bit 1 is %0.) The 6 5 Timer B driving source
two selections for output type are pulse and toggle. For pulse 0 0 System <&2 clock
output, selected when this bit is set to %0, the output line is 0 1 CNT line transitions
held low except for a very brief high pulse each time timer B 11 0 Timer A underflows
overflows. The line will be held high for one cycle of the O2 1 Timer A underflows while the CNT line is high
clock rate. For the 128, that is equal to 0.978 microseconds in The default source, the system O2 clock, provides a "tick"
NTSC (North American) systems, or 1.01 microseconds on every 0.978 microseconds in NTSC (North American) systems,
PAL (European) systems. For toggle output, selected when this °r 1.01 microseconds on PAL (European) systems. The maxi-
bit is set to % 1 , the PB7 line switches state—low-to-high or mum delay between underflows with this clock rate is in the
high-to-low—each time the timer underflows, starting from a neighborhood of 1/15 second. The CNT option (%01) allows
high state. a
n external source to drive the count rate. In this case, the

484 :
485
56336-56575 $DC10-$DCFF 56577
SDDOI

counter will be decremented once each time some external de-


vice causes a low-to-high transition on the CIA's CNT line. CiA # 2 Registers
For CIA #1, the CNT line is available at pin 4 of the user port. This CIA is used to support the serial bus, and to provide the
The CNT line is also used as the clock source for the fast se- R S - 2 3 2 interface. It also provides programmable I/O lines at
rial bus, and is connected to the SRQIN line of the serial port. the user port for custom interfacing projects. Another vital
However, the line to SRQIN will be an input only when the function of this unit is to select which area of memory is used
FSDIR bit (bit 3) of the MMU mode configuration register at aS the current VIC video bank.
54533/$D505 is set to %0. The option to count timer A under-
flows is convenient for creating longer delays. By setting timer 56576 SDDOO D2PRA
A to count system O2 clock pulses and timer B to count timer 56577 $DD01 D2PRB
A underflows, you can achieve a countdown interval of up to I/O port data registers
70 minutes when both timers start with maximum counts. These registers are used to read data from port lines which are
For CIA #1, these bits are initialized by the IOINIT rou- configured as inputs and to write data to port lines configured
tine to %00 to have the timer count system clock pulses. This as outputs. Refer to the entry for the CIA #1 ports at
setting is not changed by any other Kerna] routine. Tape oper- 56320-56321/$DC00-$DC01 for details of how these registers
ations will function properly only when CIA #1 timer B is and ports operate. For CIA #2, the ports are used as follows:
counting system clock pulses. Port A (56576/$DD00)
Bit 7: Unlike the other bits of this register, this one does not Bits 0-1 of this port (lines FA0-PA1) are normally configured
control a function of timer B. Instead, it specifies whether val- as outputs and are used to specify which 16K area of the 64K
ues written to the time-of-day clock registers at 56328-56331/ RAM block will be used for the current VIC video bank. The
$DC08-$DC0B will be directed to the clock time latch or to four possible selections are as follows:
the alarm latch (see the discussion of the time-of-day clock Bits
registers for more information on the alarm function). While 1 0 Video bank System address range
the bit is %0, values written to the registers affect the clock 0 0 3 49152-65535/$C000-$FFFF
time latch. Setting this bit to %1 allows you to set the alarm 0 1 2 32768-49252/$8000-$BFFF
time. This bit affects only writing to the time-of-day clock reg- 1 0 1 16384-32767/$4000-$7FFF
isters. When read, the registers always return the clock time, 1 1 0 0-16383/$0000-$3FFF
never the alarm time. These bits are initialized to %11 by the IOINIT routine
[$E109] during the reset and RUN/STOP-RESTORE se-
56336-56575 $DC10-$DCFF quences. This selects video bank 0, the default bank, and the
CIA #1 register images 128 itself never selects another bank. The 64K block from
Due to incomplete address decoding, images of the CIA chip which the video bank is seen is determined by bit 6 of the
registers appear repeatedly every 16 bytes throughout the re- MMU register at 54534/$D506.
mainder of this page of memory. That is, storing a value in Bit 2 (port line PA2) is connected to pin M of the user
any location in this range with an address that is an exact port. The line is normally configured as an output, and this bit
multiple of 16 greater than one of the base register addresses is initialized by the IOINIT routine to % 1 , allowing the line to
has the same effect as storing the same value in one of the go high (+5 volts). The Kernal RS-232 routines use this line
base register locations. For example, storing a value in as the transmitted data (TXD) output. You can also use the
56336/$DC10 or 56560/$DCF0 has the same effect as storing user port line for your own I/O functions.
a value in 56320/SDC00. However, it's better programming The remaining bits are used for the serial bus, the 128's
practice to use the officially designated register addresses. avenue of communications with disk drives and printers. The
lines are connected as follows:
486 487
56577 56577
6DD0i

Bit Port line Function


Line Pin RS-232 function
3 PA3 Handles output on the serial bus ATN line. FLAG B This interrupt input is tied to the received data
4 PA4 Handles output on the serial bus CLK line. line. The high-to-low transition on the line at the
5 PAS Handles output on the serial bus DATA line {for beginning of the start bit for an incoming byte will
slow serial mode). cause a FLAG interrupt to initiate the reception of
6 PA6 Handles input from the serial bus CLK line. the byte.
PA7 Handles input from the serial bus DATA line {for 0 FBO C RXD (received data). This input line is used to
slow serial mode). read incoming data bits from the modem or other
The bits for the output lines are all initialized to %0 by the external device.
\ PB1 D RTS (request to send). This output line is used to
IOINIT routine, causing the output lines to be pulled low {0 signal the modem that the 128 is ready to send a
volts). However, all these lines have inverters between the byte.
CIA and the serial port connector, so pulling the port lines low 1 PB2 E DTR (data terminal ready). This output line is used
allows the lines at the serial port connector to go high. Refer to signal the modem that the 128 RS-232 interface
to the discussion of Kernal serial input and output routines in is active.
Chapter 9 for more information on how these lines are used 3 PB3 F Rl (ring indicator). This input line is not supported
for serial bus communications. by the Kernal RS-232 routines, but is intended to
Port B (56577/$DD01) allow the modem to signal the 128 that a ringing
signal has been detected on the phone line. The
All the lines from port B are tied directly to the user port, a line, normally high, goes low when a ring is de-
24-pin connector located on the back of the 128. The lines are tected. (Commodore modems support this line.)
connected as follows: 4 PB4 H DCD (carrier detected). This input line is used to
Bit Port B line User port pin allow the modem to signal the 128 that it has de-
PBO C tected another modem on the other end of the
1 PB1 D telecommunications link. The line, normally high,
2 PB2 E goes low when the incoming carrier signal is
3 PB3 F detected.
4
PB4 H 5 PBS J This line is not formally assigned, but Commodore
5 PBS J modems use it to control whether or the not the
6 PB6 K modem is connected to the phone line. Since the
7 PB7 L line is configured by the IOINIT routine as an in-
put, you must change the corresponding data di-
All port lines are initialized as inputs, but this can be changed rection register bit to %1 to use the line as an
by changing the value in the port's data direction register at output for this control function. Writing a %0 to
56579/$DD03. The handshake line (PC) for port B is also this bit will connect the modem to the phone line
available at pin 8 of the user port, These lines provide a full (the off-hook state), while writing a %1 will dis-
eight-bit parallel I/O port for your own interfacing projects. connect (hang up) the modem.
6
However, the port B lines also have another use. The 128 PB6 K CT5 (clear to send). This input line is used to
lacks a true RS-232 hardware interface, so the Kernal RS-232 allow the modem to signal the 128 that it is ready
routines program the user port lines to support RS-232 com- to accept another byte.
7
munications (refer to Chapter 9 for details). For RS-232, the PB7 L DSR (data set ready). This input line is used to
port lines are used as follows: allow the modem to signal the 128 that it is active.
(The following port A line is also used:)
PA2 M TXD (transmitted data). This output line is used to
send data bits to the modem or external device.

488 489
56578 $DD02 SDDOD 56589

56578 $DD02 D2DDRA £fi582 $DD06 D2T2L


56579 $DD03 D2DDRB 56583 $DD07 D2T2H
Data direction registers
Timer B latch/counter registers
These registers specify whether the lines of ports A and B will Refer to the discussion of CIA #1 timer B at 56326-56327/
be inputs or outputs. Refer to the discussion of the CIA #1 $DC06-$DC07 for details of how these registers operate. For
data direction registers at 56322-56323/$DC02-$DC03 for de- CIA #2, the latch value for the register is not specifically ini-
tails of how these registers operate. For CIA #2, the IOINIT tialized during the reset or RUN/STOP-RESTORE sequences,
routine [$E1O9]—part of both the reset and RUN/STOP- although resetting the system will automatically set the latch
RESTORE sequences—initializes the port A DDR (56578/ count to 65535/$FFFF. The only use for this timer in system
$DD02) to 63/S3F, making port A lines PA0-PA5 outputs and ROM is during the routines which receive bits from the RS-
lines PA6-PA7 inputs, and the port B DDR (56579/$DD03) to 232 interface, where it is used to determine the duration of in-
0/$00, making all port B lines inputs. The port A setting is not coming bits. After RS-232 reception is completed, the timer
changed by any other ROM routine. Bits 0-1 of the port A will continue running with a latch count value dependent on
register should always remain set to %1 to keep PA0-PA1 the baud rate used in the RS-232 communications.
outputs for the VIC video bank selection function. You can
change the setting of the port B register freely to achieve the
desired user port I/O configuration. The routine to set up CIA 56584 $DD08 D2TOD1
#2 for R5-232 communications [$F0B0] will set the port B 56585 $DD09 D2TODS
DDR to 6/$06, which changes lines PB1-PB2 to outputs and 56586 $DD0A D2TODM
all the others to inputs. See the discussion of the data registers 56587 $DD0B D2TODH
at 56576-565 77/$DD00-$DD01 for more information on the Time-of-day clock registers
uses of the port lines. Refer to the discussion of the CIA #1 time-of-day clock regis-
ters at 56328-56331/$DC08-$DC0B for details of how these
56580 SDD04 registers operate. Like the CIA #1 time-of-day clock, these
D2T1L registers are unused in 128 mode, and are available for your
56581 $DD05 D2T1H own timekeeping projects.
Timer A latch/counter registers
Refer to the discussion of CIA #1 timer A at 56324-56325/ 56588 $DD0C D2SDR
$DC04-$DC05 for details of how these registers operate. For Serial data register
CIA #2, the latch value for the timer is not specifically initial- Refer to the discussion of the CIA #1 serial data register at
ized during the reset or RUN/STOP-RESTORE sequences, al- 56332/$DC0C for details of how this register operates. Unlike
though resetting the system will automatically set the latch the serial data line from CIA #1, the serial port (SP) line from
count to 65535/$FFFF. The only use for this timer in system CIA #2 is not used by the 128. It is, however, available at pin
ROM is during the routines which transmit bits over the RS- 7 of the user port on the back of the 128, along with the CNT
232 interface, where it is used to determine the duration of Une (at pin 6), so you can use this port for your own interfac-
outgoing bits. After RS-232 transmission is completed, the ing projects.
timer will continue running with a latch count value depen-
dent on the baud rate used in the RS-232 communications. 56589 $DD0D D2ICR
Interrupt control register
Refer to the discussion of the CIA #1 interrupt control register
at 56333/$DC0D for details of how this register operates. Be-
cause of the way CIA #2 is wired into the 128 system, the in-

490
491
56590 $DD0E 6nF00-$DFFF 57088-57343

terrupts it generates trigger processor NMI interrupts instead


of the IRQ interrupts generated by CIA #1. The IOINIT rou- mainder of this page of memory. That is, storing a value in
tine [$E109], executed during both the reset and RUN/ a ny location in this range with an address that is an exact
STOP-RESTORE sequences, initializes the interrupt mask for multiple of 16 greater than one of the base register addresses
this register to 0/$00, disabling all interrupt sources. Any CIA has the same effect as storing the same value in one of the
#2 interrupt source can trigger an NMI interrupt, but 128 base register locations. For example, storing a value in
ROM routines use only three of the possible sources: NMI in- 56592/SDD10 or 56816/SDDFO has the same effect as storing
terrupts generated by FLAG, timer A, and timer B are used to a value in 56576/$DD00. However, it's better programming
drive RS-232 communications. You can use any CIA #2 source practice to use the officially designated register addresses.
to generate an NMI interrupt for your own purposes. (The
FLAG interrupt input line is available at pin B of the user I/O Expansion Slot #1
port.) However, you'll have to write your own interrupt han-
dling routine. The standard NMI handler [$FA40] assumes that 56832-57087/$DE00-$DEFF
any CIA #2-generated interrupt it encounters is for RS-232, This range of addresses is available for future additional I/O
chips. No Commodore peripherals currently use this area, but
56590 $DD0E D2CRA it is possible that some third-party devices addressed in this
56591 $DD0F D2CRB area will appear. The original releases of CP/M for the 128
Control registers A and B (those dated prior to December 6, 1985) expect to find a UART
Refer to the discussions of CIA #1 control registers A and B at chip here for RS-232 serial communications, which is why the
56334/SDCOE and 56335/$DC0F, respectively, for details of RS-232 portion of those versions doesn't work. No expansion
how these registers operate. For CIA #2, these registers are card with a UART at this address was ever introduced, and
both initialized to 8/$08 by the IOINIT routine [$E109], part more recent versions of CP/M properly support RS-232 com-
of both the reset and RUN/STOP-RESTORE sequences. This munications in the standard fashion (via software). When no
value leaves both rimers stopped and set for one-shot mode. hardware chip is addressed here, all locations in this range
The only ROM routines which change those settings are the will appear to contain unpredictable changing values when
Kernal's RS-232 I/O routines. Timers A and B are used to read, and writing to addresses in this range will have no
generate the NMI interrupts which drive the transmission and effect.
reception of bits over the RS-232 interface. When RS-232
transmission is started, timer A is started, and it will continue I/O Expansion Slot #2
running in continuous mode even after the transmission is
completed and the logical file for RS-232 is closed (56590/ 57088-57343/$DF00-$DFFF
$DD0E will be set to 1/S01). Likewise, timer B is started when This range of addresses is available for additional I/O chips.
the first RS-232 byte is received, and will continue running in The REC (RAM expansion controller) chip in Commodore's
continuous mode even after the reception is complete and the RAM expansion modules is currently the only device to use
logical file has been dosed (56591/$DD0F will be set to this area, but it is possible that some other third-party devices
1/901). addressed in this area will appear. See the following section
for more information on the REC. When no hardware chip is
56592-56831 $DD10-$DDFF addressed here, all locations in this range will appear to con-
CIA #2 register images tain unpredictable changing values when read, and writing to
Due to incomplete address decoding, images of the CIA chip addresses in this range will have no effect.
registers appear repeatedly every 16 bytes throughout the re-

492
493
57088-57098 $DF00-$DF0A jDFOO 57088

REC (RAM Expansion Controller) Chip actually shuts down the 8502 microprocessor and takes com-
Registers plete control of the system. Because the REC is optimized for
the task of transferring data, it can perform its transfers with
57088-57098/$DF00-$DF0A blinding speed. The specifications for the 1700 and 1750 mod-
The REC chip is different from the other chips described in ules claim transfer rates of 1 million bytes per second for
this chapter in that it isn't part of the 128's internal hardware. stash, fetch, or verify operations, and half that rate for swap
No REC chip will be present unless you have a model 1700 or operations. In more practical terms, the REC can completely
1750 RAM Expansion Module plugged into the memory ex- fill the 8502's 64K address space in about 1/16 second, or
pansion port, since the REC is part of the hardware in the load an 8K bitmapped screen in 1/128 second—faster than
module. However, with an expansion module installed, the the 8502 itself can move the equivalent amount of data.
registers for the REC appear here just like the other hardware Table 8-9 lists the REC registers. A detailed description of
chip registers. Other chips could be addressed in this I/O slot, each register follows.
but the Kernal DMA_CALL routine [$F7A5] and the BASIC
STASH, FETCH, and SWAP statements all attempt to store
values in the REC registers listed below. Table 8-9. REC Chip Registers
Some would claim the expansion modules increase the Address Register
amount of available RAM in the system. This claim is a bit 57088/$DFO0 Status register
misleading. The 8502 processor cannot directly access any of 57089/$DF01 Command register
the 128K of RAM in a model 1700 expansion module or any 57090/$DF02 System RAM base address (low byte)
of the 512K in a 1750. RAM from the modules never appears 57091/$DF03 System RAM base address {high byte)
in the 128's normal address space; it cannot be used to fill in 57092/$DF04 Expansion RAM base address (low byte}
the missing RAM blocks 2 and 3 in the memory banking 57093/$DF05 Expansion RAM base address (high byte)
specifications. The REC chip is the 128's only gateway to the 57094/$DF06 Expansion RAM bank
expansion module RAM. The REC is actually a highly special- 57095/$DF07 Count of bytes to transfer (low byte)
ized processor dedicated to the task of transferring the con- 57096/$DF08 Count of bytes to transfer (high byte)
57097/SDF09 Interrupt mask register
tents of blocks of memory. It can perform four bask operations: 57098/$DF0A Address control register
transferring data from system RAM to expansion RAM (called
a stash operation), transferring data from expansion RAM to
system RAM (called a fetch operation), exchanging the con- 57088 SDFOO DMA ST
tents of an area of system RAM and an area of expansion Status register
RAM (called a swap operation), and comparing the contents of This register is read-only, meaning that writing values to this
an area of system RAM and an area of expansion RAM (called location has no effect on the setting of any register bits.
a verify operation). Bits 0-3: These bits hold a constant number (similar to a ROM
You'll notice that these are essentially the same basic location) indicating the version of the REC chip installed in
functions performed by a disk drive, which is why the expan- the expansion module. In the initial release of expansion mod-
sion module is sometimes referred to as a RAMdisk. The latest ules the value here is 0 (%0000), but this may change as re-
version of CP/M supports the expansion module as a virtual vised versions of the REC are introduced.
disk drive, referenced as drive M:. The 128-mode operating Sit 4: This bit indicates the amount of RAM available in the
system doesn't have this feature built-in, but a program to expansion module. A %0 here indicates that the REC is in a
provide a 128-mode RAMdisk would not be impossible to write. mode] 1700 module with 128K of RAM, while a %1 here indi-
The REC is a DMA (direct memory access) device, mean- cates that the REC is part of a model 1750 module with 512K
ing that when called upon to perform a transfer operation it of RAM.
494 495
57089 SDF01 57089
6PF0L

Bit 5: This bit, the fault flag, is set to %1 when a mismatch is eration and the Y register containing the REC command (the
detected during a verify operation. The bit is set whenever a value to be stored in this register). For example, BASIC sup-
verify error occurs, regardless of whether or not the cor- ports stash, fetch, and swap operations, but not verify. The fol-
responding bit in the interrupt mask register (57097/$DF09) is lowing routine is an example of how the current BASIC
set to trigger an interrupt on this condition. The bit is cleared program text could be verified against the expansion RAM
to %0 whenever the register is read. contents:
Bit 6: This bit, the end-of-block flag, is set to %1 when all
bytes for the operation have been transferred or verified. The 499 REM * SET SYSTEM STARTING ADDRESS TO START-OF-
PROGRAM VALUE
bit is set whenever an operation is successfully completed, re- 500 BANK 15:POKE 57090,PEEK(45):POKE 57091,PEEK{46
gardless of whether or not the corresponding bit in the inter- )
rupt mask register (57097/$DF09) is set to trigger an interrupt 509 REM * SET NUMBER OF BYTES TO END-OF-PROGRAM MI
on this condition. The bit is cleared to %0 whenever the regis- NUS START-OF-PROGRAM
ter is read. 510 POKE 57095,PEEK(4624)-PEEK{45):POKE 57096,PEEK
(4625)-PEEK(46)
Bit 7: This bit, the interrupt pending flag, signals that the REC 519 REM * SET EXPANSION ADDRESS AND BANK
has generated an IRQ interrupt. The REC can generate an IRQ 520 POKE 57092,0:POKE 57093,0:POKE 5 7 0 9 4 , 0
in response to two conditions: a verify error (fault) and the 529 REM * USE KERNAL DMA CALL ROUTINE {BANK = $00,
normal completion of an operation (end-of-block). Since the COMMAND = $83)
530 SYS 6 5 3 6 0 , , 0 , 1 3 1
8502 processor is inactive while the REC is performing a 539 REM * CHECK STATUS REGISTER FOR VERIFY ERROR F
transfer, the IRQ is actually generated after the REC returns LAG
control to the 8502, No IRQ will be generated unless the inter- 540 IF (PEEK(57088) AND 32 ) = 0 THEN PRINT"VEHIFY OK
rupt enable bit in the register at 57097/$DF09 is set to %1 ":ELSE PRINT"BYTE MISMATCH AT ADDRESS";PEEK(45)
+256*PEEK(46)+PEEK(57095)+256*PEEK(57096)-l
and one or both of the interrupt condition bits in that register
are set. Of course, a verify error will occur if a copy of the program
The normal IRQ interrupt handling routine [$FA65] has not been previously stashed in the corresponding area of
doesn't consider the REC as a source of interrupts, so you will expansion memory.
have to write your own routine to process IRQs from the REC.
See Appendix A for more information on interrupt handling. Bits 0-1: These bits determine the type of operation to be per-
Bits 5-7 of this register are cleared to %0 whenever the regis- formed by the REC. The four possible operations are specified
ter is read, so when testing this bit to determine whether an as follows:
interrupt has occurred you must save the value read from the Bits
register if you wish to subsequently test bits 5 and 6 to deter- 1 0 Operation
mine which event has caused the interrupt. 0 0 Stash (transfer from system memory to expansion RAM)
0 1 Fetch (transfer from expansion RAM to system memory)
57089 SDF01 1 0 Swap (exchange contents of system memory and expansion
DMA CMD RAM)
Command register
1 1 Verify (compare contents of system memory and expansion
This register determines the type of operation to be performed RAM)
by the REC. While it is possible to write directly to this regis- These bits are set to %00 during system reset. They retain
ter, the preferred practice is to use the Kernal DMA_CALL their settings after an operation is completed.
routine [$FF50], To use DMA_CALL, first set all the other
REC registers to their desired values; then call the routine with pits 2-3: These bits are described in Commodore literature as
the X register containing the system bank number for the op- "reserved," meaning that they have no function in the present
version of the REC, but may in some future version. For now,
496 497
57089 $DF01 $DF03. 57091

the bits seem merely to hold whatever value is written to 57090 $DF02 DMA ADL
them. They are set to %00 during system reset. 57091 $DF03 DMA ADH
Bit 4: This bit, called the $FF00 flag, controls the execution System memory base address registers
mode for REC operations. When this bit is %0, operations do This register pair specifies the starting address in the 128's ad-
not begin immediately when bit 7 of this register is set to % 1 , dress space for the current REC operation. The first register
but rather are deferred until a write to the MMU mode con- (57090/$DF02) holds the low byte and the second (57091/
figuration register (65280/$FF00) occurs. This is convenient $DF03) holds the high byte. The memory configuration in which
because it allows the memory configuration to be changed this address is seen is determined by the values in the MMU
after the MMU registers are set up. When this bit is % 1 , the configuration register (65280/$FF00) and RAM configuration
operation specified in bits 0-1 begins immediately when bit 7 register (54534/$D506). The configuration register setting de-
is set. This bit is set to %1 during reset, and also whenever an termines which ROM, if any, will be seen in the configuration,
operation is completed. Thus, the bit must always be specifi- and whether or not the I/O block will be visible. However, for
cally written with a %0 to enable the deferred execution option. REC data transfers the configuration register determines only
Bit 5: This bit, called the load flag, controls a special feature whether or not RAM is visible—not the block from which the
known as autoload mode. During a REC operation the system RAM is seen. That is, the setting of configuration register bits
and expansion base registers and expansion bank register are 6-7 is irrelevant to the REC. For DMA operations like REC
incremented and the byte-count registers are decremented. transfers, the RAM block is instead determined by the setting
When this bit is %0 {the default state after a reset), the regis- of bits 6-7 of the RAM configuration register. If you want to
ters are left at the end of an operation containing the final ad- transfer data to or from block 1 of RAM, you'll need to set bit
dresses and byte count. However, setting this bit to %1 6 of location 54534/SD506 to % 1 .
enables the autoload feature, in which case the address, bank, That RAM configuration register bit also controls the
and byte-count registers are automatically reloaded with their block from which the VIC chip (another DMA device) gets its
starting values after the operation is completed. This can be screen and character information, so be sure to reset the MMU
handy if you are repeatedly performing an operation involving register to its original value immediately after the REC opera-
the same area of memory. tion is completed. Switching the VIC to a bank with no pre-
pared screen data will turn the 40-column display to garbage,
Bit 6: This bit is described in Commodore literature as "re- but in practice REC operations are completed so quickly that
served," meaning that it has no function in the present version as long as the RAM configuration register bit is restored imme-
of the REC, but may in some future version. For now, the bit diately after the REC operation is completed, the result of the
seems merely to hold whatever value is written to it. switching is merely a barely noticeable flash of the screen. Of
Bit 7: This bit, known as the execute flag, is used to signal the course, the VIC block switching has no visible effect whatso-
REC to begin the operation specified in bits 0-1. However, the ever on the 80-column display.
start of the operation can be deferred. If bit 4 of this register is One interesting consequence of the fact that the REC uses
set to % 1 , the DMA process begins immediately when this bit the VIC block setting rather than the configuration register
is set. When bit 4 is %0, the operation does not actually start block setting is that the REC has no trouble seeing the lowest
until the next time a value is stored in location 65280/$FF00 IK of block 1 RAM, which is normally hidden from the pro-
(the MMU configuration register). In this case, the bit remains cessor under the common area from block 0. While bit 6 of the
set to %1 until the operation begins. In either case, the bit is RAM configuration register is set to % 1 , the REC can freely
cleared to %0 once the operation begins. transfer data to and from locations 0-1023/$0000-$03FF in
block 1.

498 499
ADF06 57094
57092 $DF04

wrap from the last address in the last bank to the first address
Both system base address registers are set to 0/$00 during of the first bank. Thus, the REC scarcely notices the bound-
system reset. During REC operations the address in the regis- aries between the expansion memory banks. For verify opera-
ters is usually incremented after each byte is transferred or tions that terminate with a fault (byte mismatch), the registers
verified, so that at the end of the operation the registers will will hold an address which is one location beyond the one at
hold a value one location higher than the last system memory which the mismatch was detected.
address involved in the operation. If the address reaches It is possible to have these registers automatically reloaded
65535/$FFFF, it will roll over to 0/$0000, but the configura- with the starting expansion memory address upon completion
tion will not change (the bank number will not be incre- of an operation. See the entry for bit 5 of the command regis-
mented). For verify operations that terminate with a fault (byte ter at 57089/$DF01 for details of the autoload feature.
mismatch), the registers will hold an address which is one lo- It is also possible to fix the expansion memory address so
cation beyond the one at which the mismatch was detected. that it does not increment. In this case, all bytes in the opera-
It is possible to have these registers automatically re- tion will be read from or written to the same expansion mod-
loaded with the starting system memory address upon com- ule memory location. See the entry below for the address
pletion of an operation. See the entry for bit 5 of the control register at 57098/$DF0A for more information on this
command register at 57089/$DF01 for details of the autoload feature.
feature.
It also is possible to fix the system memory address so 57094 $DF06 DMA BNK
that it does not increment. In this case, all bytes in the opera- Expansion bank register
tion will be read from or written to the same 128 memory lo-
cation. See the entry below for the address control register at This register holds the expansion bank number for REC
57098/$DF0A for more information on this feature. operations.
Bits 0-2: These bits determine the 64K bank of expansion
memory for the address in the registers at 57092-57093/
57092 $DF04 DMA LO $DF04-$DF05. The 1700 module has two 64K banks, so only
57093 $DF05 DMA HI the first two selections are valid for that model. The 1750 has
Expansion memory base address registers eight 64K banks. The possible bank selections are as follows:
This register pair specifies the starting address in the expan- Bits Expansion bank
sion module's address space for the current REC operation. 2 10 0
The first register (57092/$DF04) holds the low byte and the 0 0 0 1
second (57093/$DF05) holds the high byte. The expansion 0 0 1 2
memory bank in which this address is seen is determined by 0 10 3
O i l 4
the value in the expansion bank register at 57094/$DF06. 10 0 5
Both registers are set to 0/$00 during system reset. Dur- 1 0 1 6
ing REC operations the address in the registers is usually in- 1 1 0 7
cremented after each byte is transferred or verified, so that at 1 1 1
the end of the operation the registers will hold a value one lo- tf all the bytes involved in a REC operation are located within
cation higher than the last expansion memory address in- one bank, this register will still hold its original value after the
volved in the operation. When the address in these registers operation is completed. However, when the value in the expan-
exceeds 65535/$FFFF, the address wraps to 0/$0000, but the sion address register rolls over from 65535/$FFFF to 0/$0000,
expansion bank register is also incremented. For example, the the value here will be incremented, unless this register already
next byte after 65535/$FFFF in bank 3 of expansion RAM will
come from location 0/$0000 in bank 4, The address will also
501
500
57095 $DF07 6PF0A 57098

holds the highest bank number. In that case the bank number 57088/$DF00 signals when the REC has generated an IRQ,
will be reset to 0. These bits are reset to %000 when the com- and bits 5-6 of that register indicate which condition caused
puter is reset. the interrupt. After being set to % 1 , the bits in this register re-
Bits 3-7: Unused. Writing to these bits has no effect. The bits al- main set until specifically cleared. Thus, once REC interrupts
ways return %1 when read, so the value returned when this reg- are enabled, they remain enabled until at least bit 7 of this
ister is read will always be at least 248/$F8. To get the true bank register is reset to %0. Bits 5-7 are all reset to %0, disabling
number when reading the register, you should mask off these interrupts, when the system is reset.
bits. (Use AND 3 in BASIC or AND #$03 in machine language.) Bits 0-4: Unused. Writing to these bits has no effect. The bits
It is possible to have this register automatically reloaded always return %1 when read, which means that the value re-
with the starting bank number upon completion of an operation. turned when this register is read will always be at least 31/$1F.
See the entry for bit 5 of the command register at 57089/ $DF01 Bit 5: Setting this bit to %1 specifies that an IRQ interrupt is
for details of the autoload feature. to be generated when a verify operation terminates because
the bytes being compared do not match. However, no inter-
rupt will occur unless bit 7 of this register is also set to % 1 .
57095 $DF07 DMA DAL Bit 6: Setting this bit to %1 specifies that an IRQ interrupt is
57096 $DF08 DMA DAH to be generated if the current REC operation is completed
Count of bytes to transfer without errors, the end-of-block condition. However, no inter-
This pair of registers holds the number of bytes to be trans- rupt will occur unless bit 7 of this register is also set to % 1 .
ferred or verified in the current operation. The first register
(57095/$DF07) is the low byte of the count, and the second Bit 7: Setting this bit to %1 allows IRQ interrupts to be gener-
(57096/$DF08) is the high byte. As each byte is transferred or ated on either of the conditions specified in bits 5-6. No inter-
verified, the value in these registers is decremented. The regis- rupt will occur unless this bit is set, regardless of the settings
ters will always hold the value 1 ($01 $00) after an operation of bits 5-6. However, setting this bit to %1 won't produce in-
is successfully completed. If a verify operation stops because terrupts unless one or both of bits 5-6 are also set to % 1 .
of a fault (byte mismatch), the value in the registers will be Changing this bit to %0 does not affect the setting of bits 5-6.
the original value minus the number of bytes which have been
successfully verified when the fault occurs. All bits in these 57098 $DF0A DMA VER
registers are set to %1 (equivalent to a byte count of 65535/ Address control register
$FFFF) during system reset. Bits 0-5: Unused. Writing to these bits has no effect. The bits
It is possible to have these registers automatically re- always return %1 when read, which means that the value re-
loaded with the starting byte count upon completion of an op- turned when this register is read will always be at least 63/$3F.
eration. See the entry for bit 5 of the command register at Bits 6-7: These bits control the incrementing of the base ad-
57089/$DF01 for details of the autoload feature. dress registers. The four possible settings are as follows:
Bits
57097 $DF09 DMA SUM 7 6 Address register status
Interrupt control register 0 0 Both addresses increment
The REC can generate an 8502 IRQ interrupt on two condi- 0 1 Only the system (128) address increments
tions: When a byte mismatch is detected during a verify oper- 1 0 Only the expansion memory address increments
ation and when all bytes have been successfully transferred or 1 1 Neither address increments
verified. No IRQ will be generated unless bit 7 and one or
both of bits 5-6 are set to % 1 . Bit 7 of the status register at

502 503
57099-57119 $DFOB-$DF1F 53248-57343
$D000-$DFFF

The first option, both addresses increment, is the default set-


ting after power on or reset. With this setting, both registers Character Pattern ROM
are incremented after each byte is transferred or verified, so 53248-57343/$D000-$DFFF
that the operation involves a sequential series of locations in This ROM contains character shape information for the VIC
both system and expansion memory. However, it is possible to 40-column video chip, and also, indirectly, for the VDC 80-
fix either the system or expansion address. This allows you to column video chip. Because character shapes are drawn in an
fill either system or expansion memory with a repeating value. 8-dot X 8-dot matrix, each character pattern consists of 64
For example, to fill an area of expansion memory with a par- dots, each of which can be on or off. To store pattern infor-
ticular value, you would set these bits to increment only the mation, on-dots are represented by %1 bits and off-dots are
expansion address register, then store the value in a system represented by %0 bits. Thus, the pattern for each character
memory location and transfer the value to expansion memory requires 64 bits, or eight 8-bit bytes. Since the 128 can display
the desired number of times. The following example uses 256 different characters, a complete character set requires 256
BASIC to fill bank 1 of expansion memory with zeros: * 8 = 2048 bytes (2K). This 4K ROM has room for two com-
500 POKE 254,0: REM PLACE A ZERO IN SYSTEM MEMORY plete character sets. The first, at 53248-55295/$D000-$D7FF,
510 BANK 15:POKE 57098,128: REM FIX SYSTEM ADDRESS is known as the uppercase/graphics set. It is the default char-
520 STASH 65535,254,0,1: REM FILL EXPANSION MEMORY acter set for the 128—the one you see when you turn the
WITH THE VALUE IN SYSTEM LOCATION 254 computer on.
530 POKE 57098,0: REM RESTORE REC TO NORMAL MODE The second set, at 55296-57343/$D800-$DFFF, is known
You could use a similar technique to fill an area of system as the lowercase/uppercase set. Character patterns are stored
memory with the contents of an expansion memory location. in the ROM in screen code order. In fact, that's what screen
The final option, neither address incrementing, is useful only codes are—indexes into character ROM. See Appendix C for a
when a single byte is being transferred, table of character patterns for both sets.
As an example, consider the first character pattern in
57099-57119 $DFOB-$DF1F Unused the ROM, consisting of the eight bytes at 53248-53255/
When the REC is present, all the unused register addresses in $D000-$D007. As the first pattern, it corresponds to the char-
this range return the value 255/$FF when read. Writing to acter with screen code 0/S00, the @ character. The pattern is
these addresses has no effect. shown in Figure 8-18.

57120-57343 $DF20-$DFFF
REC chip register images Figure 8-18. Typical Character Pattern
Due to incomplete address decoding, images of the REC chip % 00111100 •» 53C
registers appear repeatedly every 32 locations throughout the % 01100110 - S66
remainder of this page of memory. That is, storing a value in % 01101110 - $6E
any location in this range with an address an exact multiple of Vn 01101110 - $6E
32 greater than one of the REC register base addresses has the % 01100000 - $60
same effect as storing that value in the base register location. % 01100010 - S62
For example, the effect of storing a value in 57121/$DF21 or % 00111100 = $3C
57313/$DFE1 is the same as storing the value in 57089/ % oooooooo = $00
$DF01. However, it's better programming practice to use the
officially designated register addresses.

504 505
53248-57343 $DOOO-$DFFF fer>O00-$DFFF 53248-57343

For the VIC chip, this character ROM is the normal source 100 BANK 14:CA = 53248:CS = 8192
of character data. Bits 1-3 of the VIC register at 53272/$D018 110 FOR 1=0 TO 2047
control which 2K block within the current 16K VIC video bank 120 POKE CS + LFEEK(CA+D
is seen as the character source. Since the VIC's default video 130 NEXT I
bank 0 corresponds to locations 0-16383/$0000-$3FFF in the To copy the lowercase/uppercase set, change the value of the
processor's address space, it would seem impossible for the variable CA to 55296. The following routine shows one
character ROM at 53248/$D000 to be used as the normal char- method for accomplishing the same thing in machine language:
acter source. However, the 128's memory manipulation ca- 1400 LDA #$08 ;number of 256-byte pages
pabilities are used to make the ROM appear to the VIC at an 1402 STA $FA ; to be copied
address within the video bank. The uppercase/graphics set ap- 1404 LDA #$00 ;load pointer at $FB with
pears at 4096-6143/$1000-$17FF and the lowercase/uppercase 1406 STA $FB ; target address ($2000)
set appears at 6144-8191/$1800-$lFFF. Only the VIC chip 1408 LDA #$20
sees the character ROM at those addresses; when the MMU 140A STA $FC
configuration register is set to allow the microprocessor to see 140C LDA #$00 ;load pointer at $FD with
the ROM, the processor always sees it at 53248/$D000. The 140E STA $FD ;source address ($D000)
VIC chip, on the other hand, never sees the ROM at its actual 1410 LDA #$D0
1412 STA $FE
address. That couldn't be possible; remember, the VIC itself 1414 LDY #$00 initialize offset
resides at 53248-53296/$D000-$D030. 1416 LDX #$0E ;read from bank 14
The VIC can see the character ROM in any of its four 1418 LDA #$FD ;use $FD as source pointer
video banks. In each case, the uppercase/graphics set appears 141A JSR $FF74 ;Kernal INDFET routine
to the VIC at an offset of 4096/$1000 from the starting ad- 141D STA ($FB),Y ;store in target address area
dress of the video bank, and the lowercase/uppercase set ap- 141F INY
pears at an offset of 6144/$1800 from the first address of the 1420 BNE $1416 ;repeat for 256 bytes per page
video bank. It is possible to disable the ROM image feature so 1422 INC $FC
1424 INC $FD ;increment page pointers
that the VIC never sees character ROM at all. This would be
useful, for example, if you wished to place a custom character 1426 DEC $FA
1428 BNE $1414 ;decrement block count
set in the free RAM at 6144-7167/$1800-$1BFF. Bit 2—called
142A RTS
the CHREN bit—in the 8502's on-chip I/O port at location
l/$01 determines whether or not the ROM image is visible in Refer to the discussion of the VIC chip earlier in this chapter
the current VIC video bank. See Chapter 2 for more infor- for more information on creating and using custom character sets.
mation on the I/O port bit and its associated shadow location, As mentioned, this ROM indirectly supplies character pat-
217/$D9. terns for the VDC (8563) 80-column video chip. That chip has
When setting up custom character sets, you may want to no character ROM of its own, so the contents of this ROM are
copy all or part of the character pattern data from this area of copied into the VDC's private block of RAM during the reset
ROM into RAM. Remember that the only standard bank con- sequence (see the INIT80 routine [$CE0C] in Chapter 7). Refer
figuration in which character ROM is visible is bank 14, The to the section on the VDC earlier in this chapter for more
following BASIC lines will copy the uppercase/graphics set information on how the 80-column character set is managed.
into RAM at 8192-10239/$2000-$2800. (You must have pre-
viously protected this area from BASIC. Using GRAPHIC
1:GRAFHIC 0 to reserve the bitmapped screen area is a simple
way to do this.)

506 L 507
Kernal ROM
In software engineering jargon, the collection of subroutines
that perform basic input and output functions for a computer
is referred to as the operating system kernel. The developers
of the kernel for the original Commodore PET spelled (or mis-
spelled) the term as kernal, and Commodore operating systems
have been referred to as the Kernal ever since. There are both
similarities and significant differences between the 128 Kernal
and the Kernals of earlier models.
The Kernal handles input from or output to five basic
sources: the keyboard, the video screen, the tape drive (Datas-
sette), the RS-232 port, and the serial bus (to which disk
drives and printers are connected). In the 128 Kernal, all key-
board and video functions have been transferred to a separate
block of ROM, the screen editor, at 49152/$C000 (see Chapter
7 for details).
Significant enhancements include the addition of an 80-
column screen, ESC-key screen-editing sequences, and key-
board table pointers in RAM that make it easy to customize
the keyboard. Tape and RS-232 support is largely unchanged
from that provided in the Commodore 64 Kernal. Serial bus
operation is significantly enhanced by the addition of a new
fast serial mode which can transfer data much more quickly
than the old system, now fittingly referred to as slow serial
mode.
Additional new features of the 128 Kernal include routines
to handle the storage, retrieval, and comparison of data from
the various memory banks supported by the system, and sup-
port for DMA (Direct Memory Access) transfer operations to
and from the 1700 and 1750 Memory Expansion Modules.
The heart of the Kernal is the collection of routines called
by the Kernal jump table at 65409-65525/$FF81-$FFF5. The
routines called from that table, and their supporting subrou-
tines, make up the bulk of the Kernal and provide access to
the majority of the 128's input/output (I/O) capabilities. Al-
most any I/O operation can (and should) be performed
through the appropriate jump table entry. The Kemal jump ta-
ble has been a feature of all Commodore operating systems.

511
57344 8E000 SE04B 57419

The 128 adds an additional jump table with 19 new entries at initialization flag (2562/S0A02) is checked. If the flag contains
65351-65407/$FF47-$FF7E These entries provide access to a nonzero value, the following memory initialization step is
most of the 128 Kernal's new or enhanced features, skipped. Since the flag is given the value 165/SA5 after the
first call to RAMTAS [$E093], zero-page values and memory
57344 $E000 RESET pointers are preserved if RUN/STOP is held down during a
Performs main system initialization sequence. subsequent reset. Otherwise, RAMTAS [$E093] is called to
Resets the processor stack pointer to the top of the stack, dis- clear all zero-page RAM locations and reestablish Kernal
ables IRQ interrupts, and insures that the processor is not in pointers.
decimal mode; then sets the MMU configuration register for RESTOR [$E056] is called to load default Kernal indirect
bank 15. Other MMU registers are initialized from the table at vectors into 788-819/$0314-$0333. CINT [$CO0O] is called to
57419/$E04B. Next, the initialization status flag (2564/$0A04) initialize the screen editor, after which IRQ interrupts are once
is reset to 0/$00 to indicate that all variables and vectors need again allowed. If the RUN/STOP key has been pressed, the
to be initialized. The interrupt and reset handling routines at monitor is entered through its cold start entry point [$B000]. If
65285-65348/$FF05-$FF44 in Kernal ROM are copied to that the Commodore key has been held down, 64 mode is entered
same area in all RAM banks, and the INDFET, INDSTA, using the C64_MODE routine [$E24B], Otherwise, BASIC 7.0
INDCMP, J5RFAR, JMPFAR, and DMA_CALL routines are is entered via the restart vector at 2560/S0A00. If the
copied from the table at 63488/$F800 into bank 0 RAM. RAMTAS step has been performed, the restart vector will
Locations 65525-65527/$FFF5-$FFF7 in bank 1 are then point to BASIC'S cold start entry point [$4000].
examined to see if they contain the character codes for the let- It is possible to perform most of the reset sequence with-
ters CBM, If not, those locations are initialized with that char- out losing the BASIC program currently in memory. Simply
acter pattern, and the soft reset vector at 65528/$FFF8 in bank hold down RUN/STOP while pressing the RESET button,
1 is initialized. However, if the test pattern is found (indicating This will skip the RAMTAS step, which would wipe out im-
that RESET has already been performed at least once), the portant program pointers. You will land in the monitor after
routine jumps to the address in the vector. Normally, the vec- the reset; type X to exit to BASIC, where the current program
tor points to the routine at 57892/$E224, which simply should still be intact.
reinitializes the test pattern and vector. You can change the Note that the reset routine does not explicitly attempt to
address to add your own extra steps to the reset sequence. See boot a disk or to initialize function ROMs that are not
the soft reset vector entry in Chapter 4 for details. autostarting. These tasks are performed by the Kernal PHOE-
The subroutine at 57922/$E242 is called to check for the NIX routine [$F867]. In 128 ROM, PHOENIX is called only
presence of a Commodore 64 cartridge. If one is detected, the during the BASIC cold start routine [$4023]. However, as long
system is switched to 64 mode and the computer becomes a as the RUN/STOP or Commodore key is not held down, the
Commodore 64. (You must press the RESET button or turn reset routine ends by jumping to the BASIC cold start routine,
the computer off and back on to return to 128 mode.) Other- so those actions are implicitly part of the normal reset
wise, the subroutine records the presence of any 128 function sequence.
ROMs in the table at 2753-2756/$0ACl-$0AC4. If a logged
function ROM is autostarting, its cold start routine is called. It 57419 $E04B
is possible that an autostarting ROM will retain control of the Table of default MMU register settings.
system and will not return to complete the reset sequence. The 11 values in this table are copied into the MMU chip reg-
Next, the IOINIT routine [$E109] is called to initialize the isters at 54528-54538/$D500-$D50A by the system reset rou-
video, CIA, and SID chip registers. The keyboard column tine [$E000]. See Chapter 8 for details of the function and
which includes the RUN/STOP and Commodore keys is default settings of the registers.
scanned. If RUN/STOP has been pressed, the Kernal memory
512 513
57430 SE056 SE109 57609

57430 SE056 RESTOR 57549 $E0CD


Restores Kernal indirect vectors to their default values. Initializes all RAM-resident Kernal routines.
{This routine has a jump table entry at 65418/$FF8A.) Copies the interrupt- and reset-handling routines at
Loads the X and Y registers with the value 57459/$E073, the 65285-65348/$FF05-$FF44 in Kernal ROM into the same ad-
address of the default vector table, then clears the status regis- dresses in both RAM banks. These routines redirect interrupts
ter carry bit, and falls through into the following routine to and reset to the proper handling routine in Kernal ROM (bank
load default vector values. 15). It's necessary to have a copy in each bank, because an in-
terrupt or reset can occur while the system is configured for
57435 $E05B VECTOR any bank. The routines are actually copied into banks 0-3,
Loads or copies Kernal indirect vector values. even though there isn't unique RAM in banks 2 and 3 in the
(This routine has a jump table entry at 65421/$FF8D.) current 128.
Transfers the address value in the X and Y registers upon en- Next the code for the RAM-resident portions of vital indi-
try into a working pointer (195-196/$C3-$C4). If the carry bit rect access routines—INDFET [$02A2], INDSTA [$02AF],
is clear, 32 bytes starting at the specified address are copied to INDCMP [$02BE], JSRFAR [$02CD], and JMPFAR [$02E3]—is
the Kernal indirect vectors at 788-819/$0314-$0333. If carry copied from the table at 63488/$F800 into page 2 of the com-
is set, the contents of the indirect vectors are copied to 32 lo- mon area of RAM. Finally, the code for the DMA_CALL exe-
cations starting at the specified address. In either case, the tar- cution routine [$03F0] is copied from 63578/$F85A into page
get address must be visible in bank 15. 3 of the common area of RAM.
57459 $E073 57609 $E109 IOINIT
Table of default Kernal indirect vector values. Initializes I/O chip registers.
The 16 two-byte values in this table are copied to the Kernal (This routine has a jump table entry at 65412/SFF84.)
indirect vectors (788-819/$0314-0$333) by the RESTOR rou- Begins by disabling all interrupt sources on both CIA chips
tine [$E056], part of the reset sequence. See Chapter 2 for the and halting all CIA timers. All lines from the four CIA I/O
default vector target addresses. ports (ports A and B on both chips) are assigned their default
directions, input or output. Output lines are also assigned their
57491 SE093 RAMTAS default states, high or low. See Chapter 8 for more infor-
Initializes zero page and Kernal pointers. mation on the functions and default settings of these lines.
(This routine has a jump table entry at 65415/$FF87.) The direction and status of lines connected to the processor's
Sets all zero page RAM locations (2-255/$02-$FF) to 0/$00, built-in I/O port are also established. See Chapter 2 for more
then initializes the cassette buffer pointer (178-179/$B2-$B3) information on the functions of these lines.
to 2816/S0B00, the RS-232 input buffer pointer (200-201/ The VIC-II video chip's raster compare register is tested to
$C8-$C9) to 3072/$0CO0, and the RS-232 output buffer determine whether the raster line count ever reaches the value
pointer (202-203/$CA-$CB) to 3328/SODOO. The MEMSIZ 264/$108. This indicates which video system, NTSC (North
pointer (2567-2568/$0A07-$0A08) is set to 65280/$FF00 American) or PAL (European), is being used. The video sys-
to mark the top of free RAM, and the MEMSTR pointer tem depends on the VIC-II chip currently installed. There are
(2565-2566/$0A05-$0A06) is set to 7168/$1COO to mark the separate versions for NTSC and PAL. The highest possible
bottom of free RAM in bank 0. The BASIC restart indirect vec- raster line for an NTSC system is 263, so a value of 264 here
tor (2560-2561/$0A00-$0A01) is loaded with 16384/$4000, means that the system is using PAL. The NTSC/PAL flag
the address of BASIC'S cold start entry point. Finally, the (2563/$0A03) is set accordingly—to 0/$00 for NTSC or
Kernal memory initialization flag (2562/$0A02) is set to 255/$FF for PAL. By designing the Kernal to adjust itself for
165/$A5 to indicate that this routine has been performed. either system. Commodore's engineers avoided the need for
514 515
57820 BE IDC SE24B 57931

separate versions of the Kernal for North American and Euro- numbers and initializes registers until a value greater than
pean 128s. 127/$7F is read for the register number. Normal X register
Next, a number of Kerna! I/O flags are cleared: clock values upon entry are 0/$00 (to initialize the 8563), 59/$3B
mode storage (2615/$0A37), IRQ vector storage (2570/$0A0A), (to adjust horizontal scrolling for different versions of the 8563
custom mode setting (2618/$0A3A), and jiffy count com- chip), or 62/S3E (to adjust register settings for a PAL video
pensation (2614/$0A36), The keyboard (device 0) is made the system).
current input device (153/S99), and the screen (device 3) is
made the current output device (154/$9A).
57840 $E1FO
VIC-II chip registers (53248-53296/$D000-$D030) are Initializes or jumps through the soft reset vector.
initialized from the table at 58055/$E2C7, and 8563 video
Examines the contents of locations 65525-65527/$FFF5-$FFF7
chip registers are initialized using the subroutine at
in bank 1 to determine whether those locations contain the
5782O/$E1DC. If the version number of the 8563 chip (bits
character codes for the letters CBM. If not, a branch is taken to
0-2 of the register at 54784/$D600) indicates that one of the
newer revisions of that chip is installed, the subroutine is the following routine to initialize the test pattern and vector. If
called again to adjust the horizontal scrolling register (R25). If the pattern is found, the reset vector has already been initial-
the PAL video system is in use, the subroutine is called yet ized, so the address in the vector at 65528-65529/$FFF8-$FFF9
again to adjust vertical display registers (R4 and R7). Bit 7 of in bank 1 is loaded into locations 2-3/$02-$03. The routine
the initialization status flag (2564/$0A04) is tested. If the bit is then takes an indirect jump to the specified address. (The sys-
set to % 1 , IOINIT has been called at least once before, so the tem will still be configured for bank 15, so the target routine
following step, which sets up the 80-column character set, is must in that bank.)
skipped. If the bit is %0 (as will normally be the case when
this routine is called as part of the reset sequence), the screen 57892 $E224
editor INIT80 routine [$C027] is called to copy the ROM char- Initializes the soft reset vector.
acter definitions into 8563 RAM. Then bit 7 of the initializa- Loads the system soft reset vector, locations 65528-65529/
tion status flag will be set to %1 to indicate that the step has $FFF8-$FFF9 in bank 1, with the value 57892/$E224, the ad-
been performed. dress of this routine. Next, the character codes for the letters
All registers for the SID sound chip (54272-54296/ CBM are copied to locations 65525-65527/$FFF5-$FFF7 in
$D400-$D418) are cleared to zero to disable any sound out- bank 1 to indicate that the vector has been initialized.
put; then VIC-II raster interrupts are enabled. The raster inter-
rupt (set by the default table value to occur at scan line 255) is 57922 $E242
the normal source of jiffy IRQ interrupts for the 128. The fast Checks for the presence of 64 cartridges or 128 function ROMs.
serial flag (2588/$0AlC) and RS-232 activity flag (2575/ Tests the GAME and EXROM lines from the memory expan-
$0A0F) are cleared to zero. Timer B of CIA #1 is loaded with sion port (reflected by bits 4 and 5 of the MMU mode configu-
65535/$FFFF and started counting continuously. Finally, a fast ration register at 54533/$D505). If either of the lines is
serial mode setup sequence is performed. grounded, the routine falls through to enter 64 mode. Other-
wise, a branch is taken to the routine at 57963/$E26B to
57820 $E1DC check for 128 function ROMs.
Initializes 80-column video chip registers.
Retrieves a byte from the position in the table at 58104/$E2F8 57931 $E24B C64_MODE
specified in the X register. The value is used as a register num- Switches the system into 64 mode.
ber and the next value in the table is written to that 8563 reg- (This routine has a jump table entry at 65357/$FF4D.)
ister, Once called, the routine repeatedly reads register Loads the processor data direction and I/O port registers
(locations 0-l/$00-$01) with their standard Commodore
516 517
57963 $E26B 58174
SE33E

64 settings, copies the reset routine from 57955-57962/ 58055 SE2C7


$E263-$E26A to 2-9/$02-$09, stores a zero in the clock rate Table of default VIC chip register values.
register (53296/$D030) to insure that the system is in slow (1 The 49 values in this table are copied to the V1C-II 40-column
MHz) mode, then jumps to the reset-to-64 routine at 2/$02. video chip registers during the IOINIT routine [$E109] to es-
The short routine copied there stores the value 247/$F7 in the tablish default register settings. See Chapter 8 for more infor-
MMU mode configuration register. Compared to the default mation on the registers and their default settings.
setting, that value clears bit 3 (prohibiting fast serial output)
and sets bit 6 (making 64 ROM visible while making 128
ROM and the MMU chip registers invisible). The routine then
58104 $E2F8
initializes 64 mode by jumping through the hardware reset Table of default 8563 chip register values.
vector (65532/$FFFC) in the now-visible Commodore 64 ROM. The first value in each two-byte table entry is the number of
the 8563 80-column video chip register into which the second
57963 $E26B value is to be copied. The register settings are initialized by
the routine at 5782O/$E1DC.
Logs 128 function ROMs.
Clears the function ROM ID table (2 753-2 75 6/$0ACl-$0AC4), 58171 $E33B TALK
then checks the seventh through ninth bytes beyond the start- Sends TALK command to a serial device.
ing address in each of the four possible memory slots for func- (This routine has a jump table entry at 65460/$FFB4.)
tion ROM: 32768/$8000 and 49152/$C000 in bank 8 for
Sets bit 6 of the device number value in the accumulator to
external (cartridge) ROM, and 32768/$8000 and 49152/$COO0
%1 (the serial bus TALK command has the format %010?jnrittn,
in bank 4 for internal ROM (in the free socket on the 128's
where %nnnnn is the number of the device being commanded
main circuit board). If the bytes are the character codes for the
to talk). A BIT opcode is used to fall through into the next
letters CBM, a valid function ROM is present in the slot, and
routine to send the byte as a serial bus command.
the sixth byte beyond the starting address (the cartridge ID) is
retrieved and stored in the ID table. If the ID value is 1, indi-
cating an autostarting ROM, the starring address of the ROM 58174 $E33E LISTEN
Sends LISTEN command to a serial device.
is loaded into the JSRFAR pointer (3-4/$03-$04), and JSRFAR
(This routine has a jump table entry at 65457/$FFBl.)
[$02CD] is used to call the ROM's cold start routine. (It is pos-
sible that the autostarting ROM will retain control of the sys- Sets bit 5 of the device number value in the accumulator to %1
tem and not return.) ROMs that don't autostart are initialized (the serial bus LISTEN command has the format %001nnnnn,
during the PHOENIX routine [$F867J. where %nnnnn is the number of the device being commanded
to listen). RS-232 activity is disabled. If a serial byte is await-
ing transmission in the buffer at 149/$95, it is sent with an
58052 $E2C4 EOI (end-or-identify) handshake; then the command byte is
placed in the buffer.
Initialization test pattern.
The subroutine at 58739/$E573 is used to disable IRQ in-
These three bytes are the character codes for the letters CBM, terrupts and standardize timing. Then the serial bus DATA
used as a test pattern in various operations: testing whether line is allowed to go high. If the serial bus ATN line is not
the soft reset vector has been initialized [$E1FO], checking for currently low, the routine attempts to establish fast serial
128 function ROM [$E26B], and checking for boot disks mode. It does this by setting the serial port for fast serial out-
[$F890]. put and sending out the value 255/$FF (eight %1 bits) using
the fast serial hardware. The port is then set for fast serial in-
put mode, and a short delay loop is executed. If a serial device

519 519
58174 SE33E 6E38C 58252

capable of fast serial communications is present, it should re- Next, the serial bus ATN line is pulled low to indicate
spond by sending back a byte. This will cause a serial register that the following byte will be a command. The serial bus
interrupt on CIA # 1 , which will be detected later to determine CLK line is pulled low, and the DATA line is allowed to go
that fast serial mode is available. high. A delay loop of approximately one millisecond is exe-
cuted, and the routine falls through into the following routine
to send the command byte. Figure 9-1 illustrates the process.
Figure 9-1. Sending a Serial Command Byte Note that there is no corresponding routine for the 128
to receive a serial bus command. The 128 has no ATN input
line, so it cannot be commanded to listen (it only listens "vol-
untarily"). It must always be the only master device on the se-
rial bus.

58252 SE38C
Sends buffered byte to a serial device.
Begins by calling the subroutine at 58739/$E573 to disable
IRQ interrupts and standardize timing. If the system is set for
the fast {2 MHz) clock mode, it will be temporarily reset to the
normal (1 MHz) mode, which explains why serial communica-
1. 128 pulls ATN line low. tions are not significantly affected by the clock mode.
2. 128 pulls CLK line low and allows the DATA line to go high. The routine makes sure that the serial bus DATA line is
3. The external device must respond by holding the DATA line low. free to go high, then tests the state of the line. If the external
If the DATA line is still high after approximately one millisecond, device is not holding DATA low, the device is considered not
it is assumed that the device is not present. present, so bit 7 of the serial status flag (144/$90) will be set
4. If the external device responded, the 128 allows the CLK line to to % 1 , the ATN and CLK lines will be allowed to go high, and
go high. the routine will exit. Otherwise, the routine will allow the CLK
5. The external device must now allow DATA to go high again. (The line to go high. If bit 7 of the EOI flag (163/$A3) is set to % 1 ,
128 will wait indefinitely for this to happen.) the routine performs the EOI (end-or-identify) handshake by
6. Once DATA goes high, the 128 responds by pulling the CLK line waiting for the external device to set the DATA line high and
low. then low. Next, the routine waits for the external device to re-
7. The command byte is then sent one bit at a time, starting with the lease the DATA line to a high state. While it's waiting, the
least significant bit (bit 0). Command bytes are always sent in routine checks whether a CIA #1 serial register interrupt has
slow serial mode. To send a bit, the DATA line is set either low or occurred, indicating that a byte has been received via the fast
high, depending on whether the bit being sent is %0 or % 1 . Then
the CLK is allowed to go high briefly to signal that a valid bit can serial hardware. If so, the external device can accept fast serial
be read on the DATA line. input, and the fast serial flag (2588/S0A1C) is set to 192/$C0
8. After the last data bit is sent, the 128 checks the DATA line. The to indicate this.
external device must pull that line low within approximately one Once the DATA line goes high, the routine immediately
millisecond or a write-timeout error will be indicated. pulls the CLK line low and proceeds to send the byte of data.
9. The status of the ATN line after a command is sent depends on If fast serial mode is available, the process is simple: The serial
the command. If it is TALK or LISTEN, ATN remains high so that port is set for fast serial output, and the buffered byte from
the secondary address can be sent as a command as well. How- 149/$95 is stored in the CIA #1 serial data register (56332/
ever, ATN is immediately pulled low following UNTALK and $DC0C). After that, the transfer is automatic, handled by the
UNLISTEN commands.

520 521
v
58252 SE38C SE38C 58252

CIA chip hardware. The routine simply waits until a serial reg- allowed to go high again. If the external device holds the
ister interrupt indicates that the byte has been completely sent, DATA line low between bits, a write-timeout occurs (the rou-
then resets the port for fast serial input (its default state). tine sets bits 0 and 1 in the serial status flag to % 1 , allows the
The process for sending a byte in standard (slow) serial ATN and CLK lines to go high, and exits).
mode is more complicated because it is handled in software. After the byte has been sent (in either mode), the routine
Bits are pulled from the buffered byte (149/$95), one at a waits for the external device to pull the DATA line low. If this
time, starting with the least significant tit (bit 0). For each bit, does not happen within approximately one millisecond, a
the serial bus DATA output line is set either high or low, de- write-timeout occurs, and the routine sets bits 0 and 1 in the
pending on whether the bit to be sent is %0 or % 1 . Then the serial status flag to % 1 , allows the ATN and CLK lines to go
CLK line is allowed to go high to signal to the external device high, and exits. Otherwise, the routine at 58783/$E59F is used
that a valid data bit can be read from the DATA line. After a to restore interrupts and the clock mode setting, then exits
brief delay, the CLK line is pulled low, and the DATA line is with the status register carry bit clear. The Y register is unused
during the routine, and the X register value is preserved. Fig-
ure 9-2 illustrates the process of sending a data byte. Figure
Figure 9-2. S e n d i n g a Serial Data Byte 9-3 illustrates the EOI handshake.

1. The 128 allows the DATA line to go high. If the external device
does not continue to hold the line low, it is assumed that the de-
vice is not present.
2. The 128 allows the CLK line to go high.
200 \is.
3. The external device must now allow DATA to go high. (The 128
will wait indefinitely for this to happen.) 1. As in a normal byte transfer, the external device must hold the
4. Once DATA goes high, the 128 responds by pulling the CLK line DATA line low or it will be assumed that the device is not
low. present.
5. The data byte is sent one bit at a time using either fast or slow se- 2. The 128 allows the CLK line to go high.
rial mode. To send a bit in slow serial mode {illustrated above), 3. The external device should then allow the DATA line to go high.
the DATA line is set either low or high, depending on whether the (The 128 will wait indefinitely for this to happen.)
bit being sent is %0 or % 1 . Then the CLK line is allowed to go 4. When the 128 does not respond by pulling the CLK line low
high briefly to signal that a valid bit can be read on the DATA within 200 microseconds, the external device should recognize
line. Fast serial mode works in a similar manner, except the trans- that an EOI handshake is being performed and should respond by
fer is managed by CIA chip hardware rather than ROM software, pulling DATA low again. (The 128 will wait indefinitely for DATA
and the bits are clocked by pulses on the SRQ line rather than on to go low.)
the CLK line, 5. The external device should then release DATA high again. The
6. After all of the byte is sent, the 128 checks the DATA line. The ex- 128 will respond by pulling CLK low, and the final byte of the file
ternal device must pull that line low within approximately one is then sent in the usual manner. (See steps 5-6 of Figure 9-2.)
millisecond, or a write-timeout error will be indicated.

522 523
58430 6E43E SE43E 58430

58430 8E43E ACPTR is preserved. Figure 9-4 illustrates the process of receiving a
Reads a byte from a serial device. data byte.
(This routine has a jump table entry at 65445/$FFA5.)
Begins by calling the subroutine at 58739/$E573 to disable Figure 9-4. Receiving a Serial Data Byte
IRQ interrupts and standardize timing. If the system is set for
the fast (2 MHz) clock mode, it will be temporarily reset to the
normal (1 MHz) mode, which explains why serial communica-
tions are not significantly affected by the clock mode. The rou-
tine insures that the serial bus CLK line is free to go high,
then tests the state of the line and waits in a loop until it goes
high. Next, a delay counter is initialized, and the DATA line is
allowed to go high. If the external device responds by pulling
the CLK line low before the delay count expires, the routine
begins to process the incoming data bits. Otherwise, it assumes
that the external device is requesting an EOI (end-or-identify)
handshake. So the EOI bit (bit 6) of the serial status flag
(144/$90) is set to % 1 , and the DATA line is pulled low, then
allowed to go high again. The external device must acknowl- 1. The 128 allows the CLK line to go high and waits for it to go high
edge the EOI handshake by pulling the CLK line low before if the external device is holding it low.
another delay period expires. If it doesn't, a read-timeout oc- 2. Once the CLK line goes high, the 128 allows the DATA line to go
high.
curs, and the routine sets bit 1 in the serial status flag to % 1 , 3. The 128 waits for the external device to respond by pulling the
allows the ATN and CLK lines to go high, and exits. CLK line low. If this hasn't happened after a delay of approxi-
If a serial register interrupt has occurred on CIA #1, a mately 260 microseconds, the 128 assumes that an EOI handshake
byte has been received via the fast serial hardware. In this is requested and briefly pulls the DATA line low. The external
case, the byte is retrieved from the serial data register device must respond by pulling CLK low before another 260-
(56332/$DC0C) and stored in 164/$A4; then the fast serial microsecond delay expires; otherwise, a read-timeout error will
flag (2588/$0AlC) is reset to 192/$C0. occur,
The process for receiving a byte in standard (slow) serial 4. Once the CLK line goes low, the 128 prepares to read data. To re-
mode is more complicated because it is handled in software. ceive a bit in slow serial mode (illustrated above), the 128 waits
The routine waits for the data line to go high and then for the until the CLK line goes high, reads the CIA port bit connected to
CLK line to go low. Then, when CLK goes high again, a bit is the DATA input line, then waits for the CLK line to go low again.
Fast serial mode works in a similar manner, except the transfer is
read from the DATA line and shifted into the working byte managed by CIA chip hardware rather than ROM software, and
(164/$A4). The routine waits until CLK goes low before at- the bits are clocked by pulses on the SRQ line rather than the
tempting to read the next bit, and the process is repeated for CLK line.
each of the eight bits of the byte. 5. After the byte is received, the 128 pulls the DATA line low to in-
After a byte has been received, the DATA line is pulled dicate the end of the byte frame.
low to mark the end of the frame. If the EOI handshake has 6. If the EOI handshake is performed, the CLK line is allowed to go
been performed, the CLK line is allowed to go high. The rou- high after the byte is received.
tine at 58783/$E59F is used to restore interrupts and the clock
mode setting. The routine exits with the status register carry
bit clear and with the received byte in the accumulator. The Y
register is unused during the routine, and the X register value

524 525
58578 $E4D2 AE515 58645

58578 $E4D2 SECOND Figure 9-5. Talk-Listen Turnaround


Sends secondary address after LISTEN.
{This routine has a jump table entry at 65427/$FF93.)
Stores the secondary address value from the accumulator into
the serial byte buffer at 149/$95, sends the buffered byte as a
command (the ATN line should still be high from the previous
LISTEN command), then falls through into the next routine to
allow the ATN line to go high again so that following bytes
will be seen as data instead of commands.

58583 $E4D7
Allows the serial bus ATN output line to go high. 1. The 128 holds the DATA line low and allows the ATN line to go
Forces bit 3 of CIA #1 port A to %0. Since that bit is con- high.
nected to the serial bus ATN output line via an inverter, this 2. The 128 allows the CLK line to go high.
will set the ATN output line to a high state ( + 5 volts). 3. The external device must respond by pulling CLK low, (The 128
will wait indefinitely for this to happen.) The external device is
now the talker and the 128 is the listener.
58592 $E4E0 TKSA
Sends secondary address after TALK.
(This routine has a jump table entry at 65430/$FF96.) 58627 $E503 CIOUT
Sends a byte to a serial device.
Stores the secondary address value from the accumulator into (This routine has a jump table entry at 65448/$FFA8.)
the serial byte buffer at 149/$95, then sends the buffered byte
Tests bit 7 of the serial buffer flag (148/S94). If the bit is %0,
as a command (the ATN line should still be high from the
indicating that the one-byte serial buffer (149/$95) is empty,
previous TALK command). If the device is not present, the
the byte in the accumulator is simply stored in the buffer and
routine exits (after allowing the ATN and CLK lines to go high
the flag bit is set to %1 before exiting. However, if the flag bit
again). Otherwise, the routine falls through into the next one
is already % 1 , a character is currently waiting in the buffer. In
to make the 128 the listener and recognize the external device
this case, the routine at 58252/$E38C is used to send the pre-
as the talker,
viously buffered character before the new character is added to
the buffer. Carry will always be clear upon exit, and the byte
58601 $E4E9
value will still be in the accumulator. The X and Y register val-
Performs talk-listen turnaround.
ues are also preserved. The success of the operation can be de-
Begins by calling the subroutine at 58739/SE573 to disable termined from the value in the serial status flag (144/$90).
IRQ interrupts and standardize timing. The DATA line is held The purpose of the buffering scheme is to make it possible to
low, and the ATN line is allowed to go high (signaling the perform the EOI (end-or-identify) handshake with the final
end of the command). The CLK line is then allowed to go character of a file,
high. The device which is commanded to talk should respond
by pulling CLK low. The routine waits for this to happen, then 58645 $E515 UNTLK
jumps to the routine at 58783/$E59F to restore interrupts and Sends UNTALK command to a serial device.
the clock mode. Figure 9-5 illustrates the talk-listen (This routine has a jump table entry at 65451/$FFAB.)
turnaround. Begins by calling the subroutine at 58739/$E573 to disable
IRQ interrupts and standardize timing. The CLK line is pulled
low; then ATN is pulled low as well to indicate that the byte

526 527
58662 $E526 SE573 58739

will be a command. The accumulator is loaded with the UN- 58720 $E560
TALK command value, 95/$5F. Then a BIT opcode is used to Pulls serial bus DATA output line low.
fall through into the next routine to send the byte as a com- Sets bit 5 of CIA #2 port A to % 1 . Since the output line for
mand. Unlike TALK, which affects only a specified serial de- that port bit is connected to the serial bus DATA output line
vice, UNTALK affects all serial devices. However, this shouldn't
cause problems because the 128 serial bus allows only one ac- via an inverter, this will set the output line to a low state (0
tive talker at any given time. volts).
58729 $E569
58662 8E526 UNLSN Reads the serial bus DATA and CLK input lines.
Sends UNLISTEN command to a serial device.
(This routine has a jump table entry at 65454/SFFAE.) Reads the value at port A of CIA #2, then shifts the value of
bit 7, connected to the serial bus DATA input line, into the
Loads the accumulator with the UNLISTEN command value, status register carry bit. This will also shift the value of bit 6,
63/$3F, then clears bit 7 of the serial mode flag (2588/$0AlC) connected to the CLK input line, into bit 7. Upon return, the
to disable fast serial mode, and sends the byte in the accumu- DATA bit can be tested with BCC/BCS or shifted into a work-
lator as a command on the serial bus. Afterward, the ATN line ing byte, and the CLK bit can be tested with BPL/BMI.
is allowed to go high (signaling the end of the command), and,
after a short delay, the CLK and DATA lines are allowed to go 58739 $E573
high as well. Unlike LISTEN, which affects only a specified se- Disables IRQ interrupts and standardizes timing during I/O
rial device, UNLISTEN affects all serial devices. However, this operations.
shouldn't cause problems because the 128 serial bus normally
has only one listener at any given time. Begins by disabling IRQ interrupts. Next (at 58740/$E574), the
custom mode flag (2618/S0A3A) is checked. If bit 7 of this
flag is set to % 1 , the routine exits without changing the clock
58693 $E545 mode setting or disabling sprites. The 128 sets this flag to zero
Allows serial bus CLK output line to go high. during the IOINIT routine (part of both the reset and
Sets bit 4 of CIA #2 port A to %0. Since the output line for RUN/STOP-RESTORE sequences) and does not normally
that port bit is connected to the serial bus CLK output line via change the value. You can set bit 7 of the flag if for some rea-
an inverter, this will set the output line to a high state ( + 5 son you want to retain fast clock mode or sprites during an
volts). I/O operation. The clock mode storage flag (2615/$0A37) is
then checked. The routine exits if bit 7 of this flag is set to
58702 $E54E % 1 , indicating that a clock mode has already been stored (bits
Pulls serial bus CLK output line low. 2-7 of $D030 are always %1). Otherwise, the value in the
Sets bit 4 of CIA #2 port A to % 1 . Since the output line for VIOII register at 53296/SD030, which determines the system
that port bit is connected to the serial bus CLK output line via clock frequency, is stored in the clock mode flag, and the
an inverter, this will set the output line to a low state (0 volts). value in the register at 53269/$D015, which determines which
sprites are currently enabled, is stored in 2616/$0A38. Both
58711 $E557 registers are then reset to zero, which disables all sprites and
Allows serial bus DATA output line to go high. sets the system to normal (1 MHz) clock speed. This is done to
Sets bit 5 of CIA #2 port A to %0. Since the output line for standardize system timing. Tape and serial data transfers rely
that port bit is connected to the serial bus DATA output line on software delay loops for critical timing functions, so the
via an inverter, this will set the output line to a high state system must be in a standard mode for the loops to provide
( + 5 volts). the correct delay. If any sprites have previously been enabled,
a delay loop is executed before the routine exits.
528
I 529
58783 $E59F SE61B 58907

58783 $E59F 58875 SE5FB SPIN_SPOUT


Reenables interrupts and restores clock mode after I/O Sets serial device for fast serial input or output.
operations. Branches to one of the fast serial setup routines, depending on
Begins by checking the custom mode flag (2618/$0A3A). If bit the setting of the status register carry bit. If carry is clear, the
7 of this flag is set to % 1 , the routine skips ahead to reenable routine at 58819/$E5C3 is used to set up the port for fast se-
interrupts and exit. The 128 sets this flag to zero during the rial input. If carry is set, the routine at 58838/$E5D6 is used
IOINIT routine (part of both the reset and RUN/STOP- to set up the port for fast serial output.
RESTORE sequences) and does not normally change the value.
You can set bit 7 of the flag if for some reason you want the 58879 $E5FF
clock mode or sprite enable setting preserved after an I/O op- prepares next bit for RS-232 transmission.
eration. The clock mode storage flag (2615/$0A37) is then (Called by the NMI handling routine when a timer A interrupt
checked. If bit 7 of this flag is set to %0, indicating that no occurs.)
clock mode is stored, the routine skips ahead to reenable inter- If the count of bits remaining to be sent is zero, indicating that
rupts and exit. Otherwise, the value in 2616/$0A38 is restored all stop bits for the current byte have been sent, a branch is
to the VIC-II sprite enable register (53269/$D015), and the taken to 58954/$E64A to prepare the next byte for transmis-
value in 2615/$0A37 is restored to the clock mode register sion. If bit 7 of the count is set, a branch is taken to 58948/
(53296/$D030). The clock mode flag is then reset to zero. IRQ $E644 to prepare to send a stop bit. Otherwise, the next bit to
interrupts are reenabled before exiting. be sent is pulled from the data byte storage (182/$B6) into the
carry bit, and the parity flag (189/$BD) is updated accordingly.
58812 $E5BC The count of remaining bits is decremented. If the result is zero,
Performs fast serial turnaround. a branch is taken to 58907/SE61B to prepare parity or stop
Waits for a serial register interrupt on CIA # 1 , indicating that bits. Finally, bit 2 of 181/SB5 is set to the bit value to be sent.
the current output byte has been completely sent, then falls
through into the next routine to reset the serial port lines for 58907 $E61B
fast serial input. The port is left set up for input so that incom- Prepares parity and stop bits.
ing fast serial communications can be detected automatically. Checks bit 5 of the RS-232 command register (2577/$0All) to
determine whether a parity bit is to be sent. If not (if the bit is
58819 $E5C3 SPIN %0), the routine skips ahead to determine the number of stop
Sets serial device for fast serial input. bits. Otherwise, a parity bit is prepared. Bits 6 and 7 of the
Sets the serial line from CIA #1 for input and halts timer A on command register determine the parity type. These are possi-
CIA #1; then clears bit 3 of the MMU register at 54533/SD505 ble types:
to set the serial port's fast communications hardware for input. Bits Parity type
7 6
58838 8E5D6 SPOUT 0 0 Odd
0 1 Even
Sets serial device for fast serial output. 1 0 Mark
Sets bit 3 of the MMU register at 54533/$D505 to set the se- 1 1 Space
rial port's fast communications hardware for output; then
clears all CIA #1 interrupts. Timer A is loaded with 4/$0004, If odd parity is specified, the parity flag (189/$BD) is
the timing constant for fast serial output bits. The serial line tested. When the flag is nonzero, indicating that an odd num-
for CIA #1 is set for output, and timer A is started. Bytes sub- ber of % 1 bits has already been sent in the current byte, the
sequently stored in the serial data register of CIA #1 will be routine prepares a parity bit of %0. When the number of %1
sent via the fast serial hardware. bits already sent is even, a parity bit of %1 is prepared to
530
I 531
$E69D 59037
58948 $E644

make the total odd. If even parity is specified, a parity bit of is loaded from 2581/S0A15. Tf the RS-232 output buffer is
%0 will be prepared when the parity flag indicates that the empty, the routine disables timer A interrupts and exits. Oth-
number of %1 bits already sent is even, and a parity bit of %1 erwise, the next available byte from the output buffer is
will be prepared when the number of %1 bits sent is odd so loaded into 182/$B6, and the pointer to the head of the buffer
that the total number of %1 bits sent (including the parity bit) (2586/S0A1A) is incremented,
will always be even. Mark and space parity are simpler: In the
former case, the parity bit is always % 1 ; in the latter, it's al- 59007 $E67F
ways %0. (Early versions of the Commodore 64 Kernal incor- Sets CIA interrupt register and RS-232 activity flag.
rectly computed even and odd parity. All types of parity are Sets or clears bits in the interrupt control register for CIA #2,
handled properly in the 128 Kernal and in the version of the depending on the value in the accumulator. If bit 7 of the ac-
Commodore 64 Kernal used for 64 mode in the 128.) cumulator value is %0, the interrupt register bits correspond-
Next, the routine prepares for the transmission of either ing to the %1 bits in the accumulator value will be cleared. If
one or two stop bits, depending on the setting of bit 7 of the bit 7 is % 1 , the interrupt register bits corresponding to any
RS-232 control register (2576/$0A10). If one stop bit is speci- other %1 bits in the accumulator value will be set. The RS-232
fied (if the register bit is %0), the count of bits remaining to be activity flag (2575/$0A0F) is then updated to reflect the new
sent (180/$B4) is decremented once {to 255/$FF). If two stop setting of the interrupt register.
bits are sent (if the register bit is %1), the count is
decremented twice (to 254/$FE). The routine ends by branch- 59022 $E68E
ing back into the previous routine to set the prepared parity or Computes bit count for the RS-232 operation.
stop bit as the next bit to send. Computes a bit count based on the setting of bits 5 and 6 of
the RS-232 control register (2576/$0A10). The count value,
58948 $E644 which will be one greater than the number of data bits speci-
Prepares to send a stop bit. fied, will be returned in the X register.
Increments the count of bits remaining to be sent (180/$B4), Bits Data bits Bit count
then prepares a %1 bit for transmission (stop bits are always 6 5
%1). 0 0 8 9
0 1 7 8
1 0 6 7
58954 SE64A 1 1 5 6
Prepares to transmit next byte.
Checks bit 0 of the RS-232 command register (2577/$0All) to 59037 $E69D
determine which handshaking mode is in use. If x-line Processes received bits.
handshaking is specified (if the register bit is %1), the RS-232 Checks the start bit flag (169/$A9) to determine whether the
DSR and CTS lines (pins K and L of the user port) are tested. start bit for a byte has been read yet. If not, a branch is taken
If the external device is not holding these lines high, the cor- to 59092/$E6D4 to see whether this is a start bit. Otherwise,
responding bit in the RS-232 status flag (2580/$0A14) is set— the received bit count (168/SA8) is decremented. If the count
bit 6 for DSR missing or bit 4 for CTS missing—then the rou- has reached zero, all bits for a byte have been received, so a
tine disables timer A interrupts to halt transmission. branch is taken to 59103/$E6DF to process the byte. Other-
For three-line handshaking, or for x-line handshaking wise, the parity indicator is toggled, and the received bit in
when DSR and CTS are held high, the parity flag (189/SBD) 167/$A7 is shifted into the work byte (170/$AA).
is cleared and the current bit flag (181/$B5) is set to 0/$00
(start bits are always %0). The count of bits to send (180/$B4)

533
532
59058 $E6B2 59228
SE75C

59058 $E6B2 the received character is padded with %0 bits if it is less than
Tests for stop bit. eight bits long and then stored at the current tail of the input
Decrements the received bit count and checks whether the re- buffer. If no parity is used, a branch is taken to 59058/$E6B2
ceived bit is a %1 (stop bits are always %1). If it is, bit 7 of to check for a stop bit. Otherwise, the current bit received
the RS-232 control register (2576/$0A10) is tested. If one stop (167/$A 7) is taken to be a parity bit and is compared against
bit is specified (if the register bit is %0), the routine falls the calculated parity for the byte. If the two do not correspond
through into the next one to prepare to receive the next byte. to the specified parity type, the parity error bit (bit 0) of the
If two stop bits have been specified, the routine exits to look status flag will be set, and the routine will jump to reset for
for another stop bit. the reception of the next byte.
If a stop bit has not been received, the routine branches to
set a bit in the serial status flag (2580/$0A14) according to the 59177 SE729
previously received byte (170/SAA): bit 1—the framing error
bit—if the previously received byte is nonzero, or bit 7—the Handles CKOUT for RS-232 device.
break error bit—if the previously received byte is zero (indi- Sets the device number in the accumulator as the current out-
cating that the received data line is being held low). put device (154/$9A), then tests bit 0 of the RS-232 command
register (2577/$0All). If the bit is %0, three-line handshaking
59074 $E6C2 has been specified, so the routine exits at this point. For x-line
handshaking, the routine tests the DSR line (pin L of the user
Prepares to receive next byte. port). If the external device is not holding this line high, a
Enables FLAG interrupts for CIA #1, then updates the RS-232 branch is taken to set bit 6 of the RS-232 status flag (2580/
activity flag (2575/$0A0F) to indicate that FLAG interrupts are $0A14) and exit with the status register carry bit clear. If DSR
active. The nonzero flag value will also be stored in the start is high, the state of the RTS line (pin D of the user port) is
bit flag (169/$A9) to indicate that no start bit has been re- checked. If the 128 previously set this line high, the routine
ceived. Timer B interrupts are then disabled, and the activity exits with carry clear. Otherwise, the routine waits until any
flag is updated to reflect this. (Timer B interrupts, used to time current transmission is completed, then waits for the external
incoming bits, are reenabled after the FLAG interrupt occurs,) device to pull the CTS line (pin K of the user port) low. The
routine then sets the RTS line high to signal that it is ready to
59092 SE6D4 send a byte and waits until an external device sets the CTS
Tests for start bit. line high to acknowledge that it is ready. (If DSR goes low
Tests the received bit (in 16 7/$A 7). If it is not %0, it is not a while the routine is waiting, bit 6 of the status flag will be
start bit, so a branch is taken to 59074/$E6B2 to look for an- set). The routine then exits with carry clear.
other byte. Otherwise, the zero value is stored in the start bit
flag (169/$A9) to indicate that a start bit has been received, 59228 $E75C
and the parity indicator flag (171/$AB) is initialized to 1/S01. Handles BSOUT for RS-232 device.
(The normal entry point for this routine is 59231/SE75F.)
59103 $E6DF Checks whether the output buffer is currently full. If no space
Stores received character in buffer and checks parity. is available, the routine loops to enable interrupts for RS-232
Checks whether space for an additional character is available transmission and waits until space becomes available in the
in the input buffer. If not, the routine branches to set the re- buffer. The buffer tail pointer (2587/$0AlB) is incremented,
ceiver buffer overflow bit (bit 2) in the RS-232 status flag and the value in the accumulator is placed at the tail of the
(2580/$0A14) and to prepare for the reception of the next output buffer. If bit 0 of the RS-232 activity flag (2575/$0A0F)
byte, (The received character is lost in this case.) Otherwise, is set to % 1 , timer A interrupts are already enabled, so the
routine exits at this point. Otherwise, timer A is loaded with
534

1 535
59285 $E795 $E805 59397

the bit timing constant value in 2582-2583/$0A16-$0A17;


then timer A interrupts are enabled, and the activity flag is up- are being used. Otherwise, the routine waits until the trans-
dated to reflect this. The routine at 58954/$E64A is called to mission or reception of the current byte is completed, then dis-
prepare to transmit the byte; then timer A is started. ables FLAG interrupts so that no further bytes can be received
and clears the activity flag so that no more bytes will be sent.
59285 $E795 The contents of the accumulator are preserved during this
routine.
Handles CHKIN for RS-232 device.
Sets the device number in the accumulator as the current in- 59397 SE805
put device (153/S99), then tests bit 0 of the RS-232 command Handles NMI interrupts for RS-232.
register (2577/lOAll). If the bit is %0, three-line handshaking
has been specified, so the routine skips ahead to test whether Controls the transmission and reception of data through the
interrupts are enabled. For x-Iine handshaking, the routine RS-232 port. Three CIA #2 interrupt sources are used in RS-232
tests bit 4 of the command register to determine the duplex communications. Timer A is used to establish the duration of
mode in use. For full duplex (bit 4 is %0), the routine skips bits being transmitted. The FLAG line, which triggers an inter-
ahead to test whether interrupts are available. For half duplex, rupt when it detects a high-to-low transition, is used to initiate
the RS-232 DSR line (pin L of the user port) is tested. If the the reception of a byte when an incoming start bit is detected.
external device is not holding this line high, a branch is taken Timer B is used to time the reception of subsequent bits.
to set bit 6 of the RS-232 status flag (2580/$0A14) and exit The routine begins by comparing the CIA #2 interrupt
with the status register carry bit clear. If DSR is high, the state register value at the time of the NMI interrupt (in the Y regis-
of the RTS line (pin D of the user port) is checked. If the 128 ter when the routine is called by the main NMI handler at
is currently holding this line high, the routine exits with carry 65285/$FF05) against the value in the RS-232 activity flag
clear, then pulls the CTS line (pin K of the user port) low. The (2575/$0A0F), If bit 0 is set in both, a valid timer A interrupt
routine then waits for DTR line to go high, after which FLAG has occurred to indicate that it is time to send the next bit. So,
interrupts are enabled to detect the start bit. the bit value (in bit 2 of 181/$B5) is written to bit 2 of CIA #2
port A, which is connected to the transmitted data line (pin M
The final step of the routine is to test whether FLAG or of the user port). RS-232 interrupts are then reenabled by
timer B interrupts are enabled. If neither is enabled, FLAG in- writing the activity flag contents to the CIA interrupt register
terrupts are enabled. The routine exits with carry clear. (56589/$DD0D). In addition, the routine checks whether bit 1
or 4 is set in both the interrupt register value and the activity
59342 $E7CE flag, indicating that a valid FLAG or timer B interrupt occurred
Handles GETIN for RS-232 device- concurrently with a timer A interrupt (RS-232 devices must be
Checks whether any characters are available in the input capable of simultaneous transmission and reception). If neither
buffer. If so, bit 3 of the RS-232 status flag (2580/$0A14) is has occurred, the routine skips ahead to prepare the next bit
cleared, the buffer head pointer (2585/$0A19) is incremented, for transmission. For timer B interrupts, the subroutine at
and the character from the buffer is returned in the accumu- 59512/SE878 is called to read a bit. For FLAG interrupts, the
lator. If no characters are available, bit 3 of the status flag is subroutine at 59561/$EA81 is called to start reception of a
set to % 1 , and the value 0/$00 is returned in the accumulator. byte. The subroutine at 58879/$E5FF is then called to prepare
The carry bit will be set in this case. the next bit for transmission. CIA interrupt sources are again
enabled before exiting.
59372 $E7EC If no timer A interrupt occurred, the routine checks
Disables RS-232 activity during tape or serial bus operations. whether bit 1 is set in both the interrupt register value and the
Exits immediately if the RS-232 activity flag (2575/$0A0F) activity flag, indicating that a valid timer B interrupt occurred.
contains the value 0/$00, indicating that no RS-232 operations If so, the subroutine at 59512/$E878 is called to read a bit.
536
537
1
59472 $E850 SE8D0 59600

Otherwise, a test is made of bit 4 in both the interrupt register 59561 $E8A9
value and the activity flag. If the bit is set in both, a valid
FLAG interrupt has occurred, so the subroutine at 59561/ Initiates reception of RS-232 byte.
$E8A9 is called to start reception of a byte. In either case, the (Called by the NMI handling routine when a FLAG interrupt
activity flag value is stored in the CIA interrupt register to occurs.)
reenable RS-232 interrupts before exiting. Begins by copying the bit timing constant value (2578-2579/
$0A12-$0A13) into the latch for timer B (56582-56583/
59472 $E850 $DD06-$DD07) and starting timer B. Then, FLAG interrupts
Table of baud rate timing constants for NTSC systems. are disabled and timer B interrupts are enabled. The RS-232
activity flag (2575/$0A0F) is updated to reflect the change.
The ten two-byte values in this table (in low-byte/high-byte The latch for timer B is loaded with $FFFF so that the timer
order) are the CIA timer settings used to transmit and receive
bits at the ten standard baud rates when the 128 is operating will count continuously after it counts down for the next bit.
with NTSC clock frequency (1.02273 MHz). This is the for- Finally, the count of bits to be received for the current char-
mula for table values: acter is loaded from 2581/$0A15 into the working counter
(168/SA8).
value = 1.02273E6 / (2 * baud rate) - 100
59492 $E864 59600 SE8D0
Reads next header block from tape.
Table of baud rate timing constants for PAL systems. Calls the subroutine at 59890/$E9F2 to fill the cassette buffer
The ten two-byte values in this table (in low-byte/high-byte with the next block from tape, exiting with the status register
order) are the CIA timer settings used to transmit and receive carry bit set if the RUN/STOP key is pressed while the block
bits at the ten standard baud rates when the 128 is operating is being loaded.
with PAL clock frequency (0.985265 MHz). This is the formula
for table values: The first byte in the header block, the type identifier, is
then examined. If the identifier value is 5, this is an end-of-
value = 0.985265E6 / (2 * baud rate) - 100 tape marker, so the routine branches to exit with carry set (in
this case, the Y register will hold the value 255/$FF). If the
59512 $E878 identifier value is something other than 1, 3, or 4, the routine
Reads a bit from RS-232 device. loops back to read another block. If Kernal messages are al-
(Called by the NMI handling routine when a rimer B interrupt lowed, FOUND is displayed, followed by 16 filename charac-
occurs.)
ters from the buffer. (The buffer is filled with space characters
Reads the current status of the R5-232 received data line (pin when the header is written, so the displayed name will be
C of the user port) and stores the bit value in 167/$A7. The padded with spaces if it is fewer than 16 characters long.) A
interrupt time for the next bit is calculated and stored in the delay loop lasting for two increments of the middle byte of the
timer B latch (56582-56583/$DD06-$DD07); then timer B is jiffy clock (161/$A1), about 8-1/2 seconds, is then started. If
restarted. CIA #2 interrupts are reestablished by storing the the space key is pressed during this delay, the routine loops
RS-232 activity flag (2575/$0A0F) in the interrupt register back to the beginning to read another header. If any other key
(56589/$DD0D), and the timer latch is reloaded with $FFFF. in the same column (for example, Commodore or CONTROL)
The routine ends by jumping to 59037/$E69D to process the is pressed, the loop is terminated. At the end of the loop, the
received bit. routine exits with carry clear. The X register will hold the type
identifier value for the header.

538
539
59673 SE919 $E9DF 59871

59673 $E919 59802 SE99A


Writes a header block to tape. Searches for a specified header.
Stores the type identifier value from the accumulator in 158/ Calls the routine at 59600/$E8D0 to load the next header
$9E, then checks the address of the cassette buffer, exiting im- from tape into the cassette buffer; exits if carry is set upon re-
mediately if it is less than 512/$0200. Otherwise, the contents turn from that routine (indicating that the RUN/STOP key has
of the starting address pointer (193-194/ $C1-$C2) and end- been pressed or that an end-of-tape header has been read).
ing address pointer (174-175/$AE-$AF) for the current opera- Characters from the current filename (pointed to by 187-188/
tion are stored on the stack, and the cassette buffer is filled $BB-$BC in the bank specified in 199/SC7) are compared
with space characters (32/$20). The type identifier value is against those in the buffer. If all characters match up to the
placed in the first byte of the buffer, and the starting address end of the current filename, the names are considered match-
and ending address values are placed in the next four bytes ing, and the routine exits with carry clear, regardless of how
(each in standard low-byte/high-byte order). The characters, if many characters may remain untested in the buffer (there's
any, of the current filename are then copied into the buffer nothing to indicate the length of the name read from tape).
following the filename (the filename can fill the remainder of However, if a mismatch is found, the routine loops back to
the buffer, up to 187 characters). The buffer starring and end- search for another filename.
ing addresses are then set as the operation starting and ending
addresses; the leader flag (171/$AB) is loaded with 105/$69 59838 $E9BE
for a long interfile leader; and the subroutine at 59932/$EAlC
is called to write the buffer contents to tape as a header. The Checks for cassette buffer filled or emptied.
original starting and ending address pointer values are then Calls the routine at 59776/$E980 to get the high byte of the
restored from the stack. Carry will be clear upon exit unless cassette buffer address into the X register. The buffer index
the RUN/STOP key is pressed while the header is being (166/$A6) is then incremented, loaded into the Y register, and
written. compared against the value 192/$C0, the maximum count of
characters in the buffer. Upon exit, the status register Z and
carry bits will reflect the result of the comparison (both will be
59776 8E980 set if the end of the buffer is reached),
Loads and tests cassette buffer address.
Loads the address value in the cassette buffer pointer (178-179/ S9848 $E9C8
$B2-$B3) into the X and Y registers; then compares the high Requests PLAY button if necessary.
byte (in the Y register) with the value 2/$02 to test whether Checks whether a tape button is currently pressed; exits with
the buffer address is greater than 511/$01FR Upon exit, the the status register carry and Z bits set if any buttons are al-
status register carry and Z bits will reflect the result of the ready pressed. Otherwise, if Kernal messages are allowed,
comparison. PRESS PLAY ON TAPE is displayed. The routine then waits
for a tape button to be pressed. If the RUN/STOP key is
59783 $E987 pressed in the meantime, the routine exits with the status reg-
Sets buffer address as block address ister carry bit set. When a button is pressed, the routine dis-
Loads the address of the cassette buffer into the pointer to the plays OK (if messages are allowed) and exits.
starting address of the block to be read or written (193-194/
$C1-$C2) and the ending address of the buffer (192 bytes be- 59871 8E9DF
yond the starting address) into the pointer to the end of the Checks tape buttons.
block (174-175/$AE-$AF). Tests the setting of bit 4 of the processor on-chip I/O port
(l/$01), connected to the cassette button sense line. The status

540 541
59881 SE9E9 $EA26 59942

register Z bit will be clear if no button is pressed or will be set 59928 $EA18
if any button is detected. Writes a block to tape.
Loads the leader flag (171/SAB) with 20/$14 to specify a
59881 $E9E9 short leader between the header and the block; then calls the
Requests RECORD and PLAY buttons if necessary. subroutine at 59881/$E9E9 to request that the PLAY and
Checks whether a tape button is currently pressed; exits with RECORD buttons be pressed. (The routine will exit with carry
the status register carry and Z bits set if any buttons are al- set if the RUN/STOP key is pressed during the subroutine.)
ready pressed. Otherwise, if Kernal messages are allowed, IRQ interrupts are disabled and the accumulator is loaded with
PRESS RECORD & PLAY ON TAPE is displayed. The routine 130/$82 (the value to enable timer B interrupts), and the X
then waits for a tape button to be pressed. If the RUN/STOP register is loaded with 8/$08 (the offset to write leader bits).
key is pressed in the meantime, the routine exits with the sta- The routine then falls through into the next one to perform
tus register carry bit set. When a button is pressed, OK is dis- the operation.
played (if messages are allowed) and the routine exits.
59942 $EA26
59890 $E9F2 Initiates tape I/O operation.
Reads next header or data block from tape. Begins by disabling all VIC-II interrupt sources and clearing
Clears the tape status flag (144/$90) and operation flag any pending VIC-II interrupts. The value in the accumulator
(147/$93) to zero; then sets the starting and ending addresses upon entry is loaded into the interrupt control register for CIA
of the cassette buffer as the starting and ending addresses for #1 (56333/$DC0D), and timer B is started. Tape operations de-
the current operation and falls through into the next routine. pend on precise timing, so all other activities that affect system
timing are disabled: RS-232 interrupts are disabled, the 40-
59899 $E9FB column screen is blanked, and the subroutine at 58740/ $E574
Reads or verifies a block from tape. is called to switch to standard (1 MHz) clock mode and disable
Calls the subroutine at 59848/$E9C8 to request that the PLAY sprites. The current address in the IIRQ vector at 788-789/
button be pressed and exits (with carry set) if the RUN/STOP $0314-$0315 is preserved in 2569-2570/$0A09-$0A0A; then
key is pressed during that subroutine. IRQ interrupts are dis- the subroutine at 61083/$EE9B is called to load a new value
abled, and a series of variables and counters are initialized. into IIRQ, according to the value in the X register. This new
The accumulator is loaded with 144/$90 (the value to enable IRQ service routine will be responsible for reading or writing
FLAG interrupts), and the X register is loaded with 14/$0E data to tape. The count of blocks to be read or written (190/
(the offset for read interrupts), and the routine branches to the $BE) is initialized to 2 (blocks are always read or written in
main tape I/O routine (59942/SEA26). pairs). The subroutine at 60762/$ED5A is called to initialize
variables; then the tape motor is started, the interlock location
59925 $EA15 (192/$C0) is set to keep it on, and a delay loop is executed to
Writes a header or data block to tape. allow the motor to get up to normal speed. IRQ interrupts are
Calls the subroutine at 59783/$E987 to set the buffer ad- then enabled to begin the reading or writing process.
dresses as the starting and ending addresses for the operation- Since the actual tape operations are performed during IRQ
then falls through into the next routine to write the buffer interrupts, the routine must now wait in a loop for the opera-
block to tape. tion to be completed. It continually tests the IRQ storage flag
(2570/S0A0A), waiting for the IIRQ vector to be reloaded with
the address stored there, which will happen after the IRQ-
driven tape routines are finished. In the meantime, the RUN/
STOP key is also tested. If that key is pressed, the operation is
542 543
.
60047 8EA8F $ED51 60753

halted and the routine exits with carry set. Otherwise, when
the original IIRQ address is restored at the end of the opera-
tion, the vector storage flag will be reset to zero, and the rou-
tine will exit with carry clear.
i Briefly, the routine reads dipoles from tape and deter-
mines whether they represent leaders, word markers, or data
bytes. The routine does not demand that the dipoles have an
absolutely exact duration, but rather it employs a concept
known as an adjustable baseline to determine whether the di-
60047 $EA8F pole is within an acceptable range for a particular type. This
Checks for RUN/STOP keypress during tape operations. makes it possible to compensate for minor variations in the
Calls the Kernal STOP routine [$FFE1] to determine whether motor speed of different Datassette units. Because two com-
the RUN/STOP key has been pressed. If it has been, the cas- plete copies of the data block are recorded, error correction is
sette motor is stopped, the default IIRQ vector address is re- possible. If an error is detected while a byte is being read from
stored, the return address of the calling routine is removed the first block, the address of the byte which could not be read
from the stack, and the IRQ vector storage flag (2570/$0A0A) is recorded in page 1. Up to 31 error addresses can be re-
is cleared. corded in 256-317/$0100-$013D. When the second block is
read, the bytes can be corrected if no error is encountered
60065 $EAA1 when the byte is read from that block.
Sets timer A to check for FLAG interrupts. When a byte is successfully read from tape, the handling
The reception of tape dipole is normally initiated by a FLAG of the byte depends on the value in the operation flag (147/
interrupt from CIA #1, which is triggered by the low-to-high $93). If the flag value is zero, the byte is stored in the location
transition on the cassette read line at the start of a dipole. pointed to by 172-173/$AC-$AD in the bank specified in
Timer A of CIA #1 is loaded with a timing value for the type 198/$C6. If the value is nonzero, the byte is compared against
of dipole being read, and it's used to check whether too much the contents of the location pointed to by 172-173/$AC-$AD
time elapses between FLAG interrupts (which should be in the bank specified in 198/$C6 (a verify operation).
equally spaced) in an attempt to determine whether any di- Errors which cannot be corrected are recorded in the tape
poles might have been missed. If no FLAG interrupt occurs status flag (144/S90). If the end of a block is reached before
before the timer counts down to zero, the timer will trigger an the specified ending address (a short-block error), bit 2 of the
interrupt. This prevents the 128 from waiting indefinitely for a flag is set to % 1 . If more than 31 errors occur while the first
FLAG interrupt. block is being read, or if an error recorded during the first
block cannot be connected during the second block, an unre-
60139 $EAEB coverable-read error occurs, and bit 4 of the flag is set to % 1 .
Reads or verifies a block of data from tape. That bit is also set during a verify operation if the byte in
{This is a tape IRQ service routine.) memory doesn't match the corresponding byte in either block
on tape. If the byte read from tape as a checksum doesn't
Reads magnetic patterns (known as dipoles) from tape, assem-
match the calculated checksum for the bytes previously read
bles them into bytes, and loads the bytes into memory (or
from tape, a checksum error occurs, and bit 5 of the flag is set
compares the bytes against memory) until a specified ending
to % 1 .
address is reached. The routine for reading from tape is the
longest and most complex one in the Kernal, and will not be
discussed in detail here. For a thorough description of the pro- 60753 $ED51
cess, refer to COMPUTERS VIC-20 and Commodore 64 Tool Kit: Loads working pointer with starting address.
Kernal, by Dan Heeb. Transfers the starting address of the current block (193-194/
$C1-$C2) to the tape working pointer (172-173/$AC-$AD).

544 545
60762 SED5A SEE57 61015

60762 $ED5A leader. As each byte is written, it is also excIusive-ORed with


Initializes tape variables between each byte. a checksum work byte. This checksum byte is written to tape
Resets the count of bits for the next byte (163/$A3) to 8; then following the second copy of the block to provide an addi-
clears the dipole flag (164/$A4), the word marker half-dipole tional error check. For a more thorough description of the pro-
flag (168/$A8), the parity work byte (155/$9B), and the word cess, refer to COMPUTE'S VIC-20 and Commodore 64 Tool Kit:
marker flag (169/$A9). Kernal, by Dan Heeb.

60777 $ED69 60974 $EE2E


Writes a leader to tape and prepares to write a data block.
Initiates writing of a tape half-dipole. (This is a tape IRQ service routine.)
Reads the bit value for the current half-dipole to be sent (the
current value of the rightmost bit in 189/$BD) and loads CIA Writes leader dipoles to tape until the count specified in
#1 timer B with the appropriate value: $0060 for a short half- 171/$AB is decremented to zero, about 9.5 seconds for the
dipole if the bit is %0 or $00B0 for a long half-dipole if the bit leader before a header, 1.9 seconds for the leader between a
is % 1 . The routine then clears the CIA interrupt register, starts header and the first data block, or 0.045 seconds between data
timer B, and toggles the cassette write line (bit 3 of the 8502's blocks. The IIRQ vector is then loaded with the address of the
on-chip I/O port at location l/$01) to begin writing the cur- routine to write the data block [$ED90], but if both blocks
rent half-dipole. Upon exit, the status register 2 bit will be set have been written, the routine branches to 61077/$EE95 to re-
if the line is currently low or will be clear if the line is cur- store normal IRQs and exit from the operation. Otherwise, the
rently high. starting address for the block to be written is loaded into the
working pointer (173-174/$AC-$AD), and a branch is taken
into the block write routine to write the block countdown
60816 6ED90 characters. Each block is preceded by a countdown character
Writes a block of data to tape. pattern—8 7 6 5 4 3 2 1 0—to mark the end of the leader and
(This is a tape IRQ service routine.) the beginning of data. (For the second block of a pair, bit 7 of
Writes bytes of data from memory to tape until the specified the countdown character codes will be set to %1.)
ending address is reached. The system used for representing
the bytes on tape is rather complex. Each bit of a byte is rep- 61015 6EE57
resented by a magnetic pattern called a dipole, which is gener-
ated by holding the cassette write line (bit 3 of the 8502's on- Restores IRQ vector and operating modes after tape operation.
chip I/O port at location l/$01) high for a period, then low Reenables the screen (it is normally blanked during tape oper-
for a different period. The duration of the periods is deter- ations), then checks the custom mode flag (2618/$0A3A). If
mined by the value loaded into CIA #1 timer B, which con- the flag has bit 7 set, indicating that a special operation mode
trols the amount of time between IRQ interrupts for tape. The has been specified, the routine skips ahead to turn off the cas-
routine at 60777/$ED69 actually writes each half of the di- sette motor and restore the IRQ vector. Otherwise, the VIC-II
pole. A %0 bit is represented by a short half-dipole followed chip sprite enable register is reloaded with the value stored in
by a long one, while a %1 bit is represented by a long half- 2616/$0A38 at the start of the operation. The clock mode reg-
dipole followed by a short one. Each byte is preceded by a ister is reloaded with its original value from 2615/$0A37; then
word marker dipole, which consists of an extra-long word the clock mode storage location is reset to zero to indicate that
marker half-dipole followed by a long half-dipole. Each byte is no value is stored. The routine to turn off the cassette motor
followed by a parity bit dipole. The parity bit will be either [SEEBO] is called; then raster interrupts are reenabled, and the
%0 or % 1 , as necessary to provide an odd total number of %1 IIRQ vector (788-789/$0314-$0315) is reloaded with its origi-
bits in the byte and parity bit combined. The routine writes nal address, stored in 2569-2570/$0AO9-$0A0A at the begin-
two complete copies of the data block, separated by a short ning of the operation.

546 547
61077 $EE95 61163
$EEEB

61077 6EE95 61136 $EED0


Ends tape write interrupts. Controls tape motor interlock.
Calls the subroutine at 61O15/$EE57 to restore the IRQ inter- Checks bit 4 of the processor I/O port (location l/$01) to de-
rupt vector address and system operating modes to their origi- termine whether any buttons are pressed on the Datassette. If
nal values; then exits from the interrupt to return to normal no button is pressed (indicated when the bit is %1), the inter-
processing. lock byte (192/$C0) is cleared and the tape drive motor is
turned off by setting bit 5 of the processor I/O port to % 1 . If a
61083 $EE9B button is pressed (if bit 4 is %0), the interlock byte is checked.
Loads IIRQ vector for tape operation. If that byte already contains a nonzero value, the routine exits.
Loads the IIRQ vector (788-789/$0314/$0315) with a value Otherwise, the tape motor is turned on by setting bit 5 of the
from the table at 61096/$EEA8, depending on the offset speci- processor I/O port to %0.
fied in the X register: This routine is part of the normal IRQ sequence, so it's
Offset Vector address Function not possible to control the tape motor by directly changing bit
8/$08 60974/$EE2E Write a leader to tape 5 of the processor I/O port. If you turn on the motor while no
10/$0A 60816/$ED90 Write a block to tape buttons are pressed, it will be turned off again during the next
12/$0C 64101/$FA65 Restore normal IRQ functions IRQ interrupt. If you turn off the motor while a button is
14/$0E 60139/$EAEB Read a block from tape pressed, it will be turned on again during the next IRQ inter-
rupt (unless the interlock byte contains a nonzero value).
61104 $EEB0
Turns cassette motor off- 61163 $EEEB GETIN
Sets bit 5 of the processor I/O port (location l/$01) to % 1 , Retrieves a byte from the current input device.
which has the effect of turning off power to the cassette motor (This routine is the normal target of the jump table entry at
65508/$FFE4, via the indirect vector at 810/$032A.)
(pins 3 and C of the cassette port).
Checks whether the current input device (153/$99) is the key-
61111 $EEB7 board (device 0) or RS-232 (device 2). If it is neither of these,
Tests whether ending address has been reached. the routine branches to 61205/SEF15 in the BASIN routine to
Compares the value in the working pointer for tape and serial accept a byte from the specified device. For keyboard and RS-
operations (172-173/$AC-$AD) against the ending address in 232, the significant difference between GETIN and BASIN is
174-175/$AE-$AF. Upon exit, the status register carry and Z that GETIN returns the value 0/$00 if no character is avail-
bits will reflect the result of the comparison. able, whereas BASIN will wait until a valid character becomes
available.
61121 $EEC1 For keyboard input, the routine checks the number of
Increments the working pointer- characters available in the keyboard buffer (208/$D0) and the
number of characters available from the current programmable
Increments the address in 172-173/$AC-$AD. key string (2O9/$D1). If both are zero (no characters avail-
61128 $EEC8 able), the routine exits with 0/$00 in the accumulator and
carry clear. However, if characters are available, the screen
Handles FLAG interrupts for tape.
routine at 49158/SC006 is used to retrieve the next available
Insures that the B bit in the status register value on the stack character and return it in the accumulator. Neither the X nor
is clear, then jumps to the IRQ interrupt handler [$FF17]. the Y register values are preserved in this case.
For RS-232 input, the routine at 59342/SE7CE is used to
retrieve a byte from the RS-232 input buffer and return it in
548 549
61190 SEF06 61305
SEF79

the accumulator. If the buffer is empty, the accumulator will the X register contents will be preserved. Carry will be clear
contain 0/$00, and bit 3 of the RS-232 status flag (2580/ unless the RUN/STOP key has been pressed (the accumulator
$0A14) will be set to % 1 . For RS-232 input, the X register is will contain 0/$00) or an error is encountered when reading
unused, and the Y register value is preserved. the data block from tape (the accumulator will contain the er-
ror code).
61190 $EF06 BASIN
Accepts a byte from the current input device. 61276 SEF5C
(This routine is the normal target of the jump table entry at
65487/$FFCF, via the indirect vector at 804/$0324.) Accepts a byte from a serial device.
If the current input device (153/$99) is the keyboard (device Checks the serial status flag (144/$90) and returns the code
0), the routine sets the current cursor row and column for the RETURN character (13/$0D) if the status is nonzero
(232/$E8 and 233/$E9) as the starting row and column for in- (indicating error or end of file). Otherwise, the routine jumps
put (235/SEB and 236/$EC); then it calls the screen editor to the Kernal ACPTR routine [$E43E] to retrieve a byte from a
routine to retrieve a character from a keyboard input line serial device.
[$C009], For input from the screen (device 3), the routine
stores the device number in the input source flag (214/$D6) 61287 6EF67
and sets the current right window margin (231/$E7) as the Accepts a byte from RS-232.
ending column for input (234/$EA); then it calls the screen Calls the RS-232 GETIN routine at 61181/SEEFD to retrieve a
editor routine to retrieve a character from the screen line character from the RS-232 input buffer. If the character value
[$C009], Unfortunately, this is not the proper setup procedure is nonzero, indicating that a valid character has been returned,
for screen input, so BASIN from the screen does not work in the routine exits with that value in the accumulator. However,
the current 128 Kernal. For screen input, the ending row for because of a branch to an incorrect address, the routine ne-
input (2608/$0A30) must be specified, and the setting of bit 7 glects to clear the carry bit, which will be set as a result of the
of the input source flag must be preserved so that the screen comparison with zero. Thus, contrary to other versions of the
editor routine will know when the end of the input line is Kernal, the carry bit will be set when the character code is
reached. See the entry at 49819/$C29B for details of the valid. If the value returned is zero, the routine checks bit 6 of
proper procedure. the RS-232 status flag (2580/$0A14) to determine whether the
To retrieve a byte from a serial device (device number DSR signal is still present (indicating that the external device
greater than 3), a branch is taken to the routine at 61276/ is still active). If the flag value indicates that the DSR signal is
$EF5C. For RS-232 input (device 2), a branch is taken to the present, the routine loops back to see whether a character has
routine at 61287/$EF67. For tape (device 1), this routine falls arrived in the input buffer. If DSR is missing, the character
through into the next routine. code for RETURN, 13/$0D, is returned in the accumulator
with the carry bit clear. In any case, the X register value is un-
61224 $EF28 used and the Y register value is preserved.
Accepts a byte from tape.
Retrieves a byte from the cassette buffer (2816-3007/
61305 $EF79 BSOUT
$OBO0-$0BBF), then checks the next character in the buffer. If Sends a byte to the current output device.
that character is the zero byte marking the end of the file, bit (This routine is the normal target of the jump table entry at
6 of the tape status flag (144/S90) will be set to %1 to indicate 65490/$FFD2, via the indirect vector at 806/$0326.)
that the end has been reached. If all characters have been re- If the current output device (154/S9A) is the screen (device 3),
trieved from the buffer, the next block of data will be read. the routine jumps to the screen editor routine to display the
The retrieved byte will be in the accumulator upon exit and character in the accumulator [$C00C]. If a serial device is spec-
ified (device number greater than 3), the routine jumps to the
550 551
61332 SEF94 61430
8EFF6

CIOUT routine [$E503] to send the byte in the accumulator Checks whether the specified logical file number (184/$B8) is
over the serial bus. Otherwise, the value to be sent is stored in already used for a currently open file and exits with a Kernal
158/$9E, and the X and Y register contents are placed on the file-open error if it is (the status register carry bit will be set,
stack for later restoration. For RS-232 (device 2), a branch is and the accumulator will hold the error code, 2/$02).
taken to 61367/$EFB7. The branch will also be taken if the Next, the routine checks the number of files currently
keyboard (device 0) is specified as the output device, but that open (152/$98) and exits with a Kernal too-many-files error if
shouldn't happen if you use normal Kernal calls to set the de- ten files are already open (the carry bit will be set and the ac-
vice number—CKOUT [$F14C] won't accept the keyboard as
cumulator will hold the error code, l/$01). Otherwise, the
an output device. For tape (device 1), this routine falls through
into the following routine. number of open files is incremented and the logical file num-
ber is added to the file number table (866/$0362), The current
secondary address (185/$B9) is ORed with the value 96/S60
61332 $EF94 and placed in the corresponding position in the secondary ad-
Sends a byte to tape. dress table (886/$0376). The OR step is significant; some Kernal
Checks whether the cassette buffer has been filled. If not, the routines expect bits 5 and 6 of the secondary address to be set.
byte stored in 158/$9E is placed in the next available position The current device number (186/$BA) is placed in the cor-
in the buffer. However, if the buffer is currently full, the cur- responding position in the device number table (876/S036C).
rent block must be written before the character can be placed For files opened to the keyboard (device 0) or screen (de-
in the buffer. The subroutine to write the block to tape vice 3), the routine exits at this point, since no further setup
[$EA15] is called; then the type identifier value for a data steps are required for those devices. For RS-232 files (device
block (2/$02) is placed in the first byte of the buffer, and the 2), a branch is taken to the routine at 61504/$F040. For tape
buffer pointer (166/SA6) is initialized to the next buffer posi- (device 1), a branch is taken to the routine at 61430/$EFF6.
tion, If the RUN/STOP key is pressed while the block is being For a serial device (device number greater than 3), the subrou-
written, the routine will exit with the status register carry bit tine at 61643/$F0CB is called; then the routine exits with
set and with the accumulator containing the value 0/$00. carry clear (except in the case where the specified device is not
After the character is placed in the buffer, the X and Y present).
register values will be restored from the stack, and the accu-
mulator will be reloaded with the stored byte value so that all 61430 SEFF6
registers have the same value on exit that they did on entry. Opens a file for input or output to tape.
The carry bit will be clear upon exit. Checks the cassette buffer address and exits with a Kernal ille-
gal-device-number error if it is less than 512/$0200. The
61367 SEFB7 lower four bits of the secondary address are then tested. If all
Sends a byte to the RS-232 port. are %0, the file has been opened for reading, so the routine
Calls the routine at 59231/$E75F to store the character code searches for the specified tape header (or simply for the next
from the accumulator into the RS-232 output buffer; then header if no filename is specified). If the RUN/STOP key is
jumps into the preceding routine to restore the accumulator pressed while the routine is searching for the header, the rou-
and X and Y register values from the stack and exits with carry tine will exit with carry set and with the accumulator holding
clear. the value 0/$00. If an end-of-tape header is read before the
data header is found, the routine exits with a Kernal file-not-
61373 $EFBD OPEN found error (the carry bit will be set, and the accumulator will
Opens a logical file to a specified device. contain the error code, 4/$04), If a file header is found, the
(This routine is the normal target of the jump table entry at routine sets the buffer pointer (166/$A6) to 191/$BF {the
65472/SFFCO, via the indirect vector at 794/$031A.) value to indicate that the buffer is empty) so that the first
552 553
61504 SF040 61616
SFOBO

block of data will be read when BASIN is called for the first No error checking is done, so if you specify a value greater
time; then it exits with carry clear. than 10 (%1010) in those bits, you'll wind up with an invalid
This routine does have a flaw: It neglects to check timing constant and won't be able to send or receive data.
whether the loaded header block has a type identifier of 4 (the Also, for higher baud rates, the time between interrupts is so
type identifier for data file headers). Thus, if a program file short that the system may not have time to process received
(type identifier of 1 or 3) is found with the specified name, or bytes. In general, stick to rates of 1200 baud or lower.
before the next data header if no name is specified, it will be
The rate factor value in 2578-2579/$0A12-$0A13 is then
opened. However, tape program files cannot be read or writ-
converted into a bit timing constant, the number of CIA timer
ten, only saved or loaded, so it does no good to open them for
counts for the bit duration, and the result is stored in
reading. When a program file is opened, a long block error oc-
2582-2583/$0A16-$0A17. The formula is bit time equals rate
curs after you try to read the first block.
factor times 2 plus 200.
If any of bits 0-3 of the secondary address are % 1 , a data Next, the routine checks the handshaking setting specified
file will be opened for writing. The subroutine to request that by bit 0 of the command register. For x-line handshaking, the
the PLAY and RECORD buttons be pressed is called. If the routine checks the CIA port bit connected to the DSR line (pin
RUN/STOP key is pressed during that subroutine, the routine L of the user port). If the external RS-232 device is not holding
will exit with carry set and with the accumulator containing this line high, bit 6 of the RS-232 status flag will be set. How-
0/$00. The subroutine at 59673/$E919 is then called to write ever, there's a bug here: If the line is high, indicating that the
a data header for the file (type identifier of 4). After the external device is present, the routine will proceed with carry
header is written, the data block type identifier value (2/$02) set, which is normally used to indicate a problem. (Carry clear
is placed in the first position of the cassette buffer; then the upon return from OPEN is supposed to mean that the file has
buffer pointer is initialized to the next position, and the rou- been opened successfully.)
tine exits with carry clear.
If you're calling OPEN from machine language, you can
just remember that a set carry can be ignored when x-line
61504 $F040 handshaking is in use. However, BASIC still thinks a problem
Opens a file for RS-232 communications. has occurred and will give a DEVICE NOT PRESENT error
Calls the subroutine at 61616/$F0B0 to initialize the CIA #2 when the device is present. The converse side of the problem
port lines to the user port; then clears the RS-232 status flag is that carry will be clear when DSR is low, so BASIC will
(2580/$OA14) and retrieves up to four characters from the cur- think everything is okay when the device is absent.
rent filename (if more are specified, those after the first four The final step is to set the input buffer tail pointer
are ignored). The first character, if present, is placed in the RS- (2585/S0A19) equal to the head pointer (2584/$0A18), and
232 control register (2576/$0A10), the second into the com- the output buffer head pointer (2586/S0A1A) equal to the tail
mand register (2577/$0All), and the last two into the baud pointer (2587/$0AlB). This effectively makes both buffers ini-
rate timing constant (2578-2579/$0A12-$0A13). The number tially empty.
of bits to be sent or received is calculated and stored in
2581/$0A15. The lower four bits of the control register value
61616 $F0B0
are checked to determine the baud rate to use. If the bits are
Sets up CIA #2 ports for RS-232 communications.
all %0, a custom rate is indicated, so the following step to
load a value from the tables is skipped. Otherwise, the value Disables all interrupt sources from CIA #2; then makes the
from bits 0-3 is used as an index into one of the baud rate user port lines connected to bits 0 and 3-7 of port B inputs,
timing constant tables, depending on the video system in use while making the lines for bits 1-2 outputs and setting them
(59470/$E84E for NTSC or 59490/$E862 for PAL), and the high (+5 volts). The line for bit 2 of port A (initialized to an
specified table entry is loaded into 2578-2579/$0A12-$0A13. output line during IOINIT) is set high. This is the transmitted
data line, which is normally held high when no data is being
554 555
61643 $FOCB $F14C 61772

sent. For information on the usage of the other lines, refer to address values are loaded into 186/SBA and 185/SB9, respec-
the discussion of CIA #2 in Chapter 8. Finally, the RS-232 ac-
tively. If the device number is 0 (keyboard) or 3 (screen), the
tivity flag (2575/S0A0F) is cleared to indicate that no CIA #2
interrupts are enabled. routine skips ahead to set this as the input device number and
exit, since that's all that's necessary for input from those
sources. For device numbers greater than 3 (serial devices), a
61643 $FOCB branch is taken to the routine at 61735/$F127. For device 2
Opens a file for serial bus communications. (RS-232), a jump is taken to the routine at 59285/$E795 to
Checks the current secondary address (185/$B9) and exits im- prepare for RS-232 input. For device 1 (tape), the secondary
mediately (with the status register carry bit clear) if the sec- address is tested. If it is not 96/$60 (0/$00 before the OR in
ondary address value has bit 7 set (if the value is greater than the OPEN routine), the file has been opened for writing, so
127). The routine also exits without performing any other ac- the routine exits with a Kernal not-input-file error (the status
tions if the length of the name specified for the file being register carry bit will be set and the accumulator will hold the
opened (183/SB7) is zero. Otherwise, the serial status flag error code, 6/$06). Otherwise, the device number is set as the
(144/$90) is cleared to zero, and the specified device (186/ current input device (153/$99), and the routine exits with
$BA) is commanded to listen. If the serial status flag indicates carry clear.
that the device has not responded, the return address of the
calling routine will be discarded and the routine will exit with 61735 $F127
a Kernal device-not-present error (the carry bit will be set and
Prepares a serial device file for input.
the accumulator will contain the error code, 5/$05). If the de-
vice has responded, the secondary address is sent as a com- Sends a TALK command to the serial device specified in the
mand using the SECOND routine [$E4D2]. (The upper four accumulator, then tests the serial status flag (144/$90) to see
bits of the secondary address are masked to %0000, so only whether the device has responded. If the flag indicates that
the lower four bits are significant.) Again, if the device does the device is not present, the routine exits with a Kernal de-
not respond, the routine exits OPEN with a Kernal device-not- vice-not-present error (the status register carry bit will be set
present error. If a filename has been specified, the characters and the accumulator will contain the error code, 5/$05). If the
of the name are sent to the serial device. (Since the ATN line device has responded, the routine checks the value of the sec-
is allowed to go high after the secondary address is sent, the ondary address (185/$B9). If bit 7 of the value is %1 (if the
filename characters are not seen as commands.) The routine secondary address is 128 or greater), no secondary address is
ends by commanding the device to unlisten. sent—the routine simply performs the talk-listen turnaround.
Otherwise, the TKSA routine [$E4E0] is called to send the sec-
ondary address as a command on the serial bus and perform
61702 $F106 CHKIN the talk-listen turnaround. If the device responds again, the
Sets the current input file for GETIN and BASIN.
routine sets the device number as the current output device
(This routine is the normal target of the jump table entry at
65478/$FFC6, via the indirect vector at 798/$031E.) (154/$9A) and exits with carry clear. If the device does not re-
spond, the routine exits with a Kernal device-not-present error.
Checks whether a file with the logical file number specified in
the X register is currently open by verifying that a matching 61772 $F14C CKOUT
entry exists in the logical file table at 866-875/$0362-$036B. Sets the current output file for BSOUT.
If no match is found, the routine exits with a Kernal file-not- (This routine is the normal target of the jump table entry at
open error (the status register carry bit will be set and the ac- 65481/$FFC9, via the indirect vector at 800/$0320.)
cumulator will hold the error code, 3/$03). If an entry for the Checks whether a file with the logical file number specified in
file is found in the table, the file number is loaded into the X register is currently open by verifying that a matching
184/SB8, and the corresponding device number and secondary entry exists in the logical file table at 866-875/$0362-$036B.
556
557
61805 $F16D 61865
SF1A9

If no match is found, the routine exits with a Kernal file-not-


open error (the status register carry bit will be set and the ac- 61832 $F188 CLOSE
cumulator will hold the error code, 3/$03). If an entry for the Closes a specified logical file.
file is found in the table, the file number is loaded into 184/ (This routine is the normal target of the jump table entry at
$B8, and the corresponding device number and secondary ad- 65475/$FFC3, via the indirect vector at 796/$031C.)
dress values are loaded into 186/$BA and 185/$B9, respec- Shifts the value of the status register carry bit upon entry into
tively. If the device number is 0, the routine exits with a bit 7 of 146/$92; then checks whether a file with the logical
Kernal not-output-file error (the status register carry bit will be file number specified in the accumulator is currently open. If
set and the accumulator will hold the error code, 7/$07), since not, the routine simply exits with carry clear. If an entry for
it's not possible to send output to the keyboard. If the device the file is found in the file number table, the file number is
number is 3, the routine skips ahead to set this as the output loaded into 184/$B8, and the corresponding device number
device number and exit, since that's all that's necessary to and secondary address values are loaded into 186/$BA and
route output to the screen. For device numbers greater than 3 185/$B9, respectively. The file's position in the tables is
(serial devices), a branch is taken to the routine at 61805/ placed on the stack for later retrieval. The routine then checks
$F16D. For device 2 (RS-232), a jump is taken to the routine whether the file is open to the keyboard (device 0) or screen
at 59177/$E729 to prepare for RS-232 output. For device 1 (device 3). In either of these cases, simply removing the table
(tape), the secondary address is tested. If it is 96/$60 (0/$00 entries for the file is sufficient to close the file, so a branch is
before the OR in the OPEN routine), the file has been opened taken to the routine at 61924/$F1E4. For device numbers
for reading, so the routine exits with a Kernal not-output-file greater than 3 (serial devices), a branch is taken to the routine
error. Otherwise, the device number is set as the current out- at 619O3/$F1CF. For device 1 (tape), a branch is taken to the
put device (1154/$9A), and the routine exits with carry clear. routine at 61865/$F1A9. For device 2 (RS-232), the table en-
tries for the file are deleted, then a jump is taken to the rou-
tine at 61616/$F0B0 to reinitialize the CIA ports and disable
61805 8F16D the interrupts that drive RS-232 communications.
Prepares a serial device file for output.
Sends a LISTEN command to the device specified in the accu- 61865 $F1A9
mulator, then tests the serial status flag (144/$90) to see Closes a tape file.
whether the device has responded. If the flag indicates that Checks the secondary address for the file (185/$B9). If it is 0,
the device is not present, the routine exits with a Kernal de- indicating that the file has been opened for reading, all that is
vice-not-present error (the status register carry bit will be set required is to delete the table entries for the file, so a branch is
and the accumulator will contain the error code, 5/$05), If the taken to 61924/$F1E4. If the file has been opened for writing,
device has responded, the routine checks the value of the sec- the routine adds a zero following the last data byte in the
ondary address (185/$B9). If bit 7 of the value is %1 (if the
secondary address is 128 or greater), no secondary address is buffer (which contains the final block of data for the file), then
sent—the routine simply allows the serial bus ATN line to go writes the final block to tape. If the RUN/STOP key is pressed
high. Otherwise, the SECOND routine [$E4D2] is called to while the last block is being written, the routine will exit with
send the secondary address as a command on the serial bus. If status register carry bit set and with the accumulator holding
the device responds again, the routine sets the device number 0/$00. If bit 1 of the secondary address is set to % 1 , then an
as the current output device (154/$9A) and exits with carry end-of-tape header will be written following the final data
clear. If the device does not respond, the routine exits with a block. The routine then jumps to 61924/$F1E4 to remove the
Kernal device-not-present error. table entries for the file.

558 559
61903 SF1CF SF23D 62013

61903 SF1CF 61970 $F212


Closes a file on a serial device. Load parameters for a logical file.
Checks the preserved status of the cany bit when the CLOSE Loads the current logical file number (184/$B8), current de-
routine is entered. If carry is set, and if the device number vice number (186/SBA), and secondary address (185/$B9)
(186/$BA) is 8 or greater, and if the secondary address for the with the values for a specified open file from the tables at
file is 15 (indicating that the file has been opened as a com- 866-895/$0362-$037E The routine should be called with the
mand channel to the drive), a branch is taken to 61924/$F1E4 X register containing the offset (0-9) into the tables for the
to simply remove the file entries rather than actually closing file's entry.
the file. This provides a solution to a problem in previous ver-
sions of the Kernal. Closing the command channel to a drive 61986 8F222 CLALL
also closes all other open files on the drive, possibly an un- Clears file table entries,
wanted side effect. By calling CLOSE with carry set, this can (This routine is the normal target of the jump table entry at
now be avoided. 65511/$FFE7, via the indirect vector at 812/$032C.)
If carry is clear when CLOSE is called, the normal closing Resets the number of open files (152/$98) to zero, then falls
steps are performed: The subroutine at 62878/$F59E is called through into the next routine to reestablish default I/O channels.
to close the file on the serial device; then the routine falls Note that this routine doesn't actually close any files that may
through into the next one to remove the table entries for the be open to external devices. Unclosed tape or disk files may
file. cause problems and should be avoided. See the CLOSE ALL
entry at 62013/$F23D for a routine that properly closes all
61924 SF1E4 files opened to a specified serial device.
Removes an entry from the logical file tables.
Retrieves the offset to the file's position in the logical file 61990 $F226 CLRCH
number, device number, and secondary address tables from Resets default I/O channels.
the stack and decrements the number of open files (152/$98). (This routine is the normal target of the jump table entry at
Next, the routine checks whether the file to be deleted is the 65484/$FFCC, via the indirect vectoT at 802/$0322.)
last entry in the tables. If so, decrementing the number of Sends an UNLISTEN command over the serial bus if the cur-
open files is sufficient to effectively remove the file's table en- rent output device number (154/S9A) is greater than 3, and an
tries; and the routine exits at this point. Otherwise, the current UNTALK command if the current input device number (153/
last entry in the table is copied to the specified file's position, $99) is greater than 3. The channels are then reset to the de-
overwriting the entries for the file to be deleted. Carry will al- fault devices: 3 (screen) for output and 0 (keyboard) for input.
ways be clear upon exit.
62013 $F23D CLOSE_ALL
61954 $F202 Closes all open files for a specified serial device.
Checks whether a file is already open. (This routine has a jump table entry at 65354/$FF4A.)
Clears the serial status flag (144/$90), then searches the logi- Stores the value in the accumulator as the current device num-
cal file number table (866-875/$0362-$036B) for an entry ber (186/$BA). If the specified device number is the current
with the same number as the value specified in the X register. input or output device, the input or output channel is reset to
If no match is found, or if no files are open, the routine exits the default device (keyboard or screen). Next, the routine
with the status register N bit set (test with BMI). If a file using searches the device number table at 876-885/$036C-$0375
the specified number is already open, the status register Z bit for files that might be open to the specified device. Any that
will be set (test with BEQ). are found are closed by using the Kemal CLOSE routine
65475/$FFC3.
560 561
62053 8F265 SF326 62246

62053 $F265 LOAD the filename to the specified device; then the device is com-
Loads or verifies a program file from disk or tape. manded to talk and is sent the secondary address. The first
(This routine has a jump table entry at 65493/SFFD5.) two bytes, which, for a program (PRG) file, contain the start-
Stores the address value from the X and Y registers into the ing address, are loaded into the working pointer (174-175/
pointer to the starting address for the load (195-196/ $AE-$AF). If the original secondary address value in 158/$9E
$C3-$C4), then takes an indirect jump through the ILOAD is 0/$00, indicating that a relocating load has been specified,
vector (816/$0330). The vector normally points back to the lo- the starting address in the pointer is replaced with the one in
cation immediately following the jump, but you can modify 195-196/$C3-$C4. If Kernal messages are allowed, LOAD-
the action of the LOAD routine by redirecting this vector to a ING or VERIFYING is displayed.
routine of your own. See the ILOAD entry for details. The main reading step consists of clearing the read
The operation type value in the accumulator is stored in timeout bit (bit 1) of the serial status flag, checking for a
the load/verify flag'(147/$93), and the tape/serial status flag RUN/STOP keypress, calling ACPTR [$E43E] to read a byte
(144/$90) is cleared. The device number (186/$BA) is then from the program file, and testing whether the read timeout
tested. If it's 4 or greater, a branch is taken to the routine at bit has been set during the read. If it has been set, the routine
62075/$F27B to attempt a load from the specified serial de- loops back to try to read the byte again. If RUN/STOP is
vice. Otherwise, a jump is taken to the routine at 62246/ pressed, the routine goes to 62901/$F5B5 to halt the
$F326 to attempt a load from tape. operation.
For a verify operation (nonzero value in 147/$93), the
62075 $F27B byte read from disk is compared to the one at the address
Loads or verifies a file from a serial device. pointed to by 174-175/$AE-$AF in the bank specified in
Begins by clearing bits 6 and 0 of the fast serial flag 198/$C6. If the bytes do not match, the verify error bit (bit 4)
($2588/$0AlC). Bit 6 is cleared so that the routine which at- in the serial status flag is set to % 1 . For a load operation (0 in
tempts fast serial output will have to verify for itself that fast 147/$93), the byte read from disk is stored at the address
communications are available; there is no apparent reason for pointed to by 174-175/$AE-$AF in the bank specified in
clearing bit 0. The current secondary address (185/$B9) is 198/$C6. In either case, the address in the pointer is then in-
placed in temporary storage (158/$9E). If the length of the cremented and compared against the value 65280/$FF00. If it
current filename (183/$B7) is zero, the routine exits with the reaches this value, a Kernal out-of-memory error occurs (the
Kernal missing-filename error (the status register carry bit will routine exits with carry set and with the accumulator holding
be set and the accumulator will hold the error code, 8/$08). the error code, 16/$10). If the EOI bit in the serial status flag
Otherwise, the length value is placed in temporary storage (bit 6) is not % 1 , the routine loops back to read another byte.
(159/$9F), and (if Kernal control messages are allowed) When EOI is set, indicating that the end of the file has been
SEARCHING FOR, followed by the filename, is displayed. reached, the routine sends an UNTALK command, closes the
The subroutine at 62369/$F3Al is called to attempt a fast se- file, loads the address from 174-175/$AE-$AF (which will
rial load or verify of the specified file. If carry is clear upon re- point to the location immediately following the last byte
turn (indicating that a fast load or verify has been performed), loaded) into the X and Y registers, then exits with carry clear.
the routine exits with carry clear and with the X and Y regis-
ters holding the ending address for the data. Otherwise, the 62246 $F326
routine proceeds with the standard serial load or verify. Loads or verifies a program file from tape.
The filename length is restored from temporary storage, Exits with the Kernal illegal-device-number error if the device
and the current secondary address is set to 96/$60—cor- number in the accumulator is not 1/S01, or if the cassette
responding to a secondary address of zero, the value for read- buffer address is less than $0200. (The status register carry bit
ing a file. The serial OPEN routine [$F0CB] is called to send will be set and the accumulator will hold the error code,
562 563
62369 8F3A1 8F3EA 62442

9/$09.) Otherwise, a request for the PLAY button will be exits with the Kernal device-not-present error (tVie status regis-
printed if no buttons are currently pressed, and if Kernal mes- ter carry bit will be set and the accumulator will hold the error
sages are allowed. If the RUN/STOP key is pressed while code, 5/$05). If the command channel has been opened, the
waiting for a button press (or at any other time during the burst mode load command—UO, followed by the value 3 1 /
routine), the routine will exit with carry set and with 0/$00 in $1F to specify a program file, followed by the codes for the
the accumulator. If Kernal messages are allowed, SEARCHING characters of the filename—is sent to the drive. The CLRCH
is displayed; if a nonzero filename length is specified, that will routine [$FFCC] is called to reset the default I/O channels. Bit
be followed by FOR and the filename. If a filename is sup- 7 of the fast serial flag at 2588/$0AlC is then tested. If the se-
plied, the routine looks for a specified header block [$E99A], rial device is capable of fast serial communications, the bit will
Otherwise, it merely loads the next header block [$E8D0], In have been set to %1 by the BSOUT routine calls used to send
either case, if an end-of-tape header (type identifier of 5) is characters to the device. In this case, the routine branches to
encountered, the routine exits with a Kernal hie-not-found er- 62442/SF3EA to perform the operation using the very high
ror (the carry bit will be set and the accumulator will hold the speed burst mode. If fast serial communications are not avail-
error code, 4/$04). The routine also exits with carry set if bit 4 able, the command channel file is closed, and the routine re-
of the tape status flag (144/$90) is %1 after the header is turns with carry set, indicating that a standard (slow) load or
loaded, indicating that a read error has occurred. If the type verify must be performed.
identifier byte for the header is not 1 or 3, this is not a pro-
gram file, so the routine loops back to read another header. 62442 $F3EA
If the type identifier is 3, indicating that this is a Loads or verifies a file using fast serial burst mode.
nonrelocatable program file, or if the secondary address Performs a high-speed load or verify of the file specified in the
(185/$B9) is nonzero, the current starting address pointer preceding routine. Burst mode loads are quite different from
value in 195-196/$C3-$C4 is replaced with the one specified standard loads. In burst mode, data is sent a sector (254 bytes)
in the two header bytes following the type identifier. Next, the at a time. A status byte is sent before the data bytes for each
ending address for the file is calculated and stored in sector. The serial bus CLK line must be toggled between bytes
174-175/$AE-$AF. If the ending address value is greater than to acknowledge receipt of the byte.
65279/$FEFF, the routine exits with a Kernal out-of-memory The routine begins by restoring the filename length
error (the carry bit will be set and the accumulator will hold (183/$B7) from temporary storage (159/$9F), then disabling
the error code, 16/$10). The starting address is transferred to IRQ interrupts, allowing the serial bus CLK line to go high
a working pointer (193-194/$C1-$C2) and, if Kernal mes- and setting the serial port for fast serial input. The status byte
sages are allowed, LOADING or VERIFYING is displayed. The for the first sector is read. If the status value is 2/$02, the
subroutine at 59899/$E9FB is used to read the program data specified file has not been found, so the command channel to
from tape into the specified area of memory (carry should be the drive is closed and the routine exits with a Kernal file-not-
clear upon return if the load is successful). Finally, the ending found error (the status register carry bit will be set and the ac-
address is loaded into the X and Y registers before exiting. cumulator will hold the error code, 4/$04). If the status byte is
31/$1F, the file is only one block long. The LOADING or
62369 $F3A1 VERIFYING message is then displayed (if Kernal control mes-
Attempts to set up fast serial load or verify. sages are allowed), and the first two data bytes from the first
Checks the first character of the filename to be loaded and ex- sector are then read and stored in the starting address pointer
its immediately if it's $, indicating that a disk directory rather (174-175/$AE-$AF), If the stored secondary address (158/
than a program is to be loaded. Otherwise, the routine opens $9E) is zero, a relocating load has been specified, so the
a command file (secondary address of 15) to the specified se- pointer is reloaded with the value from 195-196/$C3-$C4.
rial device. If the file is not opened successfully, the routine The starting address is then transferred to the working pointer
(172-173/$AC-$AD).
564 565
62616 $F498 SF503 62723

Before each sector is read, the RUN/STOP key is tested. 62642 $F4B2
If that key has been pressed, a branch is taken to the routine Aborts burst mode load/verify if maximum address exceeded.
at 62630/$F4A6 to halt the operation. Otherwise, the count of Closes the file, then discards the return address of the calling
data bytes in the sector (165/$A5) is initialized—252 bytes for routine and exits with the Kernal out-of-memory error (upon
a full first sector, 254 bytes in following full sectors, and a exit, the status register carry bit will be set and the accumu-
variable number of bytes in the last sector—and the subrou- lator will hold the error code, 16/$10).
tine at 62661/$F4C5 is called to load or verify the data bytes.
After each sector is loaded or verified, the status byte for the
62650 SF4BA
next sector is read. If the status value is 0 or 1, the routine
Reads a byte using fast serial hardware.
loops to read the next sector. If it is 31/$IF, the next block is
the last one for the file, so an additional byte is read from the Waits for a serial register interrupt to occur on CIA # 1 (indi-
device. This value will be the number of bytes in the final sec- cating that a byte has been received via the fast serial hard-
tor. If the status value is 2 or greater (but not 31), an error has ware), then retrieves the byte from the serial data register and
occurred, so a branch is taken to the routine at 62616/$F498 returns it in the accumulator.
to handle the error.
62661 $F4C5
After all bytes for the file have been read, the routine al-
Loads or verifies a block of data using burst mode.
lows the CLK line to go high, reenables IRQ interrupts, and
closes the command channel file. (The status register carry bit Waits for a serial register interrupt to occur on CIA #1 (indi-
is set before CLOSE [$FFCC] is called so that the special com- cating that a byte has been received via the fast serial hard-
mand file close is performed.) The status register carry bit will ware); then retrieves the byte from the serial data register and
be clear upon exit for a successful load. Bit 4 of the serial sta- toggles the CLK line to acknowledge reception of the byte. If
tus flag (144/$90) will reflect the success of a verify operation. the operation flag (147/S93) contains a nonzero value, indicat-
ing verify, the byte read from the serial bus is compared with
62616 $F498 the one pointed to by 174-175/$AE-$AF in the bank speci-
Handles read error during burst mode load/verify. fied in 198/$C6. If the bytes do not match, the verify error bit
(bit 4) of the serial status flag (144/$90) is set to % 1 . For a
Sets bit 1 of the serial status flag (144/$90) to %1 to indicate a load operation, the byte read from the bus is stored at the ad-
read timeout. Then it discards the return address of the calling
dress pointed to by 174-175/$AE-$AF in the bank specified
routine and exits with the status register carry bit set and the
accumulator holding the value 41/$29, the code for BASIC'S in 198/$C6. The address value in the pointer is then incre-
FILE READ error message. mented; if it exceeds 65279/$FEFF, the routine will exit with
the status register carry bit set. The count of bytes to be read
from this sector (165/$A5) is decremented. If bytes remain to
62630 SF4A6 be read, the routine is repeated. Otherwise, it exits with carry
Stops burst mode load/verify if RUN/STOP key pressed.
clear and with the accumulator holding the high byte of the
Closes the file, then changes the current secondary address to next load address.
zero, discards the return address of the calling routine, and ex-
its with the status register carry bit set and the accumulator 62723 $F503
holding the value 0/$00.
Toggles state of serial bus CLK line.
Reverses the value of bit 4 of CIA #2 port A. Since the line for
this bit is connected to the serial bus CLK output line, this will
reverse the state of the line. This is the handshake for burst
mode loads from disk.

566 567
62735 $F50F 62901
SF5B5

62735 $F50F ary address is set to 97/$61, the value to open a program file
Displays SEARCHING FOR message. for writing; then a file is opened using the current filename
Checks the Kernal message flag (157/$9D), exiting immedi- (pointed to by 187-188/$BB-$BC). A LISTEN command is
ately if messages are not allowed. The message SEARCHING sent to the current device (186/$BA) along with the secondary
is displayed; then the current filename length (183/$B7) is address. The low and high bytes of the starting address for the
tested. If it's nonzero, the message FOR and the characters of save are then written as the first two bytes of the file.
the filename are displayed following SEARCHING. The subroutine at 63436/$F7CC is used to retrieve a byte
from the specified memory area, and the subroutine at 58629/
62771 $F533 $E503 is used to write the byte to the file (using fast serial
Displays LOADING or VERIFYING message. mode if it is available). After each byte, the routine checks
Loads the accumulator with the offset for either the LOAD- whether the RUN/STOP key has been pressed. If it has been
ING or VERIFYING message, depending on whether the value pressed, a branch is taken to the routine at 62901/$F5B5 to
in the operation flag (147/S93) is zero or nonzero. The routine abort the SAVE. Otherwise, the address pointer is incremented,
at 63262/$F7lE is then called to display the message (if and the process repeats until all bytes have been written.
Kernal messages are allowed). (Before this routine is called, the starting address must be
loaded into 193-194/$C1-$C2 and the ending address plus 1
62782 $F53E SAVE into 174-175/$AE-$AF.) When all bytes have been written,
Saves a block of memory to tape or disk. an UNLISTEN command is sent to the serial device; then the
routine falls through into the following one to close the file.
(This routine has a jump table entry at 65496/$FFD8.)
Stores the address value from the X and Y registers into the When fast serial communications are available, files are
pointer to the ending address for the save (174-175/$AE-$AF), loaded by sectors (254-byte chunks of data) using a special
and stores the address from the two-byte zero-page pointer feature of the 1571 drive known as burst mode. However, fast
specified in the accumulator into the pointer to the starting ad- mode SAVEs are still done byte by byte. This is the reason
dress for the save (193-194/$C1-$C2). The routine then takes more time is required to save a file using fast serial mode than
to load a file of the same length,
an indirect jump through the ISAVE vector at 818/$0332.
That vector normally points back to the location immediately
following the indirect jump, but you can modify the actions of 62878 $F59E
the SAVE routine by redirecting the vector to your own rou- Closes a file on a serial device.
tine. See the ISAVE entry in Chapter 2 for details. Exits immediately if the secondary address is greater than
The device number (186/$BA) is then tested. If it's 1 127/$7F (if bit 7 of 185/$B9 is %1). Otherwise, a LISTEN
(tape), a branch is taken to the routine at 62920/$F5C8. If it's command is sent to the current serial device; then the upper
4 or greater (serial device), a branch is taken to the routine at four bits of the secondary address are set to %1110/$E to
62817/$F561. Otherwise, the routine exits with the Kernal form the CLOSE command for the logical file. This command
illegal-device-number error (the status register carry bit will be is then sent to the current serial device, followed by an
set and the accumulator will hold the error code, 9/$09). UNLISTEN command. The routine then exits with the status
register carry bit clear. The serial status flag (144/S90) will re-
62817 SF561 flect the success of the operation.
Saves a block of memory to a serial device.
Begins by checking the filename length (183/$B7). If the 62901 $F5B5
length value is zero, the routine exits with the Kernal missing- Aborts LOAD or SAVE to serial device.
filename error (the status register carry bit will be set and the Calls the subroutine at 62878/SF59E to close the file, then
accumulator will contain the error code, 8/$08). The second- loads the accumulator with zero and exits with the status reg-
ister Z and carry bits set.
568
569
62908 $F5BC 8F65E 63070

62908 $F5BC 2589-2591/$0AlD-$0AlF is decremented. The 128 uses this


Displays SAVING message and filename. timer only when executing the BASIC SLEEP statement; other-
Checks the Kernal message flag (157/$9D) and exits immedi- wise, it is available for your own timing applications.
ately if Kernal messages are not allowed. Otherwise, the mes- If the PAL/NTSC flag (2563/S0A03) indicates that PAL
sage SAVING is printed. If a filename is being used (indicated (European) video is in use, the jiffy clock compensation
by a nonzero length value in 183/$B7), the name is also counter at 2614/$0A36 is decremented. Each time this counter
printed following SAVING. rolls over from 0 to 255/$FF, it is reset to 5 and the routine is
repeated. Thus, in a PAL system the timers are updated 6
62920 $F5C8 times for every 5 IRQ interrupts, or 60 times for every 50 in-
Saves a block of memory to tape. terrupts. As a result, the clock is incremented 60 times per sec-
Begins by checking the tape buffer address, exiting immedi- ond regardless of whether the system interrupts occur at the
ately if it is less than $0200. If no buttons are currently NTSC rate (60 times per second) or the PAL rate (50 times per
pressed on the tape drive, the subroutine to print PRESS second). The routine then falls through into the following one.
PLAY &. RECORD ON TAPE (if Kernal messages are allowed)
and wait for a button press is called. If the RUN/STOP key 63037 $F63D
has been pressed while waiting for the tape button (or at any Scans RUN/STOP key column.
other time during this routine), the routine exits with the sta- Reads the CIA port connecting the rows of the keyboard ma-
tus register carry bit set and with the accumulator holding trix. The keyboard scan routine [$C55D], normally performed
0/$00. Otherwise, if Kernal messages are allowed, the SAV- earlier in the IRQ sequence, leaves the CIA port connected to
ING message is displayed, followed by the filename (if one is the columns of the keyboard matrix set to scan column 7, the
used). Next, a header type identifier value is selected for the column containing the RUN/STOP key (see Figure 7-1 in
file, according to bit 0 of the secondary address (185/$B9). If Chapter 7). If the RUN/STOP key is pressed, the matrix rows
that bit is %0, a type identifier of 1 (relocatable file) is used. If for columns 1 and 6 (containing the SHIFT keys) are tested. If
the bit is % 1 , the type identifier byte will be 3 (nonrelocatable any key in those columns is pressed, the routine exits (so
file). The subroutine at 59673/$E919 is used to write the SHIFT-RUN/STOP will not be registered as a RUN/STOP
header for the file. The subroutine at 59928/$EA18 is used to keypress). Otherwise, the row register value is stored in
write the data to the file. (Before this routine is called, the 145/$91.
starting address must be loaded into 193-194/$C1-$C2 and
the ending address plus 1 into 174-175/$AE-$AF.) Finally, bit 63070 $F65E RDTIM
1 of the secondary address is tested. If that bit is %0, the rou- Reads the software jiffy clock.
tine exits with carry clear. However, if the bit is % 1 , an end-
{This routine has a jump table entry at 65502/$FFDE.)
of-file header (type identifier of 5) is written to tape following
Returns the values in the software jiffy clock locations
the program.
(160-162/$A0-$A2), which hold the count of jiffies (1/60 sec-
ond intervals) since the system has been turned on or since
62968 $F5F8 UDTIM the clock time has last been reset. Upon return, the accumu-
Updates jiffy timers and checks RUN/STOP key column. lator will hold the low byte of the clock value (from 162/$A2),
(This routine has a jump table entry at 65514/$FFEA.) the X register will hold the middle byte (from 161/$A1), and
Increments the software jiffy clock at 160-162/$A0-$A2 (part the Y register will hold the high byte (from 160/$A0).
of the normal IRQ sequence). If the timer has reached a count
of 5184OO1/$4F1AO1 (corresponding to a time of 24:00:00), all
three timer bytes are reset to zero. Next, the jiffy timer at

570 571
63077 SF665 $F731 63281

1
63077 $F665 SETTIM Kernal error messages are normally disabled when BASIC
Sets the software jiffy clock. is active. (BASIC substitutes its own, more verbose error mes-
{This routine has a jump table entry at 65499/$FFDB.) sages.) However, Kernal error messages are enabled while the
Stores the value in the accumulator upon entry in 162/$A2, machine language monitor is active,
the low byte of the clock. The X register contents will be
placed in 161/$A1, the middle byte of the clock value, and 63152 $F6B0
the Y register contents will be placed in 160/$A0, the high
byte of the clock value. Table of Kernal control messages.
The messages in this table are displayed by the following rou-
63086 $F66E STOP tine. The end of each message is marked by a character with
Tests for a RUN/STOP keypress. its high bit set to % 1 .
(This routine is the normal target of the jump table entry at Offset Message
655O5/$FFE1 via the 1ST0P vector at 808/$0328.) 0/$00 I/O ERROR #
Checks the STOP key flag (145/191), set during the UDTIM 12/SOC SEARCHING
routine [$F5F8] in the IRQ sequence. If the flag contains the 23/$17 FOR
value 127/$7F, indicating that RUN/STOP has been pressed, 27/$lB PRESS PLAY ON TAPE
46/$2E PRESS RECORD & PLAY ON TAPE
the Kernal CLRCH routine [$FFCC] is called to restore default 73/$49 LOADING
I/O, and the count of characters in the keyboard buffer (208/ 81/$51 SAVING
$D0) is reset to zero. Upon exit, the status register Z bit will be 89/$59 VERIFYING
set if the RUN/STOP key has been pressed or clear otherwise. 99/$63 FOUND
106/$6A OK
63100 $F67C
Handles Kernal I/O errors. 63262 $F71E
Loads the accumulator with an error number depending on Handles Kernal control messages.
the entry point into the routine, then uses BIT opcodes to fall Begins by checking the Kernal message flag (157/$9D), exiting
through to handle the error. immediately if bit 7 of the flag is %0 (indicating that Kernal
Entry point Error number Meaning control messages are disabled). If control messages are al-
63100/$F67C 1 Too many files lowed, the value in the Y register is used as an offset to the
63103/SF67F 2 File open first character of the message in the table at 63152/$F6B0.
63106/$F682 3 File not open Characters from the message string are printed until a charac-
63109/$F685 4 File not found ter with its high bit set is encountered. Upon exit, the carry bit
63112/$F688 5 Device not present will be clear,
63115/$F68B 6 Not input file
63118/$F68E 7 Not output file 63281 SF731 SETNAM
63121/$F691 8 Missing filename Sets the length and address of filename for I/O operations.
63124/$F694 9 Illegal device number (This routine has a jump table entry at 65469/$FFBD.)
63127/$F697 16 Out of memory
Stores the value in the accumulator upon entry as the length
Next the CLRCH routine [$FFCC] is used to reset default of the current filename (183/$B7), and the value in the X and
I/O (output to screen). If Kernal error messages are allowed, Y registers as the starting address of the character codes for
I/O ERROR # is printed, followed by the character code for the the current filename (187-188/$BB-$BC). The low byte of the
digit corresponding to the error number. Upon exit, the error address should be in the X register and the high byte in Y.
number will be in the accumulator and the carry bit will be set.
572
573
63288 SF738 SF786 63366

63288 $F738 SETLFS 63331 SF763 MEMTOP


Sets logical file number, device number, and secondary address Sets or reads the system's top-of-memory pointer.
for I/O operations. (This routine has a jump table entry at 65433/$FF99.)
(This routine has a jump table entry at 65466/$FFBA.) Begins by checking the status register carry bit. If carry is
Stores the value in the accumulator upon entry as the current clear, the values in the X and Y registers are loaded into the
logical file number (184/$B8), the value in the X register as svstem top-of-memory pointer (2567-2568/$OA07-$OA08),
the current device number (186/$BA), and the value in the Y the low byte from X and the high byte from Y. If carry is set,
register as the current secondary address (185/$B9). the current top-of-memory pointer value is returned in the X
63295 $F73F SETBNK and Y registers, the low byte in X and the high byte in Y.
Sets data and filename banks for I/O operations. 63346 $F772 MEMBOT
(This routine has a jump table entry at 65384/$FF68.) Sets or reads the system's bottom-of-memory pointer.
Stores the value in the accumulator upon entry as the bank (This routine has a jump table entry at 65436/$FF9C.)
number for data being saved or loaded (198/$C6), and the Begins by checking the status register carry bit. If carry is
value in the X register as the bank where the current filename clear, the values in the X and Y registers are loaded into the
can be found (199/SC7). system bottom-of-memory pointer (2565-2566/$0A05-$0A06),
the low byte from X and the high byte from Y. If carry is set,
63300 SF744 READSS the current bottom-of-memory pointer value is returned in the
Reads the tape/serial or RS-232 status byte. X and Y registers, the low byte in X and the high byte in Y.
(This routine has a jump table entry at 65463/$FFB7.)
Checks the current device number (186/$BA); if it's 2 (RS- 63361 $F781 IOBASE
232), the value in the RS-232 status flag (2580/$0A14) is re- Returns base address of I/O block.
turned in the accumulator and the status flag is reset to zero. (This routine has a jump table entry at 65523/$FFF3.)
For other device numbers, the value in the tape/serial status Returns the value 53248/$D000, the lowest address in the
flag (144/$90) is returned in the accumulator. system's I/O block, in the X and Y registers, 0/$00 in X and
208/$D0 in Y.
63324 $F75C SETMSG
Sets the Kernal message control flag. 63366 $F786 LKUPSA
(This routine has a jump table entry at 65424/SFF90.) Checks whether a secondary address value is used.
Stores the value in the accumulator upon entry as the Kernal (This routine has a jump table entry at 65372/$FF5C.)
message flag (157/S9D). Searches the secondary address table (886-895/$0376-$037F)
for an open file with the secondary address value specified in
63327 $F75F SETTMO the Y register upon entry. If no match is found, the status reg-
Sets the IEEE timeout flag. ister carry bit will be set upon exit. If an open file with the
(This routine has a jump table entry at 65442/$FFA2,) same secondary address is found, the corresponding logical
Stores the value in the accumulator upon entry as the IEEE file number will be returned in the accumulator, the device
timeout (2574/$0A0E). This location is unused by the 128. number in the X register and the secondary address in the Y
The routine is a holdover from the original PET/CBM Kernal; register. In this case the carry bit will be clear upon exit.
the IEEE-488 parallel interface is not implemented in the 128.

574 575
63389 $F79D 63440

63389 $F79D LKUPLA 63420 $F7BC


Checks whether a logical file number value is used.
(This routine has a jump table entry at 65369/$FF59.) Writes a byte value to memory.
Stores the value in the accumulator upon entry into the loca-
Searches the logical file number table (866-875/$0362-$036B)
tion specified by the address in 172-173/$AC-$AD (plus the
for an open file with the logical file number value specified in
the accumulator upon entry. If no match is found, the status offset specified in the Y register) in the bank specified in
register carry bit will be set upon exit. If an open file with the 198/SC6.
same file number is found, the logical file number will be re-
63423 $F7BF
turned in the accumulator, with the corresponding device num-
Writes a byte value to memory.
ber returned in the X register and the secondary address in the
Y register. In this case the carry bit will be clear upon exit. Stores the value in the accumulator upon entry into the loca-
tion specified by the address in 174-175/$AE-$AF (plus the
offset specified in the Y register) in the bank specified in
63397 $F7A5 DMA-CALL 198/SC6.
Performs a DMA operation.
(This routine has a jump table entry at 65360/$FF50.)
Translates the bank number for the current operation, in the X 63433 $F7C9
register upon entry, into the equivalent MMU configuration Reads a byte value from memory.
register setting value; then forces bit 0 of the setting value to Returns with the accumulator holding the value from the loca-
%0 to insure that the I/O block will be visible at 53248-57343/ tion specified by the address in 174-175/$AE-$AF (plus the
$D000-$DFFF. With that value in the accumulator, and with offset specified in the Y register) in the bank specified in
the DMA chip command register value in the Y register, the 198/$C6.
routine then jumps to the DMA request routine in common
RAM [$03F0]. 63436 $F7CC
This routine is provided for the purpose of passing com- Reads a byte value from memory.
mands to the REC (RAM Expansion Controller) chip in the Returns with the accumulator holding the value from the loca-
Commodore 1700 and 1750 RAM Expansion Modules. The tion specified by the address in 172-173/$AC-$AD (plus the
chip appears in 128 memory at 57088-57098/$DF00-$DF0A offset specified in the Y register) in the bank specified in
in the I/O block when one of the modules is plugged in. Ad- 198/$C6.
ditional setup steps may be required, depending on the com-
mand. See the REC chip description in Chapter 8 for more 63440 $F7D0 INDFET
information. Retrieves a character from any bank.
(This routine has a jump table entry at 65396/$FF74.)
63406 $F7AE Stores the zero-page pointer address, in the accumulator upon
Retrieves a character from the current filename. entry, in the INDFET address pointer byte (682/$02AA); then
Loads a character from the current filename address (pointed converts the bank number for the target address, in the X reg-
to by 187-188/$BB-$BC) in the bank specified in 199/$C7. ister upon entry, into the corresponding MMU configuration
The Y register value is used as an offset into the filename. The register setting and calls the RAM-resident portion of the
character will be returned in the accumulator; the X register INDFET routine [$02A2]. Upon return, the accumulator will
value upon entry will be preserved during this routine. hold the value from the location at the address specified in the
zero-page pointer (plus the offset specified in the Y register) in
the specified bank.

577
63450 SF7DA 63591
SF867
r
63450 $F7DA INDSTA Bank MMU Configuration Setting
Stores the accumulator contents in any bank. o/$oo 63/$3F (%00111111)
{This routine has a jump table entry at 65399/$FF77.) l/$01 127/$7F (%0111111I)
Converts the bank number for the target address, in the X reg- 2/$02 191/$BF (%10111111)
ister upon entry, into the corresponding MMU configuration 3/$03 255/$FF (%111I1111)
register setting; then calls the RAM-resident portion of the 4/$04 22/$16 (%00010110)
INDSTA routine [$02AF]. This will place the value in the ac- 5/$05 86/$56 (%01010110)
6/$06 150/$96 <%10010110)
cumulator into the specified bank at the address specified in a 214/$D6 (%11010ll0)
zero-page pointer, plus the offset in the Y register. The ad- 7/$07
8/$08 42/$2A (%00101010)
dress of the zero-page pointer must be stored in location 106/$6A (%0I101010)
697/$02B9 before this routine is called. 9/$09
10/SOA 170/$AA (%10101010)
11/$OB 234/$EA (%11101010)
63459 8F7E3 INDCMP 12/$0C 6/$06 (%00000110)
Compares the accumulator contents with a value from any bank. 13/$0D 13/$0D (%00001110)
{This routine has a jump table entry at 65402/$FF7A.) 14/$0E l/$01 (%00000001)
15/$0F 0/$00 {%00000000}
Converts the bank number for the target address, in the X reg-
ister upon entry, into the corresponding MMU configuration
register setting; then calls the RAM-resident portion of the 63488 8F800
INDCMP routine [$02BE], This will compare the value in the Code for Kernal RAM-based subroutines.
accumulator with the value at the address specified in a zero- This area of ROM contains the code for the RAM-resident por-
page pointer, plus the offset in the Y register, in the specified tions of the INDFET, INDSTA, INDCMP, JSRFAR, JMPFAR,
bank. The address of the zero-page pointer must be stored in and DMA_CALL routines. The routines are copied to the ap-
location 712/$02C8 before this routine is called. Upon return, propriate areas of RAM by the routine at 57549/SEOCD, part
the status register N, Z, and C (carry) bits will reflect the result of the reset sequence.
of the comparison.
63591 $F867 PHOENIX
63468 8F7EC GETCFG Initializes function ROMs and attempts to boot a disk in the
default drive.
Translates a bank number into an MMU register setting. (This routine has a jump table entry at 65366/$FF56.)
(This routine has a jump table entry at 65387/$FF6B.) Initializes any internal or external 128 function ROMs logged
Returns with the accumulator holding the MMU register set- during the reset sequence (by the routine at 57963/$E26B). If
ting value corresponding to the bank number in the X register a ROM is detected at one of the four possible address areas for
upon entry. See Chapter 8 for more information on the MMU. function ROMs, the corresponding byte in the ROM ID table
63472 6F7F0 at 2753-2756/$0ACl-$0AC4 will contain a nonzero value.
For logged ROMs, the JSRFAR routine is used to call the cold
Table of MMU register settings for standard banks. start vector of the ROM ($8000 or $C0O0 in bank 4, or $8000
Each of the 16 values in this table corresponds to the MMU or $C000 in bank 8). Depending on the ROMs, there may be
configuration register value that sets up one of the 16 standard no return from the JSR. However, if the routine does return
banks. from all the ROM initializations {or if no ROMs are present),
the X register is loaded with the value 8, and the accumulator
with 48/$30, the character code for 0. The routine then falls
through into the following one to attempt to boot a disk in
drive 0 of device 8.
578 579
63632 SF890 63923

63632 $F890 BOOT_CALL the name of a file to be loaded, and the drive number and a
Attempts to boot a disk. colon are placed immediately before the name in the buffer. If
(This routine has a jump table entry at 65363/SFF53.) a filename is found, the routine attempts to load a file with
Stores the value in the accumulator upon entry as the charac- that name into bank 0. Because the Kernal LOAD routine is
ter code for the current drive number and the value in the X used, this file must be PRG (program) type. This file is always
register as the current device number; then closes any open loaded into bank 0, regardless of the bank number specified
files on the specified device. The sector number ($C2/194) is for boot sectors.
initialized to 0 and the track number is initialized to 1 (booting After the file is loaded (or if no filename is specified), the
begins at sector 0 of track 1). The disk block read command is JSRFAR address pointer (3-4/$03-$04) holds the address of
copied from the table at 64008/$FA08 into the disk command the buffer location following the end-of-filename zero byte,
buffer at 256-268/$0100-$010C. Logical file 0 (the system and the JSRFAR bank (2/$02) is set for bank 15. The JSRFAR
file) is opened as a command channel and logical file 13 as a routine is then used to execute the machine language subrou-
data channel. The first boot sector is read from the specified tine following the filename in the boot sector buffer. (Some
drive into the buffer at 2816-3071/$0B00-$0BFF. If the first machine language code must be present, even if it's only an
three bytes in the sector (bytes 0-2) are the character codes for RTS opcode.) Finally, the routine exits with the status register
the letters CBM, this is a valid first boot sector. Otherwise, the carry bit clear.
drive will be reset and the routine will exit.
For a valid first boot sector, the message BOOTING is 63883 SF98B
printed; then bytes 3-4 from the sector (the load address for Resets the disk drive.
data from any following boot sectors) are stored in locations Preserves the status register and accumulator values on the
172-173/$AC-$AD, byte 5 from the sector (the bank number stack for later retrieval, then restores the data channel for
into which data is to be loaded) is stored in 174/$AE, and booting (logical file 13). The reset command (UI) is sent to the
byte 6 (the number of additional boot sectors to load) is stored disk drive; then I/O channels are reset and the command
in 175/$AF. Subsequent bytes from the sector are printed to channel (logical file 0) is closed as well. Finally, the status reg-
the screen as character codes until a byte with the value zero ister and accumulator are restored to their original values
is encountered or until the end of the sector is reached. Fol- before exiting.
lowing that message, three periods (...) will be printed.
The bank number for boot data is transferred into the 63923 $F9B3
working bank number location (198/$C6). If any more boot Loads additional boot sectors.
sectors are to be loaded (if the value in 175/$AF is nonzero), Begins by incrementing the sector number (194/SC2). If the
data from the sectors is loaded into the bank specified in count exceeds 20 (the maximum sector number for tracks
198/$C6, starting at the address in 172-173/$AC-$AD. Addi- 1-17), the sector number is reset to zero and the track number
tional sectors are loaded sequentially starting with sector 1 of (193/$C1) is incremented. (Since a maximum of 255 addi-
track 1. The high byte of the load address will not be allowed tional sectors can be loaded, all boot sectors will be located on
to roll over from 255/$FF to 0/$00, regardless of the number tracks 1-13.) The equivalent ASCII digits for the track and sec-
of boot sectors specified, (That is, the boot sectors should not tor values are then added to the block read command in the
attempt to load data to addresses above 65279/$FEFF.) buffer at 256-268/$0100-$010C, and the command is sent to
After all additional boot sectors are loaded (or if no addi- the drive via the command channel (logical file 0). The 256
tional sectors are to be loaded), the drive is reset. The routine data bytes from the sector are then read via the data channel
then searches the buffer from the zero byte marking the end (logical file 13) and are stored starting at the address in
of the message until another byte containing a zero is found. 172-173/$AC-$AD in the bank specified in 198/SC6.
The characters, if any, between the zero bytes are taken to be

580 581
63995 8F9FB SFA65 64101

63995 $F9FB Begins by clearing the status register D (decimal) bit to insure
Converts a byte value into two ASCII digits. that the system is not in decimal mode. Next, all CIA #2 inter-
Returns two character codes representing digits for the decimal rupt sources are disabled, and the interrupt control register for
equivalent of the value in the accumulator upon entry. The that chip is checked to determine whether any CIA #2 source
left digit will be in the X register upon return, and the right triggered the NMI interrupt. If so, the routine skips ahead to
digit will be in the accumulator. This routine works only for call the RS-232 handling routine. (CIA #2 interrupts are used
input values in the range 0-99/$00-$63. to drive RS-232 output.) If the NMI was not triggered by a
CIA #2 source, the routine checks whether the RUN/STOP
64008 $FA08 key is pressed. If so, it's assumed that the NMI was triggered
Table of disk commands for booting. by pressing the RESTORE key, so the RUN/STOP-RESTORE
This table holds the text for the disk block read command for sequence is performed. Otherwise, the RS-232 NMI handling
booting (Ul:13 0 01 00), the initialize command (I), and the routine [$E805] is called (if the NMI was not triggered by a
channel number command (#). CIA #2 source, this step will simply reenable any active RS-
232 CIA #2 interrupt sources), and the routine exits via the
64023 $FA17 PRIMM common interrupt return [SFF33],
Handles PRIMM (print immediate) function. The RUN/STOP-RESTORE sequence consists of the fol-
(This routine has a jump table entry at 65405/$FF7D.) lowing steps:
Begins by stashing the accumulator and X and Y register val- • A call to the RESTORE routine [$E056] to restore default
ues on the stack for later retrieval, then increments the return Kernal indirect vectors.
address on the stack and loads it into a working pointer at • A call to the IOINIT routine [$E109] to reset all I/O chip reg-
206-207/$CE-$CF. The pointer thus contains the address of isters to their default values (character definitions for 80-
the location immediately following the JSR which called this column video are normally not reinitialized).
routine. The byte at that location is retrieved and, unless its • A call to the CINT routine [$C000] to restore screen editor
value is zero, is printed as a character. The routine then loops variables to their default values (keyboard table pointers and
back to increment the address on the stack and retrieve an- programmable key definitions will normally be preserved).
other character, repeating until a zero byte is found. At that • A jump back to BASIC through the restart vector
point, the original accumulator and X and Y register values are (2560/$0A00), which normally points to the BASIC warm
restored and the routine exits. Because the return address on start entry vector, 16387/$4003.
the stack has been incremented, the routine will return to the
address following the zero byte rather than to the address fol- You can modify NMI handling by redirecting the INMI
lowing the calling JSR. vector (792-793/$0318-$0319) to a routine of your own. See
the INMI entry and Appendix A for details.
It's very important always to call this routine (or its jump
table entry) with JSR, not JMP, Only JSR puts a return address
on the stack in the expected position; entering with JMP will 64101 $FA65 IRQ
cause the stack to be garbled, which will almost certainly re- Handles IRQ interrupts.
sult in a crash. (This routine is the default target of the IIRQ indirect vector at
788/$0314.)
64064 $FA40 NMI Begins by clearing the status register D (decimal) bit to insure
that the system is not in decimal mode. The screen editor IRQ
Handles NMI interrupts.
{This routine is the default target of the INMI indirect vector at routine [SC024] is called to handle screen mode settings, scan
792/$0318.) the keyboard, and blink the cursor. If the carry is clear upon
return from that routine, indicating that the interrupt was trig-
gered by a midscreen raster interrupt, the routine exits without
583
64128 SFA80 SJTF05 65285

performing any further actions. Otherwise, the UDTIM routine This also means that these character codes cannot be re-
[$F5F8] is called to update the jiffy timers; then the tape motor turned by a key in the standard table. The special functions of
interlock handling routine [$EED0] is called. The interrupt the RUN/STOP key (halting a BASIC program, stopping a
control register for CIA #1 is read to clear any CIA #1 inter- listing, aborting a save or load, working with RESTORE, and
rupts that might have occurred. Next, the initialization status so forth) cannot be transferred to another key. That key has a
flag (2564/$0A04) is checked. If the flag has bit 0 set to % 1 , character code of 3/$03 in the standard table, but for its spe-
indicating that BASIC has been initialized, the BASIC IRQ cial functions, the keyboard column containing RUN/STOP is
routine [$4006] is called to handle sprite movement and sound scanned separately (see 63037/$F63D), and its character code
statements. Finally, the routine exits via the common interrupt is irrelevant.
return [$FF33]. Table 9-5 (the CAPS LOCK table) shows one of the more
You can modify IRQ handling by redirecting the IIRQ amusing bugs in the first version of 128 Kernal ROM. Note
vector (788-789/$0314-$0315) to a routine of your own. See the entry for the Q key. That key is separated from the other
the IIRQ entry and Appendix A for details. alphabetic keys, so the programmer at Commodore who pre-
pared this table overlooked it and neglected to change the en-
64128 $FA80 try when the other letter values were changed to their
Standard keyboard decoding tables. SHIFTed equivalents. The Q entry should be 2O9/$D1, which
The following five 89-byte tables are used to translate the explains why the Q key is unaffected by CAPS LOCK.
keyscan code generated by the SCNKEY routine [$C55D] into
the corresponding character code. The appropriate table is se- 64573-6S279 $FC3D-$FEFF Unused
lected according to the value in the shift key flag (211/$D3), All bytes in this unused area of Kernal ROM hold the value
and its address is loaded into the keyboard table pointer 255/$FF.
(204-205/$CC-$CD). Then the keyscan code is used as an
offset into the table to retrieve the appropriate character code. 65280-65284 $FF00-$FF04 MMU Registers
The table starting addresses are as follows: The MMU configuration and load configuration registers ap-
Address Table pear here in all banks (refer to Chapter 8 for details).
64128/$FA80 Standard (unshifted) and ALT
64217/$FAD9 SHIFT 65285 $FF05 JNMI
64306/$FB32 Commodore Jump to NMI handler routine.
64395/$FB8B CONTROL (This routine is the target of the processor NMI vector at
64484/$FBE4 CAPS LOCK 65530/$FFFA.)
Tables 9-1 through 9-5 show the character codes for each ta- Pushes the accumulator and X and Y register values onto the
ble. See 830-841/$033E-$0349 for information on how you stack, then places the current MMU configuration register
can customize the tables. Values in the standard table (the one value onto the stack as well. (Thus, 128 interrupts place one
addressed in 830-831/$033E-$033F, normally 64128/$FA80), more byte on the stack than do Commodore 64 interrupts.)
rather than the physical keyboard layout, determine which The routine then configures the system for bank 15 and jumps
keys are treated as shift keys. Any key having an entry in that through the INMI indirect vector at 792/$0318 to a routine to
table with one of the following values is treated as the cor- handle the NMI. The vector normally points to 64064/$FA40,
responding shift key: but you can redirect it to a routine of your own for special
l/$01 SHffT handling. See the INMI entry for details. If normal processing
2/$02 Commodore is to continue following the interrupt handling, the handling
4/$04 CONTROL routine should end with a jump to the routine at 65331/$FF33
8/$08 ALT to restore the processor registers and MMU configuration to
their original values.
584 585
r
Table 9-1. Standard (Unshifted) and ALT Decoding Table
64128-64216/$FA80-$FAD8 Table 9-2. SHIFT Decoding Table
64217-64305/$FAD9-$FB31
Table Key Character Table Key Character
index code index code Table Key Character Table Key Character
0/$00 INST/DEL 20/$14 index code index code
45/$2D 58/S3A
l/$01 RETURN 13/SOD 0/S00 INST/DEL 148/S94 45/$2D 91/55B
46/$2E @ 64/$40
2/S02 CRSR w 29/$lD 47/$2F l/$01 RETURN 141/$8D 46/$2E @ 186/5BA
44/$2C CRSR ~ 157/S9D 47/$2F 60/53C
3/$03 F7 136/$88 48/530 E 92/$5C 2/$02
4/$04 Fl 133/$85 49/$31 3/$03 F7 140/$8C 48/$30 £ 169/$A9
* 42/52A
Fl 137/$89 49/$31 * 192/$C0
5/$05 F3 134/586 50/$32 59/S3B 4/S04
6/506 F5 135/$87 5/$05 F3 138/$8A 50/$32 93/$5D
51/$33 CLR/HOME 19/$13
7/$07 CRSR I 17/$11 52/$34 6/S06 F5 139/$8B 51/$33 C L R / H O M E 147/$93
right SHIFT 1/501
8/$08 3 51/$33 53/$35 — 7/$07 CRSR 1 145/S91 52/534 right SHIFT 1/501
61/$3D
9/509 W 87/$57 54/$36 8/S08 3 35/$23 53/535 61/53D
94/$5E
10/$0A A 65/541 55/$37 9/$09 W 215/SD7 54/$36 222/$DE
/ 47/S2F A 193/$C1 55/$37
11/SOB 4 52/S34 56/$38 1 10/SOA / 63/$3F
49/S31
12/50C Z 90/$5A ll/$0B 4 36/$24 56/$38 1 33/$21
57/$39 < 95/$5F
13/$0D 83/$53 58/S3A 12/$0C Z 218/SDA 57/539 4 95/$5F
s CONTROL 4/$04
14/$0E E 69/$45 59/$3B 13/$0D s 211/SD3 58/53A CONTROL 4/$04
2 50/$32
15/$0F left SHIFT l/$01 14/$0E E 197/SC5 59/S3B 2 34/$22
60/$3C space bar 32/520
16/$10 5 53/535 61/$3D 15/$0F left SHIFT l/$01 60/$3C space bar 160/SAO
Commodore 2/S02
17/S11 82/$52 16/S10 5 37/$25 61/$3D Commodore 2/$02
R 62/$3E Q 81/$51 R 210/SD2
17/111 62/$3E Q 209/5D1
18/$12 D 68/$44 63/$3F RUN/STOP 3/$03
19/$13 6 54/S36 18/$12 D 196/SC4 63/53F RUN/STOP 131/483
64/$40 HELP 132/$84
19/$13 6 38/$26 64/540 HELP 132/$84
20/$14 C 67/$43 65/$41 8 (keypad) 56/S38
20/$14 C 195/$C3 65/541 8(keypad) 56/$38
21/$15 F 70/$46 66/$42 5(keypad) 53/$35
22/$16 84/$54 21/$15 F 198/SC6 66/$42 5 (keypad) 53/S35
T 67/$43 TAB 9/$09
23/$:7 88/$58 22/$16 T 212/SD4 67/543 TAB 24/$18
X 68/544 2 (keypad) 50/S32 23/$17 X 216/SD8 68/544 2 (keypad) 50/$32
24/$18 7 55/537 69/$45 4 (keypad) 52/$34
25/$19 Y 89/559 24/$18 7 39/$Z7 69/545 4 (keypad) 52/$34
70/$46 7 (keypad) 55/$37 Z5/S19 Y 217/$D9 70/546 7(keypad) 55/$37
26/51A G 71/$47 71/$47 1 (keypad) 49/$31 26/$1A G 199/$C7 71/$47 1 (keypad) 49/$31
27/$IB S 56/$38 72/S48 ESC 27/S1B 27/$lB 8 40/$28 72/548 ESC 27/$lB
28/$lC B 66/$42 73/$49 + (keypad) 43/S2B 28/$1C B 194/SC2 73/549 + (keypad) 43/$2B
29/$ ID l-l 72/548 74/$4A — (keypad) 45/$2D 29/$ ID H 200/$C8 74/54A - (keypad) 45/$2D
30/S1E U 85/$55 75/54B LINE FEED 10/$0A 30/$1E U 213/$D5 75/54B LINE FEED 10/$0A
31/S1F V 86/$56 76/$4C ENTER 13/$0D 31/$1F V 214/$D6 76/$4C ENTER 141/58D
32/$20 9 57/S39 77/$4D 6(keypad) 54/S36 32/$20 9 41/$29 77/$4D 6(keypad) 54/$36
33/$21 I 73/549 78/$4E 9 (keypad) 57/539 33/$21 [ 201/$C9 78/$4E 9(keypad) 57/$39
34/S22
35/523
j0 74/$4A
48/$30
79/$4F
80/$50
3 (keypad)
ALT
51/533
8/$08
34/$22
35/123
J
0
202/$CA
48/530
79/$4F 3(keypad)
ALT
51/533
8/508
36/$24 M 77/$4D 80/$50
81/$51 0(keypad) 48/$30 36/$2* M 205/$CD 81/$51 0(keypad) 48/530
37/$25 K 75/54B 82/$52 . (keypad) 46/S2E 37/$25
K 203/5CB 82/$52 . (keypad) 46/52E
38/$26 O 79/S4F 83/$53 t (cursor) 145/$91 38/$26 0 207/5CF 83/$53 T (cursor) 145/$91
39/527 N 78/S4E 84/$54 1 (cursor) 17/$11 39/$27 N 206/5CE 84/$54 1 (cursor) 17/511
40/528 + 43/52B 85/555 *- (cursor) 157/S9D 40/$28
+ 219/$DB 85/$55 - (cursor) 157/$9D
41/$29 P 80/$50 86/$56 - (cursor) 29/S1D 41/$29 P 208/5D0 86/$56 - (cursor) 29/51D
42/$2A L 76/$4C 87/$57 N O SCROLL 255/SFF 42/$2A L 204/$CC 87/$57 NO SCROLL 255/$FF
43/$2B 45/$2D 88/$58 no key 43/$2B
44/$2C - 221/$DD 88/$58 no key
46/52E pressed 255/SFF 44/$2C 62/$3E pressed 255/$FF

586
587
Table 9-3. Commodore Decoding Table Table 9-4. CONTROL Decoding Table
64306-64394/$FB32-$FB8A 64395-64483/$FB8B-$FBE3
Table Key Character Table Key Character
index code Table Key Character Table Key Character
index code cade index code
0/$00 index
1NST/DEL 148/$94 45/$2D 91/$5B 0/500 INST/DEL 255/5FF 45/$2D 27/51B
1/S01
2/502
RETURN
CRSR —
141/SSD
157/$9D
46/S2E
47/52F
@ 164/SA4
60/$3C
l/$01
2/502
RETURN
CRSR —
255/$FF
255/SFF
46/$2E
47/S2F
b 0/$00
255/$FF
3/$03 F7 U0/$8C 48/$30 E 168/5A8 3/503 F7 255/$FF 48/S30 £ 28/$lC
4/$04 Fl 137/$89 49/$31 223/$DF 4/$04 Fl 255/$FF 49/$31 255/$FF
5/$05 F3 138/$8A 50/$32 93/55D 5/$05 F3 255/$FF 50/$32 ; 29/$lD
6/$06 F5 139/$8B 51/$33 CLR/HOME 147/S93 6/$06 F5 255/SFF 51/S33 C L R / H O M E 255/$FF
7/$07 CRSR I 145/$91 52/534 right SHIFT l/$01 7/S07 255/$FF 52/S34
8/$08 3 150/596 53/$35 =
CRSR I right SHIFT 255/$FF
61/S3D 3 28/51C 53/$35 = 31/51F
9/$09 W 179/$B3 54/$36 * 222/5DE 9/$09 W 23/517 54/$36 30/51E
10/50A A 176/$B0 55/$37 / 63/53F 10/$0A A l/$01 55/537 / 255/$FF
11/50B 4 151/S97 56/$38 1 129/$81 ll/$0B 4 159/$9f 56/$38 1 144/S90
12/50C Z 173/$AD 57/539 4 95/$5F 12/$0C Z 26/51A 57/$39 4 6/$06
13/SOD 174/$AE 58/$3A
14/$0E
s
E 177/5B1 59/$3B
CONTROL
2
4/$04 13/$0D S 19/513 58/$3A CONTROL 255/$FF
149/595 14/$0E E 5/$05 59/S3B 2 5/505
15/$0F left SHIFT 1/S01 60/$3C space bar 160/$A0 15/$0F left SHIFT 255/$FF 60/$3C space bar 255/$FF
16/$10 5 152/$98 61/S3D Commodore 2/$02 16/S10 5 156/$9C 61/$3D Commodore 255/$FF
17/511 R 178/$B2 62/53E Q I71/5AB 17/$11 R 18/512 62/$3E Q 17/$11
18/$12 D 172/$AC 63/$3F RUN/STOP 3/$03 1S/S12 D 4/$04 63/53F S U N / S T O P 255/$FF
19/$13 6 153/$99 64/$40 HELP 132/584 19/$13 6 30/S1E 64/$40 HELP 132/$84
20/$14 C 188/$BC 65/$41 8(keypad) 56/538 20/$14 C 3/$03 65/$41 8(keypad) 56/$38
21/515 F 187/$BB 66/542 5 (keypad) 53/$35 21/S15 F 6/$06 66/$42 5 (keypad) 53/535
22/516 T 163/$A3 67/543 TAB 24/$18 22/$16 T 20/514 67/$43 TAB 24/$18
23/$17 X 189/5BD 68/$44 2 (keypad) 50/S32 23/$17 X 24/518 68/$44 2(keypad) 50/532
24/$18 7 154/$9A 69/$45 4 (keypad) 52/534 24/$18 7 31/51F 69/$45 4 (keypad) 52/534
25/$19 Y 183/5B7 70/S46 7 (keypad) 55/537 25/$19 Y 25/519 70/$46 7(keypad) 55/$37
26/51A G 165/SA5 71/$47 1 (keypad) 49/$31 26/$1A G 7/$07 71/$47 1(keypad) 49/$31
27/51B 8 155/59B 72/548 ESC 27/$IB 27/$lB 158/$9E
8 72/$48 ESC 27/51B
28/51C B 191/SBF 73/$49 + (keypad) 43/$2B 28/$lC B 2/S02 73/$49 + (keypad) 43/52B
29/$ ID H 180/$B4 74/$4A - (keypad) 45/$2D 29/$ ID H 8/$08 74/54A - (keypad) 45/52D
30/$IE U 184/$B8 75/S4B LINE FEED 10/$0A 30/$IE 21/$15 75/$4B LINE FEED
31/$1F 190/$BE
U 10/50A
V 76/S4C ENTER 141/58D 31/51F V 22/516 76/$4C ENTER 141/$8D
32/$20 9 41/529 77/54D 6 (keypad) 54/J36 32/$20 9 18/512 77/$4D 6(keypad) 54/$36
33/$21 I 162/$A2 78/$4E 9 (keypad) 57/539 33/$21 1 9/$09 78/$4E 9(keypad) 57/$39
34/$22 I 181/$B5 79/$4F 3(keypad) 51/533 34/$22 10/50A 79/$4F 3(keypad) 51/533
35/$23 0 48/$30 80/S50 ALT 8/508 35/S23 r0 146/$92 80/550 ALT 8/$08
36/$24 M 167/$A7 81/$51 0(keypad) 48/530 36/$24 M 13/50D 81/S51 0(keypad) 48/530
37/$25 K 161/$A1 82/$52 .(keypad) 46/$2E 37/525 K 82/$52 .(keypad) 46/$2E
ll/$0B
3S/$26 0 185/$B9 83/$53 T (cursor) 145/591 38/526 O 15/50F 83/S53 f (cursor) 145/$91
39/$27 N 170/$AA 84/$54 •I (cursor) 17/$11 39/527
N 14/SOE 84/$54 i (cursor) 17/$11
40/$28 + 166/$A6 85/S55 * (cursor) 157/$9D 40/$28
+ 255/$FF 85/S55 - (cursor) 157/$9D
41/S29 P 175/SAF 86/$56 - (cursor) 29/$ ID 41/529
P 16/$10 86/$56 •• (cursor) 29/51D
42/$2A L 182/5B6 87/$57 N O SCROLL 255/$FF 42/52A
43/$2B 43/S2B L 12/SOC 87/$57 N O SCROLL 255/$FF
- 220/5DC 88/558 no key 255/5FF
44/S2C 62/$3E 44/S2C - 88/$58 no key
pressed 255/5FF 255/5FF pressed 255/$FF

588 589
SFFiZ. 65303

Table 9-5. CAPS LOCK Decoding Table This routine is also copied into all RAM banks to handle
64484-64572/$FBE4-$FC3C interrupts which occur when the system is configured for a
Table Key Character Table Key Character bank where Kernal ROM is not visible.
index code index code
0/$00 INST/DEL 20/$14 45/$ 2D : 58/S3A
l/$01 RETURN 13/$0D 46/S2E
65303 $FF17 JIRQ
@ 64/$40
2/E02 CRSR <- 29/$ ID 47/$2F 44/$2C Jump to IRQ or BRK handler routine.
3/$03 F7 136/$88 48/$30 £ 92/$5C (This routine is the target of the processor IRQ/BRK vector at
4/$04 Fl 133/$85 49/$31 • 42/$2A 65534/$FFFE.)
5/$05 F3 134/S86 50/$32 59/$3B Pushes the accumulator and X and Y register values onto the
6/$06 F5 135/$87 51/$33 CLR/HOME 19/313
7/S07 CRSR ! 17/S11 52/$34 right SHIFT l/$01
stack, then places the current MMU configuration register
8/$O8 3 51/$33 53/$35 — 61/$3D
value onto the stack as well. (Thus, 128 interrupts place one
9/$09 W 215/$D7 54/$36 * 94/S5E more byte on the stack than do Commodore 64 interrupts.)
10/$0A A 193/SCI 55/$37 / 47/$2F The routine then configures the system for bank 15 and reads
11/$OB 4 52/$34 56/$38 1 49/$31 the processor status register value on the stack (the interrupt
12/SOC Z 218/SDA 57/$39 4 95/$5F
automatically causes the status register value and return ad-
13/SOD s 211/$D3 58/$3A CONTROL 4/$04
H/$0E E 197/$C5 59/$3B 2 50/$32 dress to be placed on the stack before this routine is called). If
15/SOF left SHIFT l/$01 60/$3C space bar 32/S20 the B bit (bit 4) of the status register is set to % 1 , indicating
16/$10 5 53/135 61/$3D Commodore 2/$02 that the interrupt is the result of the execution of a BRK in-
17/$11 R 210/SD2 62/$3F_ Q 81/$51 struction (a software interrupt), the routine jumps through the
1S/S12 D 196/$C4 63/$3F RUN/STOP 3/$03 IBRK indirect vector at 790/$0316 to a routine to handle the
19/$13 6 54/$36 64/$40 HELP 132/$84
BRK. That vector normally points to 45059/$B003, the break
20/$14 C 195/$C3 65/$41 8 (keypad) 56/$3S
21/$15 F 198/$C6 66/$42 5 (keypad) 53/$35 entry point into the machine language monitor. If the B status
22/$16 T 212/$D4 67/$43 TAB 9/$09 bit is %0, a hardware interrupt has been triggered by an exter-
23/$17 X 216/$D8 6S/$44 2 (keypad) 50/S32 nal source, so the routine jumps through the IIRQ indirect vec-
24/$18 7 55/$37 69/$45 4 (keypad) 52/$34 tor at 788/$0314. That vector normally points to the handling
25/$19 Y 217/$D9 70/$46 55/$37
7 (keypad) routine at 64101/$FA65. In either case, you can redirect the
26/$lA G 199/SC7 71/$47 1(keypad) 49/$31
vector to a routine of your own for special handling. See the
27/$lB 56/$38 72/$48 ESC 27/$IB
28/$lC
eB 194/$C2 73/$49 + (keypad) 43/$2B IBRK and IIRQ entries for details.
29/$lD H 200/$C8 74/$4A - (keypad) 45/$2D If normal processing is to continue following the interrupt
3O/$1E U 213/$D5 75/$4B LINEFEED 10/$0A handling, the handling routine should end with a jump to the
31/$1F V 2U/SD6 76/$4C ENTER 13/$0D
routine at 65331/$FF33 to restore the processor registers and
32/$20 9 57/S39 77/$4D 6(keypad) 54/$36
33/S21 I 201/SC9 78/S4E 9(keypad) 57/$39
MMU configuration to their original values. For example, the
34/$22 J 202/SCA 79/$4F 3(keypad) 51/$33 normal IRQ service routine exits in this manner, so processing
35/$23 0 48/S30 80/$50 ALT 8/$08 resumes unaffected after a standard IRQ interrupt. However,
36/$24 M 205 /$CD 81/S51 0(keypad) 48/$30 the BRK service routine does not return, since normal process-
37/$25 K 203/$CB 82/$52 . (keypad) 46/$2E ing is halted when the monitor is entered.
38/$26 O 207/$CF 83/$53 ! (cursor) 145/$91
39/$27 N 206/$CE 84/S54 I (cursor) 17/$11 This routine is also copied into all RAM banks to handle
40/$28 + 43/$2B 85/$55 *• (cursor) 157/$9D interrupts which occur when the system is configured for a
41/$29 P 208/SDO 86/$56 -• (cursor) 29/$lD bank where Kernal ROM is not visible.
42/$2A L 204/$CC 87/$57 NO SCROLL 255/$FF
43/$2B - 45/S2D 88/$58 no key
44/$2C 46/S2E pressed 255/SFF

590 591
65331 SFF33 $FF53 65363

65331 8FF33 CRTI device. (This is different from the Kernal CLALL routine
Common exit routine for all interrupt routines. f$FFE71, which merely resets the number of open files to zero
Retrieves the MMU configuration register value from the stack without explicitly closing any open files.) Enter the routine
and restores the system to its original bank setting, then re- with the accumulator holding the number of the device on
stores the Y and X register and accumulator values from the which files are to be closed. If the specified device is the cur-
stack. Processing resumes at the instruction following the one rent input or output device, the channel will be reset to the
during which the interrupt has occurred. default device {screen or keyboard). If all files to the device
have been successfully closed, the status register carry bit will
65341 $FF3D JRESET clear upon return. A set carry bit indicates that a device error
Jump to reset handler routine. has occurred.
(This routine is the target of the processor RESET vector at
65532/$FFFC.) 65357 $FF4D JC64_MODE
Sets the system for the bank 15 configuration, then jumps to Entry point for the Kernal C64_MODE routine at 57931/
the RESET routine [$E000]. $E24B, which switches the system immediately to 64 mode.
This routine is also copied into all RAM banks to handle To get back to 128 mode, it is necessary to reset the computer
any reset which might occur when the system is configured or to turn it off and back on.
for a bank where Kernal ROM is not visible.
65360 $FF50 JDMA_CALL
65349-65350 $FF45-$FF46 Unused Entry point for the Kernal DMA_CALL routine at 63397/
Two unused bytes, filled with the value 255/SFF. $F7A5, which passes commands to a DMA (direct memory
access) controller. The DMA device will take control of the
system to perform the requested command. The only DMA
New 128 Kernal Jump Table peripherals currently available for the 128 are the 1700 and
Locations 65351-65407/$FF47-$FF7F are a table of jump vec- 1750 Memory Expansion Modules, controlled by a DMA chip
tors to routines found in 128 ROM, but not in previous ver- known as the REC (see Chapter 8 for more information). Call
sions of the Kernal for earlier Commodore computers. As with the routine with the Y register holding the command for the
the other jump tables, each table entry consists of a JMP DMA device and the X register holding the bank number for
opcode (76/$4C) followed by the address of the target routine. the operation. Additional setup steps may be required, de-
pending on the command.
65351 SFF47 JSPIN_SPOUT
Entry point for the Kernal SPIN-SPOUT routine at 58875/ 65363 SFF53 JBOOT_CALL
$E5FB, which sets up the serial bus for fast communications Entry point for the Kernal BOOT_CALL routine at
mode. Enter with the status register carry bit clear to establish 63632/$F890, which attempts to load and execute boot sectors
fast serial input or with the bit set to establish fast serial out- from a specified disk drive. Call the routine with the X register
put. Unless you are writing a custom data transfer routine, it's holding the device number for the desired disk drive (usually
not necessary to call this routine explicitly. All the standard 8) and the accumulator holding the character code correspond-
serial I/O routines already include this setup step. ing to the desired drive number—not the actual drive number.
(For example, the single drive in 1541 and 1571 units is desig-
65354 $FF4A JCLOSE^ALL nated drive 0, so you would use 48/$30, the character code
Entry point for the Kernal CLOSE_ALL routine at 62013/ for zero.) If the specified drive is not present or turned off, or
$F23D, which closes all files currently opened to a specified tf the disk in the drive does not contain valid boot sectors, the

592 593
65366 SFF56 65381
SFF65

routine will return with the status register carry bit set. If boot
sectors are found and executed, the boot code may or may not the X register the device number. However, if the secondary
return to the calling routine. address is not currently used, the carry bit will instead be set
upon return (the secondary address value will still be in the Y
65366 8FF56 JPHOENIX register).
Entry point for the Kernal PHOENIX routine at 63591/$F867, 65375 $FF5F JSWAPPER
which initializes any installed-function ROMs and attempts to
boot a disk from the default drive (drive 0 of device 8). The Calls the Kernal SWAPPER routine's screen editor jump table
Kernal reset routine [$E000] records the presence of function entry at 49194/$C02A. The routine switches active screen dis-
ROMs in cartridges plugged into the expansion port or into plays by exchanging the active and inactive screen editor vari-
the spare ROM socket on the system circuit board, but it does able tables, tab stop bitmaps, and line link bitmaps, and by
not initialize them unless they are autostarting (unless their toggling bit 7 of the active screen flag (215/$D7). The routine
cartridge ID byte holds the value 1). This routine initializes all doesn't physically turn either video chip on or off; both chips
recorded function ROMs by calling their cold start entry ad- remain enabled. Instead, the routine determines which display
dresses (the first address of the memory slot for the ROM). If will be the recipient of subsequent printing. (Only the active
any ROMs are present, they may or may not return to this screen will have a "live" cursor.)
routine, depending on the initialization steps performed. If all
ROMs return after initialization (or if no ROMs are present), 65378 $FF62 JDLCHR
the routine attempts to boot a disk in drive 0 of device 8. Calls the Kernal INIT80 routine's screen editor jump table en-
try at 49191/$C027. The routine copies character shape data
65369 $FF59 JLKUPLA from ROM into the 8563 80-column video chip's private
block of RAM (the 8563 has no character ROM of its own).
Entry point for the Kernal LKUPLA routine at 63389/$F79D,
which checks whether a specified logical file number is cur- 65381 $FF65
rently in use. Call the routine with the accumulator holding JPFKEY
the desired logical file number. If that number is used for a Calls the Kernal KEYSET routine's screen editor jump table
currently open file, the status register carry bit will be clear entry at 49185/$C021. The routine assigns a new definition to
upon return. The accumulator will still hold the logical file one of the ten programmable function keys (F1-F8, SHIFT-
number; the X register will hold the associated device number, RUN/STOP, and HELP). Call the routine with the accumu-
and the Y register the secondary address. However, if the logi- lator holding the address of a three-byte string descriptor in
cal file number is not currently used, the carry bit will instead zero page, the X register containing the key number (1-10),
be set upon return (the logical file number will still be in the and the Y register containing the length of the new definition
accumulator). string. The descriptor in zero page should consist of the two-
byte address of the new definition string (in standard low-
65372 $FF5C JLKUPSA byte/high-byte order), followed by the bank number where
the definition string is located. The key number is not checked
Entry point for the Kernal LKUPSA routine 63366/$F786, for validity; if you specify a value outside the acceptable
which checks whether a specified secondary address is cur- range, you may garble existing definitions. Upon return, the
rently in use. Call the routine with the Y register holding the carry bit will be clear if the new definition has been success-
desired secondary address. If that number is used for a cur- fully added, or it will be set if there is insufficient room in the
rently open file, the status register carry bit will be clear upon definition table for the new definition.
return. The Y register will still hold the secondary address; the
accumulator will hold the associated logical file number, and

594
595
65384 $FF68 SFF74. 65396

65384 $FF68 JSETBNK value, and 9/$ 09 will hold the stack pointer value. The sys-
Entry point for the Kernal JSETBNK routine at 63295/$F73F, tem is always reconfigured for bank 15 upon exit.
which establishes the current bank from which data will be
read or to which data will be written during load/save opera- 65393 $FF71 JJMPFAR
tions, as well as the bank where the filename for the I/O op- Entry point for the Kernal JMPFAR routine at 739/S02E3,
erations can be found. Call the routine with the accumulator which jumps to a routine in a specified bank, with no return
holding the bank number for data and the X register holding to the calling bank. Prior to calling this routine, you must load
the bank for the filename. All register values are preserved location 2/$02 with the bank number (0-15) of the target rou-
during this routine. tine and locations 3-4/$03-$04 with the address of the target
routine (in high-byte/low-byte order, the opposite of the nor-
65387 $FF6B JGETCFG mal arrangement). You should also load location 5/$05 with
Entry point for the Kernal GETCFG routine at 63468/$F7EC, the value you want placed in the status register when the tar-
which translates a bank number into the MMU register setting get routine is entered. (The behavior of many routines is influ-
which will configure the system for that bank. Call the routine enced by the status register setting, particularly the state of the
with the X register containing the bank number (0-15). Upon carry bit. Load 5/$05 with the value 0/$00 if the target rou-
return, the accumulator will hold the corresponding MMU tine is to be entered with carry clear or with l/$01 if it is to
configuration register setting value. The routine does not check be entered with carry set.) If you wish to pass other register
the validity of the bank number input. If you specify a number values to the routine you will be calling, store the desired ac-
outside the acceptable range, the routine will return a mean- cumulator value in location 6/$06, the X register value in
ingless value. 7/$07, and the Y register value in 8/$08.

65390 SFF6E JJSRFAR 65396 SFF74 JINDFET


Entry point for the Kernal JSRFAR routine at 717/$02CD, Entry point for the Kernal INDFET calling routine at
which jumps to a subroutine in a specified bank and returns to 63440/$F7DO, which retrieves a byte from a specified bank.
the calling routine in bank 15. Prior to calling this routine, you Prior to calling this routine, you must load a two-byte zero-
must load location 2/$02 with the bank number (0-15) of the page pointer with the address of the location from which the
target routine and locations 3-4/$03-$04 with the address of byte is to be retrieved (or the base location if a series of bytes
the target routine (in high-byte/low-byte order, the opposite are to be retrieved). Call the routine with the accumulator
of the normal arrangement). You should also load location holding the address of the zero-page pointer, the X register
5/$05 with the value you want placed in the status register holding the bank number (0-15) for the target location, and
when the target routine is called. (The behavior of many the Y register holding an offset value which will be added to
routines is influenced by the status register setting, particularly the address in the pointer to determine the location from
which the byte is to be loaded. (Load Y with zero if no offset
the state of the carry bit. Load 5/$05 with the value 0/$00 if is desired.) Upon return, the accumulator will hold the byte
the target routine is to be called with carry clear, or with from the specified address. The value in the Y register will be
l/$01 if it is to be called with carry set,) If you wish to pass preserved during the routine. If you are retrieving data from a
other register values to the routine you will be calling, store series of locations, it is necessary to reload the accumulator
the desired accumulator value in location 6/$06, the X register a
nd X registers with the pointer address and bank number
value in 7/$07, and the Y register value in 8/$08. Upon re- before every call to this routine, but you can read up to 256
turn, location 5/$05 will hold the status register value at the sequential locations without changing the address in the zero-
time of exit, 6/$06 will hold the accumulator value, 7/$07 page pointer by simply incrementing the Y register between
will hold the X register value, 8/$08 will hold the Y register calls.

596 597
65399 $FF77 $fF84 65412

65399 $FF77 JINDSTA changing the address in the zero-page pointer by simply incre-
Entry point for the Kernal INDSTA calling routine at 63450/ menting the Y register between calls.
$F7DA, which stores the accumulator contents at an address
in a specified bank. Prior to calling this routine, you must load 65405 $FF7D JPRIMM
a two-byte zero-page pointer with the address of the location Entry point for the Kernal PRIMM routine 64023/$FA17,
at which the byte is to be stored (or the base location if a se- which prints the string of character codes immediately follow-
ries of bytes is to be stored); then store the address of this ing the JSR to this routine. You must always call this routine
pointer in location 697/$02B9. Call the routine with the accu- with JSR, never with JMP. Only JSR places the required ad-
mulator holding the byte to be stored, the X register holding dress information on the stack. The end of the character code
the bank number (0-15) for the target location, and the Y reg- string is indicated by a byte containing 0/$00 (the routine
ister holding an offset value which will be added to the ad- continues printing bytes as character codes until a zero byte is
dress in the pointer to determine the location in which the encountered). When the ending marker is found, the routine
byte is to be stored. (Load Y with zero if no offset is desired.) returns to the address immediately following the zero byte.
Upon return, the accumulator will still hold the byte value.
The value in the Y register will also be preserved. If you are 65408 $FF80
writing data to a series of locations, it is necessary to reload
the X register with the bank number before every call to this Some Commodore literature suggests that this location will be
routine, but you can write to up to 256 sequential locations updated in future revisions of the Kernal ROM to indicate the
without changing the address in the zero-page pointer by sim- revision number. For the original version of the 128 Kernal,
ply incrementing the Y register between calls. this location contains the value 0/$00.

65402 $FF7A JINDCMP Standard Commodore Jump Table


Entry point for the Kemal INDCMP calling routine at 63459/ Locations 65409-65525/$FF81-$FFF5 are a table of jump vec-
$F7E3, which compares the accumulator contents against the tors to the standard Commodore Kernal routines, most of
contents of a location in a specified bank. Prior to calling this which have been part of previous versions of the Kernal. As
routine, you must load a two-byte zero-page pointer with the with the other 128 jump tables, each table entry consists of
address of the location with which the byte is to be compared either a direct JMP opcode (76/$4C) followed by the address
(or the base location if a series of bytes are to be compared); of the target routine or an indirect JMP opcode (108/$6C) fol-
then store the address of this pointer in location 712/$02C8. lowed by the address of a Kernal indirect vector containing the
Call the routine with the accumulator holding the byte to be address of the target routine.
compared, the X register holding the bank number (0-15) for
the target location, and the Y register holding an offset value 65409 SFF81 JCINT
which will be added to the address in the pointer to determine Calls the Kernal CINT routine's screen editor jump table entry
the location with which the byte is to be compared. (Load Y at 49152/$C000. This routine initializes all the RAM locations
with zero if no offset is desired.) Upon return, the accumulator used by the screen editor, clears both displays, and redirects
will still hold the byte value, and the status register N, Z, and printing to the display indicated by the position of the 40/80
C (carry) bits will reflect the result of the comparison. The DISPLAY key.
value in the Y register will also be preserved. If you are com-
paring a series of locations, it is necessary to reload the X reg- 65412 $FF84 JIOINIT
ister with the bank number before every call to this routine, Entry point for the Kemal IOINIT routine at 57609/$E109,
but you can compare up to 256 sequential locations without which initializes the CIA, SID, and 40- and 80-column video
chips, along with related RAM locations.
598 599
65415 SFF87 65442
6FKA2.

65415 SFF87 JRAMTAS Cl44/$90) upon return will indicate whether the operation is
Entry point for the Kernal RAMTAS routine at 57491/$E093, successful.
which clears zero-page RAM (locations 2-255/$02-$FF) and
initializes Kernal memory pointers. The routine also sets the 65433 $FF99 JMEMTOP
BASIC restart vector (2560/$0A00) to point to BASIC'S cold Entry point for the Kernal MEMTOP routine at 63331/$F763,
start entry address, 16384/$4000. which reads or sets the value of the Kernal's top-of-memory
pointer (2567-2568/$0A07-$0AO8). To read the pointer, call
65418 SFF8A JRESTOR the routine with the carry flag set; the pointer value will be re-
Entry point for the Kernal RESTOR routine at 57430/$E056, turned in the X and Y registers (low byte in X, high byte in Y).
which restores the Kernal indirect vectors at 788-819/ To set the pointer, call the routine with the carry flag clear
$0314-$0333 to their default values. and with the X and Y registers containing the low and high
bytes, respectively, of the desired pointer value.
65421 $FF8D JVECTOR
Entry point for the Kernal VECTOR routine at 57435/SE05B, 65436 $FF9C JMEMBOT
which loads or stores the Kernal indirect vectors at 788-819/ Entry point for the Kernal MEMBOT routine at 63346/$F772,
$0314-$0333. When this routine is called, the X and Y regis- which reads or sets the value of the Kernal's bottom-of-memory
ters should be loaded with the address of a 32-byte table (low pointer (2565-2566/$0A05-$0A06). To read the pointer, call
byte in X, high byte in Y). If the status register carry bit is the routine with the carry flag set; the pointer value will be re-
clear when the routine is called, the vectors will be loaded turned in the X and Y registers (low byte in X, high byte in Y).
with the values from the table. If carry is set, the 16 two-byte To set the pointer, call the routine with the carry flag clear
address values currently in the vectors will be copied to the and with the X and Y registers containing the low and high
table. bytes, respectively, of the desired pointer value.

65424 $FF90 JSETMSG 65439 $FF9F JKEY


Entry point for the Kernal SETMSG routine at 63324/$F75C, Calls the Kernal SCNKEY routine's screen editor jump table
which sets the value of the Kernal message flag (157/$9D). entry at 49170/$C012. The routine scans the keyboard matrix
Call the routine with the accumulator holding the desired flag to determine which keys, if any, are currently pressed. The
value. Refer to the entry for 157/$9D for information on flag character code for the key currently pressed is loaded into the
values. keyboard buffer at 842/$034A, from which it can be retrieved
using the Kernal GETIN routine [$FFE4], The matrix code of
65427 $FF93 JSECOND the keypress read during this routine can also be read in loca-
Entry point for the Kernal SECOND routine at 58578/$E4D2, tion 212/$D4, and the status of the shift keys can be read in
which sends a secondary address to a serial device which has 211/$D3. Since this routine is normally called as part of the
been commanded to listen. The value in the serial status flag standard IRQ service routine, it's not usually necessary to call
(144/$90) upon return will indicate whether the operation is it explicitly to read the keyboard.
successful.
65442 $FFA2 JSETTMO
65430 $FF96 JTKSA Entry point for the Kernal SETTMO routine at 63327/$F75F,
which sets the value of the IEEE timeout flag <2574/$0A0E).
Entry point for the Kernal TKSA routine at 58592/$E4E0,
which sends a secondary address to a serial device which has This routine is superfluous, since the flag isn't used by any
been commanded to talk. The value in the serial status flag 128 ROM routine. It is present merely to maintain consistency
with previous versions of the Kernal.
600 601
65445 SFFA5 ftFFBP, 65469

65445 $FFA5 JACPTR 65457 $FFB1 JLISTN


Entry point for the Kernal ACPTR at routine 58430/$E43E, Entry point for the Kernal LISTN routine at 58174/$E33E,
which retrieves a byte from a serial device. The success of the which sends a LISTEN command to a specified serial device.
operation will be indicated by the value in the serial status Call the routine with the accumulator holding the device num-
flag (144/$90) upon return. If the operation is successful, the ber (4-31) of the desired serial device. The success of the op-
accumulator will hold the byte received from the device. The eration will be indicated by the value in the serial status flag
value in the Y register will be preserved. For the routine to (144/S90) upon return.
function properly, the serial device must currently be a talker
on the serial bus, which requires a number of setup steps. $FFB4 JTALK
Generally, it's preferable to use higher level Kernal calls such 65460
as BASIN [$FFCF] instead. Entry point for the Kernal TALK routine at 58171/$EE3B,
which sends a TALK command to a specified serial device.
Call the routine with the accumulator holding the device num-
65448 $FFA8 JCIOUT ber (4-31) of the desired serial device. The success of the op-
Entry point for the Kernal CIOUT routine at 58627/$E503, eration will be indicated by the value in the serial status flag
which sends a byte to a serial device. Call the routine with the (144/$90) upon return.
accumulator holding the byte to be sent. All register values are
preserved during this routine. The success of the operation 65463 8FFB7 JREADSS
will be indicated by the value in the serial status flag Entry point for the Kernal READSS routine at 63300/$F744
(144/$90) upon return. For the routine to function properly, (called READST in previous versions of the Kernal), which re-
the serial device must currently be a listener on the serial bus, turns the status of the previous I/O operation. The status
which requires a number of setup steps. However, if you have value will be in the accumulator upon return; the contents of
already performed all the preparatory steps necessary for the X and Y registers are unaffected. If the current device
BSOUT [$FFD2] to a serial device (SETLFS, SETBNK, number is 2 (indicating an RS-232 operation), the status value
SETNAM, OPEN, and CKOUT), you can freely substitute is retrieved from the RS-232 status flag (2580/$0A14), and the
CIOUT for BSOUT since for a serial device BSOUT simply flag is cleared. Otherwise, the status value is retrieved from
jumps to the CIOUT routine. the tape/serial status flag (144/$90). That flag is not cleared
after being read.
65451 $FFAB JUNTLK
Entry point for the Kernal UNTLK routine at 58645/$E515, 65466 $FFBA JSETLFS
which sends an UNTALK command to all devices on the serial Entry point for the Kernal SETLFS routine at 63288/$F7E8,
bus. Any devices which are currently talkers will cease send- which assigns the logical file number, device number, and sec-
ing data. ondary address for an I/O operation. Call the routine with the
accumulator holding the logical file number, the X register
65454 $FFAE JUNLSN holding the device number, and the Y register holding the sec-
Entry point for the Kernal UNLSN routine at 58662/$E526, ondary address. All register values are preserved during the
which sends an UNLISTEN command to all devices on the se- routine.
rial bus. Any devices which are currently listeners will cease
receiving data. 65469 SFFBD JSETNAM
Entry point for the Kernal SETNAM routine at 63281/SF731,
which assigns the length and address of the filename for an
I/O operation. Call the routine with the accumulator holding
602 603
65472 $FFCO 65478
$FFC6

the length of the filename and the X and Y registers holding direct vector (796/$031C), which normally points to the
the address of the first character of the name (low byte in X, CLOSE routine at 61832/$F188. You can modify the actions
high byte in Y). The Kernal SETBNK routine [$FF68] must be of the routine by changing the vector to point to a routine of
used to specify the appropriate bank for the filename address. your own. See the ICLOSE entry for details.
If no name is used for the current operation, load the accumu- The standard CLOSE routine should be called with the
lator with the value 0/$00; the values in X and Y are then ir- accumulator holding the number of the logical file to be
relevant. All register values are preserved during this routine. closed. If no file with the specified logical file number is cur-
rently open, the routine exits immediately. (No error will be
65472 $FFCO JOPEN indicated.) If a file with the specified number is open, its entry
Entry point for the Kernal OPEN routine, which opens a logi- in the logical file number, device number, and secondary ad-
cal file to a specified device. The routine is entered via the dress tables will be removed. For RS-232 files, the driving CIA
IOPEN indirect vector (794/$031A), which normally points to #2 interrupts will be disabled. For tape files, the final block of
the OPEN routine at 61403/$EFDB. You can modify the ac- data will be written (followed by an end-of-tape marker, if one
tions of the routine by changing the vector to point to a rou- has been specified). For disk files, the EOI sequence will be
tine of your own. See the IOPEN entry for details. performed. However, the 128 Kernal routine offers a special
At least one preparatory step is required before the stan- close function for disk files: If this routine is called with the
dard OPEN routine is called: The SETLFS routine [$FFBA] status register carry bit set, and if the device number for the
must be called to establish the logical file number (184/$B8), file is 8 or greater, and if the file has been opened with a sec-
the device number (186/SBA), and the secondary address ondary address of 15, the EOI sequence is skipped (the table
(185/$B9). For tape (device 1), RS-232 (device 2), or serial (de- entries for the file are deleted, but that's all). This provides a
vice 4 or higher), SETBNK [$FF68] and SETNAM [$FFBD] are solution to a problem in earlier versions of the Kernal. A disk
also required to specify the length (183/$B7) and address file opened with a secondary address of 15 is a command
(187-188/$BB-$BC) of the associated filename and the bank channel to the drive. Performing an EOI sequence to such a
number (199/$C7) where the filename can be found. file closes all files currently open to the drive, not just the
The status register carry bit will be clear if the file is suc- command channel file. This special mode allows the command
cessfully opened, or set if it cannot be opened. When carry is channel file to be closed without disturbing other files that
set upon return, the accumulator will hold an error code indi- may be open to the drive.
cating the problem. Possible error code values include 1 (10
files, the maximum allowed, are already open), 2 (a currently 65478 $FFC6 JCHKIN
open file already uses the specified device number), and 5 Entry point for the Kernal CHKIN routine, which specifies a
(specified device did not respond). One exception is when RS- logical file as the source of BASIN and GETIN input. The rou-
232 files are opened with x-line handshaking. Because of a tine is entered via the ICHKIN indirect vector (798/$031E),
bug in the RS-232 OPEN routine [$F040], carry will be set if which normally points to the CHKIN routine at 61702/$F106.
the RS-232 device is present when x-line handshaking is used You can modify the actions of the routine by changing the
(if the DSR line is high), or it will be clear if the device is ab- vector to point to a routine of your own. See the ICHKIN en-
sent—the opposite of the proper setting. The RS-232 and try for details.
tape/serial status flags (2580/$OA14 and 144/$90, respec- For a logical file to receive input, it must first be opened
tively) also reflect the success of the operation. (see the OPEN routine entry at 65472/$FFC0). The standard
CHKIN routine should be called with the desired logical file
65475 $FFC3 JCLOSE number in the X register. The input channel (153/$99) is set
Entry point for the Kernal CLOSE routine, which closes a to the device number for that file. If the device is RS-232 (de-
specified logical file. The routine is entered via the ICLOSE in- vice number 2), the routine also enables the CIA #2 interrupts
604 605
65481 SFFC9 65487
SFFCF

responsible for RS-232 reception. If a serial device (device actions of the routine by changing the vector to point to a rou-
number 4 or greater) has been specified, the device is also made tine of your own. See the ICLRCH entry for details.
a talker on the serial bus. If the file has successfully been set The standard CLRCH routine resets the output channel
for input, the carry bit will be clear upon return. If carry is set, (154/$9A) to device 3, the video display. (If the previous out-
the operation is unsuccessful and the accumulator will contain put channel is a serial device, it will be sent an UNLISTEN
the Kernal error code indicating which error has occurred. Pos- command.) The input channel (153/$99) is reset to device 0,
sible error codes include 3 (file not open), 5 (device did not re- the keyboard. (If the previous input channel is a serial device,
spond), and 6 (file not open for input). The RS-232 and serial it will be sent an UNTALK command.)
status flags (2580/$0A14 and 144/$90, respectively) also re-
flect the success of the operation on one of those devices. 65487 $FFCF JBASIN
Entry point for the Kernal BASIN routine (called CHRIN in
65481 SFFC9 JCKOUT previous versions of the Kernal), which receives a byte from
Entry point for the Kernal CKOUT routine, which specifies a the logical file currently specified for input. The routine is en-
logical file as the recipient of BSOUT output. The routine is tered via the IBASIN indirect vector (804/$0324), which nor-
entered via the ICKOUT indirect vector (800/$0320), which mally points to the BASIN routine at 61190/$EF06. You can
normally points to the CKOUT routine at 61772/$F14C. You modify the actions of the routine by changing the vector to
can modify the actions of the routine by changing the vector point to a routine of your own. See the IBASIN entry for
to point to a routine of your own. See the ICKOUT entry for details.
details. Except to retrieve input from the keyboard when the sys-
For output to be sent to a logical file, it must first be tem is set for default I/O, you must open a logical file to the
opened (see the OPEN routine entry at 65472/$KFC0). The desired device and specify the file as the input source (see the
standard CKOUT routine should be called with the desired entries for the OPEN and CHKIN routines, 65472/$FFC0 and
logical file number in the X register. The output channel 65478/$FFC6, respectively). For keyboard input (device 0), the
(154/$9A) is set to the device number for that file. If the de- standard BASIN routine accepts keypresses until RETURN is
vice is RS-232 (device number 2), the routine also enables the pressed; then it returns characters from the input string one at
CIA #2 interrupts responsible for RS-232 transmission. If a se- a time on each subsequent call. The character code for RE-
rial device (device number 4 or greater) has been specified, the TURN, 13/$0D, is returned when the end of an input string is
device is also made a listener on the serial bus. If the file has reached. (Generally, the GETIN routine [$FFE$] is preferred
successfully been set for output, the carry bit will be clear for retrieving individual keypresses.) BASIN from tape (device
upon return. If carry is set, the operation is unsuccessful and 1) retrieves the next character from the cassette buffer. If all
the accumulator will contain the Kernal error code indicating characters have been read from the buffer, the next data block
which error has occurred. Possible error codes include 3 (file is read from tape into the buffer. BASIN from RS-232 (device
not open), 5 (device did not respond), and 7 (file not open for 2) returns the next available character from the RS-232 input
output). The RS-232 and serial status flags (2580/$0A14 and buffer. If the buffer is empty, the routine waits until a charac-
144/$90, respectively) also reflect the success of the operation ter is received—unless the RS-232 status flag (2580/$0A14)
on one of those devices. indicates that the DSR signal from the external device is miss-
ing, in which case a RETURN character code, 13/$0D, is
65484 $FFCC JCLRCH returned.
Entry point for the Kernal CLRCH routine, which resets the BASIN from the screen (device 3) is supposed to retrieve
system for default I/O sources. The routine is entered via the characters one at a time from the current screen line, ending
ICLRCH indirect vector (802/$0322), which normally points with a RETURN character code when the last nonspace char-
to the CLRCH routine at 61990/$F226. You can modify the acter on the logical line is reached. However, it does not work

606 607
65490 SFFD2 $FFD5 65493

properly in the current version of the 128 Kernal (see the en- full, the routine waits until a character is sent. BSOUT to the
try for 49819/SC29B in Chapter 7 for details). BASIN from se- screen (device 3) [$C00C] prints the character on the active
rial devices (device numbers 4 and higher) returns the next display at the current cursor position. The CIOUT routine
character available from the serial bus, unless the serial status r$FFA8] is used for output to serial devices (device numbers 4
flag (144/S90) contains a nonzero value. In that case, the RE- and higher).
TURN character code is returned. Regardless of the output device, the contents of the accu-
For all input devices, the received byte will be in the ac- mulator and X and Y registers will be preserved during this
cumulator upon return. The contents of the X and Y registers routine. The status register carry bit will always be clear upon
will be preserved during input from keyboard, screen, or RS- return unless tape output has been aborted by pressing the
232. For input from tape, only the X register contents are pre- RUN/STOP key (in that case, the accumulator will also be set
served. For input from serial devices, only the Y register to 0/$00 to set the Z bit as well). For tape, serial, or RS-232
contents are preserved. For input from screen, keyboard, or se- output, the success of the operation will be indicated by the
rial devices, the status register carry bit will always be clear value in the status flag (144/$90 for tape or serial operations;
upon return. For tape input, the carry bit will be clear unless 2580/$0A14 for RS-232).
the operation has been aborted by pressing the RUN/STOP
key. For tape and serial input, the success of the operation will
be indicated by the value in the tape/serial status flag 65493 $FFD5 JLOAD
(144/$90). Due to a bug in the RS-232 portion of BASIN, the Entry point for the Kernal LOAD routine 62053/$F265, which
carry bit will be set if a byte has been successfully received; it loads or verifies a program file from tape or disk into a speci-
will be clear only if a RETURN character code is returned fied area of memory. Before calling this routine, the SETLFS
when the DSR signal is missing. The success of an RS-232 op- routine [$FFBA] must be called to establish the device number
eration will be indicated by the value in the status flag (186/$BA) and the secondary address (185/SB9) for the opera-
(2580/$0A14). tion. The logical file number (184/$B8) isn't significant for
loading. The secondary address value determines whether the
load/verify will be absolute or relocating. If bit 0 of the sec-
65490 SFFD2 JBSOUT ondary address is %0 (if the value is 0, for example), the file
Entry point for the Kernal BSOUT routine (called CHROUT in will be loaded starting at the address specified in the X and Y
previous versions of the Kernal), which sends a byte to the registers when the LOAD routine is called (a relocating load).
logical file currently specified for output, The routine is en- If the bit is %1 (if the value is 1, for example), the data will be
tered via the IBSOUT indirect vector (806/$0326), which nor- loaded starting at the address specified in the file itself (an ab-
mally points to the BSOUT routine at 61305/$EF79. You can solute load). For tape files, the secondary address specification
modify the actions of the routine by changing the vector to can be overridden by the file type. Nonrelocatable tape pro-
point to a routine of your own. See the IBSOUT entry for gram files always reload to their absolute address, even if the
details. secondary address value specifies a relocating load. The
Except to send output to the screen when the system is SETNAM routine [$FFBD] must be called to specify the length
set for default I/O, you must open a logical file to the desired (183/$B7) and address (187-188/$BB-$BC) of the associated
device and specify the file as the output target (see the entries filename. The SETBNK routine [$FF68] must be called to spec-
for the OPEN and CKOUT routines, 65472/$FFC0 and 65481/ ify the bank number where the filename can be found (199/
$FFC9, respectively). For output to tape (device 1), the charac- $C7) and the bank into which data is to be loaded (198/$C6).
ter is stored at the next available position in the cassette buffer. When the routine is called, the accumulator should hold
When the buffer is full, the data block is written to tape. For the operation type value (0/$00 for a load or any nonzero
output to RS-232 (device 2), the character is stored in the next value for a verify). If the secondary address specifies a relocat-
available position in the RS-232 output buffer. If the buffer is ing load, the X and Y registers should hold the starring ad-
608 609
^
65496 SFFD8 SFFDE 65502

dress at which data is to be loaded (low byte in X, high byte


in Y). The load will be aborted if it extends beyond address ending address plus 1 for the save (low byte in X, high byte in
65279/$FEFF. This is to prevent corruption of the MMU con- Y). To save all bytes in the desired area, it's important to re-
figuration register, which appears at 65280/$FF00 in every member that X and Y must hold an address that is one loca-
bank. tion beyond the desired ending address.
The status register carry bit will be clear upon return if The status register carry bit will be clear if the file has
the file has successfully been loaded, or it will be set if an er- successfully been saved, or it will be set if an error has oc-
ror has occurred or if the RUN/STOP key has been pressed to curred or if the RUN/STOP key has been pressed to abort the
abort the load. When carry is set upon return, the accumulator save. When carry is set upon return, the accumulator will hold
will hold the Kernal error code indicating the problem. Possi- the Kernal error code indicating the problem. Possible error
ble error code values include 4 (file was not found), 5 (device code values include 5 (serial device was not present), 8 (no
was not present), 8 (no name was specified for a serial load), 9 name was specified for a serial save), and 9 (an illegal device
(an illegal device number was specified), and 16 (the load ex- number was specified). The success of the operation will also
tended beyond address $FEFF). The success of the operation be indicated by the value in the tape/serial status flag
will also be indicated by the value in the tape/serial status (144/S90) upon return.
flag (144/$90).
65499 6FFDB JSETTIM
65496 $FFD8 JSAVE Entry point for the Kernal SETTIM routine at 63077/$F665,
Entry point for the Kernal SAVE routine at 62782/$F53E, which sets the value in the software jiffy clock (160-162/
which saves the contents of a block of memory to disk or tape. $A0-$A2). The clock is normally incremented 60 times per
Before this routine is called, the SETLFS routine [$FFBA] must second by the UDTIM routine [$FFEA] as part of the IRQ se-
be called to establish the device number (186/$BA) and sec- quence. The value in the accumulator is transferred to the low
ondary address (185/$B9) for the operation. The logical file byte (162/$A2), the value in the X register to the middle byte
number (184/$B8) isn't significant for saving. The secondary (161/$A1), and the value in the Y register to the high byte
address is irrelevant for saves to serial devices, but for tape it (160/$A0). The specified value should be less than $4F1AO1,
specifies the header type. If bit 0 of the secondary address the count corresponding to 24:00:00. Whenever the clock
value is %1 (if the value is 1, for example), the data will be reaches that value (which corresponds to the number of jiffies
stored in a nonrelocatable file—one that will always load to in 24 hours), the UDTIM routine resets all three bytes to zero.
the same memory address from which it has been saved.
Otherwise, the data will be stored in a relocatable file. If bit 1 65502 $FFDE JRDTIM
of the secondary address is %1 (if the value is 2 or 3, for ex- Entry point for the Kernal RDTIM routine at 63070/$F65E,
ample), the file will be followed by an end-of-tape marker. which returns the current value in the jiffy clock (160-162/
The SETNAM routine [$FFBD] must be called to specify the »A0-$A2). The clock is normally incremented 60 times per
length (183/$B7) and address (187-188/$BB-$BC) of the as- second by the UDTIM routine [$FFEA] as part of the IRQ se-
sociated filename. The SETBNK routine [SFF68] must be called quence. The clock value corresponds to the number of jiffies
to specify the bank number where the filename can be found U/60 second intervals) that have elapsed since the system
(199/$C7) and the bank from which data is to be saved J ! a s t u n i e d on or reset, or the number of jiffies since midnight
(198/SC6). UW:00:00) if the clock value has been set. The low byte of the
A two-byte zero-page pointer should be loaded with the oock value (162/SA2) is returned in the accumulator, the mid-
starting address of the block of memory to be saved. The rou- , . e 5 t e (161/SA1) in the X register, and the high byte (160/
$A0) in the Y register.
tine should be called with the accumulator holding the address
of the zero-page pointer and the X and Y registers holding the
610
611
65505 $FFE1 SFFFO 65520

65505 SFFE1 JSTOP routine to reset default I/O. Note that, despite its name, the
Entry point for the Kernal STOP routine, which checks routine doesn't actually close any files that may be open to
whether the RUN/STOP key is pressed. The routine is en- ta ne, disk, or RS-232 devices. Unclosed files may cause prob-
tered via the ISTOP indirect vector (808/$0328), which nor- lems' particularly on disks, so this routine is of limited useful-
mally points to the STOP routine at 63086/$F66E. You can n e 5 S ' s e e the Kernal CLOSE_ALL entry [$FF4A] for a routine
modify the actions of the routine by changing the vector to that properly closes all files open to a serial device.
point to a routine of your own. See the ISTOP entry for
details. 65514 $FFEA JUDTIM
The standard STOP routine returns with the status regis- Entry point for the Kernal UDTIM routine at $62968/$F5F8,
ter Z bit clear if the key is not pressed or with the bit set if it which increments the software jiffy clock, decrements the
is. Additionally, if RUN/STOP is pressed, the CLRCH routine countdown timer, and scans the keyboard column containing
[$FFCC] is called to reset default I/O, and the count of keys in the RUN/STOP key.
the keyboard buffer (208/$D0) is reset to zero.
65517 $FFED JSCRORG
65508 8FFE4 JGETIN Calls the Kernal SCRORG routine's screen editor jump table
Entry point for the Kernal GETIN routine, which retrieves a entry at 49167/$C00F. (This routine was called SCREEN in
character from the current input device. The routine is entered previous versions of the Kernal.) The routine returns infor-
via the IGETIN indirect vector (810/S032A), which normally mation on the size of the screen's current output window.
points to the GETIN routine at 61163/$EEEB. You can modify Upon return, the X register will contain the number of col-
the actions of the routine by changing the vector to point to a umns minus 1 in the current window, and the Y register will
routine of your own. See the IGETIN entry for details. contain the number of rows minus 1. The accumulator will
The standard GETIN routine checks to see whether the hold the maximum column number for the display currently
current input device is 0 (keyboard) or 2 (RS-232). If it's not active (39 for the 40-column screen or 79 for the 80-column
one of these, the BASIN routine [$EF06] is used instead. (See screen).
the BASIN entry for information on GETIN's behavior for
other devices.) For keyboard or RS-232, the retrieved character 65520 $FFF0 JPLOT
will be in the accumulator upon return, and the status register Calls the Kernal PLOT routine's screen editor jump table entry
carry bit will be clear. The value 0/$00 will be returned if no at 49176/$C018. The routine reads or sets the cursor position
character is available from the device. The contents of the Y on the active display. If it is called with the status register
register are unaffected by this routine. For RS-232, bit 3 of the carry bit clear, the value in the X register will specify the new
status flag (2580/$0A14) will be set if no characters are cursor row (vertical position), and the value in the Y register
available. will specify the column (horizontal position). The position will
be relative to the home position of the current output window
65511 $FFE7 JCLALL rather than to the upper left corner of the screen. (Of course,
Entry point for the Kernal CLALL routine, The routine is en- in the case of a full-screen output window, the default condi-
tered via the ICLALL indirect vector (812/$032C), which nor- tion, the upper left comer of the screen is the home position
mally points to the CLALL routine at 61986/SF222. You can of the window.) The carry bit will be set upon return if the
modify the actions of the routine by changing the vector to specified column or row value is beyond the right or bottom
point to a routine of your own. See the ICLALL entry for margin of the current output window. If the routine is called
details. with the carry bit set, the row number for the current cursor
The standard CLALL routine resets the number of open position is returned in the X register, and the current column
files (152/$98) to zero, then falls through into the CLRCH
612 613
65523 8FFF3 65534
6FFFE

r
number is returned in the Y register. Again, the position is rel- the stack. The address in this vector is then loaded into the
ative to the home position of the output window rather than program counter, and execution continues from that address.
the absolute home position of the screen, In the 128, this vector contains 65285/SFF05, the address of a
routine that saves the accumulator, X and Y register, and
65523 8FFF3 JIOBASE MMU configuration register values on the stack; it then config-
Entry point for the Kernal IOBASE routine at 63361/$F781, ures the system for bank 15 and jumps through the INMI vec-
which returns the base address of the system I/O block tor at 792/$0318.
(53248/$D000). The low byte, 0/$00, is returned in the X reg-
ister, and the high byte, 208/$D0, is returned in Y. 65532 $FFFC RESET
When a reset signal is detected, the processor immediately
65526-65527 $FFF6-$FFF7 Unused terminates the current operation and loads the program
Two unused bytes filled with the value 255/$FF. counter with the address in this vector, Execution then re-
sumes with the routine at that address. In the 128, this vector
65528 $FFF8 System Vector contains 65341/$FF3D, the address of a routine which config-
These locations in bank 1 are the soft reset vector, an address ures the system for bank 15, then jumps to the reset routine at
through which the reset routine [$E000] takes an indirect 57344/$E000.
jump. The ROM vector (in bank 15) is not normally used, but
it still contains the default address (57892/$E224). 65534 SFFFE IRQ/BRK
When a BRK opcode is executed or an IRQ signal is detected,
the processor completes execution of the current instruction,
8502 CPU Vectors then stores the contents of the status register and the address
One of the hardware features of the 8502 microprocessor (and of the next instruction on the stack. The address in this vector
its predecessors, the 6502 and 6510) is that certain events is then loaded into the program counter, and execution contin-
cause the processor to jump to an address held in one of the ues from that address. In the 128, this vector contains 65303/
following two-byte vectors. This implies that any system using $FF17, the address of a routine that saves the accumulator, X
one of these processors must have ROM at these addresses, or, and Y register, and MMU configuration register values on the
as in the case of the RAM banks of the 128, must have some stack; it then configures the system for bank 15, determines
method of initializing the RAM at these addresses with the ap- whether the interrupt was the result of a BRK or IRQ, and
propriate values. jumps accordingly through either the 1BRK vector at 790/S0316
An NMI (nonmaskable interrupt), triggered by a high-to- or the IIRQ vector at 788/$0314.
low transition on the processor's NMI input line, causes a
jump to the address at 65530/$FFFA. A reset, triggered when
the RESET input line is pulled low, causes a jump to the ad-
dress in 65532/$FFFC An IRQ (interrupt request), triggered
when the IRQ input line is pulled low, causes a jump to the
address in 65534/$FFFE, as does the execution of a BRK
opcode (0/$00),

65530 $FFFA NMI


When an NMI signal is detected, the processor completes exe-
cution of the current instruction, then stores the contents of
the status register and the address of the next instruction on
614 615
Appendix A

Interrupts
Todd Heimarck

The 8502 microprocessor that is the brains of the 128 is highly


methodical and single-minded. When executing a program, it
fetches an operation code from memory, fetches additional op-
erand bytes (depending on the opcode it gets), and executes
the instruction. Then it goes back for the next one, the next
one, and so on. If you left the 8502 to itself, it would execute
lots of instructions, but it would never communicate with the
outside world. For example, the 8502 has no way of remem-
bering by itself to check the keyboard. Without the keyboard,
you'd
yc have an awfully tough time writing a program.
The situation is analogous to the absent-minded professor
who would forget to eat dinner or go to sleep if it weren't for
the housekeeper's help. The 8502 needs an assistant to give it
a nudge occasionally to remind it to attend to other tasks. In
computer parlance, this nudge is called an interrupt. When an
interrupt request occurs, the 8502 saves its position in the cur-
rent program and goes off to run another program elsewhere
in memory. When it's finished with the interrupt routine, the
8502 returns to the main program that was running before the
interrupt occurred.
Interrupts for the 8502 fall into two broad classes: mask-
able interrupts (called IRQs) and nonmaskable interrupts
(NMIs). As the names imply, the processor can be told to ig-
nore IRQ interrupts (using the SEI instruction), but NMIs
demand immediate attention. The 128 uses both types to man-
age a variety of housekeeping chores.

The Housekeeping Chores


The main housekeeping interrupt is an IRQ generated 60 times
per second. It's called the system hardware interrupt, or some-
times the jiffy interrupt—a 1/60-second unit of time is called
a
j^fy. (Actually, if you have a European 128 using the PAL
video system, your jiffies last 1/50 second, and your system
IRQ interrupts occur 50 times per second.) The interrupt

619
causes several things to happen. First, the 8502 automatically
pushes the current address in the program counter onto the Nonmaskable Interrupts (NMIs)
stack, as if it were executing a JSR, Next other sources of in- The other type of interrupt, the NMI, is normally caused by
terrupts are turned off, so an interrupt doesn't happen in the one of two things: pressing the RESTORE key, or performing
middle of servicing the IRQ. The accumulator and X and Y a n RS-232 operation. When an NMI occurs, the 128 jumps to
registers are pushed on the stack, and the current state of the the address held at 65530/SFFFA, which points to the Kernal
MMU configuration register at 65280/$FF00 is also put on the area at 65285/$FF05. This is a very short program, which
stack (because the computer has to return to the proper bank ends up bouncing off the RAM vector at 792-793/
setup when it's finished handling the interrupt). $0318-$0319.
The IRQ handling routine has several distinct segments. If the interrupt was triggered by the RESTORE key, the
The first sets up the current screen display mode. For example, system immediately checks to see if the RUN/STOP key was
if you've created a split graphics screen with either GRAPHIC held down at the time RESTORE was pressed. If not, the 8502
2 or GRAPHIC 4, the VIC chip has to be set up for the proper merely returns to the program it was running. If both RUN/
screen and color memory areas. Next, the keyboard is scanned. STOP and RESTORE were pressed, the RUN/STOP-RESTORE
If a key has been pressed, the appropriate character code is initialization sequence is performed, ending with a warm start
determined and stored in the keyboard buffer at 842/$034A. of BASIC (see the entry for 64064/$FA40 in Chapter 9).
If it's time for the 40-column display's cursor to blink, that's If something's happening at the RS-232 port, the incom-
taken care of. The software jiffy clock at 160-162/$A0-$A2 is ing character is processed and stored in the buffer at 3072/
clicked up a notch. The last big segment of the IRQ sequence $0C00, or the outgoing character is sent from the buffer at
is the BASIC IRQ routine, which handles a variety of sprite 3328/$0D00.
and sound support functions. For example, if you've used the
MOVSPR to put a sprite into motion, the new locations have
to be calculated and the sprite position updated. COLLISION Other Sources of IRQs
is also an interrupt-driven command, handled during the IRQ The hardware interrupt is not the only way to have an IRQ
routine. And the sound durations for the SOUND and PLAY happen. You can force the equivalent of an IRQ by including
statements are manipulated during this routine. the BRK instruction (the opcode is $00) in a machine language
program. Any of the the interrupt sources in the VIC chip or
Then, the interrupt ends. The registers are restored to CIA #1 can generate an IRQ request. These include sprite col-
their former values and the bank configuration is stored back lisions, raster interrupts, the light pen input, or any of the CIA
to 65280/$FF00. Interrupts are reenabled and the RTI instruc- timers. Of these, only the raster interrupt is used by the sys-
tion brings the 8502 back to the program it was working on. tem. As mentioned, a raster interrupt occurs when the screen
In 128 mode, the timing of the system IRQ interrupt is redraw routine reaches a certain line on the screen. The line to
tied directly to the position of the raster beam that traces the trigger the standard jiffy interrupt is off the bottom of the visi-
video screen. When the VIC chip gets to the point where it's ble area of the screen. However, the system also supports mid-
drawing a certain line on the screen, the interrupt occurs. This screen raster interrupts to manage the split-screen displays of
is a convenient way to tie in the split-screen modes. In 64 the GRAPHIC 2 and GRAPHIC 4 modes. The IRQ routine
mode, the interrupt request is generated by a hardware timer checks for mid-screen raster interrupts, and performs only the
in one of the CIA chips; this timer is not necessarily in sync screen-setup portion of the interrupt routine in that case. For
with the current position of the raster beam. an
y other type of IRQ, you must write your own handling
routine.

620
621
The first thing the 128 does at the start of an IRQ is jump
10 ; This program sets up an interrupt that checks the 40/80 key
off the processor vector at 65534/$FFFE, which takes it to the 20 ; and switches to the appropriate screen if a change has been made
short routine at 65303/$FF17. At this point, it decides whether 30 !oRG $0C00 ; Put the program at $0C0O
the interrupt was caused by software (a machine language 40 FORTY = $D7 ; 0 if set to 40 columns, 128 if 80
BRK instruction) or hardware (the raster, the timer, the light 50 KEYNDX = $D0 ; Index to how many keys are waiting in the
pen, a sprite collision, and so on). buffer
60 IRQVEC = $0314 ; Vector to the IRQ routine
A BRK instruction causes the system to proceed to a RAM 70 KEYBUF = $034A ; The keyboard buffer
vector at 790-791/$0316-$0317. The usual response to a BRK 80 SWITCH = $D505 ; Bit 7 tells us if the 40/80 switch is up or down
is to start up the built-in monitor, which is also called by the 90 ; %0 is down, %1 is up
BASIC MONITOR command. The advantage to this is plain: 170 ;
When you're writing a machine language program, you can 180 ; The first step is to save the current address in the IRQ vector
insert $00s here and there in the program (breakpoints) and 190 ;
monitor the progress of the program. 200 SEI ; Disable interrupts while the vector is being
changed
Any type of hardware interrupt sends the computer to the 210 LDA IRQVEC ; Get the low byte of the vector
vector at 788-789/$0314-$0315, where the interrupt is han- 220 CMP JUMP+1 ; See if we've done this before
dled. It's at this point that the keyboard is polled, the jiffy 230 BEQ LEAVE ; If ifs equal, jump ahead to exit the routine
clock is updated, and the various other housekeeping chores 240 STA JUMP +1 ; Else store the current IRQ vector address as the
250 LDA 1RQVEC+1 ; target of the JMP to exit from the MAIN routine
are done. 260 STA JUMP+ 2
265 ;
Writing Your Own Interrupt Handler 270 ; Now reset the vector to point to our routine at MAIN
Commodore has inserted a deliberately vulnerable point in the 275;
280 LDA #<MAIN ; Put the address of the MAIN routine
process of handling interrupts: the RAM vectors at 788-793/ 290 STA IRQVEC ; into IRQVEC
$0314-$0319. You can change these pointers to turn off inter- 300 LDA #>MAIN
rupts or to set up your own interrupt processing routine. 310 STAIRQVEC+1
The following machine language program provides a 320;
short example of how to wedge into the IRQ routine. Before 330 CLI ; We're done resetting the vector, so reenable
340 LEAVE RTS ; interrupts and exit from the setup routine
jumping to the normal IRQ handler, it checks the status of the 350;
40/80 DISPLAY key and switches screens if the key setting 400 MAIN = •
doesn't match the currently active screen. 420 ; First, check the status of the 40/80 switch
First, the address currently in the IRQ vector (788-789/ 430 ;
$0314-$0315) is stored as the target address of the JMP that 440 LDA FORTY ; Value is either 0 (40 columns) or $80 (80 columns)
450 EOR SWITCH ; Exclusive-OR with the 40/80 switch flag (bit 7)
ends our own routine. Then the address of our MAIN routine 460 ; if (he status register N flag is %0,
is stored into the IRQ vector. And that's the end of the in- 470 BPL CHANGE ; go ahead and switch displays
staller routine. 480 JUMP JMP $FFFF ; Else jump to the normal IRQ routine
From then on, whenever an IRQ interrupt occurs, the 128 490 ; Note: We never really jump to address $FFFF.
jumps to our custom routine, because the vector has been 495 ; The installation routine changes the $FFFF to the
500 ; address of the normal IRQ routine
changed. Within our routine, the 40/80 switch is checked and 510 ;
if it has been changed, an ESCape (CHR$(27)) and X are 520 CHANGE LDA #27; Put the code for the ESCape key
placed in the keyboard buffer. Whether or not the 40/80 DIS- 530 STA KEYBUF ; into the keyboard buffer, along with
PLAY key has been pressed, we finish the routine by execut- 540 LDA #"X" ; the letter X (ESC X means switch

1
ing a JMP to the normal IRQ routine.

622
550
560
570 JMP
580 LDA
STA JUMP
KEYBUF-1
KEYNDX
#2 ; so
Finish
active
We're
tell putting
displays)
the
up by
128going
two
that keys
2tokeys
the
in are
normal
the pressed
buffer
IRQ routine
623
Appendix B

Bugs and Quirks in


128 ROM
Like all new computer systems, the 128 has a few bugs in its
system ROMs. Neither BASIC nor the Kernal is seriously
flawed, but both include many new routines that weren't part
of earlier versions of the operating system. With all the new
code, it was inevitable that some mistakes would be made.
Some of the items described below are more idiosyncrasies
than true bugs. Others aren't really errors in programming, but
rather errors in documentation—instances where the routine
works, but not exactly as described in the 128 System Guide or
128 Programmer's Reference Guide. It's entirely possible that
some of these situations will be corrected in future versions of
either the ROMs or the manuals.

BASIC
1. Perhaps the most significant bug in BASIC 7.0 is that,
contrary to what the manuals claim, you can't use negative
relative parameters in graphics statements. For example, ac-
cording to the System Guide, DRAWTO - 5 , - 5 should be a
valid statement to draw a line five pixels up and five pixels
left of the current pixel cursor position. Instead, it causes an
ILLEGAL QUANTITY error. The graphics routines themselves
are set up to handle such coordinates, but the routine which
evaluates parameters uses a subroutine that checks the sign of
the value and causes an error if the value is negative.
2. An attempt to OPEN a logical file to an RS-232 device
such as a modem will result in a DEVICE NOT PRESENT er-
ror if x-line handshaking is specified. This is the result of the
Kernal RS-232 OPEN bug described below.
3. An attempt to use INPUT* with a logical file specified
for device 3 (the screen) will not work because of the Kernal
screen BASIN bug mentioned below.
4. In strings for the PLAY statement, any number of digits
can follow a U (volume) command, but only the last one
counts. Also, a digit alone, with no other command, is the

625
same as U followed by that digit. All four of the following 9. All BASIC disk commands automatically add the drive
statements are equivalent: 0 specification if no other drive number is specified, except for
PLAY "VI U7 ABCDE" CATALOG and DIRECTORY. Although Commodore drives
PLAY "VI U1234567 ABCDE" will supply the directory of drive 0 by default, failing to spec-
PLAY "VI U7777 ABCDE" ify a drive number sets up conditions for the infamous 1541
PLAY "VI 7 ABCDE" drive Save-with-Replace bug. Thus, it's safest to add a DO
5. The RSPRITE function accepts sprite number param- after each CATALOG or DIRECTORY.
eters up to 16, even though only 1-8 are valid. 10. In the BASIC disk commands, the ON U parameter
6. The RWINDOW function doesn't return values stated can be specified any number of times; only the last occurrence
in the System Guide. The manual states that RWINDOW(O) re- counts. CATALOG ON U6 ON U7 ON U8 is equivalent to
turns the number of lines in the current output window and CATALOG ON U8.
RWINDOW(l) returns the number of rows. Actually, 11. Commodore literature fails to describe the RREG
RWINDOW(O) returns the number of rows minus 1 in the out- statement included in BASIC 7.0. The proper format is RREG
put window, and RWINDOW(l) returns the number of col- variable 1, variable 2, variable 3, variable 4. The specified vari-
umns minus 1. ables will be set to the values in locations 6, 7, 8, and 5, re-
7. Commodore literature claims that the default scaled spectively. These locations hold the accumulator, X register, Y
size for a standard bitmapped screen (if you use SCALE 1 register, and status register values from the last time the
without additional parameters) is 1023 X 1023. Actually, it's JSRFAR routine was used, such as upon return from the most
1024 X 1024, but that's relatively trivial. A more serious prob- recent SYS statement. Any of the variables may be omitted, so
lem with scaling is that it doesn't work as claimed for multi- RREG AC,,,SP and RREG ,,YR are valid statements.
color (GRAPHIC 3 or GRAPHIC 4) screens. The default scaled 12. BASIC 7.0 allows LIST to be used as a statement
multicolor screen is also 1024 X 1024, not 511 X 511 as within a program, but the RENUMBER statement will not re-
claimed in the System Guide. When you supply scaling factors number any line numbers that may follow LIST in a program
for a multicolor screen, you must use twice the desired hori- being renumbered. This is a trivial oversight, since occasions
zontal scaling value. For example, to scale the multicolor dis- to use LIST within a program are quite rare,
play to 256 X 256, you must use SCALE 1,512,256. The
horizontal factor must be greater than 320 to prevent an ILLE-
GAL QUANTITY error. Kernal
8. The SCNCLR routine doesn't properly fill color mem- 1. The BASIN routine will not accept input from the
ory for a GRAPHIC 4 (split multicolor bitmapped and text) screen because it fails to properly mark the end of the input
screen. That is, the routine fails to fill color memory with the string. Refer to the discussion of the routine at 49819/$C29B
current color source 3 value. Since that routine is also used for in Chapter 7 for more information and a solution to the
the clear option of the GRAPHIC statement, GRAPHIC 4,1 problem.
won't properly initialize color memory either. For multicolor 2. Although it isn't mentioned in the manuals, ESC ESC
bitmapped mode, color memory determines the color of pixels is accepted as a synonym for ESC O (cancel quote mode).
with % 11 bit patterns. The solution is to follow any GRAPHIC 3. The screen editor CINT and SWAPPER routines copy
4 statement with a SCNCLR 3, which does properly fill the one too many bytes when initializing or exchanging the con-
color memory area. As part of the same bug, color memory is tents of the screen editor variable table at 224-249/$E0-$F9.
unnecessarily filled for SCNCLR 2 or GRAPHIC 2,1, but that As a result, the contents of the otherwise unused locations
has no visible effect because color memory is not used in stan- 250/$FA and 256O/$0A5A are overwritten whenever the
dard bitmapped mode. screen is initialized or switched.

626 627
Appendix C

4. The keyboard decoding table for CAPS LOCK has the


incorrect value for the Q key, so that key will appear to be un-
affected by CAPS LOCK,
Character, Screen,
5. If x-line handshaking was specified in the OPEN rou-
tine for RS-232, the routine returns with the status register
and Keyboard
carry bit set if the external device responded, or clear other-
wise. This is the opposite of the carry bit setting when any
other device is successfully opened.
Codes
The Commodore 128 represents characters in several different
manners: as characters, as screen codes, and as keyboard
codes. This appendix covers each of these possible
representations.

Character Codes
The 128 has two separate sets of 256 characters. The set that
is normally activated when the computer is turned on is called
the uppercase/graphics set. It has only uppercase (capital) let-
ters, but includes many graphics characters. The alternative
lowercase/ uppercase set has both lowercase and uppercase
letters, but includes substantially fewer graphics characters. It
is useful for creating more attractive text displays, and is es-
sential for tasks like word processing. You can switch man-
ually between sets by pressing the SHIFT and Commodore
keys simultaneously. You can also switch to the
lowercase/uppercase set within a program by printing charac-
ter 14—PRINT CHR$(14). To switch back to the normal
uppercase/graphics set, print character 142,
In the 40-column display mode, switching character sets
affects all characters currently on the screen. For example, up-
percase letters printed from the uppercase /graphics set will
change to lowercase characters after CHR$(14) is printed.
However, any character set switching in 80-column mode af-
fects only those characters printed after the switch. In this
case, uppercase letters printed from the uppercase/graphics set
will remain in uppercase after a CHR$(14) is printed.
The lowercase/uppercase character set has two identical
groups of uppercase letters, characters 97-122 and characters
193-218. When this set is being used, PRINT CHR$(97) and
PRINT CHR$(193) both cause an A to be displayed on the
screen. However, you should be aware that the ASC function
always returns values from the higher group—in lowercase/
uppercase, PRINT ASC("A") always gives 193 instead of 97.

628 629
In machine language, the Kernal GETIN routine also returns pec Hex Uppercase/Graphics Set Lowercase/Uppercase Set
values 193-218 for shifted letters in the lowercase/uppercase & &
38 26
set.
The following table lists the codes for the 128 character 39 27
40 28 ( (
25, 26, 128, 131, and 132. 29 ) )
41
Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set 42 2A * *
2 02 underline on3 43 2B + +
5 05 white 44 2C r

7 07 bell tone2 45 2D - -

8 08 disable SHIFT-Commodore3 46 2E •

9 09 tab' 47 2F / /

enable SHIFT-Commodore3 48 30 0 0
10 0A linefeed2 49 31 1 1
11 0B disable SHIFT-Commodore* 50 32 2 2
12 OC enable SHIFT-Commodore2 51 33 3 3
13 0D RETURN 52 34 4 4
14 0E switch to lowercase 53 35 5 5
6 6
15 OF flash on1 54 36
cursor down 55 37 7 7
17 11
56 38 8 8
18 12 reverse on
57 39 9 9
19 13 home
58 3A *
20 14 delete • •

24 18 tab set/clear2 59 3B
60 3C <
27 IB ESCape <

61 3D =
28 1C red =

62 3E >
29 ID cursor right >

63 3F ? ?
30 IE green
64 40 @ @
31 IF blue
65 41 A a
32 20 space
66 42 B b
33 21 ! !
67 43 C c
34 22
68 44 D d
35 23 # #
69 45 E e
36 24 $ $
70 46 F f
37 25 % %
631
630
Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set
71 47 G g 104 68 LL H
72 48 H h I
69
73 49 I i
105
E J
74 4A
106 6A ffl
J 6B K
75 4B K
j
*
107
E
k 108 6C LJ L
76 4C L 1 109 6D \ M
77 4D M m 110 6E Z N
78 4£ N n 111 6F r O
79
80
4F
50
O
P
o 112 70 n• P
p 113 71 Q
81 51 Q q 114 72 y R
82 52 R * 115 73 S
83 53 r
S 116 74 I] T
84 54 u
T t 117 75 r^
85 55 U u 118 76 V
86 56 w
V V 119 77 ip
87 57 w w 120 78 x
88
89
58
59
X X 121 79 r Y
Y y 122 7A z
90
91
5A
5B
z 2 7B s +
[ [
L
124 7C B
92 5C £ E 125 7D [E •D
93 5D
94 5E
] 1 7E SB
I r 127 7F S3
95 5F 4-
129 81 orange4
96 60 B & dark purple1
97 61
* A 130 82 underline off
98 62
DD B 133 85 Fl
99 63 C 134 86 F3
100 64 a D 87 F5
101 65 H E 88 F7
102
103
66 s F 137 89 F2
67
DD G 8A F4
632 633
Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set
139 8B F6 170 AA 3 []
140 8C F8 171 AB [B IB
141 8D SHIFT-RETURN 172 AC Ld Q
142 8E switch to uppercase 173 AD ffl ffl
143 8F flash off1 174 AE ffl T
144 90 black 175 AF U •
145 91 cursor up 176 B0 ffl ffl
146 92 reverse off 177 Bl ffl ffl
147 93 clear screen 178 B2 &H ffl
148 94 insert 179 B3 m m
149 95 brown4 180 B4 CJ
dark yellow1 181 B5 C ID
150 96 light red 182 B6 LI Ll
151 97 dark gTay4 183 B7
dark cyan1 184 B8 H n
152 98 medium gray 185 B9 U y
153 99 light green 186 BA • ~V\
154 9A light blue 187 BB H B
155 9B light gray 188 BC L3 1
156 9C purple 189 BD ffl ffl
157 9D cursor left 190 BE H H
158 9E yellow 191 BF fij BJ
159 9F cyan 192 CO H H
160 A0 SHIFT-space 193 Cl H A
194 C2 J| B
161 Al 1 E 195 C3 H C
162 A2 y y
163 A3 • — 196 C4 S D
• 197 C5 H E
164
165
A4
A5 ri r 198
199
C6
C7
H
li
F
G
166 A6 Si 200 C8 U H
167 A7 IH 1 201 C9 B I
168 A8 V. •A
169 A9 n 202 CA f? J

634 635
Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set
203 CB ffl K
236 EC H ~~m
204 CC t] L
237 ED t ^
205 CD k| M
238 EE ffl SI
206 CE g] N
239 EF U U
207 CF |-j 0
240 F0 _T L^
208 DO 3 P
209 DI \m\ Q
241 FI a m
210 D2 H R 242 F2 H ffl
211 D3 m S 243 F3 tfj J!
212 D4 11 244 F4 G I !
T
213 D5 H U 245 F5 [I II
246 F6 | ||
214 D6 X V
247 F7 H
215 D7 [g w
248 F8 H H
216 D8 t X
249 F9 y M
217 D9 [J Y
250 FA Ul ^
218 DA 3 Z
251 FB kJ B
219 DB + +
252 FC " H
220 DC BC B
253 FD B ?J
221 DD fl If
254 FE Fl
222 DE iil g| 255 FF ifl S?
223 DF ^ jg
Notes
224 E0 1. For 80-column display only
2. For 128 mode only
225 El |J |j 3. For 64 mode only
226 E2 y y 4. For 40-colunm display only
227 E3 ^ •
228 E4 •
229 E5. O Hi

231 E7 1 []
232 E8 ii ^
233 E9 B 5g
234 EA El •
235 EB DB Lfe

637
Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set
Screen Codes
There are 256 screen codes for each character set; codes 24 18 X X

128-255 are the reverse images of codes 0-127. To display 25 19 Y y


any character in reverse video, simply add 128 to its screen 1A Z z
26
code value. Thus, POKE 1024,1:POKE 1025,1 + 128 displays
an A and a reverse A. 27 IB [ [
The character ROM has a total of 153 different characters. 28 1C E E
In the uppercase/graphics set, the character patterns for codes 29 ID ] ]
32 and 96 are identical, as are those for 64 and 67, 66 and 93, IE t T
30
101 and 116, and 103 and 106.
31 IF *- «-
Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set 32 20 space
33 21 ! !
0 00 @ @ ft

1 01 A a 34 22
2 02 B b 35 23 # #

3 03 C c 36 24 $ $

4 04 D d 37 25 % %

5 05 E e 38 26 & &

6 06 F i 39 27
7 07 G g 40 28 ( (

8 08 H h 41 29 ) )

9 09 I i 42 2A
10 0A J j 43 2B + +
11 0B K k 44 2C t t

12 0C L 1 45 2D - -

13 0D M m 46 2E *

14 0E N n 47 2F / /

48 30 0 0
15 OF O o
16 10 P p 49 31 1 1
17 11 Q q 50 32 2 2
18 12 R r 51 33 3 3
19 13 S s 52 34 4 4
20 14 T t 53 35 5 5
21 15 U u 54 36 6 6
22 16 V v 55 37 7 7
23 17 W w 56 38 8 8

639
Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set
Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set
57 39 9 9
90 5A ffl Z
58 3A :
91 5B * +
59 3B ; ;
92 5C £1 £J
60 3C < <
93 5D [B T
61 3D = = 1
94 5E ff ^
62 3E > >
95 5F 15 ^
63 3F ? ?
96 60 SHIFT-space
64 40 g B
97 61 H |]
65 41 • A
98 62 y H
66 42 I]] B
99 63 n
67 43 H C
100 64 • •
68 44 g D
ioi 65 r r
69 45 —' E
70 46 — F
103 67 fl •
71 47 |] G
104 68 ki kaJ
72 48 [11 H
105 69 Fl ^
73 49 E I
106 6A • ]
74 4A V j
107 6B [B |_£
75 4B ffi K
108 6C ;H .
76 4C C L
109 6D [5 ^
77 4D SJ M
HO 6E h ffl
78 4E 2 N
79 4F C 0
in 6F ^. y
80 50 ^ P
112 70 ffl ffl
81 51 IB] Q
113 71 ffl ^
82 52 Q R H4 72 ffl T

83 53 W S H5 73 3] ffi
84 54 Hj T 116 74 Cl C
85 55 ffl U H7 75 IJ I
86 56 J£ V US 76 I d
87 57 O W ii9 77 n
88 58 |5| X
89 59 d Y
121 79 U Q
122 7A • |Z
640
641
Dec Hex Uppercase/Graphics Set Lowercase/Uppercase Set
123 7B •
124 7C
125 7D ffl
126 ?E F]
127 7F n
Keycodes
The 128 keyboard is arranged electrically as a matrix of 11 col-
umns X 8 rows of keys. Every 1/60 second, the computer
scans the keyboard to see if a key is pressed. If a key is
pressed, the keyscan routine generates a value that corre-
sponds to the key's position in the matrix. (The formula is
keycode = column * 8 + row, where column has a value from
0 to 10, and row has a value from 0 to 7.) If no key is pressed,
a value of 88 is generated. This value is stored in location 212.
Location 213 will also hold the same value. The contents of
this location can be used to determine which key is currently
being pressed, as an alternative to using GET (or the Kernal
GETIN routine inmachine language). For example, these two
lines have the the same effect—to pause the program until
any key is pressed:
100 GET K$:IF K$="" THEN 100
100 IF PEEK(212)=88 THEN 100
Figure C-l gives the keyscan codes for the 128 keyboard.
Notice that the figure shows no values for the left and' right
SHIFT keys, CONTROL, the Commodore key, and ALT. They
are the keys which use the missing codes 15, 52, 58, 61, and
80, respectively. These keys are detected later in the keyscan
routine, and location 211 is used to record their status. The
values found in that location are as follows:
No shift key pressed 0
SHIFT 1
Commodore 2
CONTROL 4
ALT 8
CAPS LOCK 16

642 643
Appendix D

For this location the values are cumulative. If you press


both SHIFT and CONTROL, the location will contain 1 + 4
= 5. Holding down SHIFT, CONTROL, Commodore, and
Musical Note
ALT together results in a value of 15.
The other "missing" keys are not part of the keyscan ma-
Frequencies
trix. RESTORE is connected to the CIA #2 chip, and acts by
generating an NMI interrupt. The 40/80 column key is con-
nected to the MMU chip and is read and acted upon only at The following table lists the frequencies for the standard musi-
power-on or reset. The SHIFT LOCK key is not scanned; it's cal notes which can be produced by the 128's SID sound chip,
merely a switch that has the effect of holding down the SHIFT along with the SID frequency register values required to pro-
key. duce these sounds. The register values shown are for 128s
using the NTSC (North American) video system. Refer to the
discussion of the SID chip in Chapter 8 for more information
on sound programming.
Although music is often considered an art rather than a
science, there is a precise mathematical relationship between
the notes in the scale. Any two adjacent notes differ in fre-
quency by a factor of 2 t (1 / 12), or about 1.05946. That is,
for any given note the frequency of the next higher note will
be equal to the current note frequency multiplied by 1.05946,
and the frequency of the next lower note will be equal to the
current note frequency divided by 1.05946. Furthermore, the
frequency of a note in one octave and that of a note with the
same letter designation in a higher or lower octave will differ
by a factor of 2 times the number of octaves between the
notes. For example, by international convention the base fre-
quency in this standard system of musical notation is the A at
440 hertz (octave 3 in the table below). You'll notice that the
A in octave 2 has a frequency of 220 hertz (440 / 2), and the
A in octave 4 has a frequency of 880 hertz (440 * 2); the A in
octave 1 has a frequency of 110 hertz (440 / 4), and the A in
octave 5 has a frequency of 1760 hertz (440 * 4). The octave
designations shown (0-6) correspond to those used with the O
parameter in the BASIC PLAY statement.
Note Frequency Frequency register value
(hertz) (low byte) (high byte)
Octave 0:
C 32.70 24/$18 2/$02
C/D 34.65 56/$38 2/$02
D 36.71 90/$5A 2/$02
D/E 38.89 126/$7E 2/$02
E 41.20 164/$A4 2/$02
644 645
.
Note Frequency Frequency register value Note Frequency Frequency register value
(hertz) (low byte) (high byte) (hertz) (low byte) (high byte)
F 43.65 204/$CC 2/$02 G/A 415.30 157/$9D 26/$lA
F/G 46.25 247/$F7 2/$02 A 440.00 50/$32 28/$lC
G 49.00 36/$24 3/$03 A/B 466.16 223/$DF 29/$lD
G/A 51.91 84/$54 3/$03 B 493.88 166/$A6 31/$1F
A 55.00 134/$86 3/$03
58.27 Octave 4:
A/B 188/$BC 3/$03 523.25 136/$88 33/$21
B 61.74 245/$F5
C
3/$03 C/D 554.37 134/S86 35/$23
Octave 1: D 587.33 163/$A3 37/$25
C 65.41 49/$31 4/$04 D/E 622.25 224/SEO 39/$27
C/D 69.30 113/$71 4/$04 E 659.25 63/$3F 42/$2A
D 73.42 180/$B4 4/$04 F 698.46 194/$C2 44/$2C
D/E 77.78 252/$FC 4/$04 F/G 739.99 107/$6B 47/S2F
E 82.41 72/$48 5/$05 G 783.99 61/$3D 50/$32
F 87.31 152/$98 5/$05 G/A 830.61 58/$3A 53/$35
F/G 92.50 237/$ED 5/$05 A 880.00 100/S64 56/$38
G 98.00 72/$48 6/$06 A/B 932.33 190/SBE 59/$3B
G/A 103.83 167/$ A 7 6/$06 B 987.77 76/$4C 63/$3F
A 110.00 12/$0C 7/$07 Octave S:
A/B 116.54 120/$78 7/$07 C 1046.50 15/$0F 67/$43
B 123.47 233/$E9 7/$ 07 C/D 1108.73 12/$0C 71/$47
Octave 2: D 1174.66 70/$46 75/$4B
C 130.81 98/$62 8/$08 D/E 1244.51 191/SBF 79/$4F
C/D 138.59 225/$El 8/$08 E 1318.51 125/$7D 84/$54
D 146,83 105/$69 9/$09 F 1396.91 131/S83 89/$59
D/E 155.56 248/$F8 9/$09 F/G 1479.98 214/$D6 94/$5E
E 164.81 144/$90 10/$0A G 1567.98 122/$7A 100/$64
F 174.61 48/$30 ll/$0B G/A 1661.22 115/$73 106/$6A
F/G 185.00 219/$DB 11/$OB A 1760.00 200/$C8 112/$70
G 196.00 143/$8F 12/$0C A/B 1864.65 124/$7C 119/$77
G/A 207.65 78/$4E 13/$0D B 1975.53 151/S97 126/$7E
A 220.00 25/$19 14/$0E Octave 6:
A/B 233.08 240/$F0 14/$0E 3O/$1E 134/S86
B
C 2093.00
246.94 211/$D3 15/$0F 2217.46 24/$18 142/$8E
C/D
Octave 3: D 2349.32 139/$8B 150/$96
C 261.63 196/$C4 16/$10 (middle C) D/E 2489.01 127/$7F 159/$9F
C/D 277.18 195/$C3 17/$11 E 2637.02 251/$FB 168/$A8
D 293.66 2O9/$D1 18/$12 F 2793.82 7/$07 179/$B3
D/E 311.13 24O/$F0 19/$13 F/G 2959.95 172/$ A C 189/$BD
E 329.63 31/$1F 21/$15 G 3135.96 243/$F3 200/SC8
F 349.23 97/$61 22/$16 G/A 3322.44 230/$E6 212/$D4
F/G 369.99 182/$B6 23/$17 A 3520.00 143/$8F 225/$El
G 392.00 3O/$1E 25/$19 A/B 3729.31 249/SF9 238/$EE
B 3951.07 47/$2F 253/$FD
647
Appendix E

64/128 Memory
Map Cross
Reference
The following list provides a cross reference of the Commo-
dore 64 and Commodore 128 memory maps. In addition to
the RAM locations shown, all I/O chips appear in the 128 at
the same addresses as in the Commodore 64. (When the 128
is used in Commodore 64 mode, the two extra VIC chip regis-
ters and the VDC 80-column chip are still available, although
they must be programmed directly, since there are no routines
to support them.) Also, the Kernal jump table at 65409-65525/
$FF81-$FFF5 is common to both the Commodore 64 and 128.

649
Commodore 64 address Commodore 128 address
s 0/$00 0/$00
Function
Processor on-chip I/O port data direction register
l/$01 l/$01 Processor on-chip I/O port data register
3-4/$03-$04 4474-4475/$117A-$117B Vector: Routine to convert a number from floating point to
signed integer
5-6/$05-$06 4476-4477/$117C-$117C Vector: Routine to convert a number from integer to floating
point
7/$07 9/$09 Search character for scanning BASIC text input
8/$08 10/$OA Search character for statement terminator or quote
9/$09 11/$OB Column position of the cursor before the last TAB or SPC
1O/SOA 12/$0C BASIC LOAD/VERIFY flag
11/$OB 13/$0D [ndex into the text input buffer / number of array subscripts
12/$0C H/$0E Flag for routines that locate or build an array
13/$0D 15/$0F Flag: Type of data {string OT numeric)
14/$0E 16/$10 Flag: Type of numeric data (integer or floating point)
15/$0F 17/$11 Flag for LIST, garbage collection, and program tokenizatiort
16/$10 I8/$12 Flag: Subscript reference to an array or user-defined function call
(FN)
17/$11 19/$13 Input source flag (GET, READ, or INPUT)
18/$12 20/$14 Flag: Sign of the result of the TAN or SIN function
19/$13 2I/$15 Current I/O channel {CMD logical file) number
20-21/$14-$15 22-23/$16-$17 Integer line number value
22/$16 24/$18 Pointer to the next available space in the temporary string stack
23-24/$17-$18 25-26/$19-$1A Pointer to the address of the last string in the temporary string
stack
25-33/$19-$21 27-35/$lB-$23 Descriptor stack for temporary strings
34-37/$22-$25 36-39/$24-$27 Miscellaneous temporary pointers and save area
38-42/$26-$2A 40-44/$28-$2C Floating point multiplication work area
43-44/$2B-$2C 45-46/$2D-$2E Pointer to the start of BASIC program text
45-46/$2D-$2E 47-48/$2F-$30 Pointer to the start of the variable storage area
47-48/$2F-$30 49-50/$31-$32 Pointer to the start of the array storage area
49-50/$31-$32 51-52/$33-$34 Pointer to the start of the area available for string storage

Commodore 64 address Commodore 128 address Function


51-52/$33-$34 53-54/$35-$36 Pointer to the bottom of the string pool
53-54/$35-$36 55-56/$37-$38 Temporary pointer for strings
55-56/$37-$38 57-58/$39-$3A Pointer to the highest address used by BASIC
57-58/$39-$3A 59-60/$3B-$3C Current BASIC line number
59-60/$3B-$3C 4608-4609/$1200-$12ul Previous BASIC line number
61-62/$3D-$3E 4610-4611/$1202-$1203 Pointer to the address of the current BASIC statement
63-64/$3F-$40 65-66/$41-$42 Current DATA line number
65-66/$41-$42 67-68/$43-$44 Pointer to the address of the current DATA item
67-68/$43-$44 69-70/$45-$46 Pointer to the source of GET, READ, or INPUT
69-70/$45-$46 71-72/$47-$48 Current BASIC variable name
71-72/$47-$48 73-74/$49-$4A Pointer to the current BASIC variable value
73-74/$49-$4A 75-76/$4B-$4C Temporary pointer to the index variable used by FOR
75-76/$4B-$4C 77-78/$4D-$4E Math operator table displacement
77/$4D 79/$4F Mask for comparison operation
78-79/$4E-$4F 80-81/$50-$5I Pointer to the current FN descriptor
80-82/$50-$52 82-84/$52-$54 Temporary pointer to the current string descriptor
83/$53 n.a. Constant for garbage collection
84-86/$54-$56 86-88/$56-$58 Jump to function instruction
87-96/$57-$60 89-98/$59-$62 BASIC numeric work area
97-101/$61-$65 99-103/$63-$67 Floating point accumulator #1
102/$66 104/$68 Floating point accumulator #1 sign
103/S67 105/$69 Number of terms in a series evaluation
104/$68 991/$03DF Floating point accumulator #1 overflow digit
105-109/$69-$6D 106-110/$6A-$6E Floating point accumulator #2
110/S6E 111/$6F Floating point accumulator #2 sign
111/$6F 112/$70 Result of a sign comparison of FAC1 to FAC2
112/$70 113/$71 Low byte of floating point accumulator #1 (for rounding)
113-114/$71-$72 114-115/$72-$73 Series evaluation pointer
115-138/$73-$8A 896-926/$0380-$039E Subroutine to get next BASIC text character (CHRGET)
139-143/$8B-$8F 4635-4639/$121B-$121F RND function seed value
Commodore 64 address Commodore 123 address Function
to 144/$90 144/$90 Kemal I/O status word (ST)
145/S91 145/$91 Flag: Was STOP key pressed?
H6/$92 146/$92 Timing constant for tape reads
147/$93 147/$93 Flag for Kerna! LOAD routine (0 = LOAD, 1 = VERIFY)
148/$94 148/$94 Serial bus buffered character flag
149/$95 149/$95 Buffered character for serial bus
150/$96 150/$96 Cassette block synchronization number
151/$97 151/$97 Temporary register save area
152/$98 152/$98 Number of open files / index into the file tables
153/$99 153/$99 Default input device (set to 0 for the keyboard)
154/$9A 154/$9A Default output (CMD) device (set to 3 for the screen)
155/S9B 155/$9B Tape character parity
156/$9C 156/$9C Flag: Tape byte received
157/$9D 157/$9D Kernal message control flag
158/$9E 158/$9E Tape pass 1 error log index
159/$9F 159/$9F Tape pass 2 error log correction index
160-162/$ A0-$A2 160-162/$ A0-$A2 Software jiffy clock
163-164/$A3-$A4 163-164/$A3-$A4 Cassette/serial work bytes
165/$A5 165/$A5 Cassette synchronization character countdown
166/$A6 166/$A6 Count of characters in tape I/O buffer
167/$A7 167/SA7 RS-232 input bits / cassette temporary storage area
168/$A8 168/$A8 RS-232 input bit count / cassette temporary storage
169/$A9 169/$A9 RS-232 start bit received flag
170/$AA 170/$AA RS-232 input byte buffer / cassette temporary storage
171/$AB 171/$AB RS-232 input parity / cassette leader counter
172-173/$AC-$AD 172-173/$AC-$AD Pointer to the starting address of a load / screen scrolling
174-175/$AE-$AF 174-175/$AE-$AF Pointer to the ending address of the load (end of program)
176-177/$BO-$B1 176-177/$B0-$BI Tape timing
178-179/$B2-$B3 178-179/$B2-SB3 Pointer to start of tape buffer
180/$B4 180/$B4 RS-232 output bit count / cassette temporary storage

Commodore 64 address Commodore 12S address Function


181/SB3 131/$B5 RS-232 next bit to send / tape EOT flag
182/SB6 182/$B6 RS-232 output byte buffer
183/$B7 183/$B7 Length of current filename
184/$B8 184/$B8 Current logical file number
185/$B9 185/$B9 Current secondary address
186/$BA 186/$BA Current device number
187-188/$BB-$BC 187-188/$BB-$BC Pointer to current filename
189/$BD 189/$BD RS-232 output parity / cassette temporary storage
190/$BE 190/$BE Cassette read/write block count
191/$BF 191/$BF Tape input byte buffer
192/$C0 192/$C0 Tape motor interlock
193-I94/$C1-$C2 193-194/$C1-$C2 I/O start address
195-196/$C3-$C4 195-196/$C3-$C4 Tape load temporary addresses
197/$C5 213/$D5 Matrix coordinate of last key pressed
198/$C6 208/$D0 Number of characters in keyboard buffer (queue)
199/$C7 243/$F3 Reverse character flag
200/$C8 2608/$OA30 Pointer to end of logical line for input
201-202/$C9-$CA 232-233/$E8-$E9 Cursor column and row position at start of input
203/$CB 212/$D4 Matrix coordinate of current key pressed
204/$CC 2599/$0A27 Cursor blink enable flag (0 = flashing cursor)
205/$CD 2600/$0A28 Timer: Countdown to blink cursor
206/$CE 2601/$0A29 Character under cursor
207/$CF 2598/$0A26 Flag: Was last cursor blink on or off?
208/$D0 2]4/$D6 Flag: Input from keyboard or screen
209-210/$Dl-$D2 224-225/$E0-$El Pointer to the address of the current screen line
211/$D3 236/$EC Cursor column on current line
212/$D4 244/$F4 Quote mode flag (0 — off)
213/$D5 238/$EE Maximum length of physical screen line
2H/$D6 235/$EB Current cursor physical line number
ON
215/$D7 240/$FO Temporary storage area for last character printed
g; Commodore 64 address Commodore 128 address Function
^ 216/$D8 245/$F5 Flag: Insert mode (any number greater than 0 is the number of
inserts)
217-242/$ D9-$F2 n.a. Screen line link table / editor temporary storage
243-244/$F3-$F4 226-227/$E2-$E3 Pointer to the address of the current screen color RAM location
245-246/$F5-$F6 204-205/$CC-$CD Pointer to current keyboard decode table
247-248/$F7-$F8 200-201 /$C8-$C9 Pointer to RS-232 input buffer
249-250/$F9-$FA 202-203/$CA-$CB Pointer to RS-232 output buffer
251-254/$FB-$FE 251-254/$FB-$FE Free zero-page locations for user programs
255-266/$FF-$010A 255-266/$FF-$010A Work area for floating point to ASCII conversion
256-317/$0100-$013D 256-217/$0100-$013D Tape input error log
256-511/$0100-$01FF 256-511/$0100-$01FF Microprocessor stack area
512-600/$0200-$0258 512-671/$0200-$02AO BASIC input buffer
601-610/$0259-$0262 866-875/$0362-$036E Table of active logical file numbers
6Jl-62O/$0263-$O26C 876-885/$036C-$0375 Table of device numbers for each logical file
621-630/$026D-$0276 886-895/$0376-$037F Table of secondary addresses for each logical file
631-640/$0277-$0280 842-851/$034A-$0353 Keyboard buffer
641-642/$0281-$0282 2565-2566/$OA05-$OA06 Pointer to start of memory
643-644/$0283-$0284 2567-2568/$OA07-$OA08 Pointer to end of memory
645/$0285 2574/$OA0E IEEE time-out flag
646/$0286 241/$F1 Current foreground color for text
647/$0287 2602/$OA2A Color of character undeT cursor
648/S0288 2619/$0A3B Top page of screen memory
649/$0289 2592/$0A20 Maximum keyboard buffer size
650/$028A 2594/$0A22 Flag: Which keys will repeat?
651/$028B 2595/S0A23 Counter for timing the delay between key repeats
652/$028C 2596/$0A24 Counter for timing the delay until the first key repeat begins
653/$028D 211/$D3 Current SHI FT/CTRL/Commodore keypress
654/$028E n.a. Last pattern of SHIFT/CTRL/Commodore keypress
655-656/$028F-$0290 826-827/$033A-$033B Vector to keyboard table setup routine
657/S0291 247/$F7 Flag: Enable/disable character set switching with SHIFT-
Commodore

Commodore 64 address Commodore 128 address Function


658/$0292 248/$F8 Flag: Screen scroll enabled
659/$0293 2576/$OA10 RS-232 control register
660/S0294 2577/$0All RS-232 command register
661-662/$0295-$0296 2578-2579/$OA12-$0A13 RS-232 Nonstandard bit timing
663/S0297 2780/$0A14 RS-232 status register
664/$0298 2581/$0A15 Number of bits left to be sent/received
665-666/$0299-$029A 2582-2583/$OA16-$0A17 Time required to send a bit
667/$029B 2584/$0A18 Index to end of RS-232 input buffer
668/$029C 2585/S0A19 Index to start of RS-232 input buffer
669/$029D 2586/$0AlA Index to start of RS-232 output buffer
670/$029E 2587/S0A1B Index to end of RS-232 output buffer
671-672/$029F-$02A0 2569-2570/$OA09-$OAOA Save area for IRQ vector during cassette operations
673/$02Al 2575/$0AOF RS-232 interrupts enabled
674/$02A2 2571/S0A0B CIA #1 control register B storage during cassette operations
675/$02A3 2572/S0A0C Save area for CIA #1 interrupt control register during cassette
read
676/$02A4 2573/S0A0D Save area for CIA #1 control register A during cassette read
677/S02A5 223/$DF Temporary index to the next 40-column line for screen scrolling
678/S02A6 2563/$0A03 PAL/NTSC Hag
768-769/$0300-$0301 768-769/$0300-$03ul Vector to print BASIC error message routine
770-771/$0302-$0303 770-771/$0302-$0303 Vector to main BASIC program loop
772-773/$0304-$0305 772-773/$0304-$0305 Vector to routine that crunches the ASCII keywords into tokens
774-775/$0306-$0307 774-775/$0306-$0307 Vector to routine that lists BASIC program tokens
776-777/$0308-$0309 776-777/$0308-$0309 Vector to routine that executes next BASIC program token
778-779/$030A-$030B 778-779/$030A-$030B Vector to routine that evaluates a single-term arithmetic
expression
780/$030C 6/$06 Storage for A register (accumulator)
781/$030D 7/$07 Storage for X index register
782/$030H 8/$08 Storage for Y index register
8 783/$030F 5/$05 Storage for status register
Appendix F

BASIC Keyword
Index
The following table lists all of the BASIC 7.0 keywords in al-
phabetical order, along with their corresponding tokens and
the addresses of the routines called to perform each token's
operation.

Keyword Token Address


ABS 182/$B6 35972/$8C84
AND 175/$AF 19593/$4C89
APPEND 254/$FE + 14/$0E 41268/$A134
ASC 198/$C6 34423/$8677
ATN 193/$C1 38067/$94B3
AUTO 220/SDC 22901/$5975
BACKUP 246/$F6 41852/$A37C
BANK 254/$FE + 2/$02 27593/$6BC9
BEGIN 254/$FE + 24/$18 [1]
BEND 254/$FE + 25/$19 21135/S528F
BLOAD 254/$FE + 17/$ll 41496/$A218
BOOT 254/$FE + 27/$lB 29493/$7335
BOX 225/$El 25271/$62B7
BSAVE 254/$FE + l6/$10 41416/$A1C8
BUMF 206/$CE + 3/$03 33660/S837C
CATALOG 254/$FE+12/$0C 41086/$A07E
CHAR 224/$E0 26583/$67D7
CHR$ 199/$C7 34239/$85BF
CIRCLE 226/$E2 26254/$668E
CLOSE 160/$AO 37274/$919A
CLR 156/$9C 20984/$51F8
CMD 157/$9D 21824/$5540
COLLECT 243/$F3 41775/SA32F
COLLISION 254/$FE + 23/$17 29028/$7164
COLOR 231/SE7 27106/$69E2
CONCAT 254/$FE+19/$13 41826/$A362
CONT 154/$9A 23136/$5A60
COPY 244/$F4 41798/$A346
COS 190/$BE 37897/$9409
DATA 131/S83 21135/I528F
DCLEAR 254/$FE + 21/$15 41762/$A322

656 657
Keyword Token Address Keyword Token Address
DCLOSE 254/$FE+15/$0F 41327/$A16F LOCATE 23O/SE6 26965/$6955
DEC 2O9/$D1 32886/$8076 LOG 188/$BC 35274/$89CA
DEF 150/$96 34042/$84FA LOOP 236/$EC 24714/$608A
DELETE 247/$F7 24199/$5E87 MID$ 202/$CA [3]
DIM 134/$86 22651/$587B MONITOR 250/$FA 45056/$B000
DIRECTORY 238/$EE 41086/$A07E MOVSPR 254/$FE + 6/$06 27846/$6CC6
DLOAD 240/$F0 41383/$A1A7 NEW 162/$A2 20950/$51D6
DO 235/$EB 24544/$5FE0 NEXT 130/$82 22516/$57F4 [4]
DOPEN 254/$FE+13/$0D 41245/$A11D NOT 168/$A8 31024/$7930
DRAW 229/$E5 26519/$6797 OFF 254/$FE + 36/$24 18502/$4846 [5]
D5AVE 239/$EF 41356/$A18C ON 145/$91 21411/$53A3 [6]
DVERIFY 254/$FE + 20/$14 4138O/$A1A4 OPEN 159/$9F 37261/$918D
ELSE 213/$D5 21393/$5391 OR 176/$B0 19590/$4C86
END 128/$80 19405/$4BCD PAINT 223/SDF 25000/$61A8
ENVELOPE 254/$FE + 10/$OA 28865/$70Cl PEEK 194/$C2 32965/$80C5
ERR$ 211/$D3 33014/$80F6 PEN 206/$CE+4/$04 33454/$82AE
EXIT 237/$ED 24633/$6039 PLAY 254/$FE + 4/$04 28129/S6DE1
EXP 189/IBD 36915/$9033 POINTER 206/$CE + 10/$0A 33530/$82FA
FAST 254/$FE + 37/$25 30643/$77B3 POKE 151/S97 32997/$80E5
FETCH 254/$FE + 33/$21 43556/$AA24 POS 185/$B9 34000/$84DO
FILTER 254/$FE + 3/$03 28742/$7046 POT 206/$CE + 2/$02 33357/$824D
FN 165/$A5 34107/$853B PRINT 153/$99 21850/$555A
FOR 129/$81 24057/$5DF9 PRINT* 152/$98 21818/$553A
FRE 184/$B8 32768/$8000 PUDEF 221/$DD 24372/$5F34
GET 161/$A1 22034/$5612[2] QUIT 254/$FE + 30/$lE 18502/$4846 [5]
GO 203/$CB 23101/$5A3D RCLR 205/$CD 33179/$819B
GOSUB 141/$8D 22991/$59CF RDOT 208/$D0 39692/$9B0C
GOTO 137/$89 23003/$59DB READ 135/$87 22185/S56A9
GRAPHIC 222/$DE 27482/$6B5A RECORD 254/$FE + 18/$12 41687/$A2D7
GSHAPE 227/$E3 25997/$658D REM 143/$8F 21149/$529D
HEADER 241/$F1 4I575/$A267 RENAME 245/$F5 41838/$A36E
HELP 234/$EA 22918/$5986 RENUMBER 248/$F8 23288/$5AF8
HEX$ 210/$D2 33090/S8142 RESTORE 23242/$5ACA
140/$8C
IF 21189/$52C5
I39/S8B RESUME 214/$D6 24418/$5F62
INPUT 133/$85 22H4/$5662 RETURN 142/$8E 21090/$5262
INPUT# 132/$84 22088/$5648 RGR 204/$CC 33154/$8182
INSTR 212/SD4 39361/S99C1 RIGHTS 201/$C9 34314/$860A
INT 181/$B5 36091/$8CFB RND 187/$BB 33844/$8434
JOY 207/$CF 33283/$8203 RREG 254/$FE + 9/$09 22717/$58BD
KEY 249/$F9 24842/$610A RSPCOLOR 206/$CE + 7/$07 33633/$8361
LEFTS 200/$C8 34262/$85D6 RSPPOS 206/$CE + 5/$05 33687/$8397
LEN 195/$C3 34408/$8668 RSPRITE 206/$CE + 6/$06 33566/$831E
LET 136/$88 21446/$53C6 RUN 138/$8A 23195/$5A9B
LIST 155/$9B 20706/$50E2 RWINDOW 206/$CE + 9/$09 33799/$8407
LOAD 147/$93 37164/$912C SAVE 148/$94 37138/$9112
658
659
Keyword Token Address Address
Keyword Token
SCALE 233/$E9 26976/$6960
SCNCLR < 179/$B3 19638/$4CB6
232/$E8 2 725 7/$ 6A 79 178/$B2 19638/$4CB6
SCRATCH 242/$F2 41633/$A2A1 > 177/$B1 19638/$4CB6
SGN 180/$B4 35941/$8C65
srN K 255/$FF [12]
191/$BF 37904/$9410
SLEEP 254/$FE + ll/$0B 27607/$6BD7
SLOW 254/$FE + 38/$26 30660/$77C4
SOUND 218/$DA 29164/$71EC
SPC( 166/$A6 Notes:
[7]
SPRCOLOR 254/$FE + 8/$08 29072/$7190
1. Normally handled during IF execution. When encountered
SPRDEF 254/$FEH-29/$lD 29554/$7372 outside IF processing, the target routine merely prints a
SPRITE 254/$FE + 7/$07 27727/$6C4F SYNTAX ERROR message.
SPRSAV 254/$FE + 22/$16 30444/$76EC 2. There are no separate tokens for the keywords GET* and
SQR 186/$BA 36791/$8FB7 GETKEY; both are handled as special cases during GET
SSHAPE 228/$E4 25643/$642B execution. GET* is represented by a GET token followed
STASH 254/$FE + 31/$lF 43551/$AA1F by a # character (code 35/$23). GETKEY is represented by
STEP 169/$A9 [8] a GET token followed by a KEY token (249/SF9).
STOP 144/$90 19403/$4BCB
STR$ 3. Can be used as either a statement or a function. The rou-
196/$C4 34222/$85AE tine at 22785/$5901 handles processing as a statement;
SWAP 254/$FE + 35/$23 43561/$AA29
SYS when a function, the routine at 34332/S861C is used.
158/$9E 22661/$5885
TAB(
TAN
163/$A3
192/$C0
m
37977/$9459
4. Can also be used in conjunction with the RESUME
statement.
TEMPO 254/$FE + 5/$05 28631/$6FD7
5. Defined but not implemented. The target routine merely
THEN 167/$A7 [9]
prints an UNIMPLEMENTED COMMAND ERROR
TO 164/$A4 message.
TRAP [10]
215/$D7 24397/$5F4D 6. Can also be used in conjunction with most disk commands
TROFF 217/$D9 to specify the device (unit) number.
TRON 22711/$58B7
216/$D8 22708/$58B4 7. Processed during PRINT execution.
UNTIL 252/$FC 8. Processed during FOR execution.
USING
USR
251/$FB
I83/$B7
m4632/$1218 9. Processed during IF execution.
VAL 197/$C5 10. Processed during the execution of several other keywords
VERIFY 32842/$804A which accept TO as part of a valid statement: DRAW, FOR,
149/$95 37161/$9129
VOL 219/$DB GO, and assorted disk commands (BACKUP, BSAVE,
WAIT 29125/$71C5 CONCAT, COPY, and RENAME).
146/$92 27693/$6C2D
WHILE 253/$FD 11. Processed during DO or LOOP execution.
WIDTH [11]
254/$FE + 28/$lC 29110/$71B6
12. Processed during the operand evaluation routine (EVAL),
WINDOW 254/$FE + 26/$lA 30935/$78D7.
XOR 29388/$ 72CC
206/$CE + 8/$08 33761/$83E1
+ 170/$AA 34888/$8848
171/$AB
* 172/$AC
34865/$8831
35367/$8A27
/ 173/$ AD 35660/$8B4C
174/$AE
36801/S8FC1
660
661
highest quality programs like Number
Quest. Address File, Treasure Hunt.
Castle Dungeon, Vocab Builder,
SpeedScript, and hundreds of other
educational, home finance, and game
More fun...More challenge... programs.
Mote all new programs So subscribe today—and unleash
each and every month. the hidden power of your Commodore
computer, Return the card below—or
Subscribe to COMPUTEVs Gazette call 1-800-247-5470 (in Iowa. 1-800-
through this special money-saving in- 532-1272). Do it now.
troductory offer—and start unleashing
the full power of your Commodore
computer.
Month after month, look to
COMPUTERS Gazette to deliver the
latest inside word on everything from
short programming tips to the best
new software. Our expert analysis and
insights mean you have more fun...get
more enjoyment...more of what you
bought your computer for.
As a subscriber, you also receive
up to 20 all-new, action-packed pro-
grams each month. Every big issue of
COMPUTEVs Gazette comes complete
with a steady supply of the most
useful, the most entertaining, the

Subscription
Savings Card
i YES!
n Payment enclosed • Bill me • Charge my VISA/MasterCard

Credit Card #_ _Exp. Date_


I know a great deal
when 1 see one. Sign Signature-
me up for 12 big issues Name_
of COMPUTEVs Gazette
for |ust $18.1 save 50% Address.
off the newsstand price. City_ -State. _Zip_

Outside US A please aJJ S6-..U.S (per year (or postage.


Say YES now to Appendix G

COMPUTE'S
Index of Locations
You can search far and wide and you
simply want find a better magazine...a
better source of insightful, stimulating,
usable information for your Com-
Add it up for yourself. Where else
can you get exciting programs each
month...expert advice...insightful
analysis...up-to-the-minute software
and Routines
modore computer than COMPUTERS reviews and so much more—all for
Gazette. just $18.
COMPUTE'S Gazette works So why wait. Subscribe now to
harder...digs deeper...researches COMPUTEfs Gazette—and get the
Chapter 2: Common Working Storage
further—all to help guarantee that you most from your Commodore computer. so Data direction register for processor's on-chip I/O
get the absolute most from your Com- Return card below—or call 1-SO0- port
modore. 247-5470 (in Iowa. 1-800-532-1272). 1 $01 Data register for processor's on-chip I/O port
Subscribe today and each and ev- 2 $02 Target bank for JMPFAR and JSRFAR
ery month you 11 receive up to 20 all- 3-4 $03-$04 Target address for JMPFAR and JSRFAR
new action-packed programs. That's up 5 $05 Status register storage for JMFFAR and JSRFAR
to 200 programs each year—game pro- 6 $06 Accumulator storage for JMPFAR and JSRFAR
grams...education programs...home ap- 7 $07 X register storage for JMPFAR and JSRFAR
plications programs...personal and g $08 Y register storage for JMPFAR and JSRFAR
budgeting programs...sorting and filing 9 $09 Stack pointer storage for JSRFAR and monitor
programs. 9 $09 Working storage for various routines
10 $0A Working storage for various routines
11 $0B Current screen column for TAB and SPC calculations
12 $0C BASIC LOAD/VERIFY flag
13 $0D Working storage for various routines
14 $0E Array dimension flag
15 $0F Variable type flag
16 $10 Numeric type flag
17 $11 Working storage for various routines
18 $12 Integer/subscript prohibit flag
19 $13 Input source flag
20 $14 Comparison type flag/Tangent sign flag
21 $15 Logical file number for BASIC input and output
22-23 $16-$17 Integer value of ASCII digit string
24 $18 Pointer into temporary string descriptor stack
25-26 $19-$1A Pointer to most recent descriptor stack entry
27-35 $lB-$23 Temporary string descriptor stack
NO POSTAGE Multipurpose address pointer
36-37 $24-$25
NECESSARY 38-39 $26-$27 Multipurpose address pointer
IF MAILED 40-44 $28-$2C Temporary storage area for multiplication and
IN THE division
UNITED STATES 45-46 $2D-$2E Start-of-BASIC-program pointer
47-48 $2F-$30 Start-of-variables pointer
BUSINESS REPLY MAIL 49-50
51-52
$31-$32
$33-$34
Start-of-arrays pointer
Start-of-free-memory pointer
FIRST CLASS PERMIT NO. 7551 DES MOINES. lA 53-54 $35-$36 Bottom-of-string-space pointer
55-56 $37-$38 Temporary pointer into the string pool
POSTAGE: WILL BE PAID BY ADDRESSEE 57-58 $39-$3A Top-of-memory pointer
59-60 $3B-$3C Current BASIC line number
Pointer for main BASIC character retrieval routine
COMPUTERS Gazette 61-62
63-64
65-66
$3D-$3E
$3F-$40
$41-542
Working pointer for varoious routines
line number of current DATA statement
PO Box 10775
67-68 $43-$44 Pointer to next DATA item
Des Moines, IA 50347-0775 69-70 $45-$46 Text pointer for input
71-72 $47-$48 Current variable name
663
IJ.I.II II..J..M...IM., j...n. < .i.i.i...r.ii
73-74 $49-$4A Pointer to variable descriptor 150 $96 Cassette block synchronization count
75-76 $4B-$4C Variable descriptor pointer and working storage 151 $97 Temporary register storage
77-78 $4D-$4E Temporary storage for text pointer 152 $98 Number of files currently open
79 $4F Relational operator flag 153 $99 Current input device
80-81 $50-$51 Defined function pointer and working pointer 154 $9A Current output device
80-84 $50-$54 Temporary storage for floating point value 155 $9B Tape character parity
82-83 $52-$53 Variable address storage and working pointer 156 $9C Tape dipole received flag
85 $55 HELP flag 157 $9D Kemal message control flag
86-88 $56-$58 BASIC function execution vector 158 $9E Tape pass 1 error-log pointer
89-93 $59-$5D Floating point work area 159 $9F Tape pass 2 error-log pointer
90-91 $5A-$5B Multipurpose working pointer 160-162 $A0-$A2 Software jiffy clock
92-93 $5C-$5D Multipurpose address pointer 163 $A3 Tape: Count of bits to be read or written
93-95 $5D-$5F String length and pointer for MID$ Serial: EOI flag
94-98 $5E-$62 Temporary storage for floating point value 164 $A4 Tape: Half-cycle indicator
94-95 $5E-$5F Working pointer for garbage collection Serial: Byte received
95 $5F Decimal point position 165 $A5 Tape: Leader synchronization countdown
96-98 $60-$62 Substring length and pointer for MID$ Serial: Count of bits to send
96-104 $60-$68 Monitor zero-page pointers and working storage 166 $A6 Pointer into cassette buffer
97-98 $61-$62 Multipurpose address pointer 167 $A7 Tape: Leader clipole count/block indicator
99-103 $63-$67 Floating point accumulator 1 RS-232: Current bit received
304 $68 Sign of FAC1 168 $A8 Tape: Half-cycle indicator for writing/error flag for
105 $69 Sign flag during conversion/Count of terms in series reading
evaluation RS-232: Count of bits remaining to be received
106-110 $6A-$6E Floating point accumulator 2 169 $A9 Tape: Word marker flag/half-cycle flag
111 $6F Sign of FAC2 RS-232: Start bit received flag
112 $70 Sign comparison flag 170 $AA Tape: Read phase flag
112-113 $70-$71 Multipurpose address pointer RS-232: Assembly byte for received bits
113 $71 Rounding flag for FAC1 171 $AB Tape: Leader dipole counter / checksum work byte
114-115 $72-$73 Multipurpose address pointer and working storage RS-232: Received byte parity
116-117 $74-$75 Step value for autoincrement 172-173 $AC-$AD Kernal working address pointer
118 $76 Graphics area flag 172-175 $AC-$AF Work area for disk booting
119 $77 General purpose working storage 174-175 $AE-$AF Kemal working storage: Used to hold the ending ad-
120 $78 String offset pointer dress for SAVE [$F53E]
121 $79 Multipurpose temporary storage 176 $B0 Kernal address pointer
122 $7A Index into input buffer for monitor 177 $B1 TEMP
122-124 $7A-$7C Descriptor for disk error string DS$ 178-179 $B2-$B3 Pointer to cassette buffer
125-126 $7D-$7E BASIC runtime stack pointer 180 $B4 Tape: leader/data flag
127 $7F RUN mode flag RS-232: Count of bits transmitted
128 $80 Decimal point position 181 $B5 Taper Leader completed flag
128-129 $80-$81 Parameter flags for DOS support commands RS-232: Next bit to send
130 $82 Storage for processor stack pointer 182 $B6 Tape: Error flag / end of block flag
131 $83 Color source for current graphics command RS-232: Character being sent
132 $84 Color source 2 storage 183 $B7 Length of current filename
133 $85 Color source 3 storage 184 $B8 Logical file number
134 $86 Current foreground color (source 1) storage 185 $B9 Current secondary address
135-136 $87-$88 Horizontal scaling factor 186 $BA Current device number
137-138 $89-$8A Vertical scaling factor 187-188 $BB-$BC Pointer to start of filename
139 $8B PAINT mode flag 189 $BD Tape: Byte read from tape / byte to be written to tape
140-141 $SC-$8D Address pointer for graphics routines RS-232: Parity calculation working storage
142-143 $8E-$8F Temporary storage for graphics routines Serial: Current byte during burst mode load
144 $90 Status flag for tape and serial bus operations 190 (BE Block count
145 $91 Scan value of STOP key column 191 $BF Drive number (ASCII) for PHOENIX
146 $92 Tape timing adjustment factor 192 $C0 Tape motor interlock
147 $93 Kernal load/verify flag/Monitor operation flag 193-194 $C1-$C2 Kernal work pointer: Used to hold starting address for
148 $94 Serial deferred character flag save
K9 $95 Serial character buffer 195-196 $C3-$C4 Kemal work pointer (starting address for load)

664 665
197 $C5 Bit read from tape / checksum of block written to 311-507 $0137-$01FB Stack space used by BASIC
tape 512-672 J0200-S02AO BASIC and monitor input buffer
198 $C6 Bank where data for save, load, or verify is found 673 S02A1 Unused
199 $C7 Bank where filename for open, save, load, or verify is 674-686 $02A2-$02AE Retrieves a value from any bank
found 687-701 $02AF-$02BD Stores a value in any bank
200-201 $C8-$C9 Pointer to RS-232 input buffer 702-716 $02BE-$02CC Compares the accumulator contents against a value
202-203 $CA-$CB Pointer to RS-232 output buffer from any bank
204-205 $CC-$CD Pointer to current keyboard decode table 717-738 $02CD-$02E2 Calls a subroutine in any bank
206-207 $CE-$CF Pointer for Kern a 1 PR1MM routine 739-763 $02E3-$02FB Jumps to a routine in any bank
208 $D0 Number of characters in the keyboard buffer 764-765 $02FC-$02FD Indirect vector for extended functions
209 $D1 Number of characters pending from programmable 766-767 $02FE-$02FF Unused indirect vector
key string 768-769 $0300-$0301 Indirect vector in BASIC ERROR routine
210 $D2 Pointer into the programmable key definition area 770-771 $0302-$0303 Indirect vector in BASIC MAIN routine
211 $D3 Shift key status flag 772-773 $0304-$0305 Indirect vector in BASIC CRUNCH routine
212 $D4 Current key pressed (matrix value) 774-775 $0306-$030; Indirect vector in BASIC QPLOP routine
213 $D5 Last key pressed 776-777 $0308-$0309 Indirect vector in BASIC GONE routine
214 $D6 Input source flag 778-779 $030A-$030B Indirect vector in BASIC EVAL routine
215 $D7 Active screen flag 780-781 $030C-$030D Indirect vector for tokenizing new keywords
216 $D8 Mode flag for 40-column screen 782-783 $030E-$030F Indirect vector for listing new keywords
217 $D9 CHAREN bit shadow 784-785 $0310-$0311 Indirect vector for executing new statements
218-223 SDA-$DF 5creen editor zero page work area 786-787 $0312-$0313 Unused
224-225 $EO-$E1 Pointer to first screen memory location for current 788-789 $0314-$0315 Indirect vector to IRQ handling routine
line 790-791 $0316-$0317 Indirect vector to BRK handling routine
226-227 $E2-$E3 Pointer to first attribute memory location for current 792-793 $0318-$0319 Indirect vector to NMI handling routine
line 794-795 $031A-$031B Indirect vector in Kernal OPEN routine
228 $E4 Bottom margin of current window 796-797 $031C-$031D Indirect vector in Kemal CLOSE routine
229 $E5 Top margin of current window 798-799 S031E-S031F Indirect vector in Kemal CHKIN routine
230 $E6 Left margin of current window 800-801 $0320-$0321 Indirect vector in Kernal CKOUT routine
231 $E7 Right margin of current window 802-803 $0322-$0323 Indirect vector in Kernal CLRCH routine
232 $E8 Cursor row for start of input 804-S05 $0324-$0325 Indirect vector in Kemal BASIN routine
233 $E9 Cursor column for start of input 806-807 $0326-$0327 Indirect vector in Kemal BSOUT routine
234 $EA Column of last nonspace character on logical line 808-809 $0328-$0329 Indirect vector in Kernal STOP routine
235 $EB Cursor row 810-811 $032A-$032B Indirect vector in Kemal GETIN routine
236 $EC Position of cursor within current logical line 812-813 $032C-$032D Indirect vector in Kemal CLALL routine
237 $ED Maximum number of rows allowed in output window 814-815 $032E-$032F Indirect vector in monitor EXMON routine
238 SEE Maximum number of columns allowed per row 816-817 $0330-$0331 Indirect vector in Kernal LOAD routine
239 SEF Character to print 818-819 $0332-$0333 Indirect vector in Kemal SAVE routine
240 $F0 Last character printed 820-821 $0334-$0335 Screen editor indirect vector
241 $F1 Attribute of current character 822-823 $0336-$O337 Screen editor indirect vector
242 $F2 Temporary storage for attribute byte 824-825 $0338-$0339 Screen editor indirect vector
243 $F3 Reverse mode flag 826-827 $033A-$033B Screen editor indirect vector
244 $F4 Quote mode flag 828-829 $033C-$033D Screen editor indirect vector
245 $F5 Number of pending inserts 830-841 $033E-$0349 Screen editor indirect vector
246 $F6 Autoinsert mode flag 842-851 $034A-$0353 Keyboard buffer
247 $F7 Case switching/scroll pause control flag 852-861 $0354-$035D Tab stop bitmap
248 $F8 Scroll/link control flag 862-865 $035E-$0361 Line link bitmap
249 $F9 Bell enable flag 866-875 $0362-$036B Logical file number table for currently open files
250 $FA Unused 876-885 $036C-$0375 Device number table for currently open files
251-254 tFB-SFE Unused 886-895 $0376-$037F Secondary address table for currently open files
255-266 $OOFF-$010A Assembly area for numeric strings 896-926 $0380-$039E CHRGET (main BASIC character retrieval routine)
256-511 $0100-$0IFF Processor stack area 927-977 $O39F-$O3D1 Alternate BASIC character retrieval subroutines
256-268 $0100-$010C Assembly area for disk boot command 978-980 $03D2-$03D4 Null descriptor
256-317 $0100-$013D Tape error log 981 $03D5 Bank number for PEEK and POKE
272-290 $0110-$0122 DOS command work area 982-985 $03D6-$3D9 Pointers for INSTR evaluation
291-310 S0I23-S0136 PRINT USING work area 986 $03DA String block flag
294 $0126 Command type indicator for PLAY processing 987-990 $03DB-$03DE Temporary storage for SHAPE data

666 667
/
991 $03DF Floating-point overflow byte 2611 S0A33 Attribute of current cursor position
992-993 $03E0-$03El Temporary pointer storage 2612 $0A34 Scan line for screen split
994 $03E2 Standard bitmap color fill value 2613 $0A35 Temporary storage for X register
995 $03E3 Multicolor bitmap color fill value 2614 $0A36 Jiffy clock compensation flag
996-1007 $03E4-$03EF Unused 2615 $0A37 Temporary storage for clock rate register
1008-1020 $03FO-$03FC DMA—CALL execution routine 2616 $0A38 Temporary storage for sprite enable register
1021-1023 $03FD-$03FF Unused 2617 $0A39 Temporary storage for VIC control register
2618 $0A3A Custom mode flag
Chapter 3: Bank 0 Working Storage 2619
2620-2621
$0A38
$0A3C-$0A3D
Starting page for 40-coiumn screen memory
Working pointer into 80-column memory
1024-2023 $0400-07FF Default VIC screen memory 2622-2623 $0A3E-$0A3F Unused
2024-2559 $0800-$09FF BASIC runtime stack 2624-2650 $0A40-$0A5A Screen editor variable storage for the inactive screen
2560-2561 $OA00-$0AOl BASIC restart vector 2651-2655 $0A5B-$0A5F Unused
2562 $OA02 Memory initialization status flag 2656-2665 $0A60-$0A69 Storage for inactive tab stop bitmap
2563 $0A03 PAL/NTSC flag 2666-2669 $0A6A-$0A6D Storage for inactive line link bitmap
2564 $0A04 System initialization status flag 2670-2687 $0A6E-$0A7F Unused
2565-2566 $0A05-$OA06 Kernal MEMBOT pointer 2688-2703 $OA80-$OA8F Filename buffer for load, save, or verify
2567-2568 $0AO7-$0A08 Kemal MEMTOP pointer 2688-2719 $0A80-$0A9F Search pattern buffer
2569-2570 $OA09-$OAOA Temporary storage for ILRQ vector during tape 2720-2727 $0AA0-$0AA7 Working storage for base conversion
operations 2720-2729 $0AA0-$0AA9 Instruction assembly buffer
2571 $OA0B CIA #1 control register A log 2730 $0AAA Instruction format flag
2572 $OA0C CIA #1 interrupt control register log 2731 $0AAB Instruction length
2573 $OA0D CIA #1 timer A status log 2732-2734 $OAAC-$0AAE Three-character mnemonic pattern
2574 $0A0E IEEE timeout flag 2735 $0AAF Temporary storage for X register
2575 $0A0F RS-232 activity flag 2736 $OAB0 Unused
2576 $OA10 RS-232 control register 2737 $0ABl Calculated opcode
2577 S0A11 RS-232 command register 2738 $0AB2 Temporary storage for X register
2578-2579 $0A12-$0A13 RS-232 baud rate factor 2739 $0AB3 Transfer direction flag
2580 S0A14 RS-232 status register 2740 $0AB4 Digit counter
2581 $0A15 RS-232 bit count 2741 $0AB5 Temporary storage for parameter conversion
2582-2583 $OA16-$0A17 R5-232 baud rate timing constant 2742 $0AB6 Number of bits per digit for base
2584 $0A18 Index to firs! character in RS-232 input buffer 2743-2745 $0AB7-$0A39 Monitor temporary storage
2585 $0A19 Index to last character in RS-232 input buffer 2746-2751 $OABA-$0ABF Unused
2586 $OA1A Index to first character in RS-232 output buffer 2752 $0AC0 Counter for function ROM testing
2587 $OA1B Index to last character in RS-232 output buffer 2753-2756 $0ACl-$0AC4 Table of identifiers for function ROMs
2588 J0A1C Fast serial mode flag 2757 $0AC5 DK_FLAG
2589-2591 $OA1D-$OA1F Software jiffy timer 2758-2815 S0AC6-$0AFF Unused
2592 $0A20 Maximum number of keys in the keyboard buffer 2816-307] $OBO0-$0BFF Cassette buffer/disk boot buffer
2593 $0A21 Scroll pause flag 3072-3327 S0C00-SOCFF RS-232 input buffer
2594 $0A22 Key repeat flag 3328-3583 $0DO0-$0DFF RS-232 output buffer
2595 $0A23 Countdown between key repeats 3584-4095 $0E00-$OFFF Sprite pattern storage area
2596 $0A24 Countdown until key repeating begins 4096-4351 $1000-$lFFF Programmable key definition storage area
2597 $0A25 Delay between case switching repeats 4352-4400 $1100-$1130 DOS command assembly area
2598 $0A26 Cursor blink flag 4401-4402 $1131-$1132 Bitmapped screen pixel cursor horizontal position
2599 $0A27 Cursor enable flag 4403-4404 $1133-$1134 Bitmapped screen pixel cursor vertical position
2600 $0A28 Cursor blink countdown 4405-4406 $1135-$U36 Final horizontal pixel position for graphics operations
2601 $0A29 Character under cursor 4407-4408 $1137-$1138 Final vertical pixel position for graphics operations
2602 $0A2A Color under cursor 4409-4455 $1139-$1177 Working storage for assorted graphics routines
2603 $0A2B VDC cursor mode 4456 $1168 Starting page for character pattern definitions
2604 S0A2C VIC text screen and character base 4457 $1169 Bit counter for shape retrieval
2605 $0A2D VIC bitmap and video matrix base 4458 $116A Scaling flag
2606 $0A2E Starting page for VDC screen memory 4459 $116B Line width for bitmapped graphics routines
2607 $0A2F Starting page for VDC attribute memory 4460 $116C BOX fill flag
2608 $0A3O Ending row for screen input 4461 $116D Bit mask value
2609-2610 $0A31-$OA32 Temporary storage for 80-column memory 4462 $116E Temporary storage for assorted routines
manipulation 4463 $116F Trace mode flag

668 669
4464-4467 $1170-$1173 Working storage for RENUMBER 4729-4734 $1279-$127D Target line numbers for COLLISION
4468 $1174 Loop counter for reading directory entries 4735 $127F Collision enable flag
4469-4470 $1175-$1176 Block count for directory entry 4736 $1280 Collision type index
4471 $1177 Working storage for graphics parameter scaling 4737 $1281 Voice for current SOUND statement
4472 $1178 Working storage for graphics parameter evaluation 4738-4770 S1282-S12A2 Table of SOUND statement settings
4473 $1179 Working storage for graphics parameter evaluation 4771-4776 $12A3-$12A8 Parameters for most recent SOUND statement
4474-4475 $117A-$117B Pointer to floating point-to-integer conversion routine 4785 $12B1 Temporary storage for POT and PEN routines
4476-4477 $117C-$117D Pointer to integer-to-floating poinl conversion routine 4786 $12B2 Temporary storage for POT routine
4478-4565 $117E-S11D5 Sprite movement control data 4787-4790 $12B3-$12B6 Temporary parameter storage for WINDOW
4566-4582 $11D6-$1IE6 Shadows for VIC sprite position registers statement
4583-4584 $11E7-$1IE8 Shadows for VIC sprite collision registers 4791-4806 $12B7-$12C6 Filename buffer for DOS support commands
4585-4586 $11E9-$11EA Shadow for VIC light pen registers 4791-4854 $12B7~$12F6 Sprite pattern storage
4587 $11EB Starting page for alternate character set during CHAK 4854-4857 $12F6-$12F9 Sprite pattern suffix
4588 $11EC Starting page for default character set during CHAR 4858 S12FA Sprite mode indicator for SPRDEF
4589 $11ED Channel number for BASIC relative file operations 4859 $12FB Sprite pattern line count for SPRDEF
4590-4607 $11EE-$11FT Unused 4860 $12FC Sprite number for SPRDEF
4608-4609 $1200-$1201 line number where program stopped 4861 $12PD BASIC IRQ activity flag
4610-4611 $1202-$1203 Pointer to the start of current line 4862-4863 $12FE-$12FF Unused
4612-4615 $1204-$!207 Character definitions for PRINT USING
4616 $1208 Number of most recent error
4617-4618 $1209-$120A Line number where most recent error occurred Chaptei 5: BASIC
4619-4620 $120B-$120C Target line number for TRAP statement 16384 $4000 BASIC cold-start entry point
4621 $120D Temporary storage for high byte of TRAP line 16387 $4003 BASIC warm-start entry point
number 16390 $4006 BASIC IRQ entry point
4622-4623 $120E-$120F Pointer to start of statement where last error occurred 16393 $4009 Performs a warm start of BASIC
4624-4625 $1210-$1211 End-of-program pointer 16416 $4020 Unused
4626-4627 $1212-$1213 Top-of-BASIC pointer 16419 $4023 Performs a cold start of BASIC
4628-4629 $1214-$1215 Temporary text pointer storage for DO 16453 $4045 Initializes BASIC pointers and constants
4630-4631 $1216-$1217 Temporary line number storage for DO 16658 $4112 Initializes SID registers and sound routine locations
4632-4634 $1218-$121A USR function jump vector 16762 $417A Initializes MMU preconfiguration registers
4635-4639 $121B-$121F Seed value for random number generation 16781 $418D Initializes sprite speed and direction table
4640 $1220 Degrees between segments for CIRCLE routine 16795 $419B Displays the power-on message
4641 $1221 Unused 16827 $41BB Text for power-on message
4642 $1222 Tempo setting for PLAY statement 16977 $4251 Initializes BASIC indirect vectors
4643-4648 S1223-$1228 Durations for currently active notes 16999 $4267 Table of default vector values
4649-4650 $1229-$122A Duration of current note 17017 $4279 Text for character retrieval routines
4651 S122B Octave for current note 17102 $42CE Assorted character retrieval subroutines
4652 $122C Sharp/flat flag 17162 $430A Tokenizes keywords in lines of BASIC program text
4653-4654 $122D-$122E Frequency for current note 17328 S43B0 Handles extended tokens
4655 $122F Voice number for current note 17356 $43CC Deletes a character in the input buffer
4656-4658 $1230-$1232 Waveforms for current notes 17378 $43E2 Searches keyword tables for match
4659 $1233 Dotted note flag 17431 $4417 BASIC keyword tables
4660-4661 $1234-$1235 Current filter cutoff frequency 17929 $4609 Table of extended token statements
4662 $1236 Current resonance setting 18121 $46C9 Table of extended token functions
4663 $1237 Current filter type 18172 $46FC Table of statement dispatch addresses
4664 $1238 Filter type index 18242 $4742 Table of statement dispatch addresses
4665 $1239 Temporary storage 18172 $46FC Table of statement dispatch addresses
4666 $123A Current instrument number 18317 $478D Table of function dispatch addresses
4667-4669 $123B-$123D Envelope parameters for current instrument 18454 $4816 Table of function dispatch addresses
4670 $123E Index into instrument table for current instrument 18472 $4828 Table of operator priorities and dispatch addresses
4671-4720 $123F-$1270 Instrument parameter tables 18502 $4846 Prints unimplemented command message
4721-4722 $1271-$1272 Current filter cutoff frequency 18507 $484B Table of BASIC error messages
4723 $1273 Current filter control and resonance setting 19074 $4A82 Sets pointer to error message
4724 $1274 Current filter type selection 19103 $4A9F Main BASIC statement execution routine
4725 $1275 Current SID chip volume setting 19190 $4AF6 Executes the next BA5IC statement
4726-4728 $1276-$!278 Collision flags 19381 S4BB5 Tests for RUN/STOP keypress

670 671
19403 $4BCB Handles the STOP and END statements 23069 $5A1D Places RETURN parameters in the runtime stack
19447 $4BF7 Handles the execution of function keywords 23101 S5A3D Handles the GO statement
19587 $4C83 Displays the SYNTAX ERROR message 23136 $5A60 Handles the CONT statement
19590 $4C86 Handles the OR logical operator 23169 $5A81 Sets flags for running a program
19593 $4C89 Handles the AND logical operator 23195 $5A9B Handles the RUN statement
19638 $4CB6 Handles relational operators (<, —, >) 23242 $5ACA Handles the RESTORE statement
19754 $4D2A Prints the READY prompt 23280 $5AF0 Table of tokens for RENUMBER
19767 $4D37 Enters MAIN with a READY prompt 23288 $5AF8 Handles the RENUMBER statement
19770 $4D3A Displays an OUT OF MEMORY error message 24057 $5DF9 Handles the FOR statement
19772 $4D3C Handles BASIC errors 24199 S5ES7 Handles the DELETE statement
19836 $4D7C Prints a specified error message 24372 $5F34 Handles the PUDEF statement
19895 $4DB7 Handles immediate mode and program line entry 24397 $5F4D Handles the TRAP statement
19938 $4DE2 Adds or deletes BASIC program lines 24418 $5F62 Handles the RESUME statement
20303 $4F4F Relinks BASIC program lines 24544 $5FE0 Handles the DO statement
20371 S4F93 Reads a line of input into the buffer 24633 $6039 Handles the EXIT statement
20394 $4FAA Searches for a particular token in the runtime stack 24714 $608A Handles the LOOP statement
20478 $4FFE Decrements the runtime stack pointer 24801 $6OE1 Assigns a definition string to a programmable key
20503 $5017 Checks for available string space 24842 $610A Handles the KEY statement
20569 $5059 Increments runtime stack pointer 24989 $619D Table of characters for KEY
20580 $5064 Searches program text for a specified line number 25000 $61A8 Handles the PAINT statement
20640 $50AO Creates integer value from a character string 25271 $62B7 Handles the BOX statement
20706 $50E2 Handles the LIST statement 25643 $642B Handles the SSHAPE statement
20771 $5123 Lists a single BASIC program line 25997 $65 8D Handles the GSHAPE statement
20950 $51D6 Handles the NEW statement 26254 $668E Handles the CIRCLE statement
20984 $51F8 Handles the CLR statement 26443 $6750 Bitmapped graphics circle drawing subroutine
21076 $5254 Resets the CHRGET text pointer 26519 $6797 Handles the DRAW statement
21090 $5262 Handles the RETURN statement 26583 $67D7 Handles the CHAE statement
21135 $528F Handles the BEND and DATA statements 26965 $6955 Handles the LOCATE statement
21149 $529D Handles the REM statement 26976 $6960 Handles the SCALE statement
21189 $52C5 Handles the IF statement 27096 $69D8 Table of scaling factors
21280 $5320 Skips a BEGIN-BEND block 27106 $69E2 Handles the COLOR statement
21393 $5391 Handles the ELSE statement 27212 $6A4C Table for translating VIC color values to VDC color
21411 $53A3 Handles the ON statement values
21446 $53C6 Handles variable value assignments 27228 $6A5C Calculates color fill values
21818 $553A Handles the PRINT* statement 27257 $6A79 Handles the SCNCLR statement
21824 $5540 Handles the CMD statement 27482 $6B5A Handles the GRAPHIC statement
21844 $5554 Handles the PRINT statement 27593 $6BC9 Handles the BANK statement
22034 $5612 Handles the GET statement (also GET# and 27607 $6BD7 Handles the SLEEP statement
GETKEY) 27693 $6C2D Handles the WAIT statement
22088 $5648 Handles the ENPUT# statement 27727 $6C4F Handles the SPRITE statement
22114 $5662 Handles the INPUT statement 27846 $6CC6 Handles the MOVSPR statement
22185 $56A9 Handles the READ statement 28129 $6DE1 Handles the PLAY statement
22474 $57CA Moves the CHRGET text pointer to the next DATA 28631 $6FD7 Handles the TEMPO statement
statement 28644 $6FE4 Data tables for PLAY string processing
22516 $57F4 Handles the NEXT statement 28689 $7011 Default values for ENVELOPE instrument tables
22648 $5878 Handles the DIM statement 28742 $7046 Handles the FILTER statement
22661 $5885 Handles the SYS statement 28865 $70Cl Handles the ENVELOPE statement
22708 $58B4 Handles the TRON and TROFF statements 29028 $7164 Handles the COLLISION statement
22717 $58BD Handles the RREG statement 29072 $7190 Handles the SPRCOLOR statement
22785 $5901 Handles MID$ when used as a statement 29110 $71B6 Handles the WIDTH statement
22901 $5975 Handles the AUTO statement 29125 $71C5 Handles the VOL statement
22918 $5986 Handles the HELP statement 29164 $71EC Handles the SOUND statement
22956 $59AC Highlights the portion of a listed line containing an 29388 $72CC Handles the WINDOW statement
error 29493 $7335 Handles the BOOT statement
2299] $59CF Handles the GOSUB statement 29554 $7372 Handles the SPRDEF statement
23003 $59DB Handles the GOTO statement 30444 $76EC Handles the SPRSAV statement

673
30643 $77B3 Handles the FAST statement 34862 $882E Subtracts value in memory from FAC1
30660 $77C4 Handles the SLOW statement 34865 $8831 Subtracts FAC1 from FAC2
30679 $77D7 Evaluates an expression with a test for type mismatch 34885 $8845 Adds value in memory to FAC1
30703 $77EF Evaluates an expression 34888 $8848 Adds FAC1 to FAC2
30935 $78D7 Evaluates a single term of a numeric expression 34993 $88B1 Normalizes FAC1
31084 $796C Displays a SYNTAX ERROR message 35110 $8926 Forms twos complement of FAC1
31096 $7978 Evaluates a variable value 35165 $895D Displays OVERFLOW error message
31407 $7AAF Finds or creates a variable 35170 $8962 Performs byte alignment of FAC1
31632 $7B90 Creates an entry in the variable table for a new scalar 35274 $89CA Handles the LOG function
variable 35342 $8A0E Adds 0.5 to FAC1
31846 $7C66 Moves arrays upward in bank 1 to make room for a 35364 $8A24 Multiplies value in memory by FAC1
new scalar variable 35367 $8A27 Multiplies value in memory by FAC1
31915 $7CAB Finds or creates an array variable 35465 $8A89 Loads FAC2 with value from the current bank
32768 $8000 Handles the FRE function 35508 $8AB4 Loads FAC2 with value from bank 1
32800 $8020 Prints designers message 35607 $8B17 Multiplies FAC1 by 10
32842 $804A Handles the VAL function 35640 $8B38 Divides FAC1 by 10
32886 $8076 Handles the DEC function 35657 $8B49 Divides value in memory by FAC1
32965 $80C5 Handles the PEEK function 35660 $8B4C Divides FAC2 by FAC1
32997 $80E5 Handles the POKE statement 35796 $8BD4 Loads FAC1 from memory
33014 $80F6 Handles the ERR$ function 35840 $8C00 Copies FAC1 value into memory
33090 $8142 Handles the HEX$ function 35880 $8C28 Copies FAC2 into FAC1
33154 $8182 Handles the RGR function 35896 $8C38 Copies FAC1 into FAC2
33179 $819B Handles the RCLR function 35911 $8C47 Rounds FAC1
332S3 $8203 Handles the JOY function 35927 $8C57 Determines the sign of the value in FAC1
33357 $824D Handles the POT function 35941 $8C65 Handles the SGN function
33454 $82AE Handles the PEN function 35972 $8C84 Handles the AB5 function
33530 $82FA Handles the POINTER function 35975 $8C87 Compares FAC1 against FAC2
33566 $831E Handles the RSPR1TE function 36039 $8CC7 Converts FAC1 to a four-byte integer
33633 $8361 Handles the RSPCOLOR function 36091 $8CFB Handles the INT function
33660 $837C Handles the BUMP function 36120 $8D18 Fills FAC1 with the value in the accumulator
33687 $8397 Handles the RSPPOS function 36130 $8D22 Generates floating point value representing character
33761 $83E1 Handles the XOR function string
33799 $8407 Handles the RW1ND0W function 36390 $8E26 Prints IN and a line number
33844 $8434 Handles the RND function 36398 $8E2E Prints a line number
33936 $8490 Table of floating point constants for RND calculation 36418 $8E42 Generates a character string representing the value in
34000 $84D0 Handles the POS function FAC1
34009 $84D9 Checks that BASIC is in run mode 36791 $8FB7 Handles the SQR function
34032 $84F0 Checks that BASIC is in immediate mode 36801 $8FC1 Handles the exponentiation (T) operator
34042 $84FA Handles the DEF statement 36869 $9005 Table of floating point constants for EXP evaluation
34107 $853B Handles user-defined functions using FN 36915 $9033 Handles the EXP function
34222 $85AE Handles the STR$ fucntion 36998 $9086 Performs series evaluation
34239 $85BF Handles the CHR$ function 370B0 $90D8 Calls the Kernal OPEN routine
34262 $85D6 Handles the LEFT$ function 37087 $90DF Calls the Kernal BSOUT routine
34314 $860A Handles the RIGHT$ function 37093 $90E5 Calls the Kernal BASIN routine
34332 $861C Handles the MTD$ function 37117 $90FD Calls the Kemal CHKIN routine
34408 $8668 Handles the LEN function 37129 $9109 Calls the Kemal GETIN routine
34423 $8677 Handles the ASC function 37138 $9112 Handles the SAVE statement
34437 $8685 Displays the ILLEGAL QUANTITY error message 37161 $9129 Handles the VERIFY statement
34440 $8688 Creates space for a string in the string pool 37164 $912C Handles the LOAD statement
34458 $869A Stores a string in the string pool 37261 $918D Handles the OPEN statement
34573 $870D Performs string concatenation 37274 $919A Handles the CLOSE statement
34683 $877B Evaluates a string parameter 37294 $91AE Evaluates parameters for SAVE, LOAD, and VERIFY
34801 $87F1 Evaluates a numeric expression 37366 $91F6 Evaluates parameters for OPEN and CLOSE
34819 $8803 Evaluates parameters for POKE or WAIT 37433 $9239 Clears DS$ after disk operations
34831 $880F Checks that the next character is a comma 37457 $9251 BASIC calls to Kemal routines
34837 $8815 Evaluates a numeric parameter 37457 $9251 BASIC call to Kernal's READSS routine

674
i 675
37463 $9257 BASIC call to Kemal's 5ETLFS routine 42872 $A778 Reads disk status string (DS$)
37469 $925D BASIC call to Kernal's SETNAM routine 42977 $A7E1 Provides AKE YOU SURF, query
37475 $9263 BASIC call to Kemal's BASIN routine 43021 $A80D Clears disk status string
37481 $9269 BASIC call to Kemal's BSOUT routine 43077 $A845 Switches to bank 15 configuration
37487 $926F 3ASIC call to Kemal's CLRCH routine 43085 $A84D BASIC IRQ service routine
37493 $9275 BASIC call to Kemal's CLOSE routine 43504 $A9F0 Common exit point from BASIC IRQ routine
37499 $927B BASIC call to Kemal's CLALL routine 43551 $AA1F Handles the STASH statement
37505 $9281 BASIC call to Kemal's PRIMM routine 43556 $AA24 Handles the FETCH statement
37511 $9287 BASIC call to Kemal's SETBANK routine 43561 $AA29 Handles the SWAP statement
37517 $928D BASIC call to Kemal's PLOT routine 43630-44642 $AA6E-$AE62 Unused
37523 $9293 BASIC call to Kemal's STOP routine 44643-44799 $AE63-$AEFF Encoded message from the designers of the 128
37529 $9299 Creates space in the string pool for a temporary string 44800 $AF00 Entry point for the AYINT routine
37610 $92EA Performs garbage collection on string pool 44803 $AF03 Entry point for the GIVAYF routine
37897 $9409 Handles the COS function 44806 $AF06 Entry point for the FOUT routine
37904 $9410 Handles the SIN function 44809 $AF09 Entry point for the VA1 1 routine
37977 $9459 Handles the TAN function 44812 $AF0C Entry point for the GETADR routine
38021 $9485 Table of constants for trig function evaluation 44815 $AF0F Entry point for the FLOATC routine
38067 $94B3 Handles the ATN function 44818 $AF12 Entry point for the FSUB routine
38115 $94E3 Table of constants for trig function evaluation 44821 $AF15 Entry point for the FSUBT routine
38176 $9520 Handles the PRINT USING statement 44824 $AF18 Entry point for the FADD routine
39361 $99C1 Handles the INSTR function 44827 $AF1B Entry point for the FADDT routine
39692 $9B0C Handles the RDOT function 44830 $AF1E Entry point for the FMULT routine
39728 $9B30 Bitmapped graphics line drawing routine 44833 $AF21 Entry point for the FMULTT routine
39931 $9BFB Bitmapped point plotting routine 44836 $AF24 Entry point for the FDIV routine
40010 $9C4A Scales graphics parameter 44839 $AF27 Entry point for the FDIVT routine
40366 $9DAE Applies scaling factor to a specified parameter 44842 $AF2A Entry point for the LOG routine
40557 $9E6D Evaluates graphics parameters 44845 $AF2D Entry point for the INT routine
40712 $9F08 Handles relative graphics parameters 44848 $AF30 Entry point for the SQR routine
40783 $9F4F Allocates the bitmapped graphics area 44851 $AF33 Entry point for the NEGOP routine
40903 $9FC7 Adjusts BASIC program pointers for graphics area 44854 $AF36 Entry point for the FPVVR routine
allocation or de-allocation 44857 $AF39 Entry point for the FPWRT routine
40994 $A022 De-allocates the bitmapped graphics area 44860 $AF3C Entry point for the EXP routine
41076 $A074 44863 $AF3F Entry point for the COS routine
Confirms that the graphics area has been allocated Entry point for the SIN routine
41086 $A07E Handles the CATALOG and DIRECTORY statements 44866 $AF42
44869 $AF45 Entry point for the TAN routine
41245 $A11D Handles the DOPEN statement Entry point for the ATN routine
41268 $A134 Handles the APPEND statement 44872 $AF48
44875 $AF4B Entry point for the ROUND routine
41303 $A157 Finds an available secondary address Entry point for the ABS routine
43327 $A16F Handles the DCLOSE statement 44878 $AF4E
44881 $AF51 Entry point for the SIGN routine
41347 $A183 Closes all open files for a specified device Entry point for the FCOMP routine
41356 $A18C Handles the DSAVE statement 44884 $AF54
44887 $AF57 Entry point for the RND_0 routine
41380 $A1A4 Handles the DVERIFY statement Entry point for the CONUPK routine
41383 $A1A7 Handles the DLOAD statement 44890 $AF5A
44893 JAF5D Entry point for the ROMUPK routine
41416 $A1C8 Handles the BSAVE statement Entry point for the MOVFRM routine
41496 $A218 Handles the BLOAD statement 44896 $AF60
44899 $AF63 Entry point for the MOVFM routine
41575 $A267 Handles the HEADER statement Entry point for the MOVMF routine
41633 $A2A1 Handles the SCRATCH statement 44902 $AF66
44905 $AF69 Entry point for the MOVFA routine
41687 $A2D7 Handles the RECORD statement Entry point for the MOVAF routine
41762 $A322 Handles the DCLEAR statement 44908 $AF6C
44914 $AF72 Entry point for the DRAWLN rotuine
41775 SA32F Handles the COLLECT statement Entry point for the GPLOT routine
41798 $A346 Handles the COPY statement 44917 SAF75
44920 $AF78 Entry point for the CIRSUB routine
41826 $A362 Handles the CONCAT statement Entry point for the RUN routine
41838 $A36E Handles the RENAME statement 44923 $AF7B
44926 $AF7E Entry point for the RUNC routine
41852 $A37C Handles the BACKUP statement Entry point for the CLR routine
41923 $A3C3 Evaluates parameters for disk commands 44929 $AF81 Entry point for the NEW routine
42535 $A627 Table of disk command templates 44932 $AF84
Entry point for the LNKFRG routine
42599 $A667 Sets up disk command buffer 44935 $AF87

676 677
44938 SAFSA Entry point for the CRUNCH routine
47284 $B8B4 Moves cursor to start of next line
44941 $AF8D Entry point for the FNDLN routine 47289 $B8B9 Clears a screen line
44944 $AP90 Entry point for the NEWSTT routine 47298 SB8C2 Prints two ASCII characters for a byte value
44947 $AF93 Entry point for the EVAL routine
44950 $AF96 47314 JB8D2 Converts a byte value into two ASCII characters
Entry point for the FRMEVL routine
44953 $AF99 47335 $B8E7 Tests next character in the input buffer
Entry poinl for the RUN routine
44956 $AF9C 47361 $B901 Transfers address and bank values to working pointer
Entry point for the SETEXC routine
44959 $AF9F 47374 $B90E Calculates number of bytes and banks to display or
Entry point for the LINGET routine
44962 $AFAZ Entry move
point for the GARBA2 routine
44965 $AFA5 Entry 47394 $B922 Decrements address or line count
point for the MAIN routine
47420 $B93C Decrements byte count
47440 $B950 Increments address pointer
47456 SB960 Decrements address pointer
Chapter 6: Machine Language Monitor ROM 47476 $B974 Changes bank and address
45056 $B0OO Monitor cold start entry point 47491 $B983 Prepares pointers for dual-address operations
45059 $B003 Monitor break entry point 47537 SB9B1 Performs number base conversion
45062 $B006 Reentry point from the IMON indirect vector 47623 $BA07 Converts a hexadecimal value to decimal
45065 $B009 Monitor entry routine when BRK instruction 47687 $BA47 Prints octal, binary, or decimal values
encountered 47760 $BA90 Handles @ (disk) commands
45089 $B021 Cold start routine for monitor 47875 $BB03 Displays disk directory
45136 $B050 Handles R (register display) command 47986-49151 $BB72-$BFFF Unused
45195 $B08B Main command execution loop for the monitor
45285 $B0E3 Handles X (exit to BASIC) command
45288 $B0E6 Table of monitor commands Chapter 7: Screei Editor ROM
45308 SB0FC Table of execution addresses for the monitor
commands
49152
49263
$cooo
$C06F
Screen editor jump table
Table of default keyboard decoding table pointers
45338 $B11A INDFET call for the monitor 49275 $C07B Initializes screen editor constants, variables, tables,
45354 $B12A INDSTA call for the monitor and vectors
45373 SB13D INDCMP call for the monitor 49474 $C142 Clears the current window and homes the cursor
45394 $B152 Handles M (memory display) command 49488 $C150 Moves the cursor to the home position of the current
45460 $B194 Handles ; (change register) command window
45483 $B1AB Handles > (change memory) command 49500 $C15C Sets starting address pointers for the current line
45526 $B1D6 Handles G (go to routine) command 49502 $C15E Sets starting address pointers for a specified line
45535 $B1DF Handles ] (jump to subroutine) command 49556 $C194 Performs screen and keyboard portion of IRQ
45544 $B1E8 Displays a line of memory as hex bytes and ASCII functions
characters 49716 $C234 Performs GETIN from keyboard
45617 $B23I Compares or transfers blocks of memory 49752 $C258 Accepts a line of keyboard input and returns the first
45774 $B2CE Searches memory for byte pattern character
45879 $B337 Prepares for save, load, or verify 49819 $C29B Performs BASIN from screen or keyboard
45983 $B39F Handles save for monitor 49919 $C2FF Handles quote mode flag
45995 $B3AB Handles load and verify 49932 $C30C Provides common exit for screen BSOUT subroutines
46033 $B3D1 Prepares for relocating load or verify 49952 $C320 Handles character printing for screen BSOUT
46043 $B3DB Fills memory with specified byte value 49982 SC33E Updates the cursor position
46086 $B406 Handles A (assemble) command, or its equivalent 50019 $C363 Moves the cursor down one line
46489 $B599 Handles D (disassemble) command 50044 $C37C Inserts a new line linked to the one above
46548 SB5D4 Disassembles a single instruction 50086 $C3A6 Scrolls the window up one line
46681 $B659 Calculates mnemonic and addressing mode 50140 $C3DC Copies lines up one row and clears bottom line
46753 $B6A1 Prints mnemonic for opcode 50189 $C40D Copies a line
46787 $B6C3 Opcode decoding table 50341 $C4A5 Clears a line
46855 $B707 Table of addressing mode indicators 50492 $C53C Fills or copies a block of 8563 RAM
46869 $B715 Scans keyboard matrix for keypress
Table of mode identification characters 50525 $C55D
468S1 $B721 Decodes key matrix value into character value and
Table of mnemonics in packed form 50769 SC651
47013 $B7A5 handles key repeating
Evaluates a parameter in the input buffer
47054 SB7CE Table of programmable key character values
Transforms numeric parameter into byte value 50909 $C6DD
47242 $BS8A Handles cursor blinking for 40-column screen
Table of bases and bits-per-digit 50919 $C6E7
47250 $B892 Prints a hexadecimal value 50989 $C72D Handles BSOUT to the screen
47277 $B8AD Moves cursor to start of current line 51055 $C76F Handles RETURN and SHIFT-RETURN characters,
CHR$(13) and CHR$(141)
678 679
51069 SC77D Cancel quote arid reverse modes and dear pending
inserts (ESC O and ESC ESC) 52023 $CB37 Enables tone for bell character (ESC G)
51084 $C78C Tables of screen control codes and dispatch addresses 52026 $CB3A Disables tone for bell character (ESC H)
51126 $C7B6 Interprets character codes less than 32 52031 $CB3F Switches 80-column screen to reverse mode (ESC R}
51162 $C7DA Handles color change characters 52040 SCB48 Switches 80-column screen to normal mode (ESC N)
51190 $C7F6 Calls control code execution routines 52050 $CB52 Moves the cursor past the last character on the cur-
51202 $C802 Interprets character codes greater than 127 rent logical line (ESC K)
51220 $C814 Handles character codes 128-159 52056 $CB58 Reads character and attribute at current cursor
51284 $C854 Handles cursor right character, CHR$(29) position
51290 $C85A Handles cursor down character, CHR$(17) 52084 $CB74 Tests whether a line is linked
51293 $C85D Checks whether cursor moved onto a new logical line 52097 $CB81 Links or unlinks the current screen line
51303 $C867 Handles cursor up character, CHR$(145) 52101 $CB85 Unlinks a screen line
51317 $C875 Handles cursor left character, CHR$(157) 52115 $CB93 Links a screen line
51328 $C880 Handles switch-to-lowercase character, CHR$(14) 52127 $CB9F Calculates offsets into the line link bitmap
51346 $C892 Handles switch-to-uppercase character, CHR${142) 52145 $CBB1 Moves the cursor to the start of logical line (ESC J)
51366 $C8A6 Handles case switching disable character, CHR$(11) 52163 $CBC3 Finds the position of the last character in a line
51372 $C8AC Handles case switching enable character, CHR$(12) 52205 SCBED Moves the cursor one position to the right
51379 $C8B3 Handles cursor home character, CHR$(19) 52224 $CC00 Moves the cursor one position to the left
51391 $C8BF Handles reverse off character, CHE${146) 52254 $CC1E Stores the cursor position for later restoration
51394 $C8C2 Handles reverse on character, CHR$(18) 52263 $CC27 Prints a space
51399 $C8C7 Handles underline on character, CHR$(2) 52271 $CC2F Displays a character using the current attribute
51406 $C8CE Handles underline off character, CHR$(130) 52274 $CC32 Displays a character using the previous attribute
51413 $C8D5 Handles flash on character, CHR$(15) 52276 SCC34 Displays a character at the current cursor position
51420 $C8DC Handles flash off character, CHR$(143) 52315 $CC5B Returns height and width of current screen window
51427 $C8E3 Handles insert character, CHR$(148) 52330 $CC6A Reads or sets the current cursor position
51483 $C91B Handles delete character, CHR$(20} 52386 $CCA2 Defines a programmable function key
51506 $C932 Restores the cursor row and column positions 52512 SCD20 Calculates the offset to the start of key definition
51517 SC93D Deletes a character in a logical line string
51535 $C94F Handles tab character, CHR$(9) 52524 $CD2C Changes screen displays (ESC X)
51553 $C961 Handles clear/set tab stop character, CHR$(24) 52526 $CD2E Switches active screen displays
51564 $C96C Tests tab stop bit for current cursor position 52567 $CD57 Sets cursor position on 80-column screen
51584 $C980 Clears all tab stops (ESC Z) 52591 $CD6F Turns cursor on
51587 $C983 Sets default tab stops (ESC Y) 52639 $CD9F Turns cursor off
51598 $C98E Handles bell character, CHR$(7) 52682 $CDCA Writes a byte value to SO-column chip memory
51633 $C9B1 Handles line feed character, CHR$(10) 52684 $CDCC Writes to an 80-column chip register
51646 $C9BE Handles ESC sequences 52696 $CDD8 Reads a byte value from 80-column chip memory
51678 $C9DE Table of ESC key dispatch addresses 52698 $CDDA Reads from an 80-column chip register
51732 $CA14 Defines the upper left corner of the window (ESC T) 52710 $CDE6 Sets the current address in 80-column screen memory
51734 $CA16 Defines the lower right comer of the window (ESC B) 52729 $CDF9 Sets the current address in 80-column attribute
51739 $CA1B Sets window boundaries memory
51748 $CA24 Resets the window to full screen size 52748 $CE0 Initializes character definitions for BO-column screen
51773 $CA3D Inserts a blank line (ESC I) 52812 $CE4C Table of color character translation values
51794 $CA52 Deletes the current logical line (ESC D) 52828 SCE5C Table of 8563 color code translation values
51830 $CA76 Erases to the end of the current logical line (ESC Q) 52844 SCE6C Table of bit mask values
51851 $CA8B Erases to the start of the current logical line (ESC P) 52852 SCE74 Tables of default screen editor variables
51871 $CA9F Erases to the end of the window (ESC (a)} 52904 $CEA8 Table of standard function key definitions
51900 $CABC Scrolls the display up one line (ESC V) 52981-53247 $CEF5-$CFFF Unused
51914 $CACA Scrolls the display down one line (ESC W)
51938 $CAE2 Enables screen scrolling (ESC L)
51941 $CAE5
51946 $CAEA
Disables screen scrolling (ESC M)
Cancels autoinsert mode (ESC C)
Chapter 8: Hardware Chip Registers, Color RAM,
51949 $CAED Enables autoinsert mode (ESC A) and Character ROM
51954 $CAF2 Changes 80-column cursor to solid block (ESC S) VIC (40-Column) Video Chip Registers
51966 $CAFE Changes 80-column cursor to underline (ESC U) 53248 $D000 Sprite 0 horizontal position register
51979 $CB0B Disables cursor blinking (ESC E) 53249 $D001 Sprite 0 vertical position register
52001 SCB21 Enables cursor blinking (ESC F) 53250 SD002 Sprite 1 horizontal position register
53251 $D003 Sprite 1 vertical position register
680
681
53252 $D004 Sprite 2 horizontal position register 54281 $D409 Pulsewidth for voice 2 (low byte)
53253 $D005 Sprite 2 vertical position register 54282 $D40A Pulsewidth for voice 2 (high byte)
53254 $D006 Sprite 3 horizontal position register 54283 JD40B Control register for voice 2
53255 $D007 Sprite 3 vertical position register 54284 $D40C Attack/decay register for voice 2
53256 $D008 Sprite 4 horizontal position register 54285 $D40D Sustain/release register for voice 2
53257 $D009 Sprite 4 vertical position register 54286 $D40E Frequency register for voice 3 (low byte)
53258 $D00A Sprite 5 horizontal position register 54287 $D40F Frequency register for voice 3 (high byte)
53259 $D00B Sprite 5 vertical position register 54288 $D410 Pulsewidth for voice 3 (low byte)
53260 $D00C Sprite 6 horizontal position register 54289 $D411 Fulsewidth for voice 3 (high byte)
53261 $D00D Sprite 6 vertical position register 54290 $D412 Control register for voice 3
53262 $D00E Sprite 7 horizontal position register 54291 $D413 Attack/decay register for voice 3
53263 $D00F Sprite 7 vertical position register 54292 $D414 Sustain/release register for voice 3
53264 $D010 Sprites 0-7 horizontal position (most significant bits) 54293 $D415 Filter cutoff frequency (low byte)
53265 SD011 Control/vertical fine scrolling register 54294 $D416 Filter cutoff frequency (high byte)
53266 $D012 Raster scan line register 54295 $D417 Resonance/filter control register
53267 $D013 Light pen horizontal position 54296 $D418 Volume/filter mode register
53268 $D014 light pen vertical position 54297 $D419 Potentiometer 0 reading
53269 $D015 Sprite enable register 54298 $D41A Potentiometer 1 reading
53270 $D016 Control /horizontal fine scrolling register 54299 $D41B Voice 3 oscillator output
53271 $D017 Sprite vertical expansion register 54300 $D41C Voice 3 envelope generator output
53272 $D018 Memory control register MMU (Memory Management Unit) Chip Registers
53273 $D019 Interrupt flag register 54528 $D500 Configuration register
53274 $D01A Interrupt mask register 54529 $D501 Preconfiguration register A
53275 $D018 Sprite-to-foreground priority register 54530 $D502 Preconfiguration register B
53276 $D01C Sprite multicolor mode register 54531 $D503 Preconfiguration register C
53277 $D01D Sprite horizontal expansion register 54532 $D504 Preconfiguration register D
53278 SD01E Sprite-to-sprite collision register 54533 $D505 Mode configuration register
53279 $D01F Sprite-to-foreground collision register 54534 $D506 RAM configuration register
53280 $D020 Border color register 54535 $D507 Page 0 page pointer
53281 $D021 Background color (source 0) register 54536 $D508 Page 0 block pointer
532S2 $D022 Background color source 1 register 54537 $D509 Page 1 page pointer
53283 $D023 Background color source 2 register 54538 $D50A Page 1 block pointer
53284 $D024 Background color source 3 register 54539 $D50B MMU version register
53285 $D025 Sprite multicolor source 0 register Chip External Registers
VDC (80-column) Video
53286 $D026 Sprite multicolor source 1 register VDC address/status register
54784 $D600
53287 $D027 Sprite 0 color register VDC data register
54785 $D601
53288 $D028 Sprite 1 color register
53289 $D029 Sprite 2 color register VDC Chip Internal Registers
53290 $D02A Sprite 3 color register Total number of horizontal character positions
53291 $D02B Sprite 4 color register Number of visible horizontal character positions
53292 SD02C Sprite 5 color register 2 $02 Horizontal sync position
53293 $D02D Sprite 6 color register 3 $03 Horizontal and vertical sync width
53294 $D02E Sprite 7 color register i $04 Total number of screen rows
53295 SD02F Extended keyboard scan register 5 $05 Vertical fine adjustment
53296 $D030 Processor dock rate control register 6 $06 Number of visible screen rows
7 $07 Vertical sync position
SID (Sound Interface IDevice) Chip Registers Interlace mode control register
8 $08
54272 $D400 Frequency register for voice 1 (low byte) 9 $09 Number of scan lines per character
54273 $D401 Frequency register for voice 1 (high byte) 10 $0A Cursor mode control
54274 $D402 Pulsewidth for voice 1 (low byte) 11 SOB Ending scan line for cursor
54275 $D403 Pulse width for voice 1 (high byte) 12 $0C Screen memory starting address (high byte)
54276 SD404 Control register for voice 1 13 SOD Screen memory starting address (low byte)
54277 $D405 Attack/decay register for voice 1 14 $0E Cursor position address (high byte)
54278 $D406 Sustain/release register for voice 1 15 $0F Cursor position address (low byte)
54279 $D407 Frequency register for voice 2 (low byte) 16 $10 Light pen vertical position
54280 $D408 Frequency register for voice 2 (high byte) 17 $11 Light pen horizontal position
18 $12 Current memory address (high byte)
682 683
.
19 $13 Current memory address {low byte) Controller)
KEC (RAM Expansion Con in Chip Registers
20 $14 Attribute memory starting address (high byte) 57088 SDF00 Status register
21 $15 Attribute memory starting address (low byte) 57089 $DF01 Command register
22 $16 Character horizontal size control register 57090 $DF02 System RAM base address (low byte)
23 $17 Character vertical size control register 57091 $DF03 System RAM base address (high byte)
24 $18 Vertical smooth scrolling and control register 57092 $DF04 Expansion RAM base address (low byte)
25 $19 Horizontal smooth scrolling and control register 57093 $DF05 Expansion RAM base address (high byte)
26 $1A Foreground/background color register 57094 $DF06 Expansion RAM bank
27 $1B Address increment per row 57095 $DF07 Count of bytes to transfer (low byte)
2$ $1C Character set address and memory type register 57096 $DF08 Count of bytes to transfer (high byte)
29 $1D Underline scan line position register 57097 $DF09 Interrupt mask register
30 $1E Number of bytes for block write or copy Address control register
Memory read/write register 57098 $DF0A
31 $1F
32 $20 Block copy source address (high byte) 53248-57343 $D000-$DFFF Character pattern ROM (bank 14)
33 $21 Block copy source address (low byte)
34 $22 Beginning position for horizontal blanking Chapter 9: Kerna
$23 Ending position for horizontal blanking
as
36 S24 Number of memory refresh cycles per scan line 57344 $EO00 Performs power-on/reset sequence
57419 $E04B Table of default MMU register settings
55296 $D800 VIC color memory (two blocks) 57430 $E056 Restores Kemal indirect vectors to their default values
57435 $E05B Loads or copies Kernal indirect vector values
CIA (Complex Interface Adapater)
Ada] Chip #1 Table of default Kernal indirect vector values
57459 E073
56320 $DC00 Port A data I/O register 57491 $E093 Initializes zero page and Kemal pointers
56321 $DC01 Port B data I/O register 57549 $E0CD Initializes all RAM-resident Kernal routines
56322 SDC02 Port A data direction register 57609 $E109 Initializes I/O chip registers
56323 SDC03 Port B data direction register 57820 $E1DC Initializes 80-column video chip registers
56324 $DC04 Timer A latch/counter (low byte) 57840 $E1FO Initializes or jumps through the soft reset vector
56325 $DC05 Timer A latch/counter (high byte) 57892 $E224 Initializes the soft reset vector
56326 $DC06 Timer B latch/counter (low byte) 57922 $E242 Checks for the presence of 64 cartridges or 128 func-
56327 $DC07 Timer B latch/counter (high byte) tion ROMs
56328 $DC08 Time-of-day dock (1/10 seconds) 57931 $E24B Switches the system into 64 mode
56329 $DC09 Time-of-day clock (seconds) 57963 $E26B Logs 128 function ROMs
56330 $DC0A Time-of-day Hock (minutes) 58052 $E2C4 Initialization test pattern
56331 $DC0B Time-of-day clock (hours) 58055 $E2C7 Table of default VIC chip register values
56332 $DC0C Serial data register 58104 $E2FS Table of default 8563 chip register values
56333 SDCOD Interrupt control register 58171 $E33B Sends TALK command to a serial device
56334 $DC0E Control register A 58174 $E33E Sends LISTEN command to a serial device
56335 $DC0F Control register B Sends buffered byte to a serial device
58252 $E38C
CIA (Complex Interface Ada] 58430 $E43E Reads a byte from a serial device
58578 $E4D2 Sends secondary address after LISTEN
56576 $DD00 Port A data I/O register Allows the serial bus ATN output line to go high
56577 $DD01 Port B data I/O register 58583 $E4D7
58592 $E4E0 Sends secondary address after TALK
56578 SDDO2 Port A data direction register Performs talk-listen turnaround
56579 $DD03 Fort B data direction register 58601 $E4E9
58627 $E503 Sends a byte to a serial device
56580 $DD04 Timer A latch/counter (low byte) Sends UNTALK command to a serial device
56581 $DD05 Timer A latch/counter (high byte) 58645 $E515
58662 $E526 Sends UNLISTEN command to a serial device
56582 $DD06 Timer B latch/counter (low byte) Allows serial bus CLK output line to go high
56583 $DD07 Timer B latch/counter (high byte) 58693 $E545
58702 $E54E Fulls serial bus CLK output line low
56584 $DD08 Time-of-day clock (1/10 seconds) Allows serial bus DATA output line to go high
56585 $DD09 Time-of-day clock (seconds) 58711 $E557
58720 $E560 Pulls serial bus DATA output line low
56586 $DD0A Time-of-day clock (minutes) Reads the serial bus DATA and CLK input lines
56587 $DD0B Time-of-day clock (hours) 58729 $E569
58739 $E573 Disables IRQ interrupts and standardizes timing dur-
56588 $DD0C Serial data register ing I/O operations
56589 $DD0D Interrupt control register
Control register A 58783 $E59F Reenables interrupts and restores clock mode after
56590 $DD0E I/O operations
56591 $DD0F Control register B
I/O Expansion Slot #1 58812 $E5BC Performs fast serial turnaround
56832-57087 $DE00-$DEFF
57088-57343 I/O Expansion Slot #2 58819 $E5C3 Sets serial device for fast serial input
$DF00-$DFFF
684 685
58838 SE5D6 Sets serial device for fast serial output 61128 $EEC8 Handles FLAG interrupts for tape
58875 $E5FB Sets serial device for fast serial input or output 61136 $EED0 Controls tape motor interlock
58879 $E5FF Prepares next bit for RS-232 transmission 61163 $EEEB Retrieves a byte from the current input device
58907 $E61B Prepares parity and stop bits 61190 $EF06 Accepts a byte from the current input device
58948 $E644 Prepares to send a stop bit 61224 $EF28 Accepts a byte from tape
58954 $E64A Prepares to transmit next byte 61276 $EF5C Accepts a byte from a serial device
59007 $E67F Sets CIA interrupt register and RS-232 activity flag 61287 $EF67 Accepts a byte from RS-232
59022 $E68E Computes bit count for the RS-232 operation 61305 $EF79 Sends a byte to the current output device
59037 $E69D Processes received bits 61332 $EF94 Sends a byte to tape
59058 $E6B2 Tests for stop bit 61367 $EFB7 Sends a byte to the RS-232 port
59074 $E6C2 Prepares to receive next byte 61373 SEFBD Opens a logical file to a specified device
59092 SE6D4 Tests for start bit 61430 $EFF6 Opens a file for input or output to tape
59103 $E6DF Stores received character in buffer and checks parity 61504 JF040 Opens a file for RS-232 communications
59177 $E729 Handles CKOUT for RS-232 device 61616 $F0B0 Sets up CIA #2 ports for RS-232 communications
5922B $E75C Handles BSOUT for RS-232 device 61643 $F0CB Opens a file for serial bus communications
59285 $E795 Handles CHKIN for RS-232 device 61702 $F106 Sets the current input file for GETIN and BASIN
59342 $E7CE Handles GETIN for RS-232 device 61735 $F127 Prepares a serial device file for input
59372 $E7EC Disables RS-232 activity during tape or serial bus 61772 $F14C Sets the current output file for BSOUT
operations 61805 SF16D Prepares a serial device file for output
59397 $E805 Handles NMI interrupts for RS-232 61832 $F188 Closes a specified logical file
59472 $E850 Table of baud rate timing constants for NTSC 61S65 $F1A9 Closes a tape file
systems 61903 $F1CF Closes a file on a serial device
59492 $E864 Table of baud rate timing constants for PAL systems 61924 $F1E4 Removes an entry from the logical file tables
59512 $E878 Reads a bit from RS-232 device 61954 $F202 Checks whether a file is already open
59561 $E8A9 Initiates reception of RS-232 byte 61970 $F212 Loads parameters for a logical Sle
59600 $E8D0 Reads next header block from tape 61986 $F222 Clears file table entries
59673 $E919 Writes a header block to tape 61990 $F226 Resets default I/O channels
59776 $E980 Loads and tests cassette buffer address 62013 $F23D Closes all open files for a specified serial device
59783 $E987 Sets buffer address as block address 62053 $F265 Loads or verifies a program file from disk or tape
59802 $E99A Searches for a specified header 62075 F276 Loads or verifies a file from a serial device
59838 SE9BE Checks for cassette buffer filled or emptied 62246 $F326 Loads or verifies a program file from tape
59848 $E9C8 Requests PLAY button if necessary 62369 $F3A1 Attempts to set up fast serial load or verify
59871 $E9DF Checks tape buttons 62442 $F3EA Loads or verifies a file using fast serial burst mode
59881 $E9E9 Requests RECORD and PLAY buttons if necessary 62616 $F496 Handles read error during burst mode load/verify
59890 $E9F2 Reads next header or data block from tape 62630 $F4A6 Stops burst mode load/verify if RUN/STOP key
59899 $E9FB Reads or verifies a block from tape pressed
59925 $EA15 Writes a header or data block to tape 62642 SF4B2 Aborts burst mode load/verify if maximum address
59928 $EA18 Writes a block to tape exceeded
59942 $EA26 Initiates tape I/O operation 62650 SF4BA Reads a byte using fast serial hardware
60047 $EA8F Checks for RUN/STOP keypress during tape 6266] SF4C5 Loads or verifies a block of data using burst mode
operations 62723 $F503 Toggles state of serial bus CLK line
60065 $EAA1 Sets timer A to check FLAG interrupts 62735 SF50F Displays SEARCHING FOR message
60139 $EAEB Reads or verifies a block of data from tape 62771 $F533 Displays LOADING or VERIFYING message
60753 $ED51 Loads working pointer with starting address 62782 SF53E Saves a block of memory to tape or disk
60762 $ED5A Initializes tape variables between each byte 62817 $F561 Saves a block of memory to a serial device
60777 $ED69 Initiates writing of a tape half-dipoie 62878 SF59E Closes a file on a serial device
60816 $ED90 Writes a block of data to tape 62901 $F5B5 Aborts LOAD or SAVE to serial device
60974 $EE2E Writes a leader to tape and prepares to write a data Displays SAVING message and filename
62908 $F5BC
block 62920 $F5C8 Saves a block of memory to tape
61015 $EE57 Restores IRQ vector and operating modes after tape 62968 $F5F8 Updates jiffy timers and checks RUN/STOP key
operation column
61077 $EE95 Ends tape write interrupts 63037 $F63D Scans RUN/STOP key column
61083 $EE9B Loads IIRQ vector for tape operation 63070 $F65E Reads the software jiffy clock
61104 $EEB0 Turns cassette motor off 63077 $F665 Sets the software jiffy clock
6U11 $EEB7 Tests whether ending address has been reached 63086 $F66E Tests for a RUN/STOP keypress
61121 $EECI Increments the working pointer 63100 Handles Kemal I/O errors
$F67C

686 687
63152 $F6B0 Table of Kernal control messages
63262 $F71E 65369 $FF59 Entry point for the Kernal LKUPLA routine
Handles Kemal control messages Entry point for the Kernal LKUTSA routine
63281 $F731 65372 $FF5C
Sets the length and address of filename for I/O $FF5F Calls the screen editor SWAPPER routine
65375
63288 SF738 operations 65378 $FF62 Calls the screen editor INIT80 routine
Sets logical file number, device number, and second- 65381 $FF65 Calls the screen editor KEYSET routine
ary address for I/O operations $FF68 Entry point for the Kemal JSETBNK routine
63295 $F73F Sets data and filename banks for I/O operations 65384
63300 $F744 65387 $FF6B Entry point for the Kemal GETCFG routine
Reads the tape/serial or RS-232 status byte $FF6E Entry point for the Kernal JSRFAR routine
63324 $F75C Sets the Kemal message control flag 65390
63327 $F75F 65393 $FF71 Entry point for trie Kemal JMPFAR routine
Sets the IEEE timeout flag $FF74 Entry point for the Kemal INDFET calling routine
63331 $F763 Sets or reads the system's top-of-memory pointer 65396
63346 $F772 65399 $FF77 Entry point for the Kemal INDSTA calling routine
Sets or reads the system's bottom-of-memory pointer Entry point for the Kemal INTJCMP calling routine
63361 $F781 Returns base address of I/O block 65402 $FF7A
63366 $F?86 65405 $FF7D Entry point for the Kemal PRIMM routine
Checks whether a secondary address value is used Calls the screen editor CINT routine
63389 $F79D Checks whether a logical file number value is used 65409 $FF81
63397 65412 $FF84 Entry point for the Kernal IOINIT routine
$F7A5 Performs a DMA operation Entry point for the Kemal RAMTAS routine
63406 $F7AE Retrieves a character from the current filename 65415 $FF87
63420 65418 $FF8A Entry point for the Kemal RESTOR routine
$F7BC Writes a byte value to memory Entry point for the Kemal VECTOR routine
63423 $F7BF Writes a byte value to memory 65421 SFF8D
63433 65424 $FF90 Entry point for the Kemal SETMSG routine
$F7C9 Reads a byte value from memory Entry point for the Kemal SECOND routine
63436 $F7CC Reads a byte value from memory 65427 $FF93
65430 $FF96 Entry point for the Kemal TKSA routine
63440 $F7D0 Retrieves a character from any bank Entry point for the Kemal MEMTOP routine
63450 $F7DA Stores the accumulator contents in any bank 65433 $FF99
65436 $FF9C Entry point for the Kernal MEMBOT routine
63459 $F7E3 Compares the accumulator contents with a value Calls the screen editor SCNKEY routine
from any bank 65439 $FF9F
65442 $FFA2 Entry point for the Kemal SETTMO routine
63468 $F7EC Translates a bank number into an MMU register Entry point for the Kemal ACPTR at routine
setting 65445 $FFA5
65448 $FFA8 Entry point for the Kemal C1OUT routine
63472 $F7F0 Table of MMU register settings for standard banks Entry point for the Kemal UNTLK routine
63488 $F800 65451 $FFAB
Code for Kemal RAM-based subroutines $FFAE Entry point for the Kemal UNLSN routine
63591 $F867 65454
Initializes function ROMs and attempts to boot a disk 65457 $FFB1 Entry point for the Kemal L1STN routine
in the default drive 65460 $FFB4 Entry point for the Kernal TALK routine
63632 SF890 Attempts to boot a disk Entry point for the Kemal READSS routine
63883 $F98B 65463 $FFB7
Resets the disk drive $FFBA Entry point for the Kemal SETLFS routine
63923 $F9B3 65466 Entry point for the Kemal SETNAM routine
Loads additional b< Jt sectors 65469 $FFBD
63995 $F9FB Converts a byte value into two ASCII digits Entry point for the Kemal OPEN routine
64008 $FA08 65472 $FFC0 Entry point for the Kemal CLOSE routine
Table of disk commands for booting 65475 $EFC3
64023 $FA17 Handles PRIMM (print immediate) function Entry point for the Kemal CHKIN routine
64064 $FA40 65478 $FFC6 Entry point for the Kernal CKOUT routine
Handles NMI interrupts 65481 $FFC9
64101 $FA65 Handles IRQ interrupts Entry point for the Kemal CLRCH routine
64128 $FA80 65484 $FFCC Entry point for the Kemal BASIN routine
Standard keyboard decoding tables 65487 $FFCE
M M U (Memory Management Unit) Chip Registers Entry point for the Kernal BSOUT routine
65490 $FFD2 Entry point for the Kemal LOAD routine
65280 5FF00 Configuration register 65493 $FFD5
65281 $FF01 Load configuration register A Entry point for the Kemal SAVE routne
65496 $EFD8 Entry point for the Kemal SETT1M routine
65282 $FF02 Load configuration register B 65499 $FFDB
65283 $FF03 Load configuration register C Entry point for the Kernal RDTIM routine
65502 $FFDE Entry point for the Kernal STOP routine
65284 $FF04 Load configuration register D 65505 $FFE1
65285 $FF05 Jump to NMI handler routine Entry point for the Kemal GETIN routine
65508 $FFE4 Entry point for the Kemal CLALL routine
65303 $FF17 65511 $FFE7 Entry point for the Kemal UDTIM routine
Jump to IRQ or BRK handler routine 65514 $FFEA
65331 $FF33 Common exit routine for all interrupt routines Calls the screen editor SCRORG routine
65341 SFF3D 65? 17 $FFED Calls the screen editor PLOT routine
Jump to reset handler routine 65520 $FFF0
65351 $FF47 Entry point for the Kemal SPIIsLSPOUT routine Entry point for the Kernal IOBASE routine
65354 $FF4A 65523 $FFF3 Soft reset vector (bank 1)
Entry point for the Kemal CLOSF_J\LL routine 65528 $FFF8
65357 $FF4D Entry point for the Kemal C64—MODE routine Processor NMI vector
65360 $FF50 65530 $FFFA Processor reset vector
Entry point for the Kema! DMA_CALL routine 65532 SFFFC
65363 $FF53 Entry point for the Kemal BOOT_CALL routine Processor BRK/IRQ vector
65366 65534 $IH1:
SFF56 Entry point for the Kemal PHOENIX routine
688 689
H ere's the complete guire to understanding the inner
workings of the Comrodore 128. Collected in this one
volume are the answe's to practically any questions you
might have about thy -vav +he Commodore 128 operates.
Moreover, the information presented here isn't just edu-
cational—it has tremendous practical value as well. Increas-
ing your understanding of how the computer operates puts
you more fully in control. Whether you program in BASIC or
machine language, or whether you are just starting out or
are an expert programmer, you'll find that this book unlocks
secrets of the 128 that will allow you to write more powerful
and more sophisticated programs. Inside you'll find:
• A complete reference to BASIC, the Kerndl, the screen edi-
tor, even the machine language monitor. Not just a list of
addresses, but detailed discussions of all the important ROM
routines.
« Thorough descriptions of all the video, sound, and Interface
chips—VIC, SID, VDC, MMU, CIA, and REC. Every register of
every chip is explained in detail.
• A clear and straightforward explanation of how the 128's
elaborate memory management system operates, and how
you can create your own custom memory configurations.
• Hundreds of suggestions and hints on how to take full ad-
vantage of the 128's enhanced capabilities.
- Examples of ways you can modify and improve the per-
formance of your computer, including how to add new
statements to BASIC and how to customize Kernal functions.
• Explanations of the bugs in BASIC and the Kernal, and how
to avoid them.
If you've mastered the fundamentals of your 128 and are
seeking to expand your knowledge of this powerful, versatile
system. Mapping the Commodore 128 can be your guide, If
you're a veteran programmer who moved up to the 128
after years of experience on an older Commodore model,
this book will help you adapt your established techniques to
your new machine. For advanced programmers. Mapping
the Commodore 128 provides a wealth of ideas for exciting
new programming projects, Much of the information gath-
ered here is available elsewhere only in bits and scraps, if at
all. You'll want to keep a copy close at hand every time you
turn on your 128,

ISBN 9-87455-060-2

You might also like