WESEfiI
SOFTWARE SERIES
Atari Assembly Language
Programmer's Guide
by
Allan E. Moose
Marian J. Lorenz
Weber Systems, Inc.
Chesterland, Ohio
The authors ha ve exercised due care in the preparation of this book and
the programs contained in it. The authors and the publisher make no
warranties either express or implied with regard to the information and
programs contained in this book. I n no event shall the authors or publisher be
liable for incidental or consequential damages arising out of the furnishing,
performance, or use of this book andl or its programs.
Atari 400', Atari 800 '". Atari 800XL'. Atari 130X E'. and Atari TOLich Table +'. arc
trad emark s or Atari Cor poration. Koala Pad' is a trademark o r Koala T ec hnologi es In c.
Published by:
Weber Systems, Inc.
8437 Mayfield Road
Chesterland, Ohio 44026
(2 I 6)729-2858
For information on translations and book distributors outside of the
United States, please contact WSI at the above address.
Atari Assembly Language Programmer's Guide
Copyright 1986 by Allan Moose and Marian Lorenz. All rights
reserved under International and Pan-American Copyright Conventions.
Printed in the United States of America. No part of this publication may be
reproduced, stored in a retrieval system, or transmitted in any form or by any
means, electronic, mechanical , photocopy, recording, or otherwise without
the prior written permission of the publisher.
Contents
List of Boxes
List of Figures
List of Tables
Preface
Introduction
7
9
11
13
15
1. Number Systems and Hardware
21
22
22
Decimal Number Systems
Binary System
Hexadecimal System
Codes
CPU
ANTIC, GTIA , POKEY, PIA
Overview of Memory
31
35
36
40
41
2. Overview of 6502 Instructions
45
Instructions by Function
Addressing Modes
48
55
3. Atari Graphics ____________________________ 63
TV Op eration
ANTIC
Display Modes
Display Lists
Page Flipping
Color
Artifacting
Character Set Graphics
ANTIC Modes 4 and 5 _ _ _ _ _ _ _ _ _ _ _ _ _ __
Player Missile Graphics
Coil i sions/ Priority
4. Getting Started In Machine Language
Programming
64
66
72
76
95
97
106
107
112
115
129
135
Di splay List Interrupts
136
Program Listing Conv entions _ _ _ __ _ _ _ _ _ ___ 149
USR
151
Strings _ _ _ _ __ _ _ __ _ _ _ _ __ _ _ _ __ 152
Branching _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ ___ 161
Parameter Passing
Arithmetic Instructions _ _ _ _ _ _ _ _ _ _ _ _ _ __
Two 's Complement Arithmetic _ _ _ _ _ _ _ __ _ __
AND , ORA , LSR
5. Sound
A Bit of Theory
Sound Hardware
Program Examples
Si xteen-Bit Music _ __ _ _ _ _ _ _ _ _ _ __ __ _
6. Advanced Techniques
The Vertical Blank Routin es
Scrolling
162
168
169
171
179
180
189
197
224
229
230
235
Vertical Scrolling
Horizontal Scrolling
Diagonal Scrolling
Vertical Blank Music
237
249
257
Touch Tablet
260
274
Appendices
281
An Atari Disassembler
Memory Map
ATASCII Codes
Instructions and Flags
Decimal Values for the 6502 Instructions
281
283
293
301
309
319
321
Musical Note Values
325
Summary of I nstruction Set
An Atari Assembler
Index
329
Li st of Boxes
1
2
3
4
5
6
7A
7B
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
25A
Flags
Memory Allocation
AND-OR-EOR
Program - Display List Dump
Program - Position Concepts
Program - Modified Graphics 8
Program - Mode 4 Display List
Program - Antic Mode 4 with Rocket
Program - Antic Mode 14 Display List
Program - Page Flipping
Program - POKEing in Colors
Program - Two Methods of Displaying
Program - Artifacting
Utility - BASIC Character Generator
Program - Redefined Character
Utility - Multicolored Character Generator
Program - Light Bulb Player
Program - Collision
Program - Display List Interrupt
Program - Display List Interrupt
Program - Display List Interrupt
Program - DLI Color Table
Program - USR , Strings
Notation/ Listing for Machine Language
Assembly Language Listing - MOV$
Assembly Language Listing - REDEF$
Assembly Language Listing - REDEF$ (256 bytes)
39
42
54
79
86
87
92
93
96
97
103
105
107
110
113
116
129
132
137
140
143
146
153
154
157
158
159
8 Atari Assembly Language Programmer's Guide
25B
26
27
28
29
30
31
31A
32
32A
33
33A
34
34A
35
35A
36
36A
37
38
38A
39
39A
40
40A
41
42
42A
42B
42C
43
43A
43B
44
44A
45
45A
45B
46
46A
47
Assembly Language Listing - REDEF$ (512 bytes)
Program - Moving Player
Assembly Language Listing - Moving Player
Program - Moving Missile
Assembly Language Listing - Moving Missile
Utility - Sound Effects Generator
Program - Sound Envelope
Assembly Language Listing - Sound Envelope
Program - Tremolo
Assembly Language Listing - Tremolo
Program - Vibrato
Assembly Language Listing - Vibrato
Program - Volume Only
Assembly Language Listing - Volume Only
Program - Volume with Frequency Variation
Assembly Language Listing - Box 35
Program - Waveform
Assembly Language Listing - Waveform
Utility - Music Data Generator
Program - Three Blind Mice (music)
Assembly Language Listing - Three Blind Mice
Program - Three Blind Mice with Chords
Assembly Language Listing - Three Blind Mice
Program - 16-Bit Music
Assembly Language Listing - 16-Bit Music
Machine Language Routine for VB Link
Program - Vertical Scrolling
Assembly Language Listing - CLEAR$
Assembly Language Listing - SUB$
Assembly Language Listing - Vertical Scroll
Program - Horizontal Scrolling
Assembly Language Listing - Horizontal Scroll
ML$ Listing
Program - Diagonal Scrolling
Assembly Language Listing - Diagonal Scrolling
Program - Finale (Scrolling/Music)
Assembly Language Listing - Finale Scrolling
Assembly Language Listing - Finale Music
Program - Reading the Atari Touch Tablet
Assembly Language Listing - Touch Tablet
Program - Atari Touch Tablet Music
160
164
166
173
174
193
198
199
201
202
204
205
208
209
210
211
214
215
216
218
219
221
222
225
226
233
238
240
241
243
253
255
256
257
259
264
267
272
276
277
278
List of Fi g ures
2-1
3-1
3-2
3-3
3-4
3-5
3-6
3-7
3-8
3-9
3-10
3-11
3-12
3-13
4-1
4-2
5-1
5-2
5-3
5-4
5-5
5-6
6-1
6-2
6-3
Relative Addressing - Branching
TV Picture Sequence
Graphics 2 Full Screen
Graphics 3 Split Screen
Graphics 2 Display List
Modified Graphics 8 Display List - Plan
Graphics 8 Display List
From 'Scratch' Display List Planning
Character Data Bytes
Constructing a Character
Designing Antic Mode 4 Character
Data Bytes for Multi-colored Character
Player/ Missile Design
Memory Map - Player/ Missile Ram
Data Movement
Program Logic - Moving Missile
Sine Wave
Modulated Sine Wave
Sound Envelope
Wave Combinations
Square Wave
Triangle Wave
Vertical Blank Interrupt Routine
Vertical Scrolling
Vertical Fine Scrolling Process
59
65
73
75
78
81
83
89
108
109
114
115
126
127
155
178
180
182
182
183
186
187
231
246
248
List of Tabl es
1-1
1-2
1-3
1-4
2-1
3-1
3-3
3-4
3-5
3-6
3-7
3-8
3-9
3-10
3-11
3-12
3-13
5-1
5-2
5-3
6-1
6-2
Concept of Weighted Position
22
Powers of Two
22
Decimal, Binary, Hex - Comparison
31
Decimal Digits and their Binary Code
36
6502 Instruction Set
46
Bit Patterns of Display Modes
69
Pixel / Color/ Screen Memory Comparison
76
Display List Factors
77
Display List Memory Locations
80
Color Registers - Hardware/ Shadow
98
Color Values
100
Colors Available/ Default
101
ColorRegistersinBitPairs
114
Player/Missile Control Registers
121
Dual Function Hardware Registers
123
Collision Detection
130
Priority
134
Octave Frequencies
188
Sound Registers - Bit Settings
196
Typical Machine Language Cycle Times
207
Vertical Blank Memory Locations _ _ _ _ _ _ _ _ _ _ 234
Touch Tablet Switch Summary
279
11
Prefac e
Atari Assembly Language Programmer's Guide is written forthe
person who has had little or no experience with 6502 machine language
(machine language and assembly language are used interchangeably)
but who would like to incorporate machine language subroutines into
BASIC programs as well as for the intermediate programmer. The
preparation and organization of the book assumes that the reader has
a working knowledge of BASIC as the book is designed to build upon
that foundation. Bya working knowledge we mean that the reader is
familiar with FOR-NEXT Loops, PEEKS and POKES, setting up
strings, etc.
As you leaf through the book , you will notice that there is a good
deal of material included besides 6502 assembly language. The reason
is that we want the book to be useful for readers who want to tap the
unique graphics and sound capabilities of Atari Home Computers.
Since many of these features are available only through machine
language, we thought it appropriate to devote two chapters to graphics
and sound. These chapters serve to give you the background necessary
to put your new machine language programming abilities to maximum
use.
13
14 Atari Assembly Language Programme(s Guide
The concepts behind much of the material presented in these two
chapters is scattered throughout technical material published by Atari,
Inc. such as De Re Atari and The Technical Reference Notes or
maga7.ines such as Compute!, Antic, Analog, Byte, and the now
defunct Micro. However, the organization and presentation is our
own. Where different sources have been in conflict , we have done our
best to sort out the differences and present the most accurate
information available.
Wherever appropriate we have suggested short exercises and
practice problems to help you develop your skills and understanding.
Throughout the book we have illustrated programming instructions
and concepts with subroutines that will make something happen on
the screen. Many of these subroutines can be used, or modified for use ,
in your own programs . When you examine these subroutines it may
occur to you that they could be improved, or the tast programmed
differently. Generally, there is more than one way to program any
given job. A good way to learn is to modify someone else's program .
So fee l free to experiment! Active involvement is the best way to learn .
A final note to people who have some acquaintance with other
books on assembly language programming. You will notice that in this
book there is a marked lack of hexadecimal numbers. Machine
language subroutines that are called from BASIC must be written in
decimal numbers . Therefore, we believe that beginners to machine
language programming will experience less confusion at the start if
they use the more familiar decimal numbers wherever possible, rather
than having to continually switch back and forth between hex and
decimal. Once you are familiar with the instruction codes and
programming techniques you may want to acquire an assembler editor
cartridge and use hexadecimal numbers . But then you are no longer
the novice or intermediate programmer for whom this book was
written .
Introduction
It has become traditional to begin a book or article written for
machine language novices with the question: "Why machine language?" The answer to the question is two-fold. First, the traditional
answers. Then, more specifically, why Atari owners will find it
advantageous to learn machine language programming.
Traditional Answer Number One: SPEED
High level languages such as BASIC, PILOT, and LOGO are
relatively easy to learn and are convenient to use for programming.
But, for sheer speed nothing surpasses machine language. The reason
for this can be readily seen. The 6502 processor used by the Atari
operates at a rate of 1.79 million cycles per second. Depending on the
command, machine language instructions take between two and seven
cycles to execute. A ten step machine language subroutine that
averages four cycles per step will take .0000235 seconds to execute. In
more concrete terms: A program to redefine the Atari character set
and display a picture made from the new characters that takes fourteen
seconds to execute in BASIC can be executed in about haifa second in
15
16 Atari Assembly Language Programmer's Guide
machine language. As a general rule, machine language programs run
ten or more times faster that similar BASIC programs. Speed of this
nature is important in games, programming for real time situations, or
in educational programs where the pupil should not have to wait for
the computer to respond.
Traditional Answer Number Two:
"KNOWLEDGE IS POWER"
This aphorism first appeared in a brief treatise called, The Art of
War, written by Sun Tzu a round the fourth century B.c. Tzu proposed
that the application of the principle is broader than the waging of war.
Similarily, while learning to program in machine language you will
gain invaluable information about the internal workings of your Atari .
This knowledge is absolutely essential to getting the most from your
computer. Furthermore, it will enable you to "program smarter"
- more efficiently and more creatively.
Traditional Answer Number Three: FLEXIBILITY
If you program solely in a higher level language, such as those
mentioned above, you are to a large extent limited to the commands
chosen by the language authors . When you program in machine
language the potential of what you do is largely determined by your
imagination, experience and ability. For example, Atari BASIC has
no RENUMBER command, but it is possible to write a machine
language routine to renumber for you .
Traditional Answer Number Four: INTERFACING
If you decide you want to become a hardware hacker and use your
Atari to control the temperature and humidity of your greenhouse,
control household security, or use it for some other "real time"
a pplication, chances are that you will need to write a machi ne la nguage
control program.
More importantly an Atari Home Computer owner should learn
machine language because learning 6502 machine language will allow
Introduction 17
you to get the 111 0s t aU! o/rour A tari's sound and grap hics capabilities.
The designers of Atari Home Computers built an excellent machine
with probably the best sound and graphics capabilities of any
microcomputer presently on the market. Because of these unique
features , one canjustify calling it a seco nd generation microcomputer.
Many of its features such as display list interrupts, vertical blank
subroutines and dynamic music are not accessible from BASIC.
Others, such as, player-miss le movement, page flipping, and scrolling,
although accessible from BASIC. are most satisfactorily implemented
by machine language s ubroutines.
Through machine language the programmer can access many of
the internal registers used in sound a nd graphics generation. There any
many things that this accessibility will allow you to do. With machine
language subroutines you can play music while a display is being
created, or generate sounds that imitate musical instruments. Machine
language is absolutely essential for dynamic sound production. In
creating graphics, machine language allows you to change colors on
the fly, use different character se ts on different parts of the same
screen, achieve smooth animation, and smooth sc rolling, to mention a
few applications.
One of the first problems that confronts a beginner is the
profusion of bu zzwo rds , acro nyms and unfamiliar number systems.
Vectors, pointers, MSB's, LSB's, AUDCI, POKMSK, binary
numbers , hex numbers and other arcania slow down the learning
process . To ease the way, chapter I begins with a discussion of the
decimal , binary, and hexadecimal number system. The computer
works with binary numbers , experienced assembly language programmers work with hexadecimal numbers, and the rest of the world
uses decimal numbers. In writing programs and reading other people's
programs, you will need to be adept at converting from one system to
another. Chapter I will help you hone your skills in this area.
The discussion of the num ber syste ms is followed by an ov.e rview
of the 6502 architecture and its operation. Usually a beginning
programmer will not need to worry about counting machine cycles or
other such details. However, a general knowledge of the inner
workings of the central processor unit (CPU) is an important aid to
visualizing what the various machine language instructions do .
18 Atari Asse mbly Language Programme(s Guide
There a re two ways to lea rn to program : o ne ca njump in a nd start
programming, lea rning new instructions along the way , or o ne ca n
survey th e in structi o n se t before beginn in g to write progra m s. We have
opted fo r th e second cho ice. Therefore an overview of th e 6502
in structi on set is presented in chapter 2. S ince there a re 15 1 different
in struction cod es th at can be used wit h the 6502, we feel th at it is
advantageous to impose structure on this ma ss of information.
In struction s have been gro uped accord ing to fu nct io n because we
believe th a t this wi ll s implify th e mastery of the codes and he lp yo u
organize th e parts into a meaningful w hole.
M a ny of the pr ogramm in g examples will make use of th e A ta ri's
special graphics capabilities . Thus, you will be ab le t o see immediate ly
what each program acco m pli shes. F urthermore, yo u will be a ble to
incorporate the subr o utines int o your own programs. C ha pte r 3 is a
comprehensive d esc ripti on of Atar i graph ics in c luding displ ay li sts,
redefining characters, a nd playe r/ missile graphics. C hapter 3 is
des igned to prese nt grap hic s fundamentals a nd to be used as a
reference a id in your la t er programming. Add iti ona ll y, th e to pics in
this cha pter a re approached in suc h a way as to introduce so me of the
concepts under lying mac hin e language. For exam ple, in trea ting
ANTIC as a microprocesso r we st ress h ow bit patterns det e rmin e the
processo r's instructions.
Actual progra mmin g begins in chap ter 4 wi th short simple
examples . Severa l examples a re display li st inte rrupts - a n Atari
feature accessible only through mac hin e language. Other exa mples
include moving p laye rs verticall y a nd redefining c ha racter se ts. Rea d y
to run program s are provided to illustrate programming concepts a nd
techniques. Here and there short programming exercises a re sugges ted
to g ive you imm ed iate feedback on yo ur un de rstanding of these
concepts.
By the end of chapter four you sh ould have a pretty good g ras p of
the in struction set; yo u'll be writing sh ort ro utines and making thin gs
happen. In addition, while learni ng abo ut Atar i grap hics, yo u will
become familiar with me mory organization in the Atari . With this
background in hand, yo u will be prepa red to exp lore so me more o f the
Atari's spec ial capabilities such as vert ica l blank int e rrupt s, POKEY
and so und generation . These topi cs and their app licatio ns are covered
Introduction 19
in chapters 5 and 6.
As mentioned before, one of our goals has been to write a book
that includes useful reference material. For this reason we've included
boxes, charts, tables , and appendices that cover all the necessary
fundamentals. This material will serve as a handy resource when
programming. Two of the appendices deserve special mention.
Appendix C is a disassembler written in BASIC. This program allows
you to input the decimal numbers representing a machine language
routine: it will return the assembly language listing. This will be helpful
in taking apart and understanding someone else's machine language
routines. Appendix B is an assembler written in BASIC. This program
will be useful in writing longer machine language programs.
Programming examples are designed to be directly applicable to
your use and are designed to illustrate general principles rather than
programming tricks. The programs in this book have been tested and
run on Atari 800's , 800XL's and the new 65XE and 130 XE computers.
Some of the programs assume that you have 48K of RAM available.
They are easy to modify . Ready to use machine language subroutines
are included. These routines have been chosen to be useful to those
readers who want to work within the Atari off-the-shelf capabilities as
opposed to system programming or arithmetic routines. The materials
and techniques presented in this book should provide the reader with
the necessary background to be comfortable with assembly language
and therefore write more sophisticated programs .
In summary, Atari Assembly Language Programmer's Guide
presents the fundamentals of machine language programming as well
as the techniques for establishing and operating machine language
programs called from BASIC. It is, therefore, in one sense a textbook
and in another sense a practical handbook. Among its purposes is to
help the reader enjoy the best of both languages-BASIC and Machine
Language by providing the necessary tools.
1
Number Systems and Hardware
Introduction
Computers use binary numbers, professional assembly language
programmers use hexadecimal numbers, and the rest of the world uses
decimal numbers. When starting to learn assembly language programming
it is necessary to begin by learning how to convert from one number
system to another. Among the reasons for learning this skill is that
many machine language routines you will come across are written
using hexadecimal numbers. If you want to call these routines from
BASIC it will be necessary to convert the hexadecimal numbers to
decimal. The first section of this chapter will discuss the decimal,
binary, and hexadecimal number systems and the representation of
characters and numbers by number codes.
In many situations assembly language programmers do not
require a detailed knowledge of computer hardware in order to write
programs that work. However, it is necessary to know some basic facts
about the 6502 processor, the AT ARI's special sound and graphics
chips, and memory organization to aid you in visualizing how to
organize and write more effective machine language routines. These
topics will be covered in the second section of this chapter.
21
22 Atari Assembly Language Programme(s Guide
The Decimal Number System
The primary distinguishing feature of a number system is its radix
or base. The base of a number system is equal to the number of digits or
characters used. The decimal system, base 10, uses the ten digits:
0, I ,2,3,4,5,6,7 ,8,9. The binary system uses two digits : and I, while the
hexadecimal system uses sixteen characters: the digits through 9 and
the letters A,B,C,D,E,F. These number systems are called positional
or weighted systems because each digit or character has a value
assigned to it according to its position. Consider the decimal number
1729. The weights assigned to the individual digits are successive
powers of 10. Table I-I illustrates the concept of weighted position:
Table 1-1. Number System Weighted Position
POSITION NAME THOUSANDS
Powers of 10
Weight
1729
HUNDREDS
TENS
UNITS
10 3
10 2
10 '
10
1000
100
10
(1 x 1000)
(7x100)
+(2x100)+ (9x1)
The Binary System
It is apparent from Table I-I that in the decimal system counting
is done in powers of 10. On the other hand, in the binary system,
counting is done in powers of 2. Table 1-2 gives the first sixteen powers
of 2:
Table 1-2. Binary system powers of two
Power
2 '5
2 '4
2 13
2' 2
2 "
2 10
29
28
27
26
25
2 4
23
22
2'
Weight in
decimal
32768
16384
8192
4096
2048
1024
512 256
128
64
32
16
Number Systems and Hardware 23
Binary numbers are expressed as sequences of ones and zeros. For
example, let's look at the binary number 110 100 10. This number can
be related to its decimal equivalent as follows:
Power of 2:
Weight in
decimal:
27
26
25
2"
23
22
2'
128
64
32
16
Binary
Number:
Conversion
to decimal: (1 x128)+(1 x64 )+(O x32 )+( 1x16)+(Ox8)+(Ox4 )+(1 x2)+(Ox1)
= 210
Each digit in a binary number is called a bit. A group of 8 bits is
called a byte. The Atari computer represents numbers and characters
in bytes. The individual bits in a byte are sometimes referred to by their
position with the letter D and a subscript as in:
The left most bit of a byte (D?) is called the Most Significant Bit (MSB)
because it has the greatest weight or value. The right most bit (Do) is the
Least Significant Bit (LSB) because it has the smallest weight.
There are several ways to convert binary numbers to decimal. One
method is to write down the powers of two as we did for I 10 100 10 and
add together the weights wherever a I appears. Another scheme is to
write down the number and use the recursive rule:
(previous result) x base + (next digit) = result
24 Atari Assembly Language Programmer's Guide
Examples to Illustrate Recursive Rule
EXAMPLE 1:
Starting with 0 7 , there is no previous result so:
[previous result=0] x2 + [next digit(07=1)] = 1
[1\2] +
[~x2]
[~ext digit(06=1)] = 3
+ [next digit(05=0)] = 6
[6x2] + [next digit(04= 1)] = 13
[13x2] + [0 3 (=0)] = 26
[2rx2] + [0 2 (=0)] = 22
[52x2] + [0, (=1)] = 105
[1Ofx2] + 0 = 210 decimal equivalent
Number Systems and Hardware 25
Example 2:
128
64
32
16
{?O
(~~~)
(1 x2) + 1 :: 3
~
~=
(3x2) + 0 = 6
(6x2) + 1
13
(1~26
/
(2lX2) + 1 = 53
{5~'06
dedmal equivalent
26 Atari Assembly Language Programme(s Guide
Notice that the middle column of numbers is a sequence of 1's and O's
that matches the binary number. With a little practice, it is possible to
make the conversion shorter and do it in your head or with a
calculator.
MSB
LSB
o
2
o
5
11
23
46
93
186 (Decimal)
In each case the number in the second row was obtained by mUltiplying
the previous result by two and adding the digit above it. Remember
that the 'previous result' for the MSB is always zero . The recursive rule
of conversion has the advantage that it can also be used to convert
hexadecimal numbers into decimal.
Another way to convert binary numbers to decimal numbers is to
be consciously aware of digit patterns and number combinations. For
example, in decimal the binary number 11111111 is 255. The binary
number 11111110 is 255 minus I or 254. The number 11111101 is 255
minus 2 (2' is missing) or 253. Similarly 11000000 is 192 in decimal and
so 11000001 is easily seen to be 193. As you work with binary numbers,
more and more of these combinations will become familiar to you.
Taking note of them can save a lot of calculations in converting from
one system to another.
As an example of where you will use conversion from binary to
decimal, to produce a pure note on the Atari, it is necessary to store the
bit pattern 10100000 at one of four memory locations. Using anyone
of the conversion techniques discussed, you can easily convert this
binary number to its decimal equivalent, 160.
The largest number that can be represented in binary with 8 bits is
255 decimal. With assembly language it will be necessary to represent
numbers as large as 65535. This is accomplished by using two bytes for
a total of 16 bits. Referring back to Table 1-2 you can see that the
largest number that can be expressed with two bytes is:
Number Systems and Hardware 27
Byte 1
r''''''--A....-_.,
11111111
Byte 2
r_ _ _ _A ...._
_.
....
11111111
32768+16384+8192+4096+2048+1024+412+256+128+64+32+16+8+4+2+1
~------------------------~I~I
=65355
____________~
Byte 1
Byte 2
The byte labeled as byte 1 is often called the Most Significant Byte
(MSB) or Hi-Byte. Byte 2 is called the Least Significant Byte (LSB) or
Lo-Byte. In order to avoid confusion with the most significant and
least significant bits, hereafter we will refer to bytes 1 and 2 as the
High-Byte and Lo-Byte respectively.
Situations in which you have to convert decimal numbers greater
than 255 to binary are rare . We will illustrate two ways to do the
conversion with 8 bit numbers. The principles are the same for larger
numbers . The first method is to use Table 1-2 and subtract powers of 2,
recording a 1 for each power used and a 0 for those powers you don't
use. For example, to convert 233 to binary proceed as follows:
22
27
24
23
26
25
2'
Power of 2:
2
Decimal Value:
Computation:
128
64
32
16
233
-123
105
105
--64
41
41
-32
9
9
-16
X
9
-8
- -4
- -2
- -1
0
0
0
The second way to convert decimal numbers to binary is to
repeatedly divide by two and record remainders. Starting with the
number, divide by 2 (see example below). If there is no remainder,
record a 0 as the LSB. Now divide the quotient and record the
remainder as the next bit. Continue until the quotient is zero.
Binary Equi:
28 Atari Assembly Language Programmer's Guide
Example 1 using 233:
Finish
Start
211
0
1
213
2
3
7
14
29
58
116
217 2[14 2129 2158 21116 21233
6
14
28
58 -116
232
-
Binary
Example 2 using 74:
2r1
0
1
2f2
2
2
2[4
4
4
2r9
8
9
2118
18
18
2m
36
37
2174
74
Number Systems and Hardware 29
In this case you "pad" the binary to 8 bits and write it as 01001010.
One of the most frequent calculations you will have is to convert a
decimal number into its Hi-Byte, Lo-Byte form where each byte is
written as a decimal number. Conceptually (not computationally!) this
is expressed as:
Dec ima l Number
Binary rBY,e
Binary Lo-Byte
Dec imal Equiva lent
Decimal Equivalent
An example using 53761 (one of those sound registers again):
53761
11010010
\
210
00000001
Binary
Decimal
30 Atari Assembly Language Programmer's Guide
Computationally this calculation is relatively simple: Divide the decimal
number by 256. The quotient is the Hi-Byte. The remainder is the
Lo-Byte.
210 . . . .f------~IHi-Byte
256153761
512
256
256
1 . . . .!--------,I Lo-Byte
Here is a place to do your long division!
Number Systems and Hardware 31
The Hexadecimal System
Use of the hexadecimal number system grew out of a need for
programmers to have a convenient way to write and think about
binary numbers without carrying around long sequences of 1's and O's.
In writing machine language routines to be called from BASIC, you
will use decimal numbers . However, the hexadecimal system is so
thoroughly entrenched in use that it is important to become familiar
with it as a part of your background knowledge. Hexadecimal
numbers take advantage of the fact that a byte is two groups of four
digits. A four bit number (sometimes called a nibble) can represent any
number from zero to fifteen. The digits to 9 are used as in the decimal
number system, but there are no single position symbols for the
equivalents to 10, 11 , 12, 13 , 14, and 15. The letters A,B,C,D,E, and F
are used so that hexadecimal numbers can be reproduced by a printer.
Table 1-3 compares the decimal, binary and hexadecimal systems.
Table 1-3. Decimal, binary, a nd hexa decimal systems.
DECIMAL
BINARY
HEX
0
1
2
3
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
0
1
2
3
4
5
5
6
7
8
9
10
11
12
13
14
15
6
7
8
9
A
B
C
D
E
F
32 Atari Assembly Language Programme(s Guide
Conversion of a binary number into hexadecimal is straight
forward. Separate it into its groups of four bits and write the hex
equivalent of each group:
10 1"
- ..
1
.... . \-1- 1--
= AF
or
Conversion from hexadecimal to binary is equally simple:
A9
1 01 0
1 00 1
9
A
Conversion from hexadecimal to decimal can be done using the
recursive rule [previous result*base]+[next digit]=result rule.
For example:
A9
[previous result(O)x16) + A(=10) = 1()
J
(lOx 16) + 9 = 169
For two digit numbers like this you'll shorten it to (l6x10) + 9 = 169.
But for numbers such as D20 I the rule is helpful :
0201
[previous result(=O)) + 0(=13)
= 13
(13 x 16) + 2 = 210
~
= 3360
(210 x 16) + 0
---------
(3360 x 16) + 1
= 53761
Number Systems and Hardware
33
Conversion of decimal numbers into hexadecimal numbers can
be accomplished by the repeated division procedure used earlier for
conversion from decimal to binary _ We'll illustrate the process with
some examples:
Example 1 - Convert 832 to its hexadecimal equivalent:
Start
Finish
o
1613
3
16152
48
4
832 (deCimal)
52
161832
80
32
32
= 340 (hexadecimal)
I
o
34 Atari Assembly Language Programmer's Guide
Example 2 Convert 54271 to its hexadecimal equivalent:
Finish
Start
16f13
0
13
13
16 f211
16
51
48
3
54271 (decimal)
211
1613391
32
19
16
31
16
15
3391
16154271
48
62
48
147
144
-31
16
15
= D3FF (hexadecimal)
At this point we s uggest tha t you complete the following
conversions for practice. These pra ctice problems have been chosen
from numbers that you will work with later on a nd are useful memory
locations or assembly la nguage codes.
A. Convert from decimal to Hi-Byte, La-Byte form:
1. 1536
2. 53768
3. 53762
4. 53249
5. 54282
6. 54286
7. 58466
Number Systems and Hardware 35
B. Convert from hexadecimal to decimal:
1.22F
2. 230
3. 26F
4. 2F4
5. D407
6. E45F
7. D20E
C. Convert from decimal to binary:
1.255
2. 198
3. 228
4. 195
5. 248
6.219
7. 63
Codes
As well as using the digits zero and one to represent numbers in
binary form, sequences ofO's and I 's can be used as codes to represent
characters, special symbols, and instructions to peripheral devices.
Such codes permit communication between the computer's central
processor unit (CPU) and the keyboard, TV screen, and printer.
One of the most common codes used in computers is the ASCII
Code (American Standard Code for Information Interchange). The
AT ARI uses a modified version of this code, called AT ASCII. The
two major differences between ASCII and AT ASCII are that the
former uses only 7 bits for each character or instruction code while
A T ASCII uses 8 bits and the AT ASCII code includes many special
graphics symbols. In fact AT ASCII makes use of all the numbers 0
through 255 while ASCII does not. This property of the AT ASCII
code will be very important later for it will allow you to store machine
language routines as strings in BASIC. Appendix E lists the A TASCII
code with its corresponding symbols and keystrokes. This listing is an
important resource in your work.
36 Atari Assembly Language Programmer's Guide
Another code that you will come across in assembly language
programming is Binary Coded Decimal, or BCD. The idea of BCD is
to use binary numbers to represent each digit of a decimal number.
Thus, the decimal number 469 is represented by:
o 1 00
01 1 0
00 1
9
The 6502 has instructions that will allow it to perform arithmetic
operations using either pure binary numbers or binary coded decimal
numbers. This is an advantage to programmers who are writing
systems and arithmetic routines. Table 1-4 lists the decimal digits and
their binary codes.
Table 1-4. Decimal / Binary eq uivalents
Decimal Digit
Binary Code
0000
0001
0011
0010
0100
0101
0110
0111
1000
1001
2
3
4
5
6
7
8
9
The Central Processor Unit
Unlike many other microcomputers, the Atari uses two processors,
the CPU and ANTIC. The central processor (CPU) is the 6502 and it
handles all data transfers , arithmetic and logic calculations. ANTIC
(Alpha-Numeric Television Interface Chip) is responsible for the
production of the TV display. In addition to these processors there are
three large scale integrated circuit chips that support the CPU and
ANTIC in communicating with the keyboard, TV screen and other
peripherals. They are POKEY and GTIA (CTIA in pre Dec. 1981
ATARI'S) and PIA.
Number Systems and Hardware 37
The 6502 is an 8-bit processor. This means that it handles data in
one byte units. The 6502 communicates with memory and peripherals
over three grou ps of wires called busses. Data travels in and out of the
CPU over an eight line data bus . Since there is one wire for each bit, a
whole byte is transferred from one place to another at once. This is
called parallel data transfer. The 6502 is a memory mapped microprocessor
which means it treats memory and peripherals on an equal basis.
Reading a byte of data in memory is, to the CPU , the same operation
as reading a byte of data sent out from a peripheral device, such as the
keyboard. Likewise writing or sending, a byte of data to memory or a
peripheral are equivalent operations. Both the CPU and the peripherals
or memory have to agree on whether a given data transfer is to be a
read or a write operation. Therefore , there is a control bus that carries
read/ write and other control signals from the CPU to external devices
and memory. Computer memory and peripheral input / output locations
are identified by number. The 6502 uses a 16 bit address bus and
consequently can identify 2 16 or 65356 different memory locations.
Internally the microprocessor has an arithmetic logic unit where
additions, subtractions and logical operations take place. There is a
control unit that decodes instructions and shifts data to and from
memory. Of primary importance to us are six special internal data
storage locations or registers. Five of these are 8 bit registers . The sixth
is a 16 bit register. The five 8 bit registers are the:
1. Accumulator
2. X-Register
3. V-Register
4. Processor Status Register
5. Stack Pointer.
The remaining register is the 16 bit program counter.
The functions of the registers are as follows:
1. The Accumulator: This is the busiest register in the CPU. It is
the only register where arithmetic and logic operations can be
performed. Data transfer from one memory location to another
usually goes through the accumulator.
38 Atari Assembly Language Programme(s Guide
2. The X and V Registers: These two registers are referred to as
index registers because one of their primary functions is to serve as a
kind of subscript or index used in addressing memory locations. The
contents of the X and Y-registers can be incremented or decremented
one unit at a time so they serve as very natural loop counters . In
addition the X and Y-registers can be used to transfer data between the
CPU and memory.
3. The Status Register: This register contains seven usable bits .
Two of the bits are control bits . The remaining five are status flags The
status flags provide information on the result of a previously executed
instruction (usually the preceding instruction). The 6502 can be
programmed to test the condition of each of these flags . Based on the
results of these tests, the 6502 can choose between two possible
sequences of instructions . The locations , labels, and functions of these
bits are described in Box 1.
4. The Stack Pointer: The stack is a special storage area in memory
at locations 256 to 511 (Page 1 of memory) . The stack works as a
last-in/ first-out storage area analogous to a stack of plates in a kitchen
cabinet. It is used to store information necessary to perform subroutine
calls and interrupts correctly. On power-up or after a reset, the stack
begins at address 511, which in Hi-Byte / Lo-Byte form is 01,255. The
stack pointer will, at this time, contain the byte 255, as data is stored or
removed on the stack, the stack pointer is incremented or decremented
so that it always gives the address of the next available stack location.
5. The Program Counter: Machine language instructions are
stored in memory in order by address. The program counter insures
that instructions are performed in the proper sequence . At any instant
the program counter contains the address of the next byte of the
program to be read .
Number Systems and Hardware 39
BOX1
D7
D6
Ds
D4
D3
D2
D,
Do
Note: If a flag is set, then there is a Logical 1 in that particular bit of the
status register. If a flag is clear, then there is a Logical 0 in that
particular bit of the status register.
C == Carry Flag. This bit is set when an addition, shift, or rotate
generates a carry. It is cleared when a subtraction or compare
produces a borrow.
Z == Zero Flag. This bit is set when the accumulator, the index
registers or a memory location contain all zeros as the result of an
instruction such as increment, decrement or the arithmetic and logical
instructions.
I == Interrupt Flag. This bit is set whenever an interrupt in the
normal processing occurs or when a Break (BRK) instruction is
executed. It is cleared whenever a Return from Interrupt (RTI)
instruction is executed.
D == Decimal Flag. This flag is used to signal the processor that
addition and subtraction are to be performed in the decimal mode
using BCD .
B == Break Flag. This flag is set, along with the I flag whenever a
BRK instruction is executed. It is cleared following an RTI instruction.
V == Overflow Flag. This flag is set when an addition or subtraction
prod uces a resu It greater than 127 or less than -128. It is used in
applications involving signed numbers.
N == Negative Flag. This flag indicates whether or not the result of a
signed arithmetic operation produced a negative result.
Box 1. Status flags
40 Atari Assembly Language Programmer's Guide
CPU Operation
A machine language program is nothing more than a series of
numbers stored as bytes in memory . When a computer is executing a
program it goes through a fundamental sequence that is repeated over
and over again. To execute a program , the CPU must fetch a byte,
decode its meaning, and execute the instruction. This fetch-decodeexecute sequence is repeated at very high speed until the program is
finished. The rate at which operations occur within the CPU, and their
sequence, is governed by a system clock that sends out electrical pulses
at the rate of 1.79 million cycles per second. One cycle per second is
a lso called one Hertz so you will often see this written as 1.79 MHz.
Instructions to the CPU are either one, two , or three bytes long. A
three byte instruction consists of a numeric code followed by two
address bytes. A typical two byte instruction is one code byte followed
by a number. A single byte instruction is simply a code byte to do some
task, for example, Return from Subroutine (RTS). CPU instructions
take from two to seven clock cycles to execute with most taking three
to four cycles. Occasionally it is necessary to time the length of a
subroutine in order to insure that it will be completed within a
specified time limit. Timing considerations will come up later when we
discuss display list interrupts.
Other Processors and Chips
By itself a CPU is limited in its capabilities for communicating
with the outside world . The inclusion offour support chips (integrated
circuits) in AT A RI computers provide a great deal of flexibility in
programming graphics and sound. Since a detailed description of how
to use these support chips is given in later chapters, we will provide
only an overview of their functions here.
1. ANTIC: The primary function of ANTIC is to fetch data from
memory and display it on the TV screen. ANTIC does this independently
of the CPU by sending a HALT signal that effectively disconnects the
CPU from the address and data busses . ANTIC is then free to use these
Number Systems and Hardware 41
busses to access the memory that it needs . This process is called Direct
Memory Access (DMA). ANTIC also controls the non-maskable
interrupts of the processor. A Non-Maskable Interrupt (NMI) is just
what its name implies - a signal to the CPU , which it cannot ignore, to
stop its current operations and go to another program . These
interrupts are useful in both sound and graphics programming.
2. GTIA: is a special television interface adaptor chip that works in
conjunction with ANTIC. Its primary purpose is the direct control of
the TV display . Thus it is responsible for controlling color and
luminance, playfield and player missile graphics, collisions and
priority.
3. POKEY: is a digital I / O chip that has a variety offunctions. One
of the foremost is sound generation . It is the keeper of the registers that
control the frequency and type of sound output. In addition POKEY
takes care of transmission of data from the keyboard and from the
serial communications port. Serial data transfer differs from the
parallel data transfer mentioned earlier in that data is transmitted one
bit at a time. Other functions of POKEY will be described in Chapter
Six.
4. PIA: is the Peripheral Interface Adaptor chip with the primary
responsibility for controlling data to and from the joystick ports . It is
used with any peripheral, such as paddles, joysticks, keypads, or the
Koala pad, that plugs into th ese ports .
Memory Organization: An Overview
The 6502 can address 65356 different memory locations and
treats Random Access Memory (RAM), Read Only Memory (ROM),
and peripherals in the same manner - as memory locations. A useful
concept in discussing memory is the idea of a page. A page in memory
is 256 bytes long. If a memory address is given in Hi-Byte / Lo-Byte
form, the Hi-Byte is the page number and the Lo-Byte is the address
within the page. To illustrate , in binary form , the first byte of page six
has the address 00000 II 0,00000000. In decimal Hi-Byte / Lo-Byte form
42 Atari Assembly Language Programmer's Guide
this is written as 6,0. As a single decimal number this is memory
location 1536. To find the page num ber of a memory address written as
a single decimal number divide that number by 256. The whole number
quotient is the page. The whole number remainder - not the decimal
fraction - is the address within the page. Occasionally we will refer to
"whole page boundaries" or "IK and 2K boundaries". A memory
location is said to lie on a one page boundary if its address is evenly
divisible by 256. A memory address lies on a I K or 2K boundary if its
address is divisible by 1024(1 K) or 2048(2K) respectively.
In the Atari computers, certain pages of memory are set aside for
use by the operating system (OS) and BASIC, while others are used
primarily for hardware registers. Which page is chosen for a particular
use depends in part on the design of the 6502 microprocessor and in
part on choices made by the Atari's designers. Two pages are especially
important to the 6502. These are page zero and page one. Page zero is
important because it can be accessed by the processor faster and more
easily than any other page. Page one is important because the 6502
uses it as the stack. Box 2 gives a summary of memory allocation. A
more detailed memory map is given in Appendix D.
BOX2
USE
LOCATION
65535
Used for the operating system
to
and
55296
Arithmetic Routines
55295
Hardware Registers
53248
ANTIC
PIA
POKEY
GTIA
53247
4K unused memory
to
54272
54016
53760
53248
54783
54271
54015
53503
to
40960
Box 2. Memory overview
BASIC or Left Cartridge
Number Systems and Hardware 43
-- -
40959
to
32768
Used for screen memory and
Display Lists. Amount used
depends on graphics mode
32767
User program RAM .
to
Location of the bottom depends
on presence or absence of DOS
and other factors
1791
to
1536
Page Six. Unused by as or
BASIC. May be used to store
machine language routines
1535
RAM used by BASIC
to
and
1152
Arithmetic routines
1151
to
512
as RAM . Contains shadow
registers used to update
hardware registers during
vertical blank
511
to
256
STACK Page 1
255
to
128
BASIC Page Zero
127
to
0
as Page Zero
Box 2. (cont.)
44 Atari Assembly Language Programmer's Guide
Machine Language Programming: Some Comments
Many of the machine language programming concepts
that will be discussed in later chapters are illustrated by sound and
graphics applications. Machine language programs
used in sound and graphics usually do one or more of three basic
operations:
1. Move massive amounts of data (500 to 1000 bytes) from
one place to another. An example is a routine to redefine the
character set that may move 512 or 1024 bytes.
2. Change the values in one or more hardware registers at
intervals in either space or time . The values placed in the
registers often come from a table. To illustrate, a table driven
display list interrupt routine changes color values at screen
(space) intervals. While a music program changes notes in
sound registers at timed intervals .
3. Increment or decrement one or more hardware registers
or memory locations . Horizontal or vertical scrolling illustrates
this operation .
In implementing the above routines , the principles used are very
similar. One makes use of the accumulator, the X-register and the
Y-register. Of these, the X and Y registers are most commonly used as
counting or indexing registers to either keep track of how many times
we've cycled through a routine or to successively locate items of data in
a table.
2
OVERVIEW OF 6502 INSTRUCTIONS
Introduction
Table 2-1 is a list of the fifty-six different instruction names for the
6502 CPU. Each instruction name has been coded into a three letter
mnemonic that is suggestive of the task to be carried out. Roughly half
of these instructions perform simple workman-like jobs such as
transferring the contents of one register into another, incrementing or
decrementing a register, and setting or clearing a bit . Approximately
half of the remaining instructions manipulate data by transfering it to
and from memory, or comparing a register with the contents of
memory.
One of the most important features of the 6502 is the number of
options available for specifying the location of the byte to be
manipulated. There are thirteen different addressing modes . This is
several more than are available on other common 8-bit microprocessors
and provides for greater flexibility in programming the 6502. The
fifty-six basic instructions in combination with the thirteen addressing
modes yields a total of 151 different instructions available to the
programmer.
45
46 Atari Assembly Language Programmer's Guide
Table 2.1. 6502 Microprocessor instruction set
ADC
Add memory to Accumulator with carry
AND
Logical "AND" of memory with Accumulator
ASL
Shift left one bit (Accumulator or memory)
BCC
Branch or carry clear
BCS
Branch or carry set
BEQ
Branch on result equal to zero
BIT
Test bits in memory with Accumulator
BMI
Branch on result minus
BNE
Branch on result not equal to zero
BPL
Branch on result plus
BRK
Force Break
BVC
Branch on overflow clear
BVS
Branch on overflow set
CLC
Clear the carry flag
CLD
Clear decimal mode
CLI
Clear the interrupt disable bit
CLV
Clear the overflow flag
CMP
Compare memory and Accumulator
CPX
Compare memory and X-Register
CPY
Compare memory and V-Register
DEC
Decrement memory by one
OveNiew of 6502 Instructions 47
Table 2.1. (cont.)
DEX
Decrement X-Register by one
DEY
Decrement V-Register by one
EOR
Logical " Exclusive-OR ", memory with Accumulator
INC
Increment memory by one
INX
Increment X-Register by one
INY
Increment V-Register by one
JMP
Jump to new location
JSR
Jump to subroutine
LDA
Load the Accumulator
LDX
Load the X-Register
LDY
Load the V-Register
LSR
Shift right one bit (Accumulator or memory)
NOP
No operation
ORA
Logical " OR ", Memory with Accumulator
PHA
Push Accumulator onto stack
PHP
Push Processor Status Register onto stack
PLA
Pull value from stack into Accumulator
PLP
Pull value from stack into Processor Status
ROL
Rotate one bit left (Accumulator or Memory)
ROR
Rotate one bit right (Accumu lator or Memory)
RTI
Return from interrupt
RTS
Return from subroutine
SBC
Subtract memory from Accumulator with borrow
SEC
Set carry flag
SED
Set decimal mode
48 Atari Assembly Language Programmer's Guide
Table 2.1. (cont.)
SEI
Set interrupt disable
STA
Store Accumu lator in memory
STX
Store X-Register in memory
STY
Store V-Register in memory
TAX
T ra nsfer Accumu lator to X-Register
TAY
Transfer Accumulator to V-Reg ister
TSX
Transfer Stack Po inter to X-Register
TXA
Transfer X-Register to Accumu lator
TXS
Transfer X-Register to Stack Pointer
TYA
Transfer V-Register to Accumu lator
The most effective approach to learning these instructions is to
group them according to their function . The first part of this chapter
will give brief descriptions of the instructions. The second part of the
chapter will discuss the different addressing modes.
Instructions by Function
1. Load and Store Instructions: Since the 6502 processor has a
memory-oriented design, the most fundamental operations involve
transferring information into and out of memory. All such transfers
can be made using either the Accumulator, the X-register, or the
Y-register. Loading consists of copying the information from memory
into one of the three registers. This is a non-destructive operation in
that the byte in memory is not altered by the load instruction. The
three load instructions are:
LOA
LOX
LOY
Load Accumu lator w ith memory
Load X-register w ith memory
Load V- register with memory
Overview of 6502 Instructions 49
2. Register Transfer Operations: There are six one-byte operations
that transfer data between the registers. These are:
TAX
TXA
TAY
TYA
TSX
TXS
Transfer Accumulator to X-register
Transfer X-register to Accumulator
Transfer Accumulator to V-register
Transfer V-register to Accumulator
Transfer Stack Pointer to X-register
Transfer X-register to Stack Pointer
Of these six instructions , the first four will be the most useful.
Examples of their use will be demonstrated with display list interrupt
routines in Chapter Four.
3. Increment and Decrement Instructions: One of the functions
of the X and Y registers is to serve as general purpose counters. In
addition it is often desirable to set aside a memory location as a
counter. Counters are useful in accessing consecutive memory locations
or keeping track of the number of passes through a loop. The
increment and decrement instructions are:
Increment X-register by one
DEX Decrem ent X-register by one
INY Increment V-register by one
DEY Decrem ent V-register by one
INC Inc rement memory by one
DEC Dec rement memory by one
INX
4. Compare and Branch: Compare instructions are commonly
used to determine if a register or memory location that is being used as
a counter has reached a certain value. The three compare instructions
are:
Compare X-register and memory'
Compare V-register and memory
CMP Compare Accumulator and memory
CPX
CPY
, Compare instructions can also compare the contents of the register
with the number immediately following the instruction code.
50 Atari Assembly Language Programmer's Guide
The compare instructions subtract the contents of memory from
the register but does not save the result. The indications of the result
are the conditions of the three status flags: N (negative), Z (zero), and
C (carry). The condition of these flags indicate whether the register
contents are less th an , equal to, or grea ter than the contents of memory
location .
A very natural follow-up to a compare instruction is to make a
decision on the basis of the comparison. A common decision is
whether or not to branch to another part of the program. There are
eight branch instructions. Two of these,
BEQ
Branch on Result Equal to zero
BNE
Branch on Result Not Equal to zero
and
work very nicely with the compare instructions when you want to
execute a loop. The remaining six branch instructions are:
BCC
BCS
BMI
BPL
BVS
BVC
Branch
Branch
Branch
Branch
Branch
Branch
on
on
on
on
on
on
Carry Clear (carry 0)
Carry Set (carry = 1)
Minus (Negative (N) = 1)
Plus (Negative (N)
0)
Overflow Set (overflow (v) = 1)
Overflow Clear (overflow (v) = 0)
5. Jump and Return: The branch instructions are called conditional
because they cause a change in a program's normal sequential flow
only if some condition is met. The jump and return instructions cause
unconditional changes in program flow. There are three of these
instructions:
OveNiew of 6502 Instructions 51
JMPJump to a specified memory location
JSR Jump to a subroutine
RTS Return from subroutine
6. Interrupt Instructions: Interrupts are signals to the processor
from another chip or peripheral requesting the processor's attention.
There are two types of interrupts; Non-Maskable Interrupts (NMI)
and Interrupt Requests (IRQ) . Whether or not the processor responds
to an IRQ depends on the IRQ disable bit (I) in the processor status
register. If the I bit is clear (ie. equal to zero), then the external
interrupt will be serviced. If the I bit is set (ie. equal to 1), the processor
will ignore the interrupt request. The instructions to set and clear this
bit arc:
SEI
eLi
Set Interrupt Disable Bit
Clear Interrupt Disable Bit
Interrupt requests cause the processor to go to a subroutine that
services the interrupting device . Such a subroutine must end with:
RTI
Retu rn from I nterru pt
7. Stack Operations: The stack is used as a temporary storage
place for register contents, parameters, and return addresses needed to
get back from a subroutine . The instructions to transfer data to and
from the stack are:
PHA Push Accumulator on stack
PLA Pull Accumulator from stack
PHP Push Processor Status on stack
PLP Pull Processor Status from stack
The instructions involving the accumulator will be useful in the
programs in later chapters. Notice that there are no instructions to
52 Atari Assembly Langua ge Programmer's Guide
move the contents of the X or Y registers directly to the stack.
Therefore. data from th ese regi sters n1L: st III transfe rred through the
accumulator to the stack. PHA is a 'copying' instruction. It does not
destroy the contents of the accumu lator. On the other hand , PLA
removes the byte from the stack.
8. Arithmetic Instructions: It is not our intention to discuss how
to write routines to add, subtract , mUltiply and divide numbers.
Routines to do thi s are covered thoroughly in many other books.
However, you may occasionally find it useful to add or subtract a pair
of numbers . The 6502 can add or subtract numb ers in a binary form or
binary coded decimal form. The form used is controlled by the two
instructions:
SED
Set Decimal mode
CLD
Clear Decimal mode
and
Of course, SED causes the CPU to work in the decimal mode while
CLD directs the CPU to act in the binary mode.
Addition can be completed with or without a carry occuring as
part of the result. Similarly subtraction can be performed with or
without borrowing. Unlike some other processors, the 6502 only has
instructions for addition with a carry and subtraction with borrow.
The digit to be 'borrowed' is contributed by the carry flag of the status
register. Before an addition the carry flag shou ld be cleared. Before a
subtraction the carry flag should be set. The relevant instructions are:
CLC Clear Carry
ADC Add with Carry
SEC Set Carry
SBC Subtract with Carry as Borrow
Other instructions used in arithmetic routines are:
Overview of 6502 Instructions 53
CLV
Clear Overflow (V) flag. Th e overflow flag is used in signed
arithmetic routines.
Accumulator Shift Left
LSR Logical Shift Right
ROL Rotate Left
ROR Rotate Right
ASL
These last instructions are commonly used in mUltiplying and
dividing numbers. They may also be used to perform serial-to-parallel
and parallel-to-serial conversions when the CPU is communicating
with serial oriented peripherals .
9. Logical and Miscellaneous Instructions: Situations may arise
in which you wish to test certain bits rather than a whole byte. Or, you
may wish to set or clear certain bits. The logical instructions will allow
you to do this. They are:
AND
EOR
ORA
And memory with Accumulator
Exc lusive Or memory with Accumulator
Or memory with Accumulator
The AND instruction is primarily used to mask out (set to zero)
certain bits in the accumulator. The EOR instruction is primarily used
to determine which bits differ between the accumulator and memory.
Finally, the ORA instruction is used to set certain bits.ln their simplest
form, the logical operations AND, ORA, and EOR produce a single
bit result after a comparision of two input bits. The possible results are
summarized in Box 3.
54 Atari Assembly Language Programmer's Guide
Box 3
AND
Input Bit #1
Input Bit #2
Result
Input Bit #1
Input Bit #2
0
0
0
0
OR
Result
EOR
Input Bit #1
Input Bit #2
Result
0
0
0
The 6502 's Logical Operations perform eight separate comparisons,
one for each pair of bits 0 7 through D o. For example 10110101 ANOed
with 11101110 produces:
Input #1
Input #2
Result
0
0
Box 3. Logical AND. Logica l OR. Ex cl us ive O R
0
1
Overview of 6502 Instructions 55
There are three instructions that we have classified as miscellaneous.
They are:
NOP
BRK
BIT
No Operation
Break
Test Bits in memory with Accumulator
A NOP instruction causes the processor to do nothing at all. NOP can
be used to reserve space in a program under development,
to make the processor pause for a few machine cycles , or to replace
instructions that have been removed without requir ing all of the
branch and jump addresses to be changed. BRK is commonly used in
debugging during the early stages of program development. It causes
the processor to execute an interrupt sequence after which you can
check what your program has accomplished to that point.
The BIT instruction will test a bit in memory by ANDing it with
the accumulator. The command does not alter either the accumulator
or memory, but records information in the status register as follows:
N flag is the original value of bit 7 of the memory
byte.
V flag is the original value of bit 6 of the memory
byte.
Z flag is set if the AND operation generates a zero .
BIT is a special purpose instruction that is used in communication
between the PIA and the 6502. It is used mainly in programs that are
written as part of hardware interfacing.
Addressing Modes
Each of the 151 instructions has its own numeric operation code
(op-code, for short). Most instructions consist of one byte of op-code
plus a one or two byte operand. The op-code tells the CPU what task is
to be performed and the mode of addressing used. The operand may be
56 Atari Assembly Languag e Programme(s Guide
data, information pertinent to the location of the next instruction to be
executed, or may refer to the location where data is to be found or
placed.
The instructions that make up a program are located sequentially
in memory. The CPU recognizes a byte as an op-code or operand
through the combined efforts of the internal decoding logic and the
program counter. At the start of a machine language routine, the
program counter contains the address of the first op-code. The
processor fetches this byte into the decoding section and at the same
time the program counter is incremented to the address of the next
byte in memory. Once the op-code has been decoded, the CPU will
know how to interpret the next byte it fetches. Thus, how a particular
byte is interpreted is context dependent. One common cause of
program failure is a branch that is executed and the byte branched to is
not a valid op-code, but is the operand of some other instruction.
As mentioned earlier, there are thirteen addressing modes. These
modes can be divided into two groups; the seven basic modes:
1.
2.
3.
4.
Immediate
Absolute
Zero Page
Indirect
5. Implied
6. Relative
7. Accumulator
and six modes that are a combination of indexed addressing and one of
the basic modes:
8. Absolute X-indexed
9. Absolute V-indexed
10. Zero Page X-indexed
11. Zero Page V-indexed
12. Indirect indexed
13. Indexed indirect
Overview of 6502 Instructions 57
Immediate Addressing Mode: The immediate addressing mode
takes its operand from the memory location immediately following the
op-code . Therefore , it is a two-byte in struction; one byte of op-code
followed by a one byte operand.
Absolute Addressing Mode: In the absolute addressing mode,
the two bytes following the op-code give the memory address from
which the CPU is to fetch data to be operated on , or where a byte of
data is to be stored . The absolute addressing mode has the following
format:
First byte
Second byte
Third Byte
Op-code
La-Byte of addr.
Hi-Byte of addr .
This 'reverse' form of writing the memory address takes a bit of
adjusting to at first, but rapidly becomes second nature.
Zero Page Addressing: This is a form of absolute addressing in
which the CPU 'knows' that the Hi-Byte of the memory location is
page zero. All that is needed in addition to the op-code is a single byte
to specify the particular memory location in page zero . The advantage
of page zero addressing is speed. A two byte instruction can be
processed more rapidly than the three byte instructions required by
other addressing modes. Unfortunately, the only zero page locations
normally available to the Atari user are 203 through 209.
Indirect Addressing: I ndirect addressing without indexing
applies only to the JMP instruction . The idea of indirect addressing is
that an intermediate storage area is used to hold the actual address that
will be used by the instruction. This can be clarified with an example:
JMP 128
06
58 Atari Assembly Language Programmer's Guide
This instruction sends the CPU to memory location 1664 (06,128) for
the Lo-Byte of the effective address . The Hi-Byte of the effective
address is in the next memory location , 1665 (06,129). The advantage
of indirect addressing is that it allows a fixed instruction sequence to
go to different memory locations simply by changing the values in the
immediate storage area.
Implied Addressing: Many instructions involve operations internal
to the CPU itself. These are simple tasks such as incrementing a
register or data transfer between registers . Since the registers involved
are internal to the 6502, they have no assigned address. Both the source
and destination address is implied in the instruction. For example,
TXA (Transfer X-register to Accumulator).
Relative Addressing: Relative addressing is used with branch
instructions . The effective address is calculated with respect to the
location of the op-code following the branch instruction. Flow chart
2-1 summarizes what takes place.
The offset of a branch instruction is specified by a single byte
operand. This implies that the numbers 0 to 255 are used to represent
both forward and backward offsets. Technically, the offset is
interpreted as a twos complement signed number. Essentially what this
means is that the numbers I to 127 represent forward branches and the
numbers 255 to 128 represent backward branches. Forward branches
should be no problem to figure out - you simply count forward
beginning with zero. For backward branches you count back from
256. Thus, an offset of minus one is represented by 255, an offset of
minus seven is represented by 249.
Accumulator: Accumulator addressing is an implied type of
addressing that is unique to the four instructions that shift and rotate
the contents of the accumulator.
OveNiew of 6502 Instructions 59
FLOW
CHART
2 -1
BRANCH
INSTRUCTION
IS
DECODED
BACKWARD
( - OFFSET)
1
IS
CONDITION
MET'
NO
YES
PROGRAM
COUNTER
POINTS TO
NE X T
INSTRUCTION
PROGRAM
COUNTER
BECOMES
PROGRAM
COUNTER
PLUS OFFSET
FO RWARD
(+OFFSETl
PROGRAM
COUNTER
POINTS TO
NE X T
INSTR UCTION
FETCH
NE XT
IN STRUC TION
60 Atari Assembly Language Programmer's Guide
Absolute Indexed Addressing: There are two forms of this
addressing mode: Absolute X-indexed and Absolute V-indexed. Both
modes function in the same manner. Remember that in absolute
addressing the two bytes following the op-code specify the address of
the data to be manipulated . In absolute indexed addressing, the
contents of either the X or Y register are added to an abso lute address
to determine the actual memory location used. One of the primary uses
for this addressing mode is to access the elements of a table or array.
Zero Page Indexed Addressing: This form of indexed addressing
is very similar to abso lute indexed addressing. The contents of either
the X or Y register are added to the operand to obtain the actual memory location used for the data. However, there are two differences. The
first difference is that because the Hi-Byte of the base address is
understood to be Page Zero, this is a two byte instruction rather than a
three byte instruction. The second difference between the two modes
occurs in the calculation of the effective address. In the Absolute
Indexed mode the index register is added to the Lo-Byte of the base
address. When this addition results in a number greater than 255 a
carry to the Hi-Byte ofthe base address is generated. In the Zero Page
Indexed mode, when the addition of the index register to the operand
results in a number greater than 255, there is a 'wrap around' back to
the beginning of Page Zero.
Indirect Indexed Addressing: This is a two byte instruction that
combines the concept of an intermediate storage location (indirect
addressing) with the use of Page Zero and the V-index register. Since it
is an indirect mode, the operand identifies the location where the base
address is stored. In particular, the operand is the location in Page
Zero of the Lo-Byte of the base address. The Hi-Byte of the base
address is in the next higher Page Zero location. Because it is an
indexed mode, the contents of the Y-register are added to the value of
the base address to obtain an effective address used by the instruction.
Overview of 6502 Instructions 61
Indexed Indirect Addressing: In the previous mode, the index was
added to the value in memory to determine the location of the data.
However, in Indexed Indirect Addressing, the operand plus the index
determines the intermediate location where the effective address is
stored. Indexed Indirect Addressing is a two byte instruction in which
the X-index register is added to the operand to give the location in
Page Zero of the Lo-Byte of the effective address. The Hi-Byte of the
actual address is stored in the next higher Page Zero location.
3
Atari Graphics
Introduction
The video portion of the Atari Home Computer system was
developed to be compa tible with the functioning of an ordinary TV set.
Forexample, the system clock was designed to have a frequency that is
a multiple of a fundamental TV frequency. This allows CPU interrupts
during horizontal and vertical blanks to be easily implemented. The
compatibility of the TV and the computer is an important feature of
Atari graphics. In addition , the Atari system is unique among home
computers because it uses a second microprocessor (ANTIC) to
control the TV display. Since there is such an intimate connection
between the Atari system and the TV set , we shall begin this chapter
with a description of how a TV operates , with the remainder of the
chapter devoted to an in depth discussion of ANTIC and Atari
graphics .
63
64 Atari Assembly Language Programmer's Guide
TV Operation
The picture on a TV screen is made up of many small picture
elements, or pixels. A TV picture is produced by the interaction of a
modulated beam of electrons with phosphors on the screen. At the rear
of the TV is an electron gun that produces a narrow beam of electrons.
In the beginning of the sequence that forms a picture, the beam is
aimed above the upper left hand corner of the TV screen (see figure
3-1). The beam sweeps from left to right across the face ofthe screen in
64/1 sec. (a microsecond is a unit of time equal to one millionth of a
second). A single horizontal sweep of the electron beam across the
screen is called a scan line. When the electron beam reaches the end of
the scan line it is shut off briefly and the electron gun is re-aimed at the
left side of the screen, but slightly lower down. The period of time that
the electron gun is turned off is called the horizontal blank (14/1 sec.).
This horizontal scanning process is repeated until a picture is built
up line by line. The complete sequence from top to bottom is called a
frame and sixty complete frames are drawn per second. In a normal
TV picture received from a broadcast station there are 525 scan lines
per frame in an arrangement called interlacing. The Atari system does
not use interlacing and there are 262 scan lines from top to bottom. In
actuality, the electron beam scanning starts slightly above and ends
slightly below the visible portion ofthe TV screen. Similarly, it extends
slightly to the left and slightly to the right of the visible screen. This
overscanning prevents unsightly borders for normal TV pictures, and
must be taken into consideration in computer displays.
Vertical positioning on the screen is measured in scan lines.
Horizontal positioning on the screen is measured in units called color
clocks. There are two machine cycles per color clock and 228 color
clocks per scan line. Display dimensions including overscan are 262
scan lines by 228 color clocks. To prevent loss of information due to
overscanning, the normal Atari display uses 192 scan lines by 160 color
clocks.
When the electron beam reaches the end of the last scan line it is
shut off and the electron gun is re-aimed at the upper left hand corner
of the screen. This period of time in which the beam is off is called the
Atari Graphics 65
TELE VISION
SCANNING
OVERSCAN
- ---
-+--~'~~--------------~~~~-r-~
~~--~'~--------------------~~-=~--HORIZONTAL
- ---
--~~-=-~~~----------------------~~_SYNC
'- -
-~
-,
-_....
-
SIGNAL
'~
,
,
VERT IC AL
SY NC SIGNAL
Figure 3-1. Television scanning
66 Atari Assembly Language Programmer's Guide
vertical blank (1400 f.1 sec.). The hori zontal and vertical blanks are
important events in the Atari system. The display hardware generates
horizontal and vertical synchronization pulses that are used by the TV
and can also be used to signal interrupts to the CPU. The Atari system
uses these synchronization signals to give programmers an opportunity
to interrupt normal program flow and have the processor carry out
machine language subroutines. In later chapters we will see that the
horizontal blank is specially useful in graphics and the vertical blank is
useful in scrolling and music.
ANTIC
At the heart of the Atari graphics system is the microprocessor,
ANTIC. Along with the integrated circuit chip GTIA, ANTIC
controls the display of text and graphics on the screen. Since it is a
microprocessor, ANTIC has control lines , a data bus , an address bus,
and an instruction set that can be used to program it. The control lines
allow ANTIC to communicate with the CPU, while the address bus
and data bus allow it to access memory. ANTIC shares the RAM
memory used by the 6502. This sharing of memory by both processors
has two interesting implications. First, it means that ANTIC must
obtain data from memory by a process known as direct memory access
(DMA). Essentially what happens is that when ANTIC needs access to
memory it halts the CPU, gets the information it needs, and then
allows the CPU to go on about its business. This process, called cycle
stealing, slows down the CPU's execution speed. The second implication
is that the CPU can modify the sections of memory used by ANTIC.
This, of course, is precisely the idea behind creating dynamic graphics
-ANTIC handles the details of generating the TV display while the
CPU changes the data ANTIC uses.
ANTIC's program is called a display list. The section of memory
used by ANTIC to determine what to disp lay on the screen is called
screen memory. The remainder of this section of the chapter is devoted
to a discussion of ANTIC's instruction set and writing display lists that
provide custom graphics.
Atori Graphics 67
Although ANTlC, like the 6502, has a 16 line address bus, it has
limitations in addressing a display list and screen memory. ANTIC has
two registers that act as program counters. There is a display list
counter for accessing the display list and a memory scan counter for
accessing screen memory (recall that a program counter holds the
address of the byte to be fetched in the fetch-decode-execute sequence).
The two counters are each 16 bits wide, but do not function as full 16
bit counters. The upper six bits of the display list counter are fixed,
leaving bits Do to 0 9 to act as the program counter. Restricting the
counter to ten bits means that a display list cannot cross a I K
boundary unless ajump instruction is used. This is because the largest
decimal number that can be represented with ten bits is 1023. If the
display list starts on a I K boundary, that is, if the starting address of
the display list is divisible by 1024 with no remainder, it usually will not
be a problem. Most display lists are short -less than a hundred bytes.
While the upper six bits of the display list counter are fixed, only
the upper four bits of the memory scan counter are fixed. This leaves
bits Do to D11 to function as the counter. Since the largest decimal
number that can be represented with twelve bits is 4095, ANTlC
cannot access screen memory that crosses a 4K boundary without a
special instruction .
ANTlC's instructions can be grouped as:
1. Display mode instructions
a. Character mode
b. Map mode
2. Blank line instructions
3. Jump instructions
a. Jump during vertical blank (JVB)
b. Jump to a new memory address (JMP)
In addition to these instructions, there are a number of special options
available. These are load memory scan (LMS), display list interrupts
(OLI's), and scrolling.
68 Atari Assembly Language Programmer's Guide
ANTIC combines the TV's scan lines into groups known as mode
lines. Each mode line is made up of one to sixteen scan lines depending
on the graphics mode. There are two types of graphics modes character mode and map mode. Character mode instructions cause
ANTIC to disRlay a mode line with alpha-numeric or character
- .'
graphics in it. Each byte in screen memory is the internal code of the
character to be displayed. Map mode instructions cause ANTIC to
display solid color pixels.
Blank line instructions cause ANTIC to display one to eight scan
lines in the background color. These instructions are most commonly
used to allow for TV overscan.
Jump instructions are analogous to the BASIC GOTO command,
except that you specify the memory address to go to, not a line
number. When the program is run the address specified is loaded into
the display list counter and consequently starts the fetch-decodeexecute sequence at the new memory location.
Instructions for any 8 bit microprocessor such as ANTIC are
coded as binary numbers . We shall examine ANTIC's instruction byte
in detail to see how to derive the decimal code for each instruction and
option. The ANTIC instruction byte can be represented as:
D7 D6 D5 D4: D3 D2 D,
instruction option nibble
I
I
I
Do
display mode nibble
Bits D 3 to Do are used to determine the display mode and bits 0 7 to 0 4
select the special options - 0 LI, LMS and scrolling. Table 3-1 gives the
display mode corresponding to each of the possible bit patterns.
Notice in Table 3-1 there are nine display modes listed as BASIC
modes and five display modes listed as ANTIC modes. The BASIC
modes are accessible with the BASIC GRAPHICS command . In the
400 / 800 the ANTI C mod es are accessi ble only by creating your own
display list for ANTIC to follow . In the XL and XE series the OS
supports the ANTIC Modes,
Atari Graphics 69
Table 3-1. Display mode acco rding to bit patterns
D3
D2
D,
Do
0
0
0
0
0
0
1
1
0
0
0
1
0
1
0
1
0
0
0
0
0
0
0
0
1
0
0
Display Mode
Decimal
Lower Nibble
0
1
0
0
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Character - BASIC Mode 0
Character - ANTIC Mode 3
Character - ANTIC Mode 4
Character - ANTIC Mode 5
Character - BASIC Mode 1
Character - BASIC Mode 2
Map mode - BASIC Mode 3
Map mode - BASIC Mode 4
Map mode - BASIC Mode 5
Map mode - BASIC Mode 6
Map mode - ANTI C Mode 12
Map mode - BASIC Mode 7
Map mode - BASIC Mode 14
Map mode - BASIC Mode 8
Note: The supporting system of the 'XL' and 'XE' series computers
supports ANTIC Modes.
To use
ANTIC
ANTIC
ANTIC
ANTIC
4
5
12
14
call a Graphics
12
13
14
15
command
Bits D7 to D4 select the special options as follows:
I. Bit D7 is used for display list interrupts. If D7is set (equal to 1)
and also bit 7 of memory location 54286 (Non-Maskable Interrupt
Enable, NMIEN) is set, the processor is interrupted during the
horizontal blank.
2. Bit 0 6 is used for the Load Memory Scan (LMS) option.
When this bit is set, the ne xt two bytes in the displa y list will be loaded
into the memory sca n counter as the address of scree n memory. As
with the 6502, the address bytes must be written in Lo-Byte / Hi-Byte
order.
70 Atari Assembly Language Programmer's Guide
3. Bit D5 if set, enables vertical fine scrolling.
4. Bit D4 if set, enables horizontal fine scrolling.
To demonstrate these concepts, consider these examples. Suppose
you need an instruction for ANTIC that enables a OLI and horizontal
scrolling in BASIC mode 7. Then the instruction code is:
Weight
Bit
Bi nary
OLl--...:.
16
32
64
128
07
06
05
04
1
0
0 ~1
Horizontal Scrolling..J
Basic mode 7
Using the techniques in chapter one you can convert this into its
decimal equivalent: 128+ 16+8+4+ 1= 157 . The decimal value is what
you will use in your display list.
As another example, suppose you need an LMS in BASIC
Graphics 2. The bit pattern is:
Weight
Bit
Binary
128
07
0
64
06
1
.LMS
32
05
0
16
04
0
8
03
0
O2
2
01
00
BASIC Mode 2
The decimal equivalent of this binary number is 64+4+2+ 1=71.
However, because of the LMS option, this is no longer a single byte
instruction. The instruction code, 71 , must be followed by two address
bytes giving the location of screen memory.
The remaining ANTI C instructions, blank line and jump instructions,
are less complicated than display mode instructions. When bits 0 3 to
Do are all zero the instruction byte is identified as a blank line
instruction. Then bits 0 7 to 0 4 determine the number of blank scan
lines as listed in Table 3-2.
Atari Graphics 71
Table 3-2. Do to D7 correlation to blank lines
D7 D6 D5 D4 D3 D2 D1 Do
Decimal Value
NumberofBlank Lines
,
0
0
0
0
0
0
0
0
0
0
0
0
1
1
1
1
0
0
1
1
0
0
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
2
3
4
5
6
7
8
0
16
32
48
64
80
96
112
As in display mode instructions , bit 7 of the blank line instruction is
used for display list interrupts.
The two jump instructions are jump during vertical blank (JVB)
and jump to a new address (JMP). The first jump instruction reloads
the display list counter with the address of the first instruction of the
display list. As its name implies the loading occurs during the vertical
blank. The JVB instruction is the last instruction in a display list and
causes ANTIC to execute an endless loop that reads the display list
each time a frame is drawn on the TV. The JMP instruction enables
ANTIC to cross a 1K boundry in a display list. The instruction format
for jumps is:
D7 D6 D5 D ~
D3 D2 D,
Do
IT kXJXI I I I I
r
DLI Bit
Doesn 't matter
If 0 then JMP
If 1 then JVB
Jump Bit
1 = jump
0= no jump
72 Atari Assembly Language Programmer's Guide
Thus a JVB without the DLI option has the code 65 and the JMP
instruction without the DLI option has the numeric code 0 I.
Display Modes
An important feature of Atari graphics is the ease with which a
programmer can mix graphics modes on the screen by writing a
custom display list. Before we discuss how to construct a custom
display list, it is important to have an understanding of Atari display
modes . First, we shall describe the modes available from BASIC. Then
we will describe the ANTIC display modes.
The fundamental structure of the TV display is 192 scan lines
vertically and 160 color clocks horizontally. The basic differences
between the display modes are how this structure is organized into
pixels, and the colors available. There are three character modes and
six map modes accessible from BASIC. These are BASIC Modes 0, 1,
2 and 3, 4,5,6,7 , 8, respectively. Atari Computers with GTIA support
three additional graphics modes (9 ,10, 11) that are enhancements of
Graphics 8. As an example of the different ways to organize the basic
structure, Graphics 0 uses pixels that are 8 scan lines by 4 color clocks,
while Graphics 2 uses pixels that are 16 scan lines by 8 color clocks.
Consequently, Graphics 2 pixels are twice as high and twice as wide as
Graphics 0 pixels. Additionally, Graphics 0 has two colors and
Graphics 2 has five colors available.
The location of pixels on the screen is conveniently described by
X-Y coordinates in which the X-coordinate labels the horizontal
position, or column and the Y-coordinate labels the vertical position,
or row. Figure 3-2 illustrates this idea with a full screen in Graphics 2.
All of the BASIC display modes except Graphics 0 and GTIA
Modes have both a full screen and a split screen version. In a split
screen version, the bottom 32 scan lines are devoted to four Graphics 0
mode lines that provide a text window. Pixel location in the text
window, when expressed in terms of coordinates, is best thought of
independently ofthe coordinates of the graphics mode above it. Figure
3-3 shows Graphics 3 with a text window to emphasize this point. In
figure 3-3, the upper lefthand pixel of the text window is labeled 0,0,
Atari Graphics 73
just as if it were at the top of the screen. This idea of locating pixels
within a particular group of mode lines independently of the other
graphics modes on the screen is useful with custom display lists and
mixed modes.
GRAPHICS 2+16
o
COORDINATES
12
16
19
Figure 3-2. X-Y coordinates
Another factor that distinguishes the various display modes is the
amount of screen memory required for each mode. In general,
character modes require much less memory than map modes. This is
due to the difference in how memory is used to determine screen
display in the two types of modes . Character modes use one byte of
screen memory per pixel, no matter what size the pixel is. It follows
that there is a one-to-one correspondence between the pixels on the
screen and the locations in screen memory. The bytes stored in
memory are the internal codes for the characters to be displayed on the
screen. Although the pixels on the screen are organized two dimensionally,
the bytes in memory are organized linearly. Referring back to figure
3-2, corresponding to the first row of pixels on the screen are the first
74 Atari Assembly Language Programme(s Guide
twenty bytes in screen memory. Location 0,0 corresponds to the first
byte; location 0,19 to the 20th byte. Corresponding to the second row
of pixels is the next twenty bytes in screen memory, and so on. As a
result, the minimum screen memory needed for a character mode is
equal to the number of pixels on the screen.
In map modes the display pixels are generally much smaller than
in character modes (BASIC Graphics 3 is an exception). The distinguishing
characteristic of map modes is that one, two, or four bits in memory
determine if a pixel is lit or unlit and, depending on the mode, the color
displayed. For example, consider Graphics 8. Graphics 8 uses pixels
that are a Y2 color clock (one machine cycle) wide by one scan line high
and so there are 320 pixels per scan line. A single bit in screen memory
determines whether a pixel is on or off. If a pixel is to be on, then its
corresponding bit is equal to one; if the pixel is to be off, its
corresponding bit is equal to zero. Since there are 320 pixels per scan
line, 320 dividing by 8 bits per byte gives 40 bytes of memory needed per
scan line in Graphics 8. Since there are 192 scan lines, the minimum
screen memory required in Graphics 8 is 7,680 bytes. Graphics 8 is
comparatively simple because there are only two colors available,
foreground and background. Thus, a single bit suffices to determine a
pixel's state. In four color graphics modes, a single bit is not sufficient
to choose colors. In these modes - BASIC Modes 3,5,7 and ANTIC
Mode 14 - a pair of bits is required to specify a color. Consequently
each byte of screen memory encodes four pixels. The four color map
modes use larger pixels than Graphics 8 to keep the screen memory
requirements within reasonable limits.
Basic Modes 4 and 6 are similar to Graphics 8. In these two color
map modes, a bit value of I selects the foreground color from color
register 0, while a bit value of 0 selects the background color from color
register 4. These map modes are especially memory efficient since each
byte of screen memory encodes 8 pixels and the pixels are 4 scan lines
by 2 color clocks (mode 4) or 2 scan lines by 1 color clock (mode 6).
The ANTIC display modes differ from the BASIC modes (in the
400 / 800 series) in that they are not available through a simple
GRAPHICS command. The BASIC GRAPHICS command causes
the operating system to generate an appropriate display list for the
Atari Graphics 75
GRAPHICS
MODE
WITH
TE X T
WINDOW
H-+-++-+-H-++++++++++++-H--I-l--l-l+-l-~~H-+-+H-+-+- -
_ _ -+-, --+--I---+-
(,
H-+++-t--+-t-++-++-t-I---H--H-+--,H--H--I---~+_H-+__I_-I_I'. -I_
,,
W-W-l-- 1-+I---
--
H-t-i=~-h IT!-/
, Lttc-t-Jf-Li-rt+-I
ttt::Jt::Jjjjjjj : tl--ttH-I-:tt-L:11_+-- LlH': -cttctEFIJJI
Figure 3-3. Graphics Mode 3 with text window
Graphics mode called . In order to use the ANTIC modes in the
400 / 800 series, you must construct your own display list. Although it
entails more work to use the ANTIC modes, the compensation is that
they offer a number of features not available in the BASIC modes.
ANTIC Mode 3 is a character mode that allows descenders on lower
case letters. ANTIC Modes 4 and 5 are four color character modes. As
with the four color map modes discussed earlier, pairs of bits
determine the colors used. We defer the more complete description of
these modes until we have discussed character sets. ANTIC Mode 14 is
a four color map mode with pixels that are one scan line high and one
color clock wide . As a result, the vertical resolution is equivalent to
BASIC Mode 8, but the horizontal resolution is only half as great.
It is worthwhile to compare BASIC Mode 8, BASIC Mode 7, and
ANTIC Mode 14 in order to see the relationship between pixel size,
colors available, and screen memory:
76 Atari Assembly Language Programmer's Guide
Table 3-4. Comparison of BASIC Mode 8, BASIC Mode 7, and ANTIC
Mode 14
COLORS SCREEN MEMORY
PIXEL SIZE
MODE
7680
2
BASIC8 1 scan line x % co lor clock
4
3840
BAS IC 7 2 scan lines x 1 co lor clock
7680
4
ANTIC 14 1 scan line x 1 co lor clock
"
You can see that there are trade offs made between resolution, colors,
and screen memory. Consideration of these factors is important when
you are planning large or complex programs that may use several
different colorful screen displays.
Display Lists
The Atari Home Computer, with its many different display
modes and its built in capability for mixing these modes on the TV
screen allows you many opportunities for creative programming. You
can mix character and map modes almost at will. The way to do this is
to write your own custom display list. There are two ways to proceed
when creating a display list. First, you can modify one that is accessible
from BASIC. Second, you can create your own display list from
scratch, store it in memory, and tell the computer to use it.
When planning a custom display list, there are two categories of
items to take into account. The first category relates to the overall
organization of the display you wish to create. These factors are: the
types of modes you wish to use, the colors available, and special
features such as scrolling and display list interrupts. The second
category of factors to consider are of primary importance in actually
constructing the display list. These are: the number of scan lines per
mode line, the number of memory bytes per mode line, and the total
screen memory needed. Since these factors are essential in planning a
display list, Table 3-4 summarizes this information.
Atari Graphics 77
Table 3-4. Essential informati o n when pla nning a display list
MODE NUMBER
BASIC ANTIC
0
-
5
6
7
3
4
5
6
8
9
10
11
12
13
14
15
COL/ROW
SCAN LINES
SCRN RAM
MINIMUM
with
no
per
per
TOTAL
TEXT WINDOW
TEXT WINDOW
MODE LINE
MODE LINE
SCRN MEM
40 X 24
40 X 19
40 X 24
40 X 12
20 X 24
20 X 12
40 X 24
80 X 48
80 X 48
160 X 96
160x192
8
10
8
16
40
960
760
960
480
480
240
2
3
4
1
2
7
-
COL/ROW
20 X 20
20 X 10
40 X 20
80 X 40
80 X 40
160 X 80
160
80
320
160
160 X 96
160 X 192
320 X 192
8
16
8
4
4
2
1
2
1
1
40
40
40
20
20
10
10
20
20
20
40
40
40
240
480
960
1920
3840
3840
7680
7680
Prior to discussing the steps necessary to create a display list, it
will be helpful to examine a display list available from BASIC. Figure
3-4 is a Graphics 2 display list.
Antic executes the display list program sixty times each second,
once each time a TV frame is drawn. Certain features of display lists
generated by the OS are consistent among all the graphics modes.
These are: Blank line instructions, LMS instructions, and the JVB
instruction. Examine the Graphics 2 display list. You will see that the
first three bytes tell ANTIC to display 24 blank scan lines at the top of
the screen to allow for TV overscan. The fourth byte of the display list
serves a dual function. First, bit six is set. Therefore this byte includes
the LMS option. Second, the lower four bits tell ANTIC to display the
first mode line of Basic Mode 2. Each instruction in a display list that
includes the LMS option must be followed by a two byte address that
tells ANTIC where the screen memory is located. These bytes are
78 Atari Assembly Language Programmer's Guide
DL Byte
Decimal Value
Binary
2
3
112
112
112
0111 0000
24
Blank
Lines
4
5
6
71
01000111
158
LMS and GR . 2
Lo-Byte
Hi-Byte
7
8
10
00000111
BASIC
MODE
112
11
12
13
14
15
7
7
16
17
18
19
20
65
92
158
01000001
JVB
Lo-Byte
Hi-Byte
Figure 3-4. Graphics display list
written in Lo-Byte / Hi-Byte order. In this particular display list, which
was generated by an Atari with 48 K of memory, the screen memory
started at location 112 of page 158 . The next eleven bytes in the display
list are BASIC Mode 2 instructions. Including byte 4, there are a total of
twelve Mode 2 lines, each consisting of 16 scan lines for a total of 192
horizontal scan lines from top to bottom on the TV screen. The last
three bytes ofthe display list are the JVB instruction. 65 is the JVB op
code. The next two bytes are the operand, in this case the Lo-Byte / HiByte of the address of the first byte in the display list.
Atari Graphics 79
The addresses following the JVB and LMS op codes allow you to
infer how the OS has positioned the display list and screen memory
within the computer's memory. According to the JVB instruction, the
display list starts at 40540 (158 ,92). If you count the number of bytes in
the display list you will see that the last one is in memory location
40559 (I58, Ill). Checking the LMS instruction, we see that the next
byte in memory, 40560 (158,1 12), is the start of screen memory. In the
Atari the OS locates screen memory immediately following the display
list. The exact addresses where the OS positions the display list and
screen memory are dependent on the amount of system memory and
graphics mode .
Box 4 is a short BASIC program that will allow you to print out
display lists for each of the BASIC display modes. It is useful to have
these printouts for reference when planning a custom display list.
BOX 4
Utility Progra..
Display List Dump
II,
5 REM ** DISPLAY LIST DUMP **
OPEN #3, 8, J~, "P: "
20 GRAPHICS 0:CLR
30 DIM INSTI204',ADDR(204)
40 POSITION 4, 10:TRAP 20
5J3 PRINT "WHAT GRAPHICS MODE " ;
60 INPUT A
70 GRAPHICS A:CNTR=0
80 DL=PEEK(560)+PEEKI561)*256
90 FOR X=0 TO 204
100 ADDRIX)=DL+X
1 113 M=PEEK IDL + X)
120 IF M=65 AND CNTR=0 THEN CNTR=X+2
130 INSTIX)"'M
140 NEXT X
1513 PRINT #3; "GRAPHICS
': ; A
160 PRINT In;" "
170 FOR X=J3 TO CNTR
180 PRINT tt3;"AOOR
"IAODRIX);"
OL BYTE ";X+1;"
";INSTIX)
190 NEXT X
200 CLOSE #3
\..
Box 4.
80 Atari Assembly Language Programme(s Guide
We have mentioned that there are two ways to proceed in
developing your own display list: (1) from within the framework of a
display list provided by BASIC, or (2) start from scratch. We shall
describe both methods. In each case there are certain memory
locations of crucial importance. These are listed in Table 3-5.
Table 3-5. Important memory locations when developing a display list
LOCATION
FUNCTION
SDLSTL
560,561
560 Lo-Byte of DL Address
561 Hi-Byte of DL Address
SAVMSC
88,89
88 La-Byte of start of screen memory
89 Hi-Byte of start of screen memory
DINDEX
87
Contains the value telling the as what
display mode is in use
LAQ_E_L
The procedure to create a custom display list from within BASIC
can be organized into six steps:
Step 1: Make a sketch of what you want to appear on the screen.
You should make notes on the display modes and special options such
as display list interrupts or scrolling.
Step 2: Refer to Table 3-3 and find the display mode with the
largest minimum screen memory. This determines the display list to
modify. Choosing the mode with the largest screen memory insures
that the OS will set aside sufficient memory to hold your display. At
this point there are two requirements that must be met. First, the total
number of scan lines should not exceed 192. If it does, the screen image
may "roll". On the other hand , the total can be less than 192 with no
adverse effect. Second, when you insert new graphic mode lines into an
existing display list, it is best to group them so that the total number of
bytes per group is a whole mUltiple of the bytes per mode line in the
display list being modified. The best way to keep track of these things is
to make a drawing like Figure 3-5.
Atari Graphics 81
x 20 080
rvlODE 1
MODE B
128 "40: 5120
MODE 2
5240
SCREEN RAM
2x16=32
IQ2
SCAN LINES
Figure 3-5. Depiction of graphic mode lines
The example in Figure 3-5 modifies a Graphics 8 display list.
Each line of Graphics 8 requires 40 bytes of RAM. At the top there are
four lines of Mode I requiring 80 bytes of screen memory, an integral
mUltiple of 40. Similarly, at the bottom there are two lines of Mode 2,
each requiring 20 bytes of screen memory for a total of 40 bytes.
Matching up the byte requirements between inserted lines and existing
lines is one way to insure that text and graphics will appear where you
want them. The reason for all this calculating of byte requirements is
that there is potential for conflict between what ANTIC does and what
the OS thinks ANTIC is doing. When you start out with a Graphics 8
command, the OS will assume that there are 40 bytes per mode line in
screen memory. However, when ANTIC reads the display list and
encounters the first Mode 1 instruction it will display only 20 bytes of
what the OS thought was a 40 byte line. Including a second line of
Mode I will keep things synchronized. Later we will see that there is
another way to work around this potential conflict by changing
SA VMSC, DINDEX and their associated hardware registers.
Step 3: Begin writing your BASIC program with a GRAPHICS
command calling the display list you are going to modify. In the
example of Figure 3-5 we would have:
82 Atari Assembly Language Programmer's Guide
10 GRAPHICS 8
Next you will need a variable to keep track of the starting address of
the display list. Call this variable something like "DL" or "START"
and peek the display list pointer with the following command:
20 DL= PEEK(560)+PEEK(561 )*256
Step 4: If needed modify the original LMS instruction in the
display list to give you the proper mode line at the top of the screen. To
get the first mode line of Gra phics 1:
30 POKE DL +3,70
Step 5: Modify the remainder of the display list. Here is where the
printout of the original display list is handy because you can count
bytes in the original to figure out where to put your new instructions .
The Graphics 8 display list is shown in figure 3-6.
First, we want three more Graphics I lines at the top of the screen.
This is accomplished with:
40 POKE DL+6,6 :POKE DL+7,6:POKE DL+8,6
which will replace the three graphics 8 instructions following the LMS
address bytes.
In order to place the Mode 2 lines we count 128 Graphics 8 lines
down the display list. This example illustrates something important
about Graphics 8 display lists . Recall that the memory scan counter
cannot cross a 4K boundary and Graphics 8 needs 7680 bytes of screen
memory. Consequently screen memory is broken up into two blocks.
ANTIC is sent to the first block of screen memory by the first LMS
instruction in address 32851, and is then sent to the second block of
screen memory by the second LMS instruction in address 32947. The
need to "jump the 4K boundary" occurs only in the Graphics 8 Mode.
Care should be exercised that neither the second LMS instruction nor
its operand are accidentally clobbered by inserted mode lines. Also the
two address bytes must be allowed for in counting where you will insert
mode lines near the bottom of the screen. Taking all of this into
account we have line 50:
Atari Graphics 83
ADDRESS
32848
32849
32850
32851
32852
32853
32854
32855
32856
32857
32943
32944
32945
32946
32947
32948
32949
32950
32951
32952
DL BYTE
1
2
3
4
5
6
7
8
9
10
85 Bytes omitted
96
97
98
99
100
101
102
103
104
105
INSTRUCTION
112
112
112
79
80
129
15
15
15
15
15
15
15
15
79
0
144
15
15
15
60 Bytes omitted
33013
33014
33015
33016
33017
33018
33019
33020
33021
33022
33023
166
167
168
169
170
171
172
173
174
175
176
Figure 3-6. Graphics 8 display list
15
15
66
96
159
2
2
2
65
80
128
84 Atari Assembly Language Programme(s Guide
50 POKE DL+139,7 :POKE DL+140,7
Step 6: Once the changes in mode lines are complete, finish off
with a JVB followed by the Lo-Byte / Hi-Byte of the return address:
60 POKE DL+141 ,65
70 POKE DL +142,PEEK(560)
80 POKE DL +143,PEEK(561)
Note that after these values are put into the display list any bytes
remaining from the original display list will not be used .
Displaying characters or graphics on a modified screen involves
telling the OS how to interpret the data in screen memory. It would not
work to tell the computer to display a character in Mode 1 if the
computer thinks it is using Graphics 8. The register DINDEX
(location 87) tells the OS which display mode is in use. Accordingly, to
print in either the Mode 1 or Mode 2 portions of the above display list
it is first necessary to POKE 87,1 or POKE 87,2 respectively. In all
cases the number POKEd is the BASIC display mode number.
A second complication arises when the OS positions text or
graphics on the screen. This occurs because positioning is done by
counting bytes from the start of screen memory. The OS does its
calculation on the basis of the size of screen memory associated with
the display mode value stored in location 87. With a custom display
list, it is possible for total screen memory to be considerably longer
than the mode the OS is using. This disparity can cause the dreaded
"cursor out of range" error message as well as trouble positioning
material on the screen. Fortunately the cure for this problem is fairly
simple. Before creating a display on the screen, change the pointer to
the top of screen memory (SA VMSC) to coincide with the start of the
mode section where you want the display to appear. This means that
you temporarily treat the upper left hand pixel of that mode as being
position 0,0 and place your display within that mode section in the
usual manner. This technique also eliminates the trial and error
method of positioning things on the screen.
Atari Graphics 85
For example, suppose we had printed something in the Graphics I
section of the screen and no w wanted to display a geometric design in
the Graphics 8 section. The program would read as follows:
1. Tell the
as what mode to use;
POKE 87,8
2. Locate current top of screen address;
TPSCRN= PEEK(88)+PEEK(89) "256
3. Next, offset the variable TPSCRN by the number of
memory bytes for the Mode 1 lines plus 1 (4 lines * 20
bytes per line + 1 = 81);
TPSCRN= TPSCRN+81
4. Finally, POKE this memory location back into 88
(La-Byte) and 89 (Hi-Byte);
POKE 88,TPSCRN-(1 NT(TPSCRN/256) *256)
POKE 89,INT(TPSCRN / 256)
Box 5 presents a BASIC program that illustrates this method
of positioning.
Box 6 is a short program that modifies a Graphics 8 display list.
Near the top of the screen are two Graphics 2 mode lines. These are
followed by some Graphics 8 lines and then some Graphics mode I
lines. When you type in and run this program it will give you a feeling
for the difference in the sizes of mode lines made up of 8 and 16 scan
lines. More importantly, however, this program can serve as the focal
point for some important exercises: (a) figure out the number of mode
8 scan lines at the top of the screen by writing out the first dozen or so
bytes of the display list; (b) move the Graphics I mode lines around the
screen to get a feeling for the placement on the screen and the position
of the instruction in the display list; (c) deliberately try to overwrite the
86 Atari Assembly Language Programme(s Guide
r
BOX 5
Custom Display List
PositioninQ Concepts
5 REM ** CUSTOM DL/POSITIONING **
1111 GRAPHICS 8
20 DL=PEEK(560)+PEEK(561)*256
30 POKE DL +3,7111
40 POKE DL+6,6:POKE DL+7,6:POKE DL+8,6
50 POKE DL+139,7:POKE DL+140,7
60 POKE DL+141,65
70 POKE DL+142.PEEK(560):POKE DL+143.PEEK(561)
80 POKE 87,I:POSITION 0,0:7 #6; "GRAPHICS PROGRAMMING"
85 POSITION 1,2:? #6; "SCREEN POSITIONING"
9121 POKE 87, 8
100 TPSCRN=PEEK(88)+PEEK(89)*256
105 TPSCRN=PEEK(88)+PEEKI89)*256
110 TPSCRN=TPSCRN+81
120 POKE 88,TPSCRN-IINTCTPSCRN/256*256
130 POKE 89,INTCTPSCRN/256)
140 COLOR 1
150 FOR T=@ TO 720 STEP 3
1~0 W=T/57.26:R=5*W
170 X=INTCR*COSCW:Y=INTCR*SINCW))
180 IF T=0 THEN PLOT 160+X,64-Y
190 DRAWTO 160+X,64-Y
21110 NEXT T
210 POKE 87,2
220 TPSCRN=TPSCRN+5200
230 POKE 88,TPSCRN-CINTCTPSCRN/25611*256
240 POKE 89,INTCTPSCRN/256)
250 POSITION 111,121: 7 #6; "ATARI DISPLAY LIST"
Box 5. Custom Display List Positioning Concepts
second LMS byte in the Graphics 8 display list. See what happens!
Does it affect PLOT's and ORA WTO's? Deliberately creating programs
with 'bugs' and studying the results can be a great help in later program
debugging; (d) change the address bytes for the first block of screen
memory to page zero of memory. One thing you should see is the real
time clock in action.
Atari Graphics 87
BOX6
5 REM ** MODIFIED DISPLAY LIST **
1121 GRAPHICS 8
20 DL=PEEK(560)+PEEK(561)*256
30 POKE DL+10,7:POKE DL+l1,7
40 POKE DL+24,6:POKE DL+25,6
50 POKE DL+122,6:POKE DL+123,6
60 POKE DL+136,65
70 POKE DL+137,PEEK(560)
80 POKE DL+138,PEEK(561)
Box 6. Modified Graphics 8 Display List
Creating your own display list from scratch can seem easier than
modifying a display list provided by BASIC, because you are starting
with a clean slate. The first concern is where to store the display list and
its screen memory so that they won't be overwritten by BASIC. The
OS solves this problem by storing them between the addresses pointed
to by MEMTOP (741 ,742) and RAMTOP (106). MEMTOP is the
pointer to the last free byte available to BASIC. RAMTOP points to
the dividing line between RA M and the high memory address used for
the BASIC cartridge, GTlA, POKEY , and so on. The value in
RAMTOP is always expressed in pages (multiples of 256), and in a
48K Atari is 160, corresponding to memory address 40960.
Providing a place in memory that is safe from being overwritten
by BASIC is a problem that occurs whenever you want to use special
features such as redefined character sets, player/ missile graphics,
machine language subroutines , or when creating your own display list.
There are several solutions to the problem . One solution we shall
frequently use is to lower RAMTOP by a BASIC statement such as:
88 Atari Assembly Language Programme(s Guide
POKE(106),PEEK(106)- # of pages to reserve
or its machine language equivalent which is:
LDA RAMTOP minus the number of pages to reserve
STA 106
The space in memory between the old RAMTOP value and the new
one is essentially safe. Usually, if you are working from BASIC, it is a
good idea to follow the change in RAMTOP with a GRAPHICS or a
CLOSE #6,OPEN#6 ,8,0,"S:" sequence . This will update MEMTOP
and insure that any display list created later in the program by the OS
will not override data in your reserved area. You should be aware that
any clear screen commands or text window scrolling that occurs will
clear some memory beyond RAMTOP - up to 800 bytes for text
window scrolling. Therefore, to avoid memory conflicts it is fortuitous
to leave a buffer zone between RAMTOP and your display list, or
other special programs.
As with modifying a BASIC display list, writing a display list
from scratch should be approached in a sequential manner.
Step 1: Figure out how you want to present the screen . Be sure to:
(a) Allow for 24 blank lines at the top of the screen . (b) Plan what mode
lines you are using and their position on the screen. (c) Take into
account special options. For example, with scrolling you may want
every mode line used to have the LMS option . Figure 3-7 is a rather
complicated example that we have provided simply to give you a
feeling for the calculations involved in this and succeeding steps.
As a practical example we will construct an ANTIC Mode 4
display list. After making a drawing similar to Figure 3-7 and taking
into account special option, make a rough display list such as this:
Atari Graphics
89
LINE
BLANK
.M~
LO~8YTE
HI~BYTE
ANTIC
,3
40 X 4: 160
ANTIC
4 X 8: 32
40XI06=4.,20
ANTIC
12
108X I 106
ANTIC
2 X16 :: 32
40X5=200
47E.0
JV B
~INIMU~~
SCREE.N ME.MORY
2X 10:20
192 SCAN
D.L. LO~ ADD/?
D. L. HI~ ADDf<'
'-....--~----'/
D.L . 124 I3YTES
~
4760-t 12S :: 488)1 2tl6
=19.08
OR
20
FOR
DISPLAY
LIST
AND SCI.'EEN
MEMORY
Figure 3-7. Display List and Screen Memory
PAGES
LINES
90 Atari Assembly Language Programmer's Guide
112
112 24 blank lines
112
LMS
SCRN MEM ADDR-LO
SCRN MEM ADDR-HI
MODE LINE
MODE LINE
23 Mode 4 lines
JVB
DL ADDR-LO
DL ADDR-HI
Step 2: From the draft display list, count the number of bytes that
the display list will use. In our example, 3+3+23+3=32.
Step 3: Determine the amount of screen memory needed from the
number of bytes required per mode line. The total number of bytes
equals the amount of screen memory. (40 bytes * 24 mode lines = 960)
Step 4: The results of steps 2 and 3 determine the number of pages
needed for both the display list and screen memory (32+960= 992/ 256
or
text window scrolling later in the program, leiwe a buffer between
RAMTOP and your display list.
= 3.8 or 4 pages). If you anticipate using a clear screen command
Step 5: Decide upon the relative position, in your reserved area, of
the display list and screen memory. Although the OS locates screen
memory immediately after the display list, this is not mandatory.
Atari Graphics 91
In the example of Box 7, we construct an ANTIC Mode 4 display
list for the 400 / 800 series. The display list itself needs 32 bytes. The
screen memory needed is 960 bytes. If we put the display list on its own
page (wasteful of memory!), allow four pages for screen memory, and
allow three pages as a buffer above RAMTOP, we can plan the
positioning as:
PAGE
CONTENTS
160
Old RAMTOP
159
158
157
156
Screen Memory
155
Display List
154
153
152
New RAMTOP
Step 6: Write the program that sets up the display list.
The program in Box 7 is written in this particular form for
pedagogical reasons. First of all, Lines 10,30,50,90, and 100 contain
explicit references to page numbers so that you can clearly see the
correspondence between the planning steps, such as the chart in Step 5,
and the actual program. Because of the explicit page references, the
program as written is for an Atari with 48K. It needs modification to
be transportable to 16K or 32K machines. The modifications are
simple. Replace Line 10 with:
POKE 106,PEEK(106)-8
Also replace each number 155 with (PEEK(l06)+3) and each number
156 with (PEEK(l06)+4).
92 Atari Assembly Language Programmer's Guide
,
.,X7
Nn'IC . . . . 4 Di ... ley Uat
~ PtE'"
**
ANTI C "'ODE 4
11111 POKE 1"., 1~2
2.
3111
4111
51
..
**
aRAPHIC8 "
DL-l~~*2S6
FOR 1-" TO 2.POKE DL+I,l12:NEXT I
POKE DL+3, :POKE DL+4,":POKE DL+~,le.
FOft I-III TO 22: ..OKE DL+.+I,4:NEXT I
711 P(J(E DL+2',.e
.. POKE DL+3QII,1II
." "(J(E DL+31,l~~
1N POKE
11"
11 ~
12"
13"
14111
~. . ,IIIIPOKI S61,l~~
FOR 1-" TO 1"24:POKE lS6*~+I,.:NEXT I
PtE'" * CHANBE PO I NTEA TO TOP OF SCREEN I'tEI'tORY
POKE 88,III:POKE 89.1~.
POSITION 4,4
PRINT ,"ANTlC"
Box 7. ANTIC Mode 4 Display List
The program also makes another point about reserving a safe
place by lowering RAMTOP. When you run the program you will see
that included in the space we have reserved was the screen memory
used by the computer when the program was typed in! Line 110 allows
you the fun of watching this section of screen memory being cleaned
out! Two conclusions can be drawn. First, before using a section of
RAM as screen memory, you may want to clear it out by filling it with
zeros. Second, BASIC is very S-L-O-W at this job. In the next chapter
we'll write a machine language routine for this purpose.
Atari Graphics 93
lOX 78
MlTle ..... 4 . i th
~ket
1 REM BOX 7B
REM ANTIC MODE 4 WITH ROCKET
S REM LOWER RAMTOP
1. POKE 1'6,1~2
21 BRAPH I CS
2~ REM SET UP DISPLAY LIlT
3. DL-l~e.~
4. ~OR I . . TO 2:POKE DL+I,112:NEXT I
51 POKE DL+4,6S:POKE DL+e,':POKE DL+6.1e6
6. FOR 1-1 TO 22:POKE DL+7+I,4:NEXT I
7. POKE DL+29.6~
. . POKE DL+3I, I
. . POKE DL+31,les
IN POKE s..,lrPOKE !561. ISS
~
lie
11.
111
112
113
FOR I-I TO 1124rPOKE 1!56.~+I.'INEXT I
REM P1DYE CHAf'tACTER BET TO RAM
REM AND REDEFI NE CHARACTERS
REM THROUGH 6
POKE 1~,PEEK(1")-32
A-PEEIC (1")
START-(A+4).2S6
FOR R-. TO 511
POKE START+R.PEEK(57344+R):NEXT R
FOR X-I TO 159:READ P
POKE START+3.8+X,P:NEXT X
REM DEC I /'tAL. VALUES FOR NEW CHAf'tACTERS
DATA ., ,., 1,3
DATA 21.21.21.21.127.2ee. 24 24.
DATA S4,84,S4,S4.2S4,25e, Ie. Ie
DATA , , 128.192
DATA 7.1S.1e,IS.26.20.26,20
DATA 24'.240.2S5,255,17',174, 174.174
DATA IS. lS.25S.2S5. 17 IS6. lS6.1So
DATA 224.240.24'.24'.164.164. 164.164
DATA IS4.1S4. IS4.1S4.1S4.1S4. 154.154
DATA 174.174.174.175.175.175. 175.17'
DATA IS6.1S6.1B6.2e 25 25 250.17'
DATA 166,166.166.166.166.166. 166.166
DATA 170,175.17S.174,174,174, 175,17S
DATA 170,234,234,170,170,170, 234,234
DATA 170, 170,17S,17~,170,170, 170,170
DATA 234,234,234,234,170,171'11, 170,170
DA TAl 7, 17, 17 , 17, 1 , 1 , 1 , 1
11~
12.
12e
131
141
IS.
16.
161
16S
17.
17~
lB.
IS5
19.
195
2
2.5
210
22.
225
230
23S
240
24~
2 ~f21
CLENt OUT I'EI'IDRY
Box 7B. ANTIC Mode 4 with Rocket
94 Atari Assembly Language Programme(s Guide
2~~ DATA 74,74,74,74,74,74,74,74,74
26. DATA 161,161,161,161,161,161, 161,161
26~ DATA 6B,6B,6B,6B,64,64,64,64
27. POKE 7~6,A+4
27~ REM * LOCATE START OF SCREEN MEMORY *
276 REM * POKE IN COLORS *
2B0 POKE BB,0:POKE B9,1~6
290 POKE 70B,6':POKE 7'9,16B:POKE 71',BS:POKE 712,B
29~ REM * PRINT ROCKET ON SCREEN *
296 REM * BE PATIENT THIS TAKES 14 SECONDS *
3111. POSITION 1121,6:? "6,"".'Y.&C"
31111 POS IT I ON 1', 7:? *6,'" () * "
32111 POSITION 1I11,e:? "6,"+,-."
33111 POSITION 1',9:? *6,"+1'."
34. POSITION 1',1':? "6,"+12."
3~' POSITION 1',11:? "6, "34~6"
360 GO TO 360
***NoTE*** The .creen will remain black for a fairly Ion;
of time
the character .et i. redefined.
p~riod
Box 7B. (cont.)
a.
Atari Graphics 95
A Useful Exercise
This exercise is primarily for AT ARI 400 and 800 owners. The
operating system of the XL I XE Series computers supports ANTIC
Mode 14 through the BASIC Statement Graphics 15. Write your own
ANTIC Mode 14 display list. 00 it from scratch, NOT by modifying a
Graphics 8 display list. Modifying a Graphics 8 display list into an
ANTIC 14 display list is too easy and misses the point of the exercise.
You will have to pay special attention to allocating screen memory into
blocks. At 40 bytes per scan line, 102 scan lines of ANTIC 14 needs
4080 bytes of screen memory. A full screen of ANTIC 14 has 192 scan
lines so there will have to be an LMS instruction somewhere before the
103rd scan line. But, there is more to it than that. What about the
relative positions of the two blocks of screen memory? The OS
calculates PLOTs and ORA WTOs on the basis of screen memory size.
What will happen if your two memory blocks are not contiguous? This
raises another question: How do you tell the OS what graphics mode
to use? OINOEX (location 87) accepts BASIC Mode numbers, not
ANTIC Mode numbers. Basic Mode 7 is a four color graphics mode so
maybe we can use that.. .. But, BASIC 7 uses 3840 bytes of screen
memory while ANTIC 14 uses 7680. What does that do to a
ORA WTO from the top of the screen to the bottom?
Box 8 is one solution to the display list problem that shows how to
plot to the bottom of the screen by POKEing numbers directly into
screen memory, but doesn't answer the problem of PLOTing and
ORA Wing on a full screen.
Page Flipping
From the knowledge that you have accumulated at this point, the
concept behind page flipping should be easy to grasp and almost as
easy to implement. The intent of page flipping is to reserve several
different sections of RAM for screen memory, each with its own
display, and 'flip' from one section to another simply by changing the
address bytes of an LMS instruction. One can flip whole screens or
parts of screens depending on where the LMS instruction is placed in
the display list. This technique is useful for animation or providing a
96 Atari Assembly Language Programmer's Guide
BOX 8
ANTIC Mode 14 Display List
1 REM ** ANTIC 14 DISPLAY LIST **
5 REM ** ANTIC MODE 14 DISPLAY LIST **
10 DL=32565
20 FOR B=0 TO 2:POKE DL+B,112:NEXT B
25 REM * PUT IN LMS BYTES *
26 REM * PUT IN FIRST 1/2 OF DL *
30 POf<E DL +3, 78
40 POKE DL+4,51:POKE DL+5,97
45 REM * PUT IN LMS BYTES *
50 FOR M=6 TO 99:POKE DL+M,14:NEXT M
55 REM * PUT IN LMS BYTES *
56 REM * PUT IN SECOND 1/2 OF DL *
57 REM * THIS CROSSES A 4K BOUNDARY *
60 POKE DL+100,78
70 POKE DL+101,51:POKE DL+102,112
80 FOR M=103 TO 199:POKE DL+M,14:NEXT M
85 REM * POINT TO START OF DL *
90 POKE DL+200,65
100 POKE DL+201,53:POKE DL+202,127
.110 POKE 560,53:POKE 561,127
115 REM * POKE IN START OF SCREEN MEMORY *
120 TOPSCRN=24883
126 REM * POKE IN COLORS *
127 REM * AND DRAW SCREEN *
130 POKE 708,60:POKE 709,168
140 POKE 710,88:POKE 712,10
150 FOR 1=0 TO 191
160 POKE TOPSCRN+5+40*I,5:NEXT
170 FOR J=0 TO 191
180 POKE TOPSCRN+15+40*J,10:NEXT J
190 FOR K=0 TO 191
200 POKE TOPSCRN+25+40*K,15:NEXT K
205 POKE 88,51:POKE 89 , 97
211~ GOTO 2 11~
Box 8. ANTIC Mode 14 Display List
variety of backgrounds upon which player / missile action can take
place.
There are a few things to consider concerning page flipping. First,
every screen uses memory even when it is not being displayed. Second,
you probably wouldn't use it with Graphics 8. At nearly 8K of RAM
per screen you can use up memory in a hurry! Consequently, page
flipping is used most often with the more memory efficient character
modes. Third, transitions between screens occur most smoothly if the
LMS address bytes are changed during the vertical blank. We've
Atari Graphics 97
included a program in Bo x 9-just to take so me of th e mystery out of the
process! This program Llses Graphics 2 a nd nips scree n memory from
page ze ro to the BASIC cartridge.
,
BOX9
~
1'"
20
30
40
50
60
REM ** PAGE FLIPPING **
GRAPHICS 2
DL=PEEK(560)+PEEK(561)*256
POKE DL+4,0:POKE DL+5,0
FOR 1=1 TO 100:NEXT 1
POKE DL+5,192
FOR I=l TO 100:NEXT 1
70 GO TO 3121
Box 9. Page Flipping
An additional comment is appropriate here. Many other home
computers set aside a limited number of static blocks of RAM for
screen memory. In principle, with the Atari Home Computer you can
use any section of RAM as screen memory. Flexibility such as this
allows you more room for creative approaches to programming. As an
example, one intriguing idea is that it is possible to store both your
display list or screen memory in strings, allowing you to use Atari
BASIC's string handling routines to change displays.
Color
Another facet that distinguishes the Atari Home Computer from
other popular computer systems is the greater number of colors
available. One reason for the larger color selection is that in an Atari
one can choose a luminance and a hue to produce a color rather than
simply specify just a color number. Luminance can be thought of as
98 Atari Assembly Language Programmer's Guide
regulating the intensity of the TV's electron beam which in turn
produces variations in brightness thereby permitting a variety of
shades of the 16 basic hues. There are eight choices of luminance and
sixteen hues which means that, in principle, there are 128 different
color choices. In actuality, some hue-luminance combinations may
look pretty much the same.
The Atari Home Computer gives you more than extra colors with
which to work. It gives you more options as to where and how to
display color. This flexibility is provided, in part, by nine color
registers that exist in two incarnations: as OS shadow registers and as
hardware registers. The colors you see while a program is running are
generated from information stored in the hardware registers. During
each vertical blank, the OS updates the hardware register values using
the data stored in the shadow registers. A crisp transition is insured
when a color is changed by a BASIC SETCOLOR command, or a
POKE to a shadow register because this transition actually occurs
when the screen is blank. Besides giving crisp color changes, the
existence of two complete sets of color registers is crucial to the
implementation of display list interrupt color changes.
Four of the nine color registers are devoted to players. The
remaining five registers are used with playfield graphics . The shadow
and hardware addresses of the color registers are listed 'in Table 3-6.
The hardware addresses are listed in Hi-Byte / Lo-Byte form, as well as
decimal, for convenience when you are writing machine language
routines.
Table 3-6. Color register addresses
FUNCTION
OPERATING SYSTEM
HARDWARE
LABEL
PCOLRO
ADDRESS
704
Player 1
PCLOR1
705
COLPM1
53267
208
19
Player 2
PCOLR2
706
COLPM2
53268
208
20
Player 0
LABEL
COLPMO
ADDRESS HI-BYTE LO-BYTE
18
53266
208
Player 3
PCOLR3
707
COLPM3
53269
208
21
Playfield 0
COLORO
708
COLPFO
53270
208
22
Playfield 1
COLOR1
709
COLPF1
53271
208
23
Pl ayfield 2
COLOR2
710
COLPF2
53272
208
24
Playfield 3
COLOR3
711
COLPF3
53273
208
25
Backround
COLOR4
712
COLBK
53274
208
26
Atari Graphics 99
By now you realize that all control registers in a computer system
perform different functions according to the bit pattern that has been
set. The color registers are no exception to this general rule. The color
register format is:
I~I'-~t
I I I I I I ~
I
t
not used
Hue nibble
Luminance
Taken as a group of four bits, the hue nibble can have any value
between 0 and 15. Corresponding to these numbers are the hues listed
in Table 3-7. To POKE, or store a hue value in the left four bits of an 8
bit color register it is first necessary to mUltiply the decimal value (0 to
15) by 16 (see Table 3-7). Luminance is determined by bits D1 to D3 of
the color register. Since bit Do is not used, luminance is effectively
determined by the even numbers 0 through 14 with fourteen being the
highest luminance and therefore the brightest. To set these bits in a
color register simply add the luminance value to the appropriate hue
number:
COLOR NUMBER
= (VALUE IN COLUMN 3) + LUMINANCE
Upon power up the operating system sets default colors in the
playfield registers 708 through 712 . The player color registers 704
through 707 are all set to zero (black). Of course, the playfield registers
can be changed with the BASIC SETCOLOR command while player
color registers must be changed with a POKE or a machine language
store instruction. Table 3-8 lists all display modes, the number of
colors available and the default colors . Tables 3-8 and 3-4 are useful
for planning custom display lists .
100 Atari Assembly Language Programmer's Gu ide
Table 3-7 Hues
=-=-=--=HUE
Black
Rust
Red-orange
Dark-orange
Red
Lavender
Light purple
Purple blue
Medium blue
Dark blue
Blue grey
Olive green
Green
Yellow green
Orange green
Orange
NIBBLE VALUE
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POKEORSTOREVALU~
16
32
48
64
80
96
112
128
144
160
176
192
208
224
240
Atari Graphics 101
Table 3-8. Displa y modes with ava il ab le number of co lors a nd default colors
NUMBER
OF
COLORS
DISPLAY
MODES
SHADOW
COLORS REGISTERS
DEFAULT
BASIC 0,8 Light Blue
1 Hue
2 Luminances ANTIC 3 Dark blue
Black
709
710
712
TWO
COLORS
BASIC 4,6
ANTIC 12
Orange
Black
708
712
FOUR
BASIC 4,6
3,5,7
Orange
LtGreen
ANTIC 14
Blue
Black
708
709
710
712
Orange
Lt Green
Blue
Red
Black
708
709
710
711
712
COLORS
BASIC 1,2
FIVE
ANTIC 4,5
COLORS
..
NOTES
Regist. determ .
Background
Border
COLOR 1
Background
(COLOR 0)
COLOR 1
COLOR 2
COLOR 3
Background
(COLOR 0)
BASIC 1 &2 color
GTIA Modes
Graphics Modes 9, IO and 11 are enhancements of Graphics 8 that
give extended color choices. Briefly, Graphics 9 allows 16 luminances
of one hue; Graphics 10 allows the selection of nine colors; Graphics II
allows 16 hues with one luminance . These Modes are referred to as
GTIA Modes because their appearance on the screen is determined,
not by an instruction in ANTIC's display list, but by the setting of bits
D6 and D7 in the GTiA hardware register PRIOR (53275).
102 Atari Assembly Language Programmer's Guide
Bit: 0 7
0 6 Mode
U Determined by ANTIC's DL
1
Mode 9
o Mode 10
Mode 11
The remaining bits, Do to Os , of PRIOR are used in player/ missile
graphics and their function will be described later in this chapter.
The display list used by ANTIC with the GTIA Modes is a full
screen Graphics 8 display list. The difference between the GTIA
Modes, individually and in comparison with Graphics 8 is how the
data in screen memory is used . In Modes 9,10 and II, GTIA uses four
bits of data for each pixel. Using four bits increases the information
that can be transferred from memory to the screen. However, to keep
memory requirements within reasonable limits something had to be
given up, and in this case it is horizontal resolution. The pixels in the
GTIA Modes are one scan line high and two color clocks (four
machine cycles) wide . Consequently, the display resolution is 80 by
192.
Now, let's see how these modes work. Recall that a color register
has the following structure:
I
07
06
Os
04
03
O2
0,
Do
I
~~
Hue Nibble
Luminance Nibble
In Graphics 9, which gives the option of one hue and sixteen
luminances, the hue nibble of color register 712 (hardware equivalent
53274) is fixed and the luminance value can be changed. This mode
differs from all other display modes in that all bits in the luminance
nibble are used. From BASIC the luminance is changed with a
COLOR N statement, where N is a number from 0 to 15. If you are
working from machine language, however, it is sometimes useful to
have a memory location in which to store a value that will determine
the color displayed. The following demonstration program illustrates
Atari Graphics 103
that POKEing the numbers 0 to 15 into memory address 200 achieves
the same effect as CO LO R N.
When setting the hue values in color register 712 for Mode 9, you
want to be sure that bits Do - D3 are left as zeros . From BASIC that is
handled automatically with the command SETCOLOR 4,HUE O.
When using a POKE or a machine language store, you will want to
check the bit pattern of the number being stored. The reason for this is
based on how the value in the color register is combined with the pixel
data in screen memory to get the final display color number. The
display color number is arrived at by a logical ORing of the value in
register 712 with pixel data. For example:
Register 712
Pixel Data
0 0 0 0 Hue 13 Ok Green
o 1 0 Luminance 6
0 1 1 0 Display color #
But suppose the value stored in 712 inadvertently had some extra bits:
register 712
Pixel Data
o
o
1
1
01 Hue13 Ok Green
0 Luminance 6
Display Color #
104 Atari Assembly Language Programmer's Guide
Because of the way a logical OR works (see Box 3), the final luminance
value is IS, not 6 as originally desired.
Graphics II works analogously to Graphics 9 except that now the
luminance value is taken from Bits D1 - D3 of color register 712. Since
Do is not used, there are only eight luminances. The hue value used in
plotting is specified with a COLOR N, or POKE 200,N statement,
where N is a number from 0 to 15. Table 3-7 lists colors and their
corresponding number. Again the final color number is obtained by a
logical ORing of the hardware register a nd the pixel data. This time,
the color register should be set up with zeros in the left hand nibble so
that the ORing doesn't modify the final color data.
Graphics 10 makes use of all nine color registers 704 - 712 (53266
-53274). The color number is derived in the usual manner:
COLOR NO. = HUE *16+LUMINANCE
Registers 708 through 712 can be set with either the SETCOLOR
command or a POKE. Color in registers 704 through 708 must be set
with POKE statements. Colors to PLOT or ORA W with can be chosen
with COLOR N or POKE 200,N. However, now N is restricted to 0 to
8. Zero selects 704, one selects 705, and so on. Numbers from 9 to 15
will select one of the lower value color registers.
The GTIA Graphics Modes will run very much the same way as
other display modes. This means that you can use standard graphics
commands, player / missiles , and the full set of ANTIC options .
A Digression
When one gets involved in programming in BASIC or another
higher level language it is easy to lose sight of what's going on at the
machine level when a sequence such as,
10 COLOR 3
20 PLOT O,O:DR. 40,40
Atari Graphics 105
is executed. Suppose you are working in Graphics 10. Then the above
two lines will cause the execution of a number of subroutines that will
store the bit pattern 0 101 into screen memory in such a way that when
the screen memory is accessed by ANTIC, a colored line is displayed
diagonally on the screen. In the other display modes how the data in
screen memory is interpreted differs from the GTIA Modes but the
idea is the same. Screen memory contains information that is read and
interpreted by ANTIC and GTIA. At this point we would like to
remind you that there is absolutely no reason why you have to rely
entirely on BASIC commands such as PRINT, PLOT, DRA WTO,
and the OS to place data into screen memory. The two programs in
Box II illustrate this point. Program A draws a diagonal line with
PLOT and DRAWTO. Program B usesa FOR NEXT Loop to put the
data that generates the line directly into screen memory.
If you think back to the exercise we proposed with the ANTIC 14
display list, there is a problem using the OS's routines for PLOT and
DRA WTO . POKEing 87,7 gives you four color graphics, but limits
you to using only half the screen . The above discussion provides a clue
to one approach to using ANTIC display modes; write routines that
place display data directly into screen memory.
r
10
20
30
40
50
BOX 11
"""
GRAPHICS 10
POKE 704,144:POKE 707 , 88
COLOR 3
PLOT 0,0:DRAWTO 40,40
GOTO 50
"Box 11. Method of Displaying
r
10
20
30
40
50
60
..J
BOX 11B
""
GRAPHICS 10
POKE 704, 144 :POKE 707,88
START=PEEK (88) +PEEK(89)*2 56
FOR 1=0 TO 39
POKE START+41*I , 3: NEXT I
GOTO 60
~
Box 11B. Method of Displaying
.J
106 Atari Assembly Language Programmer's Guide
Artifacting
Artifacting is a method of putting color on the TV screen that
depends on three things: (I) how the TV produces color; (2) how the
human eye interprets combinations of color; and (3) the two to one
relationship between machine cycles and color clocks in the display
modes BASIC 0,8 and ANTIC 3.
To produce color, the inside of a color television screen is coated
with an array of dots that glow in red , green, and blue when struck by
electrons. By controlling the brightness of each dot, it is possible to
produce any desired color. At normal viewing distances, the dots are
too small for the human eye to perceive individually and so the colors
appear to merge into a single image.
The signal sent to a color television set is called a composite video
signal. It consists of horizontal and vertical synchronizing pulses ,
brightness information (luminance), and a 3.58 MHz "subcarrier" that
contains color information (chrominance) . This 3.58 MHz frequency
is a standard value designed into color TV circuitry. Incidentally, if
you divide 3.58 MHz by 2, the result is 1.79 MHz, the frequency of the
Atari CPU. In the composite video signal, the luminance is the
primary signal. Whenever the luminance changes it forces a phase shift
or timing change in the color signal. The phase or timing of the
chrominance signal is crucial to determining the color displayed. If the
luminance is changed on a whole color clock boundary, the color is
unaffected. However, ifthe luminance is changed on a half color clock
boundary, it will affect the colors. This is the reason that artifacting is
used in those modes that have one color, two luminances and a pixel
width of one-half color clock. Box 12 is a short program that illustrates
artifacting.
Atari Graphics 107
BOX 12
Artif&cting
5 REM ** ARTIFACTING **
20 GRAPHICS 8:SETCOLOR 2,0,0
30 COLOR 1
40 REM * DRAW A SERIES OF VERTICAL BARS *
50 FOR 1=1 TO 315 STEP 4
60 PLOT I, 10:DRAWTO 1,100
70 NEXT I
80 REM * REM DRAW VERTICAL BARS SHIFTED ONE HALF COLOR CLOCK
*90
FOR 1=0 TO 315 STEP 2
100 PLOT I,30:DRAWTO I,50:NEXT I
11~ REM * MORE VERTICAL BARS SHIFTED AGAIN
120 FOR 1=0 TO 315 STEP 3
130 PLOT I,60:DRAWTO 1,80
140 NEXT I
Box 12. Artifacting
Character Set Graphics
Among the many reasons for the superior graphics capabilities
of Atari Home Computers is the relative ease of using redefined
characters. Redefined characters are invaluable in playfield graphics
for games, simulations, and utilities. They may be used in any of the
BASIC or ANTIC text modes to draw blueprints, schematics,
scientific symbols, icons, maps, trees, ... almost anything you may need
to add realism and interest to a program. Another attractive feature of
character set graphics is that it allows you to create a high resolution
type screen with much less memory.
A character set is the table of data the Atari Home Computer uses
to define each letter or shape that it displays in text modes. Each
character is represented by a sequence of eight bytes. The Atari stores
128 characters in ROM at locations 57344 to 58367. Each character
and each inverse video character has been assigned a number from 0 to
255 (see Appendix E). These numbers are the AT ASCII Codes.
However the characters are not stored in ROM in AT ASCII order.
The order in which the characters are stored in ROM is listed in Table
9.6 of the Atari BASIC Reference Manual and here in Appendix F.
We have referred to this ordering of the characters as the internal
character code. (There are three misprints in our edition ofthe BASIC
108 Atari Assembly Language Programmer's Guide
Reference Manual. Internal character number 13 should be the minus
sign; character 14 should be the period ; and character 63 should be the
underline key.) This table is necessary in planning which characters
you are going to redefine and eliminates using complicated formulas
that have been devised to change AT ASCII code into internal
character numbers.
The character modes are BASIC Modes 0, 1,2 and ANTIC Modes
3,4,5. BASIC Mode
and ANTIC Modes 3,4,5 use the full 128
character set. BASIC Modes 1 and 2 use the first 64 characters listed in
Table 9.6 or Appendix F . Characters are plotted on the screen using 8
x 8 grids of pixels. The size of each pixel depends on the text mode
used. Each row of pixels is a byte of data with a 1 representing a lighted
pixel and a representing an unlighted pixel. For example:
CHARACTER
DATA BYTES
0 0
0
0
0
1
()
0 ,
0
0
0
()
0 0
Figure 3-8. Lighted and unlighted pi xe ls
Now you can see why each character occupies eight bytes in memory.
There is one byte for each row of pixels. The spacing between lines of
print on the screen is made by leaving the top and bottom rows of the
grid unlit. There are spaces between characters only if you construct
them that way. Thus, you may build up large pictures by combining
characters.
There are four basic steps to follow when redefining characters.
These are:
Atari Graphics 109
1. Construct and define your characters on an 8 x
8 grid. For large pictures use graph paper to
sketch out the complete set of characters that
make up your picture.
2. Move the standard character set from ROM to
RAM.
3. Revise the relocated standard set by POKEing
in you new data.
4. Print the redefined characters on the screen.
Step 1: Construct and define your characters. Figure 3-9 is an
example of a character that is used in the program in Box 14 .
11000000
1100000
o , 1 1 0001
o 1 1 1 1 1 10
0011 0000
00011 000
00 d 11 001
00011
001
128 +64
128t64t32
I
64132+16
64'32.1618.4,2
32 t 16
16.8
.1
1618
16.8
192
" 224
~ 112
=126
'48
24
.24
+1 .24
Figure 3.9. Example character
The sequence used to construct a character can be seen from this
figure. The character is sketched on graph paper. Then each lit pixel is
indicated by a I, each unlit pixel by a O. The resulting eight bits are
treated as a binary number which is converted into a decimal number.
The decimal numbers are the data that define the character and will be
stored sequentially in memory starting with the top byte.
When you have to redefine a large number of characters,
converting the binary numbers to decimal numbers is a tedious job.
The program in Box 13 is a simple utility that generates a character's
data numbers and print them on the screen or printer. The program
displays an 8x8 grid of "Os." Starting with the upper left '0,' a
question mark is displayed. If you want the pixel at the location of the
question mark lit, type 'yo and an 'X' is displayed. If you do not want
110 Atari Assembly Language Programmer's Guide
the pixel lit, type 'N' and the '0' is erased. After running through a grid
you may edit and then print out the data.
Step 2: Move the standard character set from ROM to RAM.
Strictly speaking this step is necessary only if you intend to use some of
the standard characters. In BASIC this is done by PEEKing each ROM
location from 57344 to 58367 (in BASIC Modes I and 2 from 57855 to
58367) and POKEing the value into a RAM location. Before doing this
you must reserve a safe place in memory. As we discussed in the section
on display lists one way to secure a safe location is to lower RAMTOP.
BOX 13
Utili ty P"'OQra/ll
BASIC Cha,..act.,.. a.ne,..ato,..
**
**
5 REM
CHARACTER GENERATOR
HI DII'1 D (8)
::I~ OPEN #2,4, 0, "f<: "
:3111 GRAPH I CS 2
35 REM
DISPLAY GRID
40 FOR J=l TO 8:FOR 1=6 TO 13
5el POSITION I,J:? +16;"0"
6111 NEXT I: NEXT J
70 PRINT "TYPE Y FOR PIXEL LIT"
8Ji1 PRINT
9111 PRINT "TYPE N FOR PIXEL OFF"
100 FOR J=1 TO 8:FOR 1=6 TO 13
110 POS I T I ON I, J:? +16; '":' ''
120 REM
GET USER'S CHOICE AND COMPUTE DATA NUMBERS
130 GET +l2,CHOICE
140 IF CHOICE=ASC ("Y") THEN GOTCJ 56111
150 IF CHOICE=ASC("N") THEN POSITION I,J:? +16;" " :GOTO 170
16111 GOTO 120
170 NEXT I
180 D(J)=DECICODE
190 DEC I CODE=~~
200 NEXT J
210 REM
GIVE USER A CHANCE TO EDIT
220 PRINT :PRINT
230 PRINT "EDIT LINE ( Y, N ) "
240 GET +12, ED IT
2~0 I F ED IT=ASC ( "Y" ) THEN GOTO 611~
260 IF EDIT=ASC ("N") THEN GOTO 290
27121 GOTO 240
280 REM
GIVE USER AN OUTPUT OPTION
PRINT :PRINT
(Continued on next page)
Atari Graphics 111
31MI PRINT "PRINT TO SCRE EN OR F'RINTER (F' , !3) "
3110 GET #2,OPTION
32121 I F OPT I ON=ASC: ( "P " ) THEN GOTO 4111121
3 3 m I F OPT I ON=ASC ( "S" ) THEN GOTO .3 ~f21
34121 GOTI] 3lilJ21
35111 PR I NT : FOR P= 1 TO 8: ~ D (P) ; " , " ;
3 6QI NEXT P
3 7 121 GOTD 480
380 REM * OUTPUT TO EP SDN PRINTER *
J90 REM * YOUR FORMAT MA Y DIFFER *
41110 OPEN #3,8,0,"P:"
410 FOR P=1 TO 8
420 PRINT #3,D(P),
430 PRINT #3;" " j
440 NEXT P
4~0 PRINT #3
460 CLOSE #3
470 PRINT :PRINT
480 PRINT :PRINT
49121 PRINT " , C' TO CoNT. ' Q' TO QUIT"
~0f21 GET #2,oPTIoN
~10 IF oPTIoN=-ASC("C")
THEN GoTo 3121
~20 IF oPTIoN""ASC("Q")
THEN GOTO 540
530 GoTo 490
540 END
550 REM * ALGORITHM TO COMPUTE DATA NUMBERS *
56QI POWER= I NT ( (2 -' ( 13- I) ) +0. 1) : POS I T I ON I, J:? *6," X"
570 DECICODE=DECICODE+POWER
5Bf2I IF FLAG=-1 THEN GoTo 710
59111 GOTO 17121
600 REM * EDITING ROUTINE *
61121 TRAP 610:PRINT "TYPE LINE NUMBER (1-8) RETURN"
62121 INPUT J
630 FLAG"1
640 TRAP 4012100
650 FOR 1"'6 TO 13:PoSITION I,J:? #6;"0":NEXT
660 FOR I -6 TO 13: POS IT ION I, J : 7 #6'''?''
670 GET #2,CHOICE
680 IF CHOICE""ASC("Y") THEN GOTO ~60
690 IF CHOICE"'ASC("N") THEN POSITION I,J:? #6;" ":GoTO 710
700 GOTo 670
710 NEXT I
72121 FLAG"0
730 D(J)"'DECICODE
740 FLAG=0:DECICODE=f21
GoTo 2310
BOX 13 continued
112 Atari Assembly Language Programmer's Guide
In the program in Box 14, lines 10 through 70 lower RAMTOP 8 pages
and move 64 characters from RO M into RAM starting at a location 4
pages above RAMTOP. This leaves a 1K buffer between RAMTOP
and the character set. There is one general rule to observe: The
character set must begin at the start of a memory page.
Step 3: Redefine the character set. Choose the characters listed in
Appendix E that you are changing and POKE in new data numbers. In
Box 14, lines 80 through 230 change characters 3 through 15 (#
through j). The redefined characters will be identified with the internal
code and the corresponding symbol of the character they replace.
When choosing characters to modify, it makes sense to choose a
continuous sequence for ease in programming.
Step 4: Displaying the characters on the screen. The new
character set will not be displayed on the screen if the OS is not aware
of its existence. Memory locations 756 (CHBAS - shadow register) and
54281 (the corresponding hardwa re register) store the page number of
the start of the character set currently in use. Switch character sets by
POKEing the appropriate address in 756. This instruction must come
after the GRAPHICS command that sets up the screen. Each time a
GRAPHICS command is executed, the OS sets 756 back to the ROM
character set. Once CHBAS is changed new characters may be printed
to the screen using the standard symbols as their names or POKEing
their internal code numbers directly into screen memory.
When you type in the program in Box 14 and run it you will
discover that using BASIC to redefine a character set is slow. The
process can be speeded up immensely by using short machine language
routines to move and redefine the character set and by storing the new
character set data as a string. We will explain how to do this in the next
chapter.
ANTIC Modes 4 and 5 (BASIC 12 and 13 in XLIXE Series)
Antic Modes 4 and 5 are four color character modes specifically
designed to be used with redefined character sets. As we previously
discovered, if you increase color options then you have to give
something up. Here, once again, it is resolution. BASIC Mode 0
characters are 8 x8 grids of pixels; ANTIC Mode 4 characters are 4 x 8
Atari Graphics 113
5 REM ** REDEFINED CHARACTERS **
10 POKE 106,PEEK(106)-8
20 GRAPHICS 2+16
30 A=PEEK(I!2l6)
4!2l START=(A+4)*256
50 FOR R=0 TO 511
6!2l POKE START+R, PEEK (57344+R)
70 NEXT R
8121 FOR X=12I TO 11213:READ P
9!2l POKE START+3*8+X,P
100 NEXT X
11121 DATA 192,224,113,126,48,24,25,25
120 DATA !2l,126,129,0,~,0,129,129
13~ DATA 3,7,30,126,12,24,152,152
14~ DATA 8,4,2,1,!2l,~,63,~
15~ DATA 49,96,192,192,192, 163,242,164
16~ DATA !2l,!2l,!2l,!2l,24,255,24,24
170 DATA 14!2l,6,3,3,3,197,79,69
18!2l DATA 16,32,64,128,!2l,!2l,252,~
19~ DATA 0,1,2,4,8,!2l,~,0
2~~ DATA 192, 128,64,32,16, 15, !2l, !2l
21!2l DATA 24,24,24,126,129,O,O,O
22!2l DATA 3,1,2,4,8,24!2l,~,~
230 DATA ~,128,64,32,16,!2l,0,0
24~ POKE 756,A+4
250 POSITION 9,1:? .. 6;""$;'''
260 POSITION 8,2:7 "6;"&<' ()*"
270 POSITION 8,3:7 "61"+,-.1"
28~ GOTO 28~
Box 14. Redefining a character set using BASIC
grids of pixels . On the screen, Mode 4 pixels are twice as wide as
Graphics 0 pixels so the characters come out to be the same size.
ANTIC Mode 5 pixels are the same width but twice as high (16 scan
lines) as Mode 4 pixels. In Mode 4 and 5 the standard characters are
unreadable.
Each pixel is assigned a pair of bits that determine the color
register used to display it. Color register selection is made according to
Table 3-9.
114 Atari Assembly Language Programmer's Guide
Table 3-9. Color register selection
Bit Pair
Internal Char.
Codes 0 - 127
Normal Video
Internal Char.
Codes 128 - 127
Inverse Video
00
01
10
11
COLBAK 712
PFO 708
COLBAK 712
PFO 708
PF1 709
PF3 711
PF1 709
PF2710
Storing the data in memory and putting ANTIC Mode 4 and 5
characters on the screen follows the same procedure described
previously. However, constructing ANTIC Mode 4 and 5 characters is
a slightly different task than redefining character sets for the other
modes.
To define your ANTIC Mode 4 characters, you will, of course,
want to sketch your picture in color first. Then assign colors to the
color registers listed in Table 3-8. Generating character data then
becomes a matter of coloring in a character and translating from color
to binary number to decimal number. For example suppose we want to
design this character as part of a space ship:
LIGHT
SLUE
~
ELLOW
Figure 3-10. Designing a character
Atari Graphics 115
We'll make the register assignments as:
00
01
10
11
COLBAK
PFO
PF1
PF2
00 01 01 01
00 01. 01 01
10 10
10 10
10 10
JO 10
10 11
to
11
10
10
10
10
'\0 10
10
10
10 1 1
10 1 1
712
708
709
710
LT . BLUE
DARK BLUE
YELLOW
RED
000 I 0 I 0 I
000 I 0 10 I
21
21
170
170
I 0 I 0 I0 I 0
I 0 I 0 I 0 I 0
I 0 I 0 I 0 I 0
170
10/0/010/70
101 I I 0 I I
187
101 I 101 I
187
Figure 3-11. Register assignments
At best, this is a tedious job so we have included a simple character
editor in Box 15.
Player Missile Graphics
Probably more has been written about Atari's Player Missile
(PM) graphics than any other feature of the Atari system. Certainly a
good portion of the reason for this is that PM graphics is essential for
high quality animation in games, and games are fun! Another part of
the reason for interest in PM graphics is that you can do things with
PMs that you can't do as easily with character set or map mode
graphics. Consequently, there is a small increase in the complexity of
the ideas involved and the number of concepts to be explored and this
also generates more articles.
116 Atari Assembly Language Programmer's Guide
Player Missile graphics is, to a great extent, independent of other
display graphics. You can use PMs in animation and games, but you
can also use PMs to enhance character set and map mode graphics. We
urge you to approach the topic of PM graphics receptive to the idea
that you can use PM for more than games. We will begin by discussing
the nature and characteristics of PM graphics. Then we will describe
how to set them up and what you can do with them.
The reason PM graphics is independent of playfield graphics is
that data for PM graphics is separate from the data used for character
or map mode graphics. You can think of ANTIC and GTIA as taking
information from two different sections of memory and from two
different sets of color/ control registers and combining it into one
video signal. In a sense the PM graphics information is superimposed
on the signal that generates the playfield. There is a fundamental
difference between screen memory organization, player memory
organization, and how the two are related to pixels on the TV screen.
Earlier in the chapter we said that in Graphics 2, the first 20 bytes
in screen memory correspond to the first row of characters (pixels) on
the screen, the second 20 bytes in screen memory to the second row of
pixels, and so on. This describes the mapping of the two dimensional
screen array into a linear memory array. With PM graphics, a linear
array of either 128 or 256 memory bytes is mapped into a vertical
column eight pixels wide on the screen. There are four players, labeled
Atari Graphics 117
BOX 1:S
Uti 11 ty ProQralll
ANTIC Character Benerator
20 REM ** MULTICOLORED CHARACTER EDITOR **
30 REM * TO USE THIS PROGRAM YOU SHOULD *
40 REM * HAVE A COLORED SKETCH FROM *
~0 REM * WHICH TO WORK *
60 PRINT "}"
7m DIM DN(8)
80 OPEN +12,4,0, "K: "
90 PRINT
100 PRINT "INPUT COLOR SELECTIONS"
110 PRINT
121Z1 PRINT "COLOR NO. - 16*HUE+LUMINANCE"
130 PRINT
140 PRINT "COLOR NUMBER TO GO WITH 01Z1 IS"
1511) INPUT A
160 PRINT
17121 PRINT "COLOR NUMBER TO GO WITH 01 IS"
1811) INPUT B
1911) PRINT
200 PRINT "COLOR NUMBER TO GO WITH 10 IS"
210 INPUT C
220 PRINT
230 PR I NT "COLOR NUMBER TO GO WITH 11 IS"
241Z1 INPUT D
2~1ZI REM * DISPLAY COLOR CHOICES ON THE CHOSEN BACKGROUND *
2~~ REM * COLOR CHOICES WILL AFFECT TEXT WINDOW
LEGIBILITY
261Z1 GRAPHICS 7
270 POKE 712,A:POKE 708,B:POKE 709,C:POKE 710,0
280 COLOR 1:Q=~:GOSUB ~000
290 COLOR 2:Q-4~:GOSUB ~000
300 COLOR 3:QE8~:GOSUB ~1ZII1)0
310 PRINT "TYPE E TO EDIT"
320 PRINT
330 PRINT "TYPE G TO GO ON"
340 GET +l2,OPTION
350 I F OPT I ON-ASC ( "E" ) THEN 14111
360 IF OPTION=ASC("GOO ) THEN 390
3"1t11 GOTD 340
380 REM * DISPLAY GRID *
390 GRAPHICS 2
400 FOR J=1 TO 8:FOR 1=6 TO 13
411~ POS I T I ON I, J: ') +16;
420 NEXT I:NEXT J
430 PRINT OOTYPE QI OR 1 IN"
440 PRINT
00
'"
Box 15. Utility Program ANTIC Character Generator
118 Atari Assembly Language Programmer's Guide
480
490
500
51121
52121
530
54121
550
560
5712l
58121
59fZl
6121121
61121
62fZl
63fZl
64121
65121
66121
670
68121
69121
700
71121
72121
73121
74121
75121
760
77fZl
78fZl
79fZl
80121
81121
82fZl
830
84121
850
86121
870
880
890
PRINT "RESPONSE TO '?'
FOR J e 1 TO 8:FOR 1=6 TO
POSITION I, J:? *6; "?"
REM * GET USER'S CHOICE
GET *2,CHOICE
IF CHOICE=ASC("1") THEN
IF CHOICE=ASC("0") THEN
GO TO 260
NEXT I
13
AND COMPUTE DATA NUMBERS
920
POSITION I,J:? "6, "121": GOTO 53fZl
DN(J)~DECICODE
DECICODE-12l
NEXT J
REM * GIVE USER A CHANCE TO EDIT *
PRINT :PRINT
PRINT "EDIT LINE?
(YIN) "
GET "2, ED IT
IF EDIT-ASC ("Y") THEN 97121
IF EDIT=ASC("N") THEN 65fZl
GOTO 6121121
REM * GIVE USER AN OUTPUT OPTION *
PRINT :PRINT
PRINT "PRINT TO SCREEN OR PRINTER? (PIS)"
GET "2,CHOICE
IF CHOICE-ASC("P") THEN 760
IF CHOICE'"ASC("S") THEN 71121
GOTO 670
PRINT :FOR pool TO 8:PRINT DN(P),","I
NEXT P
GOTO 84121
REM * OUTPUT TO EPSON PRINTER *
REM * YOUR FORMAT MAY DIFFER *
OPEN *3,8,0,"P:"
FOR P"l TO 8
PRINT *3,DN(P),
PRINT "3," '"
NEXT P
PRINT .. 3
CLOSE *3
PRINT :PRINT
PRINT :PRINT
PRINT "C TO CONT. OR Q TO QUIT"
GET "2,OPTION
IF OPTION-ASC("C") THEN 390
IF OPTION-ASC("Q") THEN 9121121
GOTO 86121
END
REM ALGORITHM TO COMPUTE DATA NUMBERS
POWER-INT2 (l3-I+f2I. l):POSITION I,J:?
A
Box 15. (cont.)
Atari Graphics 119
930
940
950
960
970
980
990
DECICODE=DECICODE+POWER
IF FLAG=1 THEN 1070
GIJTIJ 530
REM EDITING ROUTINE
TRAP 970:PRINT "TYPE LINE NUMBER (1-8)"
INPUT J
FLAG=1
10m0 TRAP 4011100
11~1I/1 FIJR 1=6 TO 13: POSITION I, J: 7 116,"''': NEXT
1020 FOR 1=6 TO 13:POSITION I,J:7 116;"7"
1030 GET 112,CHOICE
1040 IF CHOICE-ASC("I") THEN 920
111!~11I IF CHOICE=ASC("0") THEN POSITION I,J:? l+6,"0":GOTO 111!7!1l
1060 GOTO 1030
11117111 NEXT I
1080 FLAG-0
109111 DN(J)=DECICODE
1100 FLAG-0:DECICODE=0
1110 GOTO ~90
1120 REM
1130 REM
5000 FOR 1-1 TO 10
~01111 PLOT Q,~0+I:DRAWTO Q+~,51/1+I
502121 NEXT I
503111 RETURN
Box 15. (cont.)
120 Atari Assembly Language Programmer's Guide
PO - P3 and four missiles , MO - M3. Missiles are columns that are two
pixels wide. Each missile is associated with the player of the same
number by the simple technique of having both ofthem the same color.
The four missiles can be combined to form a fifth player. In order to
combine the four missiles into a player the bit D" of PRIOR (53275)
must be set. This may be done by POKEing 16 into its shadow register
at memory location 623. This sets the "fifth player enable bit". However,
using the fifth player from BASIC is clumsy since each missile retains
its own width and horizontal position. Consequently, moving the fifth
player horizontally entails four POKEs, one for each missile. The only
feasible way to utilize this option is to program the movement in
machine language.
Organization of player memory so that it represents a column on
the screen greatly simplifies movement of an image from one place to
another. Horizontal positions can be changed with a simple POKE or
ST A. Vertical positions can be changed with a short, efficient machine
language routine. The result is that animation can be accomplished
more smoothly and more rapidly than if you were moving bytes
through the normal screen memory.
PM graphics works like the normal BASIC character set graphics
in that bit mapping is used to display a pattern. As usual, "I" equals
pixel on and "0" equals pixel off. Player and missile pixel sizes can be
varied. There are two choices of vertical resolution: one scan line, (256
byte player) or two scan lines , (128 byte player). Normal horizontal
resolution of the players is eight color clocks. There is the option to set
individual players to widths of sixteen or thirty-two color clocks. The
widths of all missiles is set the same: either two, four, or eight color
clocks. Colors for each player and its associated missile are taken from
the four color registers 53266 - 53269 which are shadowed at 704
through 707.
Part of the complexity of PM graphics revolves around the fact
that there are over thirty registers or memory locations that can be
used to implement various options. In addition, some of these registers
have dual functions. To impose some order on this chaos, we have
prepared two tables that list the registers and their functions. Table
3-10 lists the general PM graphics control registers. Table 3-11 lists the
hardware registers that serve dual functions.
Atari Graphics 121
Table 3-10. Player Missile Graphics Control Registers
Player Missile Graphics
CONTROL REGISTERS
SDMCTL
559 (shadow)
DMACTL
54272 (hardware)
Direct Memory Access (DMA) enable Bit assignments are as follows:
0 1 Do Playfield Options:
00
o1
10
11
O 2 Missile DMA
no playfield
narrow playfield
standard playfield
wide playfield
0= disable
= enable
0 3 Player DMA
0= disable
1
enable
0 4 P/M Resolution
0= 2 scan lines (default)
0 5 DMA Enable
= 1 scan
line
0= shuts ANTIC off/speed up
CPU
1 DMA enable
GPRIOR
623 (shadow)
PRIOR
53275 (hardware)
This register selects which parts of the screen display wi II have priority
and allows several other options. Bit assignments are as follows:
continued on next page
122 Atari Assembly Language Programmer's Guide
BIT
HIGHEST PRIORITY - - -..... LOWEST
Do, if set :
0" if set:
Player 0-3/ Playfield
Player 0-1 / Playfield
ground
Playfield 0-3/ Player
Playfield 0- 1/ Player
Backg round
O2 , if set:
0 3, if set:
0-3/ Background
0-3/ Player 2-3/ Back0-3/ Background
0-3/ Playfield 2-3/
Only one of the above bits should be set at one time.
0 4 , if set:
Four missiles combine to a fifth player
Overlaps of players give a third color
Os, if set:
6
}
Enable GTIA Modes
07
COLOR
704-707
OS shadow color registers for Player 0 Player 4
Hardware color registers for Player 0Player 4
53266-53269
GRACTL
53277
Graphics ConTrol.
To turn on missiles set bit Do
To turn on players set bit 0 1
This register is also used with trigger inputs .
PM BASE
54297
This location, in pages, of the Player/ Missile shape data. See discussion
in text on how player miss ile memory is organized.
Atari Graphics 123
Table 3-11. Dual Function Hardware Registers
Dual Function Hardware Registers
LABEL
(W)=write
DECIMAL
(R)=read
HEX
HPOSPO
53248
0000
53249
0001
53250
0002
53251
0003
M2PF
HPOSP3
53252
0004
(W) horizontal position
of missile 0
53253
0005
(W) horizontal position
of missile 1
(R) player to playfield collision
53254
0006
(W) horizontal position
of missile 2
(R) player to playfield collision
P1PF
HPOSM2
(W) horizontal position
(R) player to playfield collision
POPF
HPOSM1
(W) horizontal position
of player 2
(R) missile-playfield collision
of player 3
(R) missile-playfield collision
M3PF
HPOSMO
(W) horizontal position
of player 1
(R) missile-playfield collision
M1PF
HPOSP2
(W) horizontal position
of player 0
(R) missile-playfield collision
MOPF
HPOS1
FUNCTION
P2PF
(cant. on following page)
124 Atari Assembly Language Programmer's Guide
HPOSM3
53255
0007
P3PF
MOPL
(R) player to playfield collision
53256
0008
SIZEPO
M1PL
53257
0007
(R) missile 1 to player
collision
(W) size of player 1
53258
DOOA
(R) missile 2 to player
collision
(W) size of player 2
SIZEP2
M3PL
53259
0008
(R) missile 3 to player
collision
(W) size of player 3
53260
DOOe
(R) player 0 to player collision
SIZEP3
POPL
(W) size for all missiles
SIZEM
GRAFPO
53261
DODD
P1PL
GRAPFP1
(R) missile 0 to player
collision
(W) size of player 0
SIZEP1
M2PL
(W) horizontal position
of missile 3
(W) graphics shape for player 0
(R) player 1 to player collisions
53262
P2PL
(cont. on following page)
DOOE
(W) graph ics shape for player 1
(R) player 2 to player collisions
Atari Graphics 125
GRAPFP2
53263
OOOF
(R) player 3 to player collisions
P3PL
GRAPFP3
53264
0010
(W) graphics shape for player 3
(R) joystick trigger 0
TRIGO
(644)
GRAPFPM
53265
0011
TRIG1
(W) graphics for all missiles
(R) joystick trigger 1
COLPMO
53266
0012
(704) color/luminence of
player/missile 0
(R) joystick trigger 2
TRIG2
(646)
COLPM1
TRIG3
(647)
(W) graphics shape for player 2
53267
0013
(705) color/luminance of
player/missile 1
(R) joystick 3 trigger
The procedure for setting up players to use in a program is quite
similar to that for setting up character graphics. In general terms:
1. Choose your colors and resolution.
2. Design your player or missile and represent it
as data bytes .
3. Set aside a location in memory for the player or
missile data and store the data bytes.
4. Tell ANTIC and GTIA to start the display and
where to place it on the screen .
126 Atari Assembly Language Programmer's Guide
Suppose we want to design a light bulb to be player zero. Its color
will be pink, we'll use normal width pixels and two line resolution.
Referring to Tables 3-10 and 3-11 we note that we'll have to keep in
mind to:
POKE 704,88 To set player's color to pink
POKE 559,88 To set Bit 0, (normal playfield)
Bit 0 3 (player OMA enable)
Bit 0 5 (screen memory OMA enable)
POKE 53277,2 To enable GRACTL
POKE 53256,0 To set the width to 8 color clocks.
Sketching the light bulb and calculating the data numbers is the
same procedure as with character sets. The major difference between
the two is that you can have many more data bytes per player than per
character.
DATA
NUt-l8ERS
60
12E>
255
255
12b
60
24
24
24
Figure 3-12. Lightbulb character
Atari Graphics 127
Memory organization for Player Missile RAM is quite different
from anything we have run into thus far and reflects the internal design
of Antic. For double line resolution PM graphics, you need I K bytes
set aside and the starting location, called PM BASE, must be on a 1K
boundary. For single line resolution, you need 2K bytes set aside and
PM BASE must start on a 2K boundary. Within the block of PM
memory there is an unused section. This memory may be used for
other things such as machine language player-movement routines .
Figure 3-13 is a detailed memory map of the PM RAM.
r-PM BASE-
r---- PMBASE
UNUSED
MAY BE USED FOR
MACHINE LANGUAGE
ROUTI/\/ES, ETC
384
BY rES
768
BYTES
PM BASE-t 384
M3IM2IMIIM
512
31 M 21 M I 1-1.1 9'
PM BASE t
t
1024
640
1280
1 768
15-36
1896
11742
-t
.,. 1024
2.048
2 LINE
RESOLUTION
PLAYER- MISSILE
768
MEM OR Y
LINE
RESOLUT ION
MAP
Figure 3-13. Player-Missile memory map
Before we put all of the above information together into a simple
demonstration program, let's look at how players are positioned on
the screen. Horizontal positions of players and missiles are determined
by POKEing or storing values from 0 to 255 in registers 53248 to
53255. The number POKEd in determines the color clock used for the
left hand edge of the player. Players are visible in the approximate
128 Atari Assembly Language Programmer's Guide
range of 47 to 208. But, due to differences in individual TV sets it might
be best to allow a smaller range, say 55 to 200. Since a normal playfield
is 160 color clocks wide, this implies that it is possible to store a player
"in the wings waiting to come on stage". Vertical positioning of a
player depends on the positioning of the image within the RAM set
aside for that player. Consider our lightbulb. When storing the data
numbers within the PM RAM we will first clear the RAM to all zeros
so no extraneous images appear. We can then place the 9 data bytes
anywhere in the section of RAM set aside for Player 0 (see Figure
3-13). The lightbulb's position on the screen will correspond roughly to
the position of the data bytes in RAM. Note that, because of TV
overscan, it is possible to locate a player or missile above or below the
visible portion of the screen.
The program in Box 16 creates and displays the Lightbulb player.
After typing in and RUNning the program, press the break key. The
resulting display dramatically illustrates the independent nature of
PM graphics and playfield graphics. Although the BASIC program
has stopped executing, ANTIC and GTIA continue to display a scrambled
player. We can use this program to illustrate how to eliminate an
unwanted player. First, make the following changes:
130 FOR 11 TO 600 :NEXT I:REM A SHORT DELAY
140 POKE 559,34:POKE 53277,0
150 GOTO 150
Line 140 turns the player off by resetting Direct Memory Access to
playfield DMA only, and clearing GRACTL. Both changes must be
made in order to clear the player from the screen. An alternate method
of disposing of an unwanted player is to store it off the edge of the
screen. Try changing line 140 to:
POKE 53248,0
Atari Graphics 129
5 REM ** PLA YER PROGRAM **
10 A=PEEK(106)-B:POKE 106,A:REM * MOVE RAM TOP ~
2vJ GRAPH I CS 2+ 16
30 POKE 54279,A:REM * SET PM BASE *
4 ~1 PBASE=A*256
45 REM * CLEAR PLAYER MEMOR Y *
5e' FOR I=PBASE+512 TO PBASE +6 40:POKE 1, 0 :NEXT I
55 REM * READ PLAYER DATA INTO THE MIDDLE OF PLA YER 0 SECTION
6 0 FOR 1=1 TO 9
70 READ D:POKE PBASE +562 + I,D
B I~ NE XT I
9 ,,1 POKE 5 3 248, 12 0:REM SET HORI ZON TA L POS ITION
101i1 POKE 704,BB:REM * SET THE COLOR *
11~5 REM TURN ON THE PLAYER
110 POKE 559,46:POKE 5 3 27 7 ,3
12 111 DATA
\..
60,1 2 6,255 , 255,1 2 6 ~ 6'~.
~ 4, 2 4, 24
13vJ FOR 1=1 TO 60 0 :NE XT I
141~ POKE 559,34:POKE 5 3277, IiI
150 GOTO 150
Box 16. Lightbulb player missile concepts
Collisions and Priority
The last topics we will consider in this chapter are collisions and
priority. A collision occurs when you have instructed GTIA to
overwrite one object on the screen with another. Objects refer to
players, missiles, and playfields . Playfields can be either character
graphics or map mode graphics displays. A collision is any overwriting
of one object by another'. in which at least one screen pixel is
overwritten. Two objects touching do not constitute a collision. There
are four types of collisions available to the programmer. These are: (1)
player to player, (2) player to playfield, (3) missile to playfield, (4)
missile to player.
The Atari Home Computer provides sixteen hardware registers to
monitor the fifty-two possible collisions. From table 3-1 1 we see that
they are the dual function hardware registers 53248 through 53263.
The various types of collision cause certain bits (Do to D 3 ) of these
registers to be set. If a bit is set a particular collision has occured. These
are read only registers consequently they can only be cleared by storing
a number in the "Hit Clear Register", 53278 (HITCLR). The OS does
not automatically clear the collision registers. As a result it must be
done by the programmer so that the program can continue checking
for collisions.
130 Atari Assembly Language Programmer's Guide
Table 3-12 gives the bits set and the values returned when ' a
collision occurs. Keep in mind that the value returned by a PEEK
statement is the decimal equivalent ofthe binary number expressed by
bits Do to 0 3 . Because ofthis , the value returned will depend on how
many different collisions have occured since the last 'hit clear',
Table 3-12 .Collision Detection
COLLISION DETECTION
VALUE RETURNED BY PEEK
MISSILE TO PLAYFIELD
REGISTER
53248
53249
53250
53251
MISSILE
COLOR 1
COLOR 2
COLOR 3
MO
M1
M2
M3
1
1
1
1
2
2
2
2
4
4
4
4
2
2
2
2
4
4
4
4
PLA YER TO PLA YFIELD
PLAYER
53252
53253
53254
53255
PO
P1
P2
P3
1
1
1
1
MISSILE TO PLAYER
53256
53257
53258
53259
MISSILE
PO
P1
P2
P3
MO
M1
M2
M3
1
1
1
1
2
2
2
2
4
4
4
4
8
8
8
8
(cont. on following page)
Atari Graphics 131
PLA YER TO PLAYER
PLAYER
53260
53261
53262
53263
PO
P1
P2
P3
0
1
1
1
2
0
2
2
4
4
0
4
8
8
8
Another facet of collision detection concerns collisions between
players. This type of collision results in bits being set in two registers.
For example, a collision between Player 0 and Player 1 sets bit 0 1 in
register 53260 and bit Do in register 53261. Suppose player 3 collides
with player 2 - the value in register 53263 is 4 and the value in register
53262 is 8. When two players collide with each other both registers
have a number written in them. Another aspect of reading collision
registers is that if player 2 collides with more than one player then the
value in 53263 will be the sum of the collisions. For example:
=2
=8
53263 = 10
Player 2 hits Player 1
Player 2 hits Player 3
It is evident that collision detection gives you several programming
options. If you only need to know that a collision has occured, it is
sufficient to set HITCLR and test the appropriate register to see if it is
greater than zero . On the other hand if you need to know exactly which
object has been in a collision, then individual bits must be tested with a
logical AND.
The program in Box 17 illustrates collision detection. In this
program the lightbulb drawn in the previous box falls onto a row of
M's at the bottom ofthe screen. As the bulb descends, the value in the
collision register is displayed in the text window allowing you to see
and hear the program in action. After typing in the program and
running it, remove line 140 and run it again. As the bulb descends
through the row of M's and on into the text window you will see the
132 Atari Assembly Language Programmer's Guide
collision register values change. These changes are a result of the color
registers, ie. the playfield registers, used to display the * and the text
window.
This illustrates another aspect of collision detection - the
values returned depend upon the color registers being used (registers
708-712) but not on the color values in the registers. Recall that in a
sense playfields are synonymous with color registers. Thus a multicolored
character in ANTIC Mode 4 or 55 could return a different value
depending on which part of the character was overwritten.
BOX 17
1 REM ** COLLISION **
5 PRINT CHR$(125)
10 DIM MOVE$(21):DOWN=ADR(MOVE$)
15 A=PEEK(106)-8:POKE 106,A
20 POKE 54279,A
30 PB=A*256
35 FOR CM=PB+512 TO PB+640:POKE CM,0:NEXT CM
40 X=120:V:z20
50 FOR P=1 TO 9:READ D:POKE PB+512+V+P,D:NEXT P
~5 DATA 60,126,255,255,126,6121,
24,24,24
60 POKE 53248, X
70 FOR I=DOWN TO DOWN+20
75 READ S:POKE I,B:NEXT I
80 DATA 104,104,133,204 , 104 , 133,203
85 DATA 160,2~,177,203,200,145,203
90 DATA 136,136,192,255 , 21218,245,96
100 GRAPHICS 2:POKE 704,88
105 POS I T I ON Iii, 8: 7 "6;" MMMMMMMMMMMMMMMMMMM"
110 POSITION 121,9:7 "6;"*******************"
120 POKE 559,46:POKE 53277, 3
125 POKE 53278,255
130 ST=USR(DOWN,PB+511+V):Y=Y+1
13~ PRINT PEEK(53252)
140 IF PEEK(53252)=4 THEN GOTO 150
145 FOR 1=1 TO 25:NEXT I:GOTO 125
15121 7 PEEK(53252):SOUND 1,2@,0,14:S0UND 2,255,10,15
165 FOR 1=1 TO 300:NEXT I
170 SOUND 1,0,0,@:SOUND 2,0,0,121
Box 17. Collision
Atari Graphics 133
When you have one or more objects on the screen, you may want
to hide one behind the other. If one of the objects is moving, this can
add a three dimensional quality to the picture. The Atari operating
system has a register at 623 (GPRIOR) that is the shadow register for
PRIOR at 53275 which controls display priority among the players
and playfields. As you can see from table 3-10, PRIOR controls
several unrelated functions. However the lower four bits Do to D3
control display priority. On power-up bit is set and players have
priority over the playfields and backround. The backround always has
the lowest priority. Setting bit 1 POKE 623,2) gives players and 1
priority over playfields and over players 2 and 3, but the playfields
have priority over players 2 and 3. The remaining priorities may be
found in table 3-13. The bits in PRIOR are mutually exclusive . This
means, theoretically, you can only set one of the bits Do to D 3 . In a
mutually exclusive situation, turning on more than one bit causes the
bits to be in opposition. When the priority bits are opposed and any of
the objects displayed overlap the display turns black in the overlapping
area.
Finally, if you have established priority between players and
playfields, the collision registers respond in the usual manner. Hence,
when two objects are on the screen at the same time and place a
collision will occur whether or not you see it and this is duly recorded
by the collision registers.
To see priority in action add the following lines to the program in
box 17:
102 POSITION O,4:PRINT #6;"####################"
103 POKE 623,8
When you run the program with this addition you will see that the
playfield #'s have priority over the light bulb so that the bulb appears to
pass behind the #'s.
134 Atari Assembly Language Programmer's Guide
Table 3-13. Priority
GPRIOR @623
07
06
Os
03
04
00
01
O2
""-
priority select
BIT
Set by
PRIORITY CONTROL
POKE 623.
0
All players have priority over all playfields
Players 0 and 1 have priority over playfields,
which have priority over players 2 and 3
All playfields have priority over all players
Playfields 0 and 1 have priority over all
players, which have priority over, Playfields 2
and 3
Within the group of players, lower numbered players have priority over
higher numbered players .
A lower numbered playfield has priority over higher numbered
playfields .
4
Getting Started in Machine Language
Programming
Introduction
After the previous three chapter's lengthy introduction to the
fundamentals of machine language and Atari graphics, it is time to get
started on some programming examples using machine language
subroutines. There are three ways in which such a subroutine can be
integrated into a BASIC program: (1) Flags set in one or more
hardware registers can cause the CPU to jump to a short subroutine;
(2) A machine language routine can be called by a BASIC USR
command; (3) Through a process called vector stealing, a subroutine
can be added to the normal tasks carried out by the operating system
during the vertical blank . The first of these three methods, flag setting,
is used by display list interrupt routines. The BASIC USR command is
useful for all sorts of routines such as moving players, clearing sections
of memory, and redefining characters sets. Using vector stealing to
insert machine language routines into the vertical blank is valuable in
fine scrolling and music. We shall begin the discussion of actual
135
136 Atari Assembly Language Programmer's Guide
machine language programming with a number of display list
interrupt routines and follow this with examples of programs carried
out using the BASIC USR command . Routines that execute during
the vertical blank will be discussed in chapter six.
Display List Interrupts
The display list interrupt (OLI) is a nice place to begin experimenting
with the 6502 instructions introduced in chapter two and writing
machine language subroutines. With just a little bit of work you can
obtain very colorful results that give immediate feedback. Furthermore,
from a few simple programs you will learn to use quite a few different
instructions and gain an understanding of several important programming
concepts. Although the examples stress color changes, DLis are useful
for many other applications, some of which we will mention as we go
along.
Box 18 is the first OLI program. The task performed is simple -the
background color of a full screen Graphics 2 display is changed
halfway down the screen from light blue to dark blue. The steps for
preparing such a program are:
(1) Plan what you want to do on the screen.
(2) Write the DLI service routine
(3) Set up the program and instructions that invoke the routine.
Before we look at the machine language routine in Box 18, let's
review what will happen within the computer. Setting bit 0 7 of a
display list instruction equal to I signals ANTIC to regard that
instruction as a request for a OLI. ANTIC then checks NMIEN
(Non-Maskable Interrupt ENable) at memory location 54286. If bits
0 6 and 0 7 of this register are set, then ANTIC will relay a NMI signal
to the CPU. In the Atari Home Computer there are three sources for a
NMI. These are the vertical blank interrupt, the OLI, or the Reset Key.
The NMI signal tells the CPU to execute a sequence of instructions to
determine the origin of the signal. Once it has found out that the
Getting Started In Machine Language Programming 137
interrupt is a DLI , the CPU goes to memory locations 512 (Lo-Byte)
and 513 (Hi-Byte) for the address of the DLI service routine.
The task of our routine is to change the number in the hardware
register 53274 from 152 to 146. To do this we will need to use the
Accumulator. In this situation, prior to executing our service routine,
the CPU was busy carrying out some other program. Consequently,
we should anticipate that the Accumulator and the X and Y registers
will be holding values that will be needed after our routine is
completed. Therefore, the first thing that the DLI routines must do is
to save the values in any of the CPU registers it will use on the stack.
The last thing it must do before returning from the interrupt is to recall
these values from the stack .
With this in mind , look at the machine language program in line
30 of Bo x 18 .
BOX 18
Dlsplay Llst Interrupt
One Color Change
\...
5 REM SIMPLE DISPLAY LIST INTERRUPT
10 REM. READ ML PROGRAM INTO PAGE SIX.
20 FOR 1=0 TO 10:READ ML:PO KE 1536+I,ML:NE XT I
3111 DATA 7 2,169,146,141,1111,21 2 , 141,26, 21118.11~4,64
40 REM. SET UP SCREEN AND SET DLI BIT IN DISPLAY LIST.
~0 PRINT CHR$ ( 125 )
60 GRAPHICS 2 +16:PO KE 71 2 ,152
70 DL=PEEK(56111)+PEEK (561 ) *256
80 POKE DL+10,7+128
90 REM. TURN ON DLI *
100 POKE 512,0:POKE 513,6
11111 PO KE 54286.19 2
1 2 ~I GOTO 120
BOX 18. Display List Int errupt One Color Change
138 Atari Assembly Language Programmer's Guide
Written out in mnemonics it is as follows:
MNEMONIC
DECIMAL VALUE
FUNCTION
PHA .. .... .. .... .. .72 ... ....... Push Accumulator to stack
LOA #146 .... .. ..169,146 .... ... Load the Accumulator with 146
ST A WSYNC ..... 141, 10,212 .... ..Synchronize OLi with screen
display
STA AOOR. .. ...141,26,208 ..... .Store 146 at 53274
PLA ...... ...... .. 104 ... .. ..... Retrive previous accu mu lator
value from stack
RTI. ..... .. .. ..... 64 .... ...... Return from interrupt
The program first saves the value of the accumulator by pushing it
on the stack. It then loads the accumulator with the color number 146
and follows with ST A WSYNC to synchronize the color change to the
horizontal blank process. The STA command (opcode value 141) is in
the absolute addressing mode. The numbers 10,212 are the LoByte j Hi-Byte form of the register WSYNC (54282).54282 is a memory
location assigned to ANTIC. An interesting sidelight concerning this
register is that apparently it does not matter what value is stored there.
The ST A operation itself is sufficient to do what is needed for
synchronization. Following ST A WSYNC, the instruction ST A
ADDR puts the colornumber 146 into the hardware register for the background
color. This sequence makes it apparent that ST A is a nondestructive
command, ie., the number remains in the accumulator after it is stored
in memory. Once again, this ST A uses absolute addressing. Finally,
the accumulator retrieves its original value from the stack and the
processor returns from the interrupt.
Getting Started In Machine Language Programming 139
Once the machine language program has been read into memory
(line 20) it is necessary to set up the proper conditions to have it
implemented. This consists of setting the DLI bit (D?) in the display
list instruction of the mode line before the one at which you want the
change to occur. Then you must tell the OS where to find the DLI
service routine by putting its starting address in 512 and 513. The final
jo b is to set bits 6 and 7 of hardware register 54286 by PO KEing in 192.
A DLI may be turned off by a POKE 54286,64.
In the previous chapter we discussed the problem of providing a
safe place for display lists, player-missile memory, and character sets.
It is of prime importance to store machine language routines where
they are not going to be overwritten by BASIC. Nothing makes a
program crash faster than a machine language routine missing an R TS
or some other vital instruction because it was overwritten with another
part of the program. One option for storing machine language routines
is to use page six (1536-1791) of memory. It has been pretty well documented
that some cassette 110 can write over the first half of page six (15361664). Consequently, if you are using cassette storage, only page six
locations 1665-1791 are safe . If you use disk storage all of page six is
safe. Later we will discuss other techniques for storing or setting aside
a safe place for machine language routines .
Display list interrupts are most advantageously used in situations
where there is an OS shadow register associated with a hardware
register. The reason for this is that during each vertical blank, the OS
uses the value in the shadow register to update the corresponding
hardware register. With a DLI you can change the number in the
hardware register. Using color as an example, you effectively partition
the screen so that the
OS controls
things her ..
DLI control,.
things h .. r ..
140 Atari Assembly Language Programmer's Guide
Of course, one doesn't have to split the screen in half. You can place a
DLI on any or all mode lines. This means that you do not have to rely
entirely on shadow register / hardware register pairs in using DLIs.
With the inclusion of a D LI in one of the three blank line instructions
at the top of ANTIC's display list, any change made in a system register
while the electron beam is partway down the screen can be restored
before the start of the drawing of a new display.
The program in Box 18 makes a single color change at a single
location on the screen and serves to illustrate the use of PHA, LDA,
ST A, PLA, and RTI. There are three good ways to build on this simple
program . One is to make up to three color changes during one
interrupt routine by using the accumulator, the X and Y registers. A
second course is to use mUltiple DLI routines. The final method is to
use DLls to access a table of color values.
The program in Box 19 makes changes in two color registers and
one control register. It illustrates the use of several commands: TXA,
TYA, LDX, LDY, STX, STY, TAY, and TAX.
Box 19. Display List Interrupt Two Color Changes / Text Inversion
r
BOX 19
Display List Interrupt
Two Color ChanQes/Text Inversion
5 REM ** DISPLAY LIST INTERRUPT **
Ig REM * READ ML PROGRAM INTO PAGE SIX *
2~ FOR I=g TO 28:READ ML:POKE 153 6+1,ML:NEXT 1
3g DATA 72,138,72,152,72,169,146,
162,42,16~,6,141,1~,212,141,26,208,142,22.2~8,14g.01,2 12,1~4.
168,104,17~,104,64
40 REM * SET UP SCREEN AND SET DLI BIT IN DISPLAY LIST
50 PRINT CHR$CI2S)
60 GRAPHICS 2+16:POKE 712,152:POKE 708,84
70 DL=PEEK(560)+PEEK(561)*256
80 POKE DL+10,7+128
90 REM * TURN ON DLI *
1IiJ0 pm~ E 512,1l':POKE 513,6
110 POKE 54286,192
120 REM * PRINT A MESSAGE *
130 POSITION 8,S:? #6j"WOW"
141!1 POSITION 8,6:? #61 "WOW"
151~ GOTO 150
Getting Started In Machine Language Programming 141
The machine language routine in Box 19 has four sections:
Section I: Save the Accumulat or, the X-register and the Y-register
onto the stack.
MNEMONIC
DECIMAL VALUE FUNCTION
PHA ....... ..... .... 72 .... ..... Save accumulator on stack
TXA. .... .......... 138 ......... Transfer X-register to
accumulator
PHA. ........ ....... 72 ...... ... Save this value, too
TY A. .... .......... 152 ... .... .. Transfer V-register to
accumulator
PHA. ... .... .... ... .72 ...... .. .Save V-register, too
Section II: Load the registers.
LOA #146 .... .... 169,146 ....... Load accumulator with the
number for medium blue
LOX #42 ....... ..162,42 ...... ..Load X-register with the
number for yellow
LOY #6 .. ........ 160,6 ....... .. Load V- register with #6
Section III: Wait for the horizontal blank. Store colors.
STA WYSNC ...... 141, 1O,212 ...... Wait for horizontal blank
STA Color1.. .... 141,26,208 ...... Medium blue to background register
STX Color2 ...... 142,22,20B ...... Yeliow to foreground register
142 Atari Assembly Language Programmer's Guide
STY Control. .... . 140,01 ,212 .... ..Change character mode control
Section IV: Restore register, return from interrupt.
PLA ............ 104 ......... ... Recall top value on stack
into accumulator
TAY ..... ... .... 168 ..... .. ..... Transfer it to Y register
PLA ............ 104 ............ Recall next value on stack
TAX ............ 170 ........ .... Transfer it to X register
PLA ...... ...... 104 ............ Recall original accumulator
value
RTI. ............ 64 ............ Return from subroutine
Observe that the order in which the values are recalled from the
stack by the PLA statements in Section IV is the reverse of the order in
which they were pushed onto the stack by the PHA commands in
Section I. This illustrates the last-in-first-out nature of the stack. You
should also note that there are no instructions that pull values from the
stack directly into the X and Y registers. Rather, one must restore these
registers in a two step process involving the accumulator and the
transfer instructions TAX, T A Y. As a final comment on this program,
observe that the load instructions use the immediate mode of addressing
and the store instructions use the absolute mode of addressing.
Suppose that you plan a screen display using several DLIs, each
doing a different job. You write the service routines and store them in
page six. But how do you tell the CPU where to find the proper service
routine for each interrupt when there is only one place to store a
starting address? The solution is to have each service routine put the
starting address for the next routine into 512 and 513. Box 20 is a very
simple program illustrating linking one routine to the next. The
program changes the background color of a Graphics 18 screen twice,
first from light blue to pink and then to gold.
Getting Started In Machine Language Programming 143
BOX 20
Display List Intarrupt
Thrae Color Chan~es
5 REM MULTIPLE DISPLA Y LI ST INTERRUPTS **
10 REM * READ ML ROUTINES INTO PAGE SIX *
20 FOR J=0 TO 31:READ ML:PO KE 153 6+J,ML:NEXT J
?0 DATA 72,169,92,141,10,212,141,
26,208,169, 16, 141,00,1~2, 11214,64
4121 DATA 72,169 , 58,141, 1I!l,212, 141,
26,208,169,00,141,00,0 2 ,104,64
50 REM + SET UP SCREEN AND SET DLI BIT IN DISPLAY LIST +
60 PRINT CHRS(125):GRAPHIC S 2 +16
70 DL=PEEK(560)+PEEK(S61)+ 256
80 POKE DL+8, 13 5;POKE DL+13,1 3 5
9'" POKE 712,154
100 REM + TURN ON DLI
110 POKE 512,0:POKE 51 3 ,6
120 POKE 54286, 192
13QI GOTO 131~
BOX 20. Display List Interrupt Three Color Changes
The two service routines are in the data lines 30 and 40. With some
counting you can see that the first routine is stored from 1536 through
1551 and the second from 1552 through 1568. Therefore, the starting
address for the first routine in Lo-Byte / Hi-Byte order is 00, 06; for the
second routine, 16, 06 . The structure of the two routines is the same.
The assembly listing of the first routine follows . You should write out
the listing for the second routine for practice.
MNEMONIC
DECIMAL VALUE
FUNCTION
PHA ..... ........ .. 72 ..... ..... Push accumulator to stack
LOA Color .. .... 169,92 ... ...... Load accumulator with pink
ST A WSYNC .... 141, 10,212 .. ..... Wait for horizontal blank
144 Atari Assembly Language Programmer's Guide
STA COLREG ... 141 ,26,208 ... .. .. Store value in accumulator
in hardware register
LOA LOAOOR .... 169, 16 ... ....... Load accumulator with LoByte of address of next routine
STA PAGE 2 ... 141,OO,02 ........ Store value in accumulator
at 512
PLA. .... ........ .104 .. ....... . Restore accumulator
RTI. ..... ..... .... 64 .. .... .... Return from interrupt.
The next display list interrupt program discussed uses a single
machine language routine to access a table of color numbers. This
program illustrates indexed addressing, branching, and relative addressing.
Before going on to that program, let's review what we have done so far.
The programs in Boxes 18, 19, and 20 have used these machine
language commands:
Column I
Column II
PHA
PLA
TAX
TAY
TXA
TYA
RTI
LOA
LOX
LOY
STA
STX
STY
The machine language instructions in column I all use the implied
mode of addressing, that is, the instruction itself indicates the source
and destination of the byte being moved. However, the instructions in
column II each have several different addressing modes. For example ,
if you look up LD A in Appendix G, you see that it has eight different
Getting Started In Machine Language Programming 145
addressing modes ; LDX and LDY each have five addressing modes;
while STX and STY have three, and ST A has seven. Recall that
addressing modes determine how the CPU locates data that is
retrieved from memory or how it locates where data is to be stored.
The large number of addressing modes provided by the 6502 processor
is an advantage in machine language programming because it allows
the programmer more options in writing code for a given task .
In Boxes 18 , 19, and 20 the ST A, STX , and STY instructions use
absolute addressing. The LDA, LDX, and LDY instructions use either
the immediate mode of addressing or absolute addressing. These two
addressing modes are used a great deal in machine language programs
and will rapidly become very familiar to you. On the other hand, they
both suffer from a severe limitation. Neither of these modes is useful
for retrieving data from , or storing data in, an array or table .
Many of the tasks carried out by machine language routines
involve either moving blocks of data called strings or arrays, or
manipulation of data stored in a table. Since these are very common
programming jobs, they are one of the first things that a beginning
assembly language programmer should master. Both arrays and tables
are stored in contiguous memory locations . Very often what is
required is to move a block of data from one location to another or to
access the items in a table in sequential order. Since the 6502 is an 8 bit
processor, these manipulations occur one byte at a time . As a
consequence, the program structure usually is a loop that cycles as
many times as there elements in the array.
The DLI routine in Box 21 illustrates the basic elements needed to
repeatedly loop through a table. In the program, six display list
interrupts are written into a Graphics 2 display list. At each interrupt,
the routine loads a color number from a table of values and puts it into
the background color register. In order to do this properly, the
program needs a way to keep track of its position in the color table and
needs to determine when it has reached the end of the color table. The
first task is handled by using a pointer and indexed addressing. The
second by a compare and branch sequence.
146 Atari Assembly Language Programmer's Guide
BOX 21
Display List Interrupt
Color Tabl e
1 REM ** DLI COLOR TABLE EXAMPLE **
5 REM * SET UP COLOR TABLE *
10 FOR CT=0 TO 5
20 READ D:POKE 1568+CT,D
31~ NEXT CT
40 DATA 200,90,56,152,88,120
50 POKE 1536+31 ,3 1:REM INITIALIZe COUNTERS
60 REM * PUT SIX INTERRUPTS IN TO THE DISPLAY LIST *
70 GRAPHICS 18
80 DL=PEEK(560'+PEEK(561'*256
90 FOR C=8 TO 13
100 POKE DL+C,135:NE XT C
180 REM * SET UP DLI SERVICE ROUTINE *
190 FOR J=0 TO 30:READ B:POKE 1536+J,B:NEXT J
200 DATA 72,138,72,23 8,31,6,174, 31,6,189,0,6,141, HI, 212
210 DATA 141,26,208,224,3 7 ,208,5,169,
31,141,31,6,104,170,11<14, 6 4
220 POKE 512,0:POKE 513.6
230 POKE 54286,192
240 GOTO 2419
BOX 21. Display List Interrupt Color Table
The service routine, pointer, and color table have been loaded
into page six as follows:
31 bytes of machine language routine at locations 1536
through 1566 .
The pointer at location 1567 .
6 bytes of the color table at 1568 through 1573.
The service routine may be split into sections as follows :
Section I: Save registers to stack and increment the pointer.
MNEMONIC DECIMAL VALUE
FUNCTION
PHA
72
Push accumulator to stack
TXA
138
Transfer X-register to accumulator
Getting Started In Machine Language Programming 147
PHA
INC POINTER
72
238,31,6
Save X-register on stack
Increment Pointer
This last instruction is carried out each time the interrupt is used. The
pointer was initialized to 31 in line 50 of the program so that when the
first DLI is encountered, this instruction will increment the pointer to
32, the Lo-Byte of the first color number's address.
Section II: Load the X-register. Get the color value.
LDX POINTER
174,31,6
Load the X-register with the value
in pointer
LDA ADDR,X
189,0,6
Load accumulator with the value in the
addr following using the X-register
as an index
When the LDA command is executed, the zero in 0,6 is added to the
value in the X-register to get the Lo-Byte of the address of the color
number in the table .
Section III: Change the color register
STA WSYNC
141,10,212
Wait forthe horizontal blank
STA COLREG
141,26,208
Store color in color register
Section IV: Test for end of the table
CPX NUM
224,37
Compare the value in the X-register
with 37
BNE END
208,5
Branch if not equal to zero
148 Atari Assembly Language Programmer's Guide
If the result of the CPX command is not equal to zero, the program
jumps ahead to restore the X-register and then returns from the
interrupt , thus by-passing the next two instructions .
Section V:
LDA RESET
STA POINTER
169,31
141,31,6
Load the accumulator with 31
Store 31 to reset pointer
Section VI: Exit the routine sequence
END PLA
104
Pull top of stack into the accumulator
TAX
170
Transfer accumulator to X-register
PLA
104
Restore accumulator
RTI
64
Return from interrupt
Here is how the program works . Each time a DLI is encountered
the accumulator and X-register values are stored on the stack. The
pointer is incremented and this value is placed in the X-register. The
accumulator is then loaded with a color value at an address, the
Lo-Byte of which is the value in the X-register. After this value has
been stored in the background color register, the program tests to see if
the address used was that of the last color value . If not, the routine ends
for that interrupt. If it is the last color, then the pointer is reset before
the routine ends.
This program shows that when dealing with a block of data or a
table there are three things that must be done: (I) A counter, or index
register must be initialized . (2) The index register or counter must be
Getting Started In Machine Language Programming 149
incremented (or decremented) as the program works through the data.
(3) The register or counter must be tested for the end of the block.
These tasks are common to all programs that are moving or
manipulating a block of data . The exact implementation depends on
the job to be done and the programmer's inclination . For example, in
this program, where each pass made through the loop by the processor
is separated from every other pass with some other processor activity,
an independent counter kept in memory was required. When a block
of data is being manipulated all at once, that is, when the loop is cycled
through continuously without interruption then it is often possible to
use one of the index registers as a counter. The next program we will
discuss does this.
The test to see if a loop has been executed the proper number of
times can be performed in several ways. Using CPX or CPY followed
by a BEQ or BNE is one method . But if you study the branching
process you can easily invent other ways to test for the end of an array.
Branch instructions occur in response to the state of certain bits in the
processor status register (see Box I). The instructions BEQ and BNE
take action according to whether the zero flag is set or reset. BMI and
BPL take action according to whether the N flag 'is set or reset. The
flags in the status register are controlled by certain of the 6502's
instructions. Appendix F lists those instructions that affect status
flags .
For example, referring to Appendix F , we see that DEX changes
the N flag and the Z flag. Therefore you could set up the X-register as a
counter and decrement it down to zero and use the BEQ to branch out
of the loop .
Program Listing
Before proceeding with the development of programs let's briefly
consider some conventions used for writing assembly language
programs. If you are familiar with more than one higher level
language, such as BASIC, PASCAL, and FORTRAN, then you know
that each language has rules as to how to construct a program - line
numbers, special punctuation, and things of this nature. Strictly
150 Atari Assembly Language Programmer's Guide
speaking, a mac hine language program is nothing more than a
sequence of bytes in the computer's memory and so the format of how
to write out the program on paper is pretty much left to personal
choice. In many of the programs that follow we will use a format for
listing program s that is si milar to that used by The Atari Assembler
Editor Cartridge and man y other assembler programs. In this format
there are six columns or fie lds as follows:
Label
Opcode Operand Numeric Numeric Comment
Mnemonic Mnemonic Opcode Operand
Optionally, a seventh field could be used, the line number preceeding
the label field. T here are so me other co nve ntions regarding notation
and inde xing that we shall adhere to. They are:
Hexadecimal numbers will be preceeded with $
Immediate operands will be preceeded with #
Absolute inde xed operands will be indicated by
- - - - - - - , X or - - - - - - - , Y
Nonindexed indirectwill be indicated by parenthesis
ie . JMP($6000)
Indexed indirectwill be indicated by (- ----,X)
ie . INC($99,X)
Indirect indexed , which uses the V-register
only will be indicated by ( - -- - - ),Y. ie . LDA
($2B) ,Y
Indexed page zero will be indicated b y - - - ---,X or - - - - - - - , Y but the number
- - - will , of course, be less than 256
Getting Started In Machine Language Programming 151
USR
The USR command is one of the handiest ways to integrate
machine language subroutines into a BASIC program . The command
is structured so that parameters can easily be passed from the BASIC
program to the subroutine. The USR command has the format:
D U MMY=USR(ADDR,parameter 1,parameter 2.. .)
DUMMY stands for 'dummy variable' which implies that it is
necessary for the format of the command, but that no useful value is
returned . ADDR is either the decimal value of the address where the
subroutine is stored , or is an expression that evaluates to the address .
Parameters are passed to the subroutine via the stack. The stack
structure for a USR command is :
TOP OF STACK
N - the number of parameters (may be 0)
Hi - Byte of parameter 1
La-Byte of parameter 1
Hi-Byte of parameter 2
La-Byte of parameter 2
BOTTOM OF
STACK
La-Byte of return address
Hi-Byte of return address
The stack structure forces at least one PLA instruction in every
routine called by a USR. If there are parameters, "N" must be removed
with a PLA before the parameters can be accessed. If there are no
parameters, then N is zero and must be removed before the return
address can be accessed.
152 Atari Assembly Language Programmer's Guide
Strings
The USR and Atari BASIC's string handling capabilities provide
a good way to store machine language routines safely within a BASIC
program. The idea is to translate the decimal numbers representing the
subroutine into AT ASCII characters and store these in a string. As
we'll see shortly, the routine can be easily addressed by USR.
Storing machine language routines in strings has several advantages.
First, it avoids memory management problems by turning the job over
to BASIC. Second , the length of the machine language program is not
limited as it is with page six storage . Third, the string method of
storage is more efficient in terms of time and space. Spacewise, the
data for the machine language routine is stored as at single symbol in
the string rather than as a sequence of numerals and commas.
Timewise, efficiency is achieved because string storage eliminates
time-consuming READ and POKE sequences such as those in lines 50
to 90 of Box 14.
Our next program combines many of the ideas discussed so far in
this chapter into one example. In this program (Box 22), machine
language routines are used to speed up redefinition of the character set
in program 14. The machine language routines that move and redefine
the standard character set are stored as strings in lines 30 and 40. Also,
the data used to redefine the characters as a cat is stored as a string in
line 50. These simple changes in program 14 yield a fantastic increase
in execution speed, as you will see when you type in and run the
program.
Storing subroutines in strings does entail some extra steps and
occasionally a little inconvenience . Consider the subroutine MOV$
which consists of twenty decimal numbers. To store these as a string it
is necessary to convert the decimal numbers into character symbols
using Appendix E. As an example, for the first four numbers of
MOV$:
DECIMAL #
KEYSTROKE
RESULT
104
162
160
inverse"
CTL D
inverse space
I.
Getting Started In Machine Language Programming 153
BOX 22
Storing Characters as a String
Cat
1 REM ** FAST CHARACTER CHANGE **
5 REM * COMPARE WITH BO X 14
10 REM * SET UP ROUTINE S IN S TRINGS *
2121 DIM MOVI(20) , REDEFS {1 4 ) , CHAR$ CI04)
3121 REM 110VI=
4121 REM REDEFI=
5121 REM CHARI=
60 REM * INITIALIZE PAGE ZERO LOCATIONS AND MOVE CHARACTER
SET *
70 A=PEE~CI06)-8:POKE 106 , A+4
80 POKE 204,A+4:POKE ~06 , 224
9121 GRAPHICS 2+16
100 M=USRCADRCMOVI
110 REM * INITIALIZE PAGE ZERO LO CATIONS AND REDEFINE
CHARACTERS *
121~1 O=ADR CCHAR$)
130 HIQ=INT CQ/256)
140 LOQ=O - HIO*25 6
151~
pmE
21~5,I_OQ:
POf': E
~'1116,
~C)
160 pmE :::'111 ~,24: r 'OfT :::,) 4, 1'l+ 1
170 R=USRCADRCREDEFI )
181~1 REM'" DISr='LAY O~J SCI;' '' 'E:~'
191~ POKE 756, A ~4
21~11~1 POSITION 'Y, 1: ';' 116; " II!!':,"
211~ POSITI CN G, 2: ';' #6: " .' . ' (). ,.
221~1 POS I T I ON 8,3: '" # 6 ;" ", _. , ;'''
2:;1~ GIJTIJ 2:1'
BOX 22, Storing Characters as a String
Storing things in strings can be a bit disconcerting when you list
the program on a printer. Very often some ofthe symbols in the string
will be interpreted by the printer as control codes, causing it to do very
strange things, Even if the string doesn't cause printer pollution, you
may find that not all of the characters print out. Our way around these
problems is illustrated in Boxes 22 and 23, As you have discovered by
now, we replace the strings with REM statements before attempting a
154 Atari Assembly Language Programmer's Guide
listing and write a separate listi ng for the machine language routine
using the notation defined in Box 23.
+MOV$ +
DECIMAL .oft
104
KEYSTROKE
RESULT
162
~
III
160
177
205
145
CLD
CL,
OJ
81
ICLQI
[i)
12
DECIMAL
203
200
208
249
230
20E-
230
204
KEYSTROKE
[]
[ill
[ill
[f]
[IJ
II
II!
[ZJ
lD
[]
RESULT
[f]
Iii
(!]
202
208
0
D
203
200
DECI~AL
KEYSTROKE
RESULT
+
DECIMAL
104
KEYSTROKE h
242
CL.
1M
REOEF$+
160
177
205
145
CL,
IT]
[0
ICLQI
[2J
iii
12
[3
ill
RESULT
DECIMAL
192
144
208
247
KEYSTROKE
ICLPI
@l
[g
RE SU LT
%
CL
CI
+LEGENO+
CL = conTrol
SP = spoCO
~rolTld= inv er5~
E. C, C=
BOX 23. Notation used to depict strings
QSC~Q
v id eo
Getting Started In Machine Language Programming 155
Let's use the subroutine MOV E$ to examine, in more detail , the
process of moving data from one area of memory to another. In order
to write a program that moves data in memory, you must have a way to
locate each byte to be moved and a way to determine where each byte is
going. This concept is presented schematically in Figure 4-l:
MENORY
ADDR I
f+-
START 57344
TO BE
DATA
NOVED
~
I' ~ "- END
ADDR 2
j~
58367
5 TART
39936 (At 4)
T ARG E T
AREA
I~
I -~ EN D 4 09 :' 9
Figure 4-1. Subroutine MOVE$ presented schematically
156 Atari Assembly Language Programmer's Guide
You also need a way to determine when you have moved all your data.
There are several ways to solve each of these programming problems
and sometimes they can be handled simultaneously by use of indexed
addressing. Such is the case here, where we want to move 1024 bytes of
character data from ROM to RAM. The source and target addresses
can be handled with indirect indexed addressing which makes use of
the Y-register and two page zero locations. The page zero locations
hold the Lo-Byte and Hi-Byte of a base address to which the current
value in the Y-register is added. The resulting value is used to
determine the location of the data for the LDA or the target for the
ST A. In MOV$, locations 205 and 206 are used to hold the base
address for the LDA. Locations 203 and 204 are used to hold the base
address for the ST A.
The assembly language listing of MOV$ is in Box 24. The first
instruction, PLA, removes the top number from the stack. This
number is the parameter count in the USR function ( in this case 0).
The next two instructions, LDX and LDY, load the X and Y registers
with values used in the looping. The Y-register serves a dual purpose
-as an index register and as a counter for the inner loop. We have to
move 1024 data bytes. However, an 8-bit register can count only 256
values . As a result we need to cycle through the inner loop four times.
Decrementing the X-register down to zero counts these cycles.
This explains the general structure of the program. There are a
couple of remaining details. The two BNE instructions depend on the
zero flag being set when the Y-register "rolls over" to zero and the
X-register is being decremented to zero. Finally, the two INC's
increment the base addresses to the next higher page when 256 bytes
have been moved .
REDEF$ moves the data stored in CHAR$ into the character set
that was stored in RAM. This subroutine is similar to but simpler
than MOV$ so we will leave it to you to figure out the details. The
assembly language listings are in Boxes 25, 25A, and 25B.
Getting Started In Machine Language Programming 157
Box 24
MOV$
203,206 Base Address (where to get it)
203,204 Base Address (where to put it)
LABEL
MNEMONIC
OPERAND
PLA
OPCODE
OPERAND
NUMBER
NUMBER
104
LOX
#4
LOY
#0
LOA
(ADDR1),Y
162
COMMENT
Remove parameter count
4
Load X with number of inner
loops
LOOP
Load Y with initial value
177
(205),Y
Load accumulator from base addr
Locations 205,206 plus value
in Y
STA
(ADDR2),Y
145
(203),Y
Store accumulator from base
locations 203,204 plus value in Y
INY
200
Increment Y to point to
next byte
ENDLP1
BNE
LOOP
208
249
If not done, then continue
INC
206
230
206
Increm e nt base address to next
higher page when 256 bytes
have moved
INC
204
DEX
230
204
202
Decrement X, counting off one
inner loop completed.
ENDLP2
BNE
RTS
BOX 24. MOV$
LOOP
208
96
242
If not done, then continue
Return from subroutine
158 Atari Assembly Language Programmer's Guide
REDEF$
Less than 256 Bytes
LABE L
MNEMONIC
OPERAND
OPERAND
NUMBER
NUMBER
COMMENT
Remove parameter count
104
PLA
#0
169
Initial ize V-register
LOA
(AOOR1),Y
177
205
Load accumulator from base + Y
STA
(AOOR2),Y
145
203
Store accumu lator at base + Y
LOY
LOOP
OPCODE
INY
Increment Y to point to next
200
Byte
CPY
#144
192
144
Compare contents of Y register
247
If move not complete, then
to 144
BNE
LOOP
208
continue
RTS
96
Otherwise return from
subroutine .
BOX 25. Assembly Language Listings
Getting Started In Machine Language Programming 159
REDEF$
More than 256 Bytes
LABEL
Mnemonic
OPERAND
OPCODE
OPERAND
NUMBER
NUMBER
COMMENT
PLA
LOOP
LOY
#0
LOA
(205 ), Y
STA
(203),Y
INY
LOOPS
SNE
LOOP
INC
204
INC
206
LOA
(205),Y
STA
(203),Y
INY
CPY
REMAINDER
SNE
LOOPS
RTS
The simplest way to redefine more than 256 bytes is to move a multiple
of 256 first and then move the remainder. We have left the Opcodes,
Operands, and Comments for you to fill in.
BOX 25A. REDEF$ (for more than 256 bytes)
160 Atari Assembly Language Programmer's Guide
REDEF$
More than 512 Bytes
LABEL
MNEMONIC
OPERAND
OPCODE
OPERAND
NUMBER
NUMBER
COMMENT
PLA
LOY
#0
LOX
#MULTIPLE
LOA
(205),Y
STA
(203).Y
INY
BNE
LOOPA
INC
204
INC
206
DE X
BNE
LOOPA
LOA
(205),Y
STA
(203).Y
INY
CPY
REMAINDER
BNE
LOOPB
RTS
The simplest way to redefine more than 512 bytes is to move multiples
of 256 first and then move the remainder. We have left the Operands,
Opcodes, Operands, and Comments for you to fill in.
Box 25B. REDEF$ (for 512 or more bytes)
Getting Started In Machine Language Programming 161
More on Branching
If you have an assembler program then calculating the address
used in a branch instruction is no problem. You identify the target
instruction with a label and use that label as the operand of the branch.
The assembler program then calculates the necessary relative address.
On the other hand, calculating relative addresses without an assembler
is a bit tricky the first few times you do it. So far we have seen a branch
forward (in Box 21) and a couple of branches backward. Here is the
branch forward section of Box 21:
CPX NUM
BNE END
LOA RESET
STA POINTER
END PLA
224
208
169
141
37
5
3'fstart counting here
31 6
104 --Target
The relative address for the BNE is 5. But, "5", from where? The
target is the PLA. The number following the BNE is added to the
program counter to get the address of the target instruction. A little
counting tells us that the program counter was pointing to LDA when
5 was added to it. Thus, the opcodefollowing the branch operand is the
starting point for count ing in relat ive addressing. Notice that all the
numbers between this opcode and the target area are counted.
Consider a segment of the code for MOV$:
LABEL
MNEMONIC
OPERAND
OPCODE
NUMBER
OPERAND
NUMBER
LOOP
LOA
STA
INY
BNE
INC
ADDR1
ADDR2
177
145
200
208
230
205
203
ENDPL 1
LOOP+206
249
206
162 Atari Assembly Language Programmer's Guide
How do we calculate the operand of the BNE instruction?
Starting at the INC (marked with an arrow) count backwards, to the
LDA marked LOOP , the result is 7. Subtract 7 from 256 and you get
249, the operand of BNE. To branch forward you count upwards from
zero . To branch backwards you count down from 256. Of course, the
counting forward and backward will eventually meet. Consequently,
you can branch forward a maximum of 127 bytes and backwards a
maximum of 128 bytes.
Passing Parameters to Subroutines
We can use the program in Box 26 to understand the details of
passing parameters from a USR instruction to a machine language
subroutine . The machine language subroutine is in lines 80 - 90 and is
used to move the lightbulb down the screen. A single parameter, the
current Y position of the bottom of the lightbulb player, is passed to
the subroutine in the USR command in line 135. Written out, the subroutine
is:
LABel
OPCODE
OPERAND
NUMERIC
OPCODE
OPERAND
PLA
104
PLA
104
STA
POS-1
PLA
STA
LOOP
NUMERIC
133
Remove parameter count
Get Hi- Byte and Lo - Byte
204
104
POS-2
133
of player's position and
store in page zero
203
LOA
#10
160
10
LOA
(POS-2) ,Y
177
203
INY
COMMENT
200
Indirect indexed addr
INC Y in order to move
the byte down
STA
DEY
(POS-2) ,Y
145
136
203
DEC Y twice in order to
fetch next player byte
Getting Started In Machine Language Programming 163
DEY
CPY
BNE
RTS
136
ENOUGH
LOOP
192
208
255
245
96
You can see from the listing that the Hi-Byte and Lo-Byte of the
Y-position are pulled offthe stack and put into page zero locations 203
and 204 respectively . Page zero locations 203 to 209 are free to use in
subroutines and probably will be sufficient in most cases. However, if
neither the machine language routine nor the BASIC part of your
program use the floating point package, then page zero locations from
212 to 255 are also free to use.
Study the structure of the loop portion of this subroutine because
it will also appear in the next program example. The object is to move
each byte, of a group, up one location in memory. This moves the
player down on the screen. The loop starts with an indirect indexed
load to get the byte at the base of the player. Incrementing the Yregister and using indirect indexed addressing with STA moves this
byte up one memory location. Then the Y-register is decremented
twice in order to get the next byte. However, before branching back to
LDA a CPY instruction checks to see if all the bytes have been moved.
If they have, the result of the CPY is zero, the Z flag is set, and the
subroutine ends. The program will loop 256 times before control is
returned to the BASIC program.
Because the next program (Box 26) is considerably more complicated
than our previous program examples , we will discuss in general terms
the program's structure before looking at the assembly language code.
Pedagogically, the program illustrates the use of simple binary
arithmetic which also involves two's complement arithmetic.
164 Atari Assembly Language Programmer's Guide
,
BOX 26
Play_r Mov __ nt
5 REM ** MOVING PLAYER **
10 A-PEEK(106)-8:PoKE 106,A:REM * MOVE RAMToP
20 GRAPHICS 2
30 POKE 54279,A:REM * SET PMBASE *
40 PBASE-A*256
45 REM * CLE~R PLAYER MEMORY *
50 FOR I =PBASE+512 TO PBASE+640:PoKE I,0:NEXT I
55 REM * READ PLAYER DATA INTO THE MIDDLE OF PLAYER 111 SECTION
6f2! FOR I-I TO 9
70 READ D:POKE PBASE+562+I,D
8121 NEXT I
90 DATA 60,126,2S5,25~, 126,60.24, 24,24
11210 POKE 53248, 1~0:REM SET HORIZONTAL POSITION
110 POKE 71114,88:REM * SET THE COLOR *
115 REM * TURN ON THE PLAYER *
120 POKE 559,46:PoKE 53277,3
13f2! FOR 1-121 TO 89:READ ML:PoKE 1536+I,ML:NEXT
140 DATA 11214,104,104,216,56,229,
203,240,43,16,42,73,2~5,24, 10~,
I, 133,204.
165,2~3,56,233.4,133
, 205, 164, 21215, 16'2, 11
150 DATA 177,206,136,145,206, 2f2!121,
200,202,208,246, 198,2j~5,198,2~4,2~18,236, 165,205,24,105,4,133,
203,96,133,21V4
160 DATA
165,21~3,24, 11~5,4, 133,2~15,
164, 2f2!5, 162, 11,177,206,20121,145,206,136,136,202
170 DATA
208,246,231~,205, 198,21~14,
208,236, 165,20~,56,233,4, 133,203.96
180 POKE 203,54:PoKE 206,0:POKE 207,A+2
200 PRINT "CHOOSE A POSITION FROM 8 TO 12f2!"
210 INPUT YPO
220 IF YPO(S OR YPO ) 120 THEN GoTO 200
230 DUMMY=USR(1536,YPoI
24121 GoTo 200
BOX 26. Player movement
In the program the user is asked to input a number between 8 and 120.
This number defines a position to which the machine language in lines
140 to 175 will move the lightbulb player. The first task that the
subroutine must do is determine whether to move the lightbulb up,
down, or not at all. This means that the position number, input by the
user, must be passed to the subroutine and compared with the bulb's
current position. Physically, the lightbulb is a group of nine bytes
located somewhere in the 128 bytes of Player O.
Getting Started In Machine Language Programming 165
PMBASE+512
Top of bulb
middle byte
...
Bottom of bulb
PMBASE+640
The bulb's current position is kept track of by noting the location of
the center byte. If the bulb is to be moved up the screen - which
corresponds to bytes being moved to smaller values in memory - the
movement routine will start at the top of the player. If the player is to
be moved down the screen, the movement routine will begin at the
bottom of the player.
The movement decision is made by subtracting the current
position from the new position and looking at the result. If the result is
equal to zero, then no change is called for and the subroutine ends . If
the result is greater than zero, the player moves up . If the result is less
than zero, the player moves down. The distance that the bulb moves is
equal to the difference between the old and new position values. That
figure conveniently serves as a loop counter. Since movement begins at
either the top or the bottom of the player, the necessary value will have
to be calculated from the current position before the player can be
moved. Finally, after the movement is complete, the location of the
center byte must be calculated and retained.
166 Atari Assembly Language Programmer's Guide
Box 27
Assembly Language Listing
Moving Lightbulb
Page Zero Usage:
POSITION = 203
COUNTER 204
OFFSET = 205
BASE 206,207
LABEL
MNEMONIC
OPERAND
OPCODE
OPERAND
104
104
PLA
PLA
Remove parameter count
Remove Position Hi-B yte ,
discard
Remove position Lo-Byte
104
216
PLA
CLD
COMMENTS
Clear decimal for binary
arithmetic
SEC
SBC
POSITION
BEQ
END
BPL
DOWN
56
229
240
16
EOR
#255
73
ADC
#1
STA
COUNTER
24
105
133
LOA
SEC
POSIT ION
Set carry bit for a
203
43
42
If result positive move player
255
Res ult must be negati ve.
Subtract with borrow
If result is zero, don't move
down
Change it to a positive number
CLC
204
Save the distance to move
203
Obtain current position
Determine the location of the
player
165
56
top of the player. Th is is The
Y-OFFSET
OUTRLP
SBC
#4
STA
OFFSET
LOY
OFFSET
L OX
#11
233
133
164
162
4
205
205
11
Load Y-reg ister with the offset
Load X-register with the byte
count
BOX 27. Assembly Language Listing Moving Lightbulb
Getting Started In Machine Language Programming 167
INNRLP
BASE,Y
177
BASE ,Y
136
145
DEC
DEC
INNRLP
OFFSET
COUNTER
200
200
202
208
198
198
BNE
OUTRLP
LO A
CLC
OFFSET
LO A
DEY
ST A
IN Y
IN Y
DEX
BNE
END
DOWN
#4
ADC
STA
RTS
POSITION
ST A
LO A
COUNTER
POSITION
C LC
208
165
24
105
133
96
133
165
24
206
206
Load accumulator with player
byte
Change Y-register
Sto re byte in new memory
location
Go back for
next byte
One byte of player was moved
246
205
204
236
205
Are all bytes moved?
If so , ad ju st offset to player top
Check off who le player moved
once
Is move comp lete?
Move is comp lete
So update the position registe r
4
203
204
203
Return from move routine
Save distance to move player
Obtain curre nt position
Determine the location of the
bottom of the player. Thi s is the
Y-O FFSET
OU TRLP
INNRLP
ADC
#4
STA
LOY
OFFSET
L OX
LOA
IN Y
STA
#11
105
133
164
162
4
205
205
11
Load X-register with the offset
Load X-register w ith the byte
BASE ,Y
177
206
coun t
Load Accumulator with player
BASE,Y
200
145
206
136
136
202
208
230
198
246
205
204
OFFSET
DEY
DEY
DEX
SN E
INNRLP
IN C
OFFSET
DE C
COUNTER
SNE
LOA
SEC
SSC
ST A
RTS
OUTR LP
OFFSET
Box 27. (Cont.)
114
POSITION
208
165
56
233
133
96
byte
Change Y-reg ister
236
205
4
203
Store byte in new memory
location
GO back for
next byte
Check off one byte was moved
Are all bytes moved?
If so, reset offset to player top
Check off player was moved
o nce
Is move Co mpl ete?
Move is comp lete so
update the
position
register
Return from move rou tine
168 Atari Assembly Language Programmer's Guide
Arithmetic Instructions
The arithmetic instructions used in this routine are simple single
byte binary instructions. To see them in action, look at Box 27 which is
the assembly language of the 'Moving Lightbulb' program. The first
two PLA's remove the parameter count and Hi-Byte of the player
position from the stack. This Hi-Byte will always be zero, so we don't
need it. The third PLA removes the byte we need and holds it in the
accumulator.
The 6502 CPU can perform two types of arithmetic, binary and
binary coded decimal. Binary arithmetic can be treated as signed or
unsigned. In this book we will only concern ourselves with binary
arithmetic. Therefore, the first instruction we use is CLD (Clear
Decimal mode). This instruction must always precede a binary
arithmetic sequence. This done, we are ready to subtract the current
position from the new position. The value of the bulb's current
position is in memory location 203; the value of the new position is in
the accumulator.
The 6502 subtract instruction is SBC (SuBtract with Carry) which
actually means subtract using the carry flag as a borrow digit, if
necessary. This allows for the possibility that the number being
subtracted from the accumulator is bigger than the number in the
accumulator. Since SBC needs the carry flag, it must be preceded by
SEC in all cases. SBC, like LDA , has eight different addressing modes.
In this program we use zero mode.
Having subtracted the current position from the new position, it is
necessary to determine which direction to move the player. BEQ END
takes care of the case in which there is no movement. BPL DOWN
sends program control to the section of the routine that moves the
player down. If neither of these conditions occur, then the routine
goes about moving the player up .
N ow we come to a somewhat technical topic. The 6502 performs
its subtraction by addition! The method used is known as two's
complement arithmetic. The practical consequence here is, that if the
result of the subtraction is a negative number, then the number left in
the accumulator will not be in ordinary binary form, but rather in
two's compliment form. Accordingly, the result will have to be
converted to its positive equivalent before we can use it as a loop
counter.
Getting Started In Machine Language Programming 169
Two's complement arithmetic works as follows . Suppose you are
adding the negative of an ordinary decimal number to itself, say 2+(-2) .
The result is, of course , zero. Now, suppose that you add the binary
number I and the binary number 255. The result in an eight bit register
is zero . In binary form the result is:
0 0 0
000
0 0 0 0 0 0 0
~
a ninth bit
8 bits, all zero stored in register
You will get the same result if you add 2 and 254 in binary form . Or if
you add 3 and 253. Or 4 and 252. By now you should see the pattern.
Every positive number up to 128 has a corresponding number (its
negative) that, when added to it, gives 256. Which, as far as an eight bit
register like the accumulator is concerned, is really zero.
N ow, what does this mean for the subroutine? Well, if we were to
subtract an input position value of80 from a current position value of
42, the result left in the accumulator would be the two's compliment
equivalent of minus 38, or 218 (in binary from 1101 1010). To use this
as a counter in the subroutine, it must be converted to a positive
number.
The algorithm for changing a number into its two's compliment
form is very simple. All you do is change every zero to a one and every
one to a zero and then add one. The algorithm works both ways.
Consider our example of 42 minus 80. The result, in decimal is -38 . The
result in 6502 subtraction is I 10 II 0 I0 which has the decimal equivalent
of 218. Parenthetically, 218+38= 256, as we would expect. By decimal
arithmetic, we have concluded that 218 must be the negative of 38.
Let's apply the algorithm:
170 Atari Assembly Language Programmer's Guide
11011010
(218)
001 001 01
Flip bits
+1
Add 1
o0 1 0 0 1 1 0
= 32 + 6 = 38
Suppose we wanted to go the other way:
o 0 1 0 0 1 1 0 = 38
Flip bits
1 1 01 1 001
+1
1 1 0 1 1 0 1 0 = 218
The 6502 instruction set has a very handy command that allows
you to change one's to zero and vice versa. It is the EOR (review Box 3)
command. To flip all the digits of a number all you have to do is to
EOR the number with 255. For example:
1 0 1 1 0 1 1 1 = 183
11111111
EOR with 255
01001000
Finally, to make it a two's complement, add 1:
01001000
+1
o 1 00 1 00
I two's complement of 183
Getting Started In Machine Language Programming 171
In conjunction with this discussion oftwo's complement arithmetic,
remember that branch instructions can go backwards 128 steps.
Backward branches use negative numbers written in two's complement
form.
In the assembly listing, the EOR command follows the BPL test,
which, if true, sends the program to the section which moves the player
down. Look at the two instructions following EOR. These instructions
are required since our program needs to add 1 to the result of the
EO Ring. The 6502 add instruction is ADd with Carry (ADC) and as
the name implies, any carry from the accumulator will go over into the
carry bit. Consequently, before using an ADC, you must first clear the
carry flag with CLC. Once this is done you are free to ADC.
Following the EOR-CLC-ADC sequence, the up-routine proper
begins with ST A counter. From t l~ is point on, the up and down
routines are mirror images of each other. Therefore, we'll comment
only on the up routine. Unlike the previous move routine, this one uses
a double loop structure. The reason is it moves only eleven of the
player's 128 bytes . Eleven bytes are moved rather than just the nine
bytes that actually form the light bulb player, so that blanks can be
moved into the position where the player originated thereby preventing
it from leaving a trail as it moves up the screen. Additional things to
note are: that the offset used by the Y-register is decremented at the
completion of the inner loop; and that at the completion of the move,
the new position is calculated by adding four to the offset.
Up to this point we have illustrated a good portion of the 6502
instruction set, introduced several fundamental programming concepts,
and discussed basic arithmetic operations. We shall conclude this
chapter by presenting a subroutine that moves missiles and in the
process demonstrates logic and shift instructions in action.
We have seen that XOR can be used to complement bits. The
other two logic commands - AND and ORA - can be used to test, clear,
or set specific bits in memory. AND and ORA make use of two bytes,
one in memory and one in the accumulator. Bit by bit com paris ions of
the two numbers are carried out according to the logic rules described
in chapter one. The result is stored back in the accumulator and the
sign and zero flags are set, if appropriate.
172 Atari Assembly Language Programmer's Guide
Using the AND j ORA instructions in a missile move routine is
dictated by the way missiles are represented in memory. The four
missiles, MO through M3, are located side by side in player-missile
memory at PMBASE384 or PMBASE768:
Missile
M2
M3
Bit
Decimal
07
06
128
64
32
M0
MI
5 04
16
03
02
-4
01
00
Now, if missiles MO and M2 exist as:
MO
M2
00
00
00
00
11
11
11
11
00
00
00
00
11
11
11
11
and you want to move MO without disturbing M2, it is
necessary to mask out, not erase, M2's bits. This masking is
accomplished by ANDing at the appropriate time. On the
other hand, if the missiles exist in memory as:
M2
00
00
00
00
00
00
00
00
00
00
00
00
11
11
11
11
MO
00
00
00
00
00
00
00
00
11
11
11
11
00
00
00
00
Getting Started In Machine Language Programming 173
and you want to move MO next to M2, you have to take care
that M2's bits are not wiped out in the process. This is accomplished
by masking with AND and unmasking with OR. Of course the
same comments hold true if it's M2 that is being moved rather
than MO.
,
80X 28
Missile Move.ent
\~5 \ REM
REM ' ** MISSILE MIJVEMENT
* LOWER RAMTOP *
1~
2111
25
30
4111
50
60
6:5
7111
7:5
.*
A-PEEK(106)-8:POKE 106,A
GRAPHICS 2
REM SET PM BASE *
POKE 54279,A
PMBASE~A*2:56
POKE 20:5,0
POKE 206,A+3
REM * CLEAR PM MEMORY *
FOR I=PMBASE+768 TO PMBASE+1024:POKE I,0:NEXT
REM * READ IN MISSILE DATA
8~ FOR 1-9 TO 3:POKE PMBASE+896+I,:51:NEXT
85 REM * SET HORIZONTAL POSITION.
90 POKE 532:52, 160: POI<:E 53254, 120
9:5 REM * READ IN MOVE ROUTINE
100 FOR I-Ill TO 63
110 READ ML:POKE 1536+I,ML
12" NEXT I
12:5 REM
130 DATA 162,6,160,25:5,1 3 6,208,2:53,
202,208,248,162,:5,164,203,200,177,205,74 ,7 4,201,12,240,17,136
,177,20:5,41,3
13:5 REM
140 DATA 200,14:5,20:5,136, 21n, 208, 236, 23~1, 21n, 76, 54, 6,1 .3 6
145 REM
1:5111 DATA 177,2i1l:5,9,48,21111~, 145,205,
136,202,208,219,230,203 , 165,204,141,4,208 ,230 ,204,76,0,6
1:5:5 REM
1:56 REM TURN ON MISSILES
157 REM * START MOTION.
160 POKE 21l13,131:POKE 21114,160
170 POKE 704,88:POKE 706,56
180 POKE 559,54:POKE 53277,1
190 FOR 1=0 TO 150:NEXT I
21110 X=USR ( 1536)
Box 28. Missile movement
174 Atari Assembly Language Programmer's Guide
BOX 29
Assembly Language Listing
Moving Missiles
Register Usage:
VPOS (Vertical position)
= 203
HPOS(Horizontal
position) = 204
BASE = 205,206
LABEL
MNEMONIC
OPERAND
OPCODE
BEGIN
OUTER
INN ER
LOX
LOY
DEY
BNE
OEX
BNE
LOX
#4
#255
OUTER
#5
162
160
136
208
202
208
162
LOY
VPOS
164
LOOP
INY
LOA
LSR
LSR
CM P
BEQ
Inner
(BASE),Y
#12
OTHER
COMMENT
Delay action
to slow missile movement
to speed the human eye
can perceive
255
253
248
5
203
205
12
17
136
DEY
LOA
AND
INY
STA
DEY
OEX
200
177
74
74
201
240
OPERAND
(BASE),Y
#3
(BASE),Y
177
41
200
145
136
202
205
3
205
Load X with number of
segments + 1
Load Y with location of bottom
segments
Increment Y to target position
Load from target position
Shift out of missi le 0 bits , if
they are present
Test for missile 2 bits
If present branch to OTHER
routine
Decrement Y to pick up missile
0
Pick up MO
Mask out M2, if present
Increment Y to store MO
Store MO
Decre ment Y
Check if one segment moved
Getting Started In Machine Language Programming 175
OTHER
BNE
LO OP
208
236
INC
VPOS
230
203
JMP
DEY
HOR IZ
54,6
LOA
ORA
INY
STA
DEY
(BASE ),Y
76
136
177
#48
(BASE),Y
DE X
HORIZ
205
48
9
200
145
136
Branc h back to move anoth er
seg ment
If done, in c rement the position
reg ister
Jump to horizontal move routin e
Dec rement Y to pick up MO
Load MO segment
Add in missile 2
Increment Y to store MO and M2
205
Store MO and M2
Dec rem ent Y for next test and
pickup
Check off segment moved
BNE
LOOP
202
208
219
Go back to move another
INC
VPOS
230
203
segm ent
If done increment position
LOA
STA
HPO S
HPO SMO
HPO S
165
141
204
4,208
230
76
204
0,6
INC
JMP
BEGIN
register
Load horizontal position
Store in MO position register
I ncrement horizontal position
Jump back to beginning
Box 29. Assembly language listing moving missiles
Box 28 is the program listing and Bo x 29 is the assembly
language listing for missile movement. In addition to illustrating
AND, ORA, and LSR instructions , machine language speed is
displayed . In order to allow the eye to perceive the missile as
one box traveling diagonally across the screen it was necessary
to begin the program with a delay loop. Even with this delay
loop the missile appears to have a tail, much the same as a
comet, as it speeds across the screen.
At the outset of the program the missiles are in memory
as:
MO
M2
00
00
00
00
11
11
11
11
00
00
00
00
11
11
11
11
176 Atari Assembly Language Programmer's Guide
Missile two will remain stationary while missile zero travels.
What we must insure is that when we move MO, we don't wipe
out M2. This involves shifting, testing, and masking. When
making a comparision it is easier if there is only one element
present. Therefore, prior to testing for M2 it makes sense to
temporarily remove MO's bits from the accumulator. This is
done with the LSR instruction.
The LSR (Logical Shift Right) instruction has four
addressing modes. In the present situation we use the accumulator
addressing mode. In the LSR, a zero is shifted into bit D7 and
bit Do is shifted into the carry flag. At this point we are
essentially not interested in the status of the carry flag, but
rather in seeing that bits Do and D1 go out of the accumulator.
Pictorially the process can be represented as:
Accumulator before LSR
M2
7 6
0
M0
Ds
D4
D3
D2
D1
De
After the first LSR
M0
06
5 4
D3
D2
D1
De
CARRY
Getting Started In Machine Language Programming 177
After the second LSR
M0
M2
D7
D6
DS
D4
D)
D2
Dl
De
Note that the MO bits are gone. The M2 bits have been shifted
to the right so they now represent the decimal number 12. It is
now a simple matter to test for their presence with a CMP #12.
There is something else we can learn from the LSR
instruction. Each LSR will divide an even number by two. 48
divided by two twice is twelve. With odd numbers the presence
of a one in the carry flag indicates the existence of a .5
remainder. What happens to a number if you shift the bits to
the left? If you answered the number is mUltiplied by two, you
are correct.
The comments in the machine language listing provide a
detailed description of the missile movement. The following
flowchart will help you to follow the logic.
178 Atari Assembly Language Programmer's Guide
Figure 4.2. Missile Program Logic Flow
5
Sound
Introduction
Second generation computers such as the Atari Home Computer
provide the programmer with the opportunity to use music and sounds
within their programs as another means of communication. In an
adventure game , music can set a mood , arouse emotions and
complement the action. In a utility program, sounds can signal a
keyboard entry error or warn that the disk is almost full. In addition to
these common applications, the hardware capabilities of the Atari
computers offer you the chance to try your hand at music synthesis via
programs dedicated solely to sound generation. For maximum
versatility and satisfaction, sound programs should be written in
machine language since BASIC is too slow for generating complex
sounds. Additionally, because of the nature of the 6502 processor, a
music program written in BASIC cannot run simultaneously with the
mam program.
179
180 Atari Assembly Language Programmer's Guide
A complete analysis of music and sound synthesis is a field of
study in and of itself and can be undertaken only by using advanced
mathematics. Consequently, we will limit our discussion to the
fundamentals of sound synthesis. This will be sufficient to suggest
ways to use the sound generation hardware that we will describe. To
aid you in exploring the sound capabilities of the Atari we have also
included reference material and some utility programs.
A Bit of Theory
A sound or musical tone may be described by its intensity or
loudness, its frequency or pitch, and its waveform or timbre. Sounds
are created by devices such as tuning forks , TV speakers, or human
vocal chords, that vibrate back and forth in a cyclic manner. These
vibrations generate pressure changes in the surrounding air that are
detected by the human ear as sound. What a human perceives as sound
is a function of both the instrument generating the sound and the
human ear - a piano sounds different from an oboe. Before we can
understand complex tones, like those generated by a piano, it is
necessary to understand simple tones or notes.
Sound transmission can be represented pictorially as waveforms
with the simplest waveform being a sine wave. A waveform is usually
drawn as a graph where the horizontal a xis represents time and the
vertical axis represents a parameter such as the displacement or
pressure of the medium carrying the wave . The sine wave is referred to
as a pure tone even though the aural perception of a pure tone may be
Impure.
sin t
Figure 5-1. Sine wave
Sound 181
The fundamental parameters describing a pure tone are its
frequency and amplitude. The frequency is the number of complete
repetitions or cycles per second that the waveform displays. A related
parameter is the period which is the time for one cycle. Mathematically,
period and frequency are related by:
frequency
= 1/period
Frequency (cycles per second) is measured in units called Hertz
(Hz), after the 19th century physicist who discovered radio waves.
Frequency is closely related to the perceived pitch . When frequency is
increased, the perceived pitch also increases. However, pitch is a
subjective parameter and the relationship between the two is not
linear. For example, an increase from 100 Hz to 200 Hz results in the
perception of a large increase in pitch upward, but an increase from
4000 Hz to 4200 Hz is a much less perceptible increase.
Likewise, amplitude is related to, but not equivalent to loudness.
Here again the characteristics of the human ear enter into what is
perceived. It has been found that the response of the ear is not
proportional to the amplitude. Instead it is useful to use a logarithmic
scale to measure loudness. Since the computer hardware puts limitations
on the amplitude of the sounds that can be generated we will not have
to worry about loudness scales . What will be important to us is the
effect of loudness variations in sound generation.
A pure tone, such as would be produced by the waveform of figure
5-1, rapidly becomes dull listening. The essence of music is variation,
variation in parameters such as amplitude, pitch and the rhythm with
which notes are played. Too much variation, such as complete
randomness, generates noise. Too little generates monotony.
One obvious way to introduce change into the sine waveform is to
vary the amplitude. figure 5-2 shows a sine wave whose amplitude is
modulated:
182 Atari Assembly Language Programmer's Guide
..
..
:"j
: :
: :
'.
\,/
,j
\)
Figure 5-2. Sine wave with modulated amplitude
Sustain
Attack
_ _J
Figure 5-3 . Sound envelope
Sound 183
If we connect the peaks with a line and throwaway the sine wave the
result is a picture of the sound envelope. This envelope is descriptive of
a single note that sounds for a short period of time. The shape of the
envelope is described by the risetime (attack), the sustain time, and the
decay time .
Ignoring amplitude modulations of notes, the tones produced by a
musical instrument are not pure tones characterized by a single
frequency, but are composites of a fundamental frequency and
overtones, or harmonics. Harmonics are waves whose frequency is an
integral mUltiple of the fundamental frequency . What we call timbre is
the result of different combinations of harmonics. One reason middle
C on a piano and an oboe sound different is due to different
combinations of harmonics .
Figure 5-4 illustrates a fundamental frequency, two overtones,
and the result when these three waves are combined. Now as far as the
ear is concerned the same result occurs if the final wave form of figure
5-4 is produced by a single instrument or if three separate instruments
sound the pure tones simultaneously .
.......
"
'
"
Figure 5-4. Fundamental frequency with two overtones
I
,I
i
184 Atari Assembly Language Programmer's Guide
.,t.
.. .
~I-------------------~
Figure 5-4. (Cant.)
Sound 185
,""''.
,'\
,,
"../
.1
1" ,
Figure 5-4. (Cont.)
The concept of adding sine waveforms of different frequency and
amplitude together to form a new and different waveform is an
extremely powerful technique in music synthesis. In fact, it's a
powerful idea in mathematics as well. If one drops the restriction of
figure 5-4, that the harmonics are integral multiples of the fundamental
frequency, waves of almost any conceivable shape can be generated.
Figures 5-5 and 5-6 show how sine waves can be added together to
make a square wave and a triangle wave.
A triangle wave sounds very much like the sustained tone of an
oboe, but the oboe's tone is much warmer and more interesting
because of minute fluctations produced by the person playing the
instrument. Such minute fluctuations are sometimes referred to as
dynamic variation of the sound parameters. Of these, dynamic
variation of frequency is perhaps the most basic. For example, in a
simple one-voice melody if the frequency transition between notes is
fairly long, the audible effect is that of a glide from note to note. Often
with conventional instruments a small wavering of the frequency,
called vibrato is added to the notes. Vibrato modifies the frequency six
186 Atari Assembly Language Programmer's Guide
- - --------- --- - ---- ,- --:i
/ i
-------~
-lr
:r
- -- -
i / -~~~
I
--
.__ ___
-,.-
- -- ~
Figure 5-5. Square wave
"
. (.. ~
):::.~ _ _
,t . . . -"\
... ....
"--
'--'
Sin
5%
:r
.'-
Sound 187
il101(::
Figure 5-6. Triangle wave
to eight Hz with possibly a one percent amplitude variation. Actually,
amplitude variation alone can be introduced and this is called tremolo.
In conventional instruments both vibrato and tremolo will usually be
present to some degree.
The discussion so far implies that there are several options
available to the programmer. He can experiment with variations in
amplitude or frequency and superimpose sounds of different frequencies.
In addition to this , with the Atari Home Computer you can create
sound effects by what might be called subtraction rather than
superposition. Before going on to consideration of the hardware
capabilities let's review the measurement of pitch.
The basic unit for measuring pitch is the octave. If tone 'A' is one
octave higher than tone 'B', then its frequency is exactly twice as high
and the sensation of pitch is twice as high . Other units of measurement
188 Atari Assembly Language Programmer's Guide
a re the half-step, which is 1/ 12 of a n octave or a frequency ratio
between two adjacent notes of 1.05946 a nd the cent, which is 1/ 100 of a
half-step or a ratio of 1.0005946. The difference in pitch between two
directly adj acent keys on a conventionally tuned piano is a half-step.
For moderately loud sounds of about 1000 Hz, the smallest change in
frequency that can be perceived is about five cents. Since these units
are purely relative there must be a sta ndard upon which to anchor any
musical scale. The most notable is the International Pitch Standard
which defines A above middle C to be 440 Hz. The most popular
musical scale is the Equal Temperment Scale which is based on the
frequency ratio of a half-step being the twelfth-root of two or 1.05946.
The name equal temperment means that all half steps are the same size.
Table 5-1 lists the eight octaves a nd the corresponding frequencies
for each note. This table will be useful in fine tuning your music
programs .
Table 5-1. Frequency
OCTAVE
NOTE
C
C#
0
0#
E
F
F#
G
G#
A
A#
16.35
17.32
18.35
19.45
20 .60
21 .83
23.12
24.50
25.96
27 .50
29.41
30.87
32.70
34.65
36.71
65.41
' =m iddle C
# =concert A
38 .89
41.20
43 .65
46.25
49.00
51 .91
55 .00
58.27
61 .74
130.81 261.63 ' 523.25
69.30 138.59 277 .18 554.37
73.42 146.83 293.66 587 .33
77.78 155.56 311.13 622.25
82.41 164.81 329.63 659.26
87.31 174.61 349.23 698.46
92 .50 185.00 369.99 739.99
98.00 196.00 392 .00 783 .99
103.83 207.65 415 .30 830.64
110.00 220.00 440.00# 880 .00
116.54 233.08 466.16 932.33
123.47 246 .94 493.88 987 .77
1046.50
1108.75
1174.66
1244.51
1318.51
2093 .00
2217.46
2349.32
2489 .02
2637.02
2793.83
2959.96
3135 .96
3322.44
3520 .00
3729.31
3951 .07
1396.91
1479.98
1567.98
1661.22
1760.00
1864.66
1975..53
Sound 189
Sound Hardware
The heart of sound generation in the Atari Home Computer is
four programmable sound channels that can operate independently or
in pairs. Associated with each sound channel is a frequency register,
that is used to determine which note is played, and an audio control
register. This is all handled by POKEY. In addition to sound
generation, POKEY is an input / output chip that controls serial I / O
and keyboard input. POKEY allows a sufficient number of control,
frequency, and volume options so that the programmer can work with
these parameters to synthesize music.
Frequency is the basis of music so we 'll look at the frequency
registers first. The frequency registers AUDFI through AUDF4 are at
memory locations 53760, 53762, 53764, and 53766 respectively.
Numbers stored in these registers provide the "N" in divide by N
counters that reduce one of the three basic clock frequencies to a
desired sound frequency . The three basic clock frequencies are 15 KHz
(kilohertz) , 64 KHz and the system clock 1.79 MHz (millionhertz).
Suppose you are working with the 15 KHz clock. This clock generates
a signal consisting of 15,000 square pulses per second:
15 KHz
Jl_---JnL...--_----llL
after divide-by-three
A simple divide by three operation allows every third pulse through
and thus reduces the frequency. If the resulting signal is fed to the TV
speaker, the speaker will vibrate in response to the pulses.
There are two formulas that are used to calculate the output
frequency. If the clock frequency chosen is 64 KHz or 15 KHz, the
formula is:
190 Atari Assembly Language Programmer's Guide
frequency out
= clock frequency/2(AUDF+1)
where AUDF is the number in the frequency register.
If the system clock, 1.79 M Hz is used then the formula is modified
to:
frequency out = clock frequency/2(AUDF+M)
Where M= 4 if the frequency registers operate singly.
Where M= 8 if the two sound channels are paired.
The option just mentioned, pairing sound channels, is provided to
give the user the opportunity to match sound frequencies more closely
than may be possible with single channels. The following numerical
examples will make this concept clearer. Suppose you are using single
channel sound. Then the numbers in the frequency registers are eight
bit numbers that can have decimal values of 0 to 255. Using 10 as the
number in AUDFI with a clock frequency of 64000 Hz, according to
the formula, the output frequency is
64000/2(10+1)
= 2909.1
Hz
If you change the number in AUDFI to II, the corresponding output
frequency will be 2666.7 Hz, a difference of 242.1 Hz. Thus a small
change in AUDFI's setting results in a large change in the output
frequency. This in turn represents a loss in resolution (selectivity of
output frequencies). The situation is not so bad when the numbers in
the frequency registers are large: 250 generates an output frequency of
127.5 Hz and 251 generates an output frequency of 126.98 Hz, which is
adequate resolution. Single sound channels will work satisfactorily in
many cases. For cases in which they are not adequate, pairing two
sound channels also pairs the frequency registers. Paired registers act
as 16 bit numbers thereby giving N values of 0 to 65535. When sound
channels are paired the clock frequency used is 1.79 MHz.
In the above discussion the values 15 KHz, 64 KHz and 1.79 MHz
are all approximate. If you need the exact values, use 15.6999 KHz,
63.9210 KHz and 1.78979 MHz respectively.
Sound 191
Associated with each frequency register is a control register
AUOCI through A UOC4. These are at the memory location following
the frequency register that they control - 53761, 53763, 53765, and
53767. There is also one-general control register AUDCTL at memory
location 53768 (see table 5-2).
The bit configuration of the control registers is :
07
06 0 5
04
03
O2
01
Distortion contro l bits fo r so und effects
Sets a vo lume on ly mode that di sab les
frequency registers
Do Volume co ntrol
For a pure tone the upper four bits of a control register must be set as:
X means it doesn't matter.
The bottom four bits (D3 - Do) determine the volume with 0000 giving
no sound, 1000 provides half volume and 1111 maximum volume. In
any case, the sum of all volumes in all sound channels should not
exceed decimal 32 or the sound quality will suffer.
The volume only option, which is chosen when bit four of the
AUOC registers is set, gives the programmer an opportunity to
experiment with waveform synthesis. When this bit is set, the
frequency registers are disconnected from the system. Then bits Do 0 3 determine the position of the TV speaker. A TV speaker consists of
a paper cone that moves in and out in response to changing voltage
values sent to it by the computer. A single pulse, consisting of a rising
voltage followed by a falling voltage
192 Atari Assembly Language Programmer's Guide
would cause the speaker to move out with the rising portion and return
to its rest position with the falling portion of the pulse.
Using the volume only mode, the speakers moves to one of sixteen
positions depending on the value stored in AUOC. In this case,
however, the speaker does not automatically return to the zero
position as with the pulse above, but remains set in a position until the
program modifies it. In principle then, synthesizing a waveform
becomes a matter of writing a progra m to move the speaker so that its
successive positions match the amplitude of the waveform. The major
limitation is that there is only sixteen position settings.
The upper three bits (0 7 - 0 5 ) of the audio control registers are
used to create sound effects where a pure tone is not wanted . These bits
control polynomial counters, also called poly-counters, that are used
to remove pulses from a normal pure tone's train of pulses. These
pulses are removed in a semi-random manner and the bit pattern that
results will repeat after a span of time. When bits are removed
randomly, giving a pulse train such as,
the resulting sound can imitate anything from a lawn mower to a
rocket blast off!
The repetition rate depends on the number of bits in the polycounter. A poly-counter is a modified shift register whose internal
operation needn't concern us . There are three poly-counters, two that
are small, being four and five bits long, and a large one - 17 bits long.
Optionally using AU DCTL, the 17 bit poly-counter can be reduced to
a 9 bit length. The poly-counters can operate singly or in pairs. Table
5-2 gives the bit settings for choosing the allowable combinations.
Keep in mind that the starting point is a train of pulses at a constant
frequency which has been determined by the clock and the frequency
register. Two factors enter into the creation of the sound heard: the
Sound 193
particular combination of poly-counters and the frequency being used.
For this reason it will take some experimentation to create a desired
effect. Box 30 is a sound effects utility program to help you
experiment.
Uti 11 ty Proor . .
Sound Eff.cts Gen~.tor
1~ REM ** SOUND EFFECTS GENERATOR **
2~ DIM ANS. (1)
3~ POKE ~3768,~:POKE ~377~,3
4121 PRINT "DO YOU WANT DEMONSTRATION SOUNDS (YIN)"
4~ TRAP 4121
5121 INPUT ANS.
6121 IF ANSS-"Y" THEN GOSUB 390
7" PRINT
8~ PRINT "PICK FREQUENCY NUMBER (1 - 2~~)"
98 PRINT
1~8 PRINT "4 --> HIGH FREQUE~CY"
1"~ PRINT
1 1'/J PRINT "128 --> MEDIUM FREQUE~Y"
11~ PRINT
12//J PRINT "2~~ --> LOW FREQUENCY"
13//J PRINT :TRAP 8//J
14//J INPUT N
14~ POKE ~3761Z1,N
1:58 PRINT
16" PRINT "CHOOSE DISTORTION"
17//J PRINT
18//J PRINT "VOL ... + BITS 7,6,5 SETTING"
19" PRINT
19~ PRINT "EQUALS DISTORTIm~ NUMBER"
2"" PRINT
2121~ PRINT "BITS 7,6,5
10,10,121 => VOL .....
21121 PRINT
21~ PRINT "BITS 7,6,5
121, I!I, 1 => 32+VDL."
22" PRINT
22~ PRINT "BITS 7,6,~
121, 1 , I!I => 64+VOL."
23121 PRINT
\.. 23~ PRINT "BITS 7,6,5 ,. 1,121,0 => 128+VOL."
..
Box 30. Sound effects generator
194 Atari Assembly Language Programmer's Guide
241~
245
250
255
260
270
275
280
290
:3111~1
310
320
:33111
34111
35ul
355
36121
3"711'
380
391~
41110
405
410
415
420
425
43111
435
440
445
450
460
470
480
PRINT
PRINT "BITS 7,6,5
l.,1,111 => 192+VOL."
PRINT :TRAP 160
INPUT DIST
POKE 53761,DIST
FOR 1=1 TO 10~0:NEXT
POKE 53761,0
PRINT :TRAP 290
PRINT "TRY AGAIN (YIN)?"
INPUT ANS$
IF ANS$="Y" THEN GOTO 70
PRINT :PRINT
PR I NT "CURREI\JT NUMBER IN AIJDF l. IS:"; N
PRINT
PR I NT " DI ~3TORTI ON-VOLUME NUMBER"
PRINT
PRINT " IN AUDCl IS:"; DIST
END
REM * DEMONSTRATION SECTION *
PRINT
PRINT "STARTING WITH A LOW FREQUENCY"
PRINT
PRII\JT "WE WILL CYCLE THROUGH"
PRINT
PRINT "THESE DISTORTION-VOL NUMBERS:"
PRINT
PRINT "8,4111,72,136,2111111"
PRINT
PRINT "IN EACH CASE tHE VOLUME IS 112 MAX."
FOR I-I TO 1000:NEXT I
POKE 53760,255
PRINT CHR$(125)
PRINT "LOW FREQUENCY"
GOSUB 640
Box 30. Cont.
Sound 195
'4ge PRINT :PRINT "CONTINUE (Y/Nl-:>"
~e~
~10
~20
~30
54{1
~~e
~6{1
~7l1
~80
5ge
600
6111
620
62~
630
640
6~0
660
670
680
\.690
INPUT ANSf:TRAP 500
IF ANSf-"N" THEN GOTO 80
PRINT CHRf(12~l:RE9TORE 650
POKE ~3760,128
PRINT "MEDIUM FREQUENCY"
aOSUB 640
PRINT :PRINT "CONTINUE (Y/Nl-:>"
INPUT ANS.:TRAP 570
IF ANS.=-"N" THEN GOTO 80
PRINT CHR.(125l:RESTORE 6~0
POKE 53760,4
PRINT "HIGH FREQUENCY"
GOSUB 640
TRAP 40000
RETURN
READ X:PRINT :PRINT "DISTORTION+VOL =";X
DATA 8,40,72,136,200,-1
IF X=-1 THEN POKE 53761,0:RETURN
POKE ~3761,X
FOR 1=1 TO 500:NEXT I
GOTO 640
BOX 30. (Cont.)
The frequency registers select the tones. The control registers
AUDC give volume and sound effects option for each sound channel.
There is one register that exerts overall control. This is A UDCTL at
memory location 53768 . The functions of the bits in this register are
listed in table 5-2 which also summarizes the functions of all other
sound hardware registers .
The high pass filters mentioned under A UDCTL in table 5-2
deserve some explanation. A high passjUter allows frequencies higher
than some predetermined limit to pass through. Here the limit is
determined by the frequency in another channel. When there is a filter
in channel '2, channel 4 sets the frequency limit. When there is a filter in
channel I, channel 3 sets the limit.The filters can be useful for creating
sound effects.
196 Atari Assembly Language Programmer's Guide
Table 5- 2. Summa ry of sound registers
A. Frequency Registers at (AUDF)
53760, 53762, 53764, 53766
B. Audio Control Registers at (AUDC)
53761,53763, 53765,53767
Bit Functions
Set Volume in frequency mode
Position (volume) in volume only mode
1 sets volume only mode
04
05
06
07
o
o
o
0
X
1
0
0
0
0
o
X
Remove pulses using 5 and 17 bit polys, divide by 2
Remove pulses using 5 bit polys, divide by 2
Remove pulses using 4 and 5 bit polys, divide by 2
Remove pulses using 17 bit poly, divide by 2
Pure tone
Remove pulses using 4 bit poly, divide by 2
O2
03
04
05
06
C. Audio Control (AUDCTL) at 53768
Bit Functions
0 gives 64 KHz clock; 1 gives 15Hz clock
when set, uses high - pass filter in channel 2
when set, uses high-pass filter in channel 1
when set, joins channels 3 and 4 (16 bit resolution)
when set, joins channels 2 and 1 (16 bit resolut ion)
when set, clocks channel 3 with 1.79 MHz
when set, clocks channel 1 with 1.79 MHz
07
when set, changes 17 bit poly to 9 bit poly
00
01
store a 0 in AUDCTL to initialize POKEY for sound
O. Serial Port Control (SKCTL) at 53775
Store a 3 here to initialize POKEY for sound
Sound 197
Program Examples
The next few programs (Boxes 3 I - 33A) illustrate the theoretical
concepts discussed earlier: Envelope, Tremolo, and Vibrato. The
programs are all structured similarly and are intended to be taken
apart and used in other programs . Each has four sections.
The first section initializes the hardware for sound by turning off
interrupts, ANTIC's direct memory access, then storing a 0 in
AUDCTL, and a 3 in SKTL. Turning off the interrupts and ANTIC is
important because in a program devoted solely to music consistent
timing is important. ANTIC turns off the CPU at odd intervals which
could wreak havoc in a music program. Note that it is not sufficient to
just store a 0 in DMACTL since it is shadowed at 559 and would be
restored during the vertical blank.
The second section of each program sets the initial sound
frequency and volume and initializes a delay loop. The third section
manipulates either AUDC or AUDF for the desired effect. Finally,
there is a delay loop. A delay loop is needed because things happen so
quickly in machine language, that you have to slow down the time
between frequency or volume changes in order for the effect to be
meaningful in terms of human perception.
Each delay loop actually has an inner and outer loop. The inner
loop takes some set amount of time say, for example, .225 milliseconds
to execute and the outer loop determines how many of these units of
time are used in the delay . The amount of time taken for delay loops
can be estimated by counting the machine cycles needed for execution
of each instruction. Using the approximate value of the CPU clock
frequency, 1.79 MHz, the time for one machine cycle is:
.000000559 seconds
198 Atari Assembly Language Programmer's Guide
BOX 31
Envelope
REM ** ENVE LOP EXAMPLE **
NUMBER=74
FOR I~0 TO NUMBER:READ D
POKE 1536+I,D:NEXT I
50 REM * INITIALIZE MACHINE *
60 DATA 104,169,O,141,14,212,
141, 14,210, 141,0, 212, 141 ,8,210, 169, 3, 141, 15,210
65 REM
70 REM * INITIALIZE DELA Y AND pOU ND REGISTERS.
80 DATA 169,20,133,203,169,72,141, O,210
90 REM * CREATE ENVELOP *
100 DATA 160,160,140,1,210,200,32,
65,6,192,176,208,245,169.100,133,203,32,65,6,136,140,1,210,16
9,200,133,2Jl13
110 DATA 32,65,6,192,160,208,241,96
120 REM * DELAY SUBROUTINE *
130 DATA 162,80,202,208,253 , 198. 2 03,208,247,96
140 XzUSR (1536)
145 REM * RESTORE SCREEN *
150 POKE 54272,34:POKE 54286,64:POKE 53774,192
10
20
30
40
Box 31. Envelope
Sound 199
BOX 31A
Assembly Language Listing
for
Attack, Sustain, Delay
Section 1: Initialize the machine
PLA
LOA
STA
STA
STA
STA
LOA
STA
#0
NMIEN
IRQEN
OMACTL
AUOCTL
#3
SKCTL
104
169,0
141,14,212
141 ,14,210
141 ,0,212
141 ,8,210
169,3
141 ,15,210
Remove parameter count
Turn off
interrupts
Turn off ANTIC
Initialize POKEY
Section 2: Initialize Delay and Sound
LOA
STA
LOA
STA
#20
COUNT
#72
AUOF1
169,20
133,203
169,72
141,0,212
Initialize
delay loop
Intialize
frequency
BOX 31A. Assembly language listing for Attack, Sustain, and Decay
200 Atari Assembly Language Programme(s Guide
Section 3: Create envelop
LOY #160
LOOPA STY AUDC1
INY
JSR DELAY
CPY #176
BNE LOOPA
LOA #100
STA COUNT
JSR DELAY
LOOPB DEY
160,160
140,1 ,210
200
32 ,65,6
192,176
208,245
169,100
133,203
32,65 ,6
DELAY LOX #80
LOOPC DEX
BNELOOPC
DEC 203
BNE DELAY
RTS
162,80
202
208,253
198,203
208,247
96
136
STY AUDC1
140,1,210
LOA #200
169,200
STA COUNT
133,203
JSR DELAY
32,65,6
CPY #160
192,160
BNE LOOPB
208,241
RTS
96
Section 4: Delay Subroutine
Box 31A. (Cont.)
Start with
zero volume
Increment for next volume
Delay before changing volume
Is volume its maximum?
If not continue
Create delay for the
sustain portion of envelop
Jump to delay
Start decay portion of
the envelop
create delay for the
decay portion
Jump to delay
Is volume zero?
If not, continue
Return to basic
Inner loop counter
Inner
Loop
Decrement delay counter
If counter not 0, continue
Return from delay
Sound 201
BOX 32
T,...,lo
REM ** TREMOLO EXAMPLE **
20 NUMBER=75
30 FOR I=~ TO NUMBER:READ D
4~ POKE 1~36+I,D:NEXT I
~0 REM * INITIALIZE MACHINE *
60 DATA 104,169,0,141,14,212,
141, 14,21~, 141,~,212, 141,8,21~, 169,3, 141, 15,210
65 REM
70 REM * INITIALIZE DELAY AND SOUND REGISTERS *
8~ DATA 169,2,133,203,16~,72,
1~
140,0,21~,160,166,140,1,210,32,62.6
90 REM * CREATE TREMOLO *
100 DATA 200,140,1,210,32,62,6,
192,169,208,24~,136,140,1,210,32,62,6.192,166,208,245,76,37,6
120 REM * DELAY SUBROUTINE *
130 DATA 162,60,202,208, 253,198, 203,208,247,169,2,133,203,96
140 X=USR ( 15.3 6)
Box 32. Tremolo
202 Atari Assembly Language Programmer's Guide
BOX 32A
Assembly Language Listing
for
Tremolo
Section 1: Initialize the machine
PLA
LDA
STA
STA
STA
STA
LDA
#0
NMIEN
IRQEN
DMACTL
AUDCTL
#3
STA SKCTL
104
169,0
141 ,14,212
141 ,14,2 10
141,0,212
141,8,210
169,3
141,15,210
Remove parameter count
Turn off
interrupts
Initialize POKEY
Section 2: Initialize Delay and Sound
\.
LDA #2
STA 203
LDY #72
STY AUDF1
LDY #166
STY AUDC1
JSR DELAY
169,2
133,203
160,72
141,0,210
160,166
140,1 ,210
32,62,6
Initialize
delay
Initialize
frequency
Initialize
volume
Jump to delay
BOX 32A. Assembly language listing for Tremolo
Sound 203
r
Section 3: Volume increase and decay
STY AUDC1
JSR DELAY
CPY #166
200
140
32,62,6
192,169
208,245
136
140,1,210
32,62,6
192,166
BNE DEeR
JMP INCR
208,245
76,37,6
INCR INY
STY AUDC1
JSR DELAY
CPY #169
BNE INCR
DECR DEY
Increment
volume
Jump to delay
Is volume increase done?
If not, continue
Decrease
volume
Jump to delay
Is volume done?
If not, continue
Jump to increase
Section 4: Delay Subroutine
DELA Y LDX #80
LOOPC DEX
BNELOOPC
DEC 203
BNE DELAY
RTS
" 32A. (Cont.)
BOX
162,80
202
208,253
198,203
208,247
96
Inner loop counter
Inner
loop
Decrement delay counter
If counter not 0, continue
Return from delay
~
204 Atari Assembly Language Programmer's Guide
BOX 33
Vibrato
10
20
30
40
50
60
REM ** VIBRATO EXAMPLE **
NUMBER=75
FOR 1=0 TO NUMBER:REA D D
POKE 1536+I,D:NEXT I
REM * INITIALIZE MACHINE *
DATA 11114,169,0,141,14,212,141,
14. 21 ~, 141 , 0, 21 2 , 141 ,8, 211!1 ~ 169, 3 , 141
15,
~ U~l
65 REM
70 REM * INITIALIZE DELAY AND SOUN D REGISTERS
80 DATA 169 , 2,1 33,203, 160,72 ,14@,
1!t,211;J, 169, 168, 141,
1, 2 11~,32 , 6: ,6
90 REM * CR~ATE TREMOLO *
100 DATA 200,140,0,210, 32, 62,6,
1 92.7~.2~8t24~,1 36 ,14 0 ,0,210,3 : .62,6.192, 7@ , :0 8,24~,76 ,37,6
120 REM * DELAY SUBROUTINE *
130 DATA 162,6f~, 2 ~2, 21~8t2 53,1 98t
141~ X=USR ( 1536)
Box 33. Vibrato
2~'3 . :!~ 8, 247 ,169,2,
133,203,96
Sound 205
BOX 33A
Assembly Language Listing
for
Vibrato
Section 1: Initialize the machine
PLA
LOA #0
STA
STA
STA
STA
LOA
STA
NMIEN
IRQEN
OMACTL
AUOCTL
#3
SKCTL
104
169,0
141,14,212
141,14,210
141,0,212
141,8,210
169,3
141,15,210
Remove parameter count
Turn off
interrupts
Turn off ANTIC
Initialize POKEY
Section 2: Initialize Delay and Sound
LOA #2
STA 203
LOY #72
\..
STY AUOF1
LOA #168
STA AUOC1
JSR DELAY
169,2
133,203
160,72
140,0,210
169,168
141,1,210
32 ,62,6
Initialize
delay loop
Initialize
frequency
Set volume
at % maximum
Jump to delay
BOX 33A. Assembly language listing for Vibrato
206 Atari Assembly Language Programmer's Guide
Section 3: Create vibrato
INCR INY
STY AUDC1
JSR DELAY
CPY #75
BNE INCR
DECR DEY
STY AUDC1
JSR DELAY
CPY #70
BNE DECR
JMP INCR
200
140,0,210
32,62 ,6
192,75
208,245
136
140,1 210
32,62,6
192,70
208,245
76,37 ,6
Increase
frequency
Jump to delay
Is frequency increase done?
If not, continue
Decrease
frequency
Jump to delay
Is f requency done?
If not, continue
jump to increase
Section 4: Delay Subroutine
DELAY LOX #80
LOOPC DEX
BNE LOOPC
DEC 203
BNE DELAY
RTS
BOX 33A. (Cont.)
162,80
202
208,253
198,203
208,247
96
Inner loop counter
Inner
loop
Decrement delay counter
If counter not 0, continue
Return from delay
Sound 207
The number of cycles taken for each instruction depends on the
instruction and its addressing mode. Some typical values are listed in
table 5-3.
Table 5-3. Typical cycle times
Add ..."sin<;l Mod.
Instruction
Immltdiat.
LDA, LDX.
LDY
DEX
INX
Pag. 0
2
Ab!loluta
Implied
DEY
INY
5
DEC
BNE
BEQ
JSR
RTS
Relative
6
.3
(same page l
(di Her-ent P9)
A complete listing of the number of cycles for all instructions can
be found in more advanced books on 6502 programming. For a simple
loop, the time calculation goes like this:
LOX #80
LOOP OEX
BNELOOP
LOX immediate 2 cycles
OEX 80 times
160 cycles
BNE 80 times
240 cycles
402 total cycles
402 cycles times 5.6 x 10- 7 =.225 milliseconds.
This , of course, is only an estimate of the time taken up by the loop
because the jump and return instructions take CPU time as will any
other instruction involving the outer loop.
Each of the machine language routines in Boxes 31, 32, and 33 is
fully documented in an accompanying assembly language listing. So
that you don't get lost in the details, keep in mind the objective of each
program . In the envelop and tremolo programs, a note frequency is
chosen and the routine manipulates the volume of the note by
changing the values in the lower four bits of AUDCl. In the vibrato
program it is the frequency value in AUDFI that is changed.
208 Atari Assembly Language Programmer's Guide
The next two program examples illustrate the simplest type of
volume only sound . Both programs generate triangle shaped waveforms
by incrementing the volume bits of AUDCI from 0000 to 1111 and
then decrementing back to 0000. In these programs, the delay loop is
placed within the straight line flow of the program, rather than in a
subroutine, because the timing requirements of the program are more
severe.
BOX 34
Voluae Only
.*
REM ** VOLUME ONLY EXAMPLE
NUMBER=53
FOR 1=0 TO NUMBER:READ D
POKE 1536+I,D:NEXT I
~@ REM * INITIALIZE MACHINE.
60 DATA 104,169,0,141,14 , 212,
141,14,210,141,0,212,141,8,::112',169, 3 ,141,15,2112'
65 REM
7 ! ~ REM * INITIALIZE DELA Y A;<D ADUC1
80 DATA 16@, 16, 140,1,2112'
90 REM CREATE TRIANGLE WAVE *
112'0 DATA 200,140,1,210,16 2 ,40 ,
l@
2Qj
30
40
~~2,2 1~ 8, 253,192 , 31,208,243,136,140,1,21 0 ,16 2 ,40 . 20~,21~8,253,1
92,16,208,243,76,25,6
12@ " X=USR (1~36)
Box 34. Volume only
Sound 209
,
BOX 34A
Assembly Language Listing
for
Volume Only - Triangle Wave
Section 1: Initialize the machine
PLA
LDA #0
STA NMIEN
STA IRQEN
STA DMACTL
STA AUDCTL
LDA#3
STA SKCTL
104
169,0
141,14,212
141 ,14,210
141 ,0,212
141 ,8,210
169,3
141 ,15,210
Remove parameter count
Turn off
interrupts
Turn off ANTIC
Initialize POKEY
Section 2: Initialize Volume
LDYVOLONLY
STA AUDC1
160,16
140,1,210
Set Bit D4 of AUDC1
for vo lume only
BOX 34A. Assembly language listing for Volume Only-Triangle Wave
210 Atari Assembly Language Programmer's Guide
Section 3: Generate triangle waveform
INCR INY
STY AUDC1
LDX,40
LOOP DEX
BNELOOP
CPY MAXVOL
BNE INCR
DECR DEY
STY AUDC1
LDX,40
LOOP DEX
BNELOOP
CPY #16
BNE DECR
JMP INCR
200
140,1,210
Increase
volume
Delay loop. Value in X
register determines
frequency of the sound
Is up-ramp complete?
162,40
202
208,253
192,31
208,243
136
140,1,210
If not, continue
If volume is max,
start down-ramp
Delay loop. Value will
determine frequency of
162,40
202
208,253
192,16
208,243
790,25,6
the sound
Is down-ramp complete?
If not, continue
If yes, go to up ramp
BOX 34A. (Cont.)
10 REM ** VOLUME ON LY EXA MPLE WITH VARYING FREQUENCY
NUMBER=79
30 FOR 1=0 TO NUMBER:READ D
40 POKE 1536+I,D:NEXT I
50 REM * INITIALIZE MACHINE *
61~ DATA 104,169 ,0,141,14. 212 ,141,
14,210,141,0,21 2.141.8,210,169,3.141, 15, 2li~
65 REM
70 REM * INITIALIZE DELAY AND ADUCI *
80 DATA 160,16,140,1,210
90 REM * CREATE TRIANGLE WAVE *
100 DATA 200,140,1,210,162,40. 202,
**
2f~
212'8,253,192,31,212'8,243,1 .3 6.14(2'.1}
6,208, 24.3
=11~,
16:, 4m,
= ~!J'2,
2Q18, 253,192,1
110 REM
12" DATA
208,2~3,
2~0, 1412' , 1,
192,31, 208,
211~). 162~
24 ~, .
32 , 2! ~ 1:: .
136, 141, 1 ~ 2
11~1.
6,208,243,76,25,6
141~
X= U5R (1536)
Box 35. Volume only with varying frequency
16 2,32, 2Q 12, 208, 253,192,1
Sound 211
,
BOX 35A
Assembly Language Listing
for
Triangle Wave - Varying Frequency
Section 1: Initialize the machine
PLA
LOA
STA
STA
STA
STA
#0
NMIEN
IRQEN
OMACTL
AUOCTL
LOA #3
STA SKCTL
104
169,0
141,14,212
141 ,14,210
141 ,0,212
141 ,8,210
169,3
141,15,210
Remove parameter count
Turn off
interrupts
Turn off ANTIC
Initialize POKEY
Section 2: Initialize Volume
LOYVOLONLY
STA AUOC1
160,16
140,1,210
Set Bit 0 4 of AUOC1
for volume only
BOX 3SA. Assembly language listing for Triangle Wave-Varying Frequency
212 Atari Assembly Language Programmer's Guide
\,.
Section 3: Generate triangle waveform
INCR1
INY
STY AUDC1
LDX,40
LOOP1
DEX
BNE LOOP1
CPY #31
BNE INCR1
DECR1
DEY
STY AUDC1
LDX,40
LOOP2
DEX
BNE LOOP2
CPY #16
BNE DECR
INCR2
INY
STY AUDC1
LDX #30
LOOP3
DEX
BNE LOOP3
CPY #31
BNE INCR2
DECR2
DEY
STY AUDC1
LDX #30
DEX
BNELOOP
CPY #16
BNE DECR2
JMP INCR1
Box 35A. (Cont.)
..,
200
140,1,210
162,40
202
208,253
192,31
208,243
136
140,1,210
162,40
202
208,253
192,16
208,243
200
140,1 ,210
162,30
202
208,253
192,31
208,243
136
141,1,210
162,30
202
208,253
192,16
208,243
76,25,6
Sound 213
You can change the pitch of the sound by changing the delay
value . A shorter delay yields a higher pitch. The two programs differ in
that the second program (box 35) effectively generates triangle waves
with two different frequencies. When you compare the two assembly
listings you will see that the program in box 34 creates a triangle
waveform with a delay value of 40 and then creates a triangle
waveform with a delay value of 30. There is a very noticeable difference
in the sound produced by this change.
There are two simple exercises that you should do at this point.
The first is to put comments into the assembly listing in box 35A. The
second is to rewrite the program so that it carries out the same task but
in a more efficient manner. The program as written is straightforward
but repetitive . Anytime that you have a repetitive set of commands
such as we have here, it should be possible to write the program code
more efficiently.
The most versatile way to use the volume only mode is to generate
sound waveforms from a set of data numbers stored in a look up table.
The data table holds different speaker position settings 0- I 5. Since
volume only sound requires bit 0 4 to be set as well, the data numbers
range from 16 to 31. The central idea of such a program is to load
successive values from the table into one of the AUOC registers.
Suppose you wanted to create a waveform such as this:
An appropriate set of data numbers would be:
16,19,22,25,28,31 - to create the initial ramp
29,26,23 ,24,25,26,27,26,25 ,24 ,23 - to create the rough jagged portion,
and
24,25,26,25 ,24,25,24,25 ,24,25 ,24,25,16 - to create the fine jagged
portion.
214 Atari Assembly Language Programmer's Guide
This waveform repeated over and over again will produce a note
subtly different from those in previous programs . The reason is that if
the waveform were synthesized by the addition of sine waves it would
have a different fundamental frequency and different harmonics or
overtones than the previous examples such as the triangle waveform.
By programming different waveforms you can experiment with note
timbre, or quality. Box 36 is a program that uses the data numbers
given above to produce a continuous note. Writing music this way is a
considerable task since the duration of the note and the frequency
must be written into the program. The frequency is controlled by the
delay portion (see the assembly listing in box 36A). For music, the
delay portion must be modified to access a table of frequencies for each
note. The frequencies must be calculated from knowledge of machine
cycles or determined experimentally with the help of a piano or other
musical instrument. The duration of the note can be handled by
replacing the JMP START instruction with program lines that make
the waveform repeat a suitable number of times.
BOX 36
Waveform
10
:::' 0
30
4 1il
50
6Vl
REM
**
WA VEFORM ExnM~~~
7f,1
~ I~ TO f'IUMP l::R : ;;'liIL D
NUMBE R~
c' OR
FOf . E
15:::.6+I, n:I~ E xr
INITI ALIZE MACHIN E '
DATA 1I"4,169,li l ,14 .1 ,'4, 2 12 .141,
RE M
t 4 ~ 21 ~I, 14 1 ~ f~l, ~ 1 ~, 141 , a, ::: t 0. 1 6?, ::. , 1111 , 15, ~ 1 1?J
6:> r, EM * G E dE RA T ~ 1HE lv AV~FOR M
71~ OA T.,
162 " ,1, JU'},41 , t. . Jf\I.1, ~ 1 0.
1 612' ~ 4 1!1 , 1 ~ ~ . ~ 0 8 , 25 '3 ~ : 3 :'. =- . ~ 4. -:: t . " \~1 8 . ~41 ?1, 7.~ . :,~! . :'J
75 REM * L D O~ UP r ~ BLE
80 DAT A 16 . 19. 2 : . 25 ,2 8 . :::1 . 2 ~.26,2 ::: .
2 4, : 5, ~6 ,:7.~ A . :~J . : 4 j :~ 3 . :0.:5 , ~ 6. : 5,:4. 25 . 2~ , 2~ , = 4.25~~4, :5 ~
6
85 RE M
9::; x=lIsr, ( 1C; '- l.)
Box 36. Waveform
Sound 215
BOX 36A
Assembly Language Listing
for
Waveform Example
START LOX #0
162,0
LOOPA LOA TABLE,X 189,41 ,6
STA AUDC1
LOY #40
LOOP B DEY
BNELOOPB
INX
CPX #31
BNELOOPA
JMP START
Initialize the inde x register
Load Accumulator from table
141,1,210 Store speaker position in AUDC1
160,40
DELAY section. Change value
in Y-register to change
136
208,253 frequency
Increment X to point to next value
232
224,31
208,240
76,20,6
Is table all read?
If not, continue
Go back to beginning.
Box 36A. Assembly language listing for waveform example
Because of the complexity of writing music programs this way,
most programmers will probably want to start experimenting with
music by using the pure tone option and loading the frequency
registers with data numbers for each note. Box 37 is a BASIC program
that calculates the data numbers for 8-bit music. This program is easy
to use and will be adequate for most applications. As a point of
reference, when the program asks "What octave?", the octave beginning
with middle C is octave four.
The next program, box 38, plays "Three Blind Mice". The notes
are taken from a data table that holds frequency and duration values.
When you study the assembly listing, you will gain further appreciation
for how fast the computer operates . In order to slow the computer
down to a human time frame, it was necessary to use three loops in the
delay portion of the program that controls the note duration and two
loops in a delay that separates one note from another. In the duration
delay, one loop uses the Y-register, another uses a page 0 memory
location that we call DREG, and the last uses a value loaded into the
accumulator from the data table. This is the value that you change to
216 Atari Assembly Language Programmer's Guide
produce a quarter note, half note, or whole note. Notice that while
there are increment and decrement instructions for the index registers
and memory locations , there aren't any such instructions for the
accumu lator. Consequently you must use addition or subtraction to
increment or decrement the accumulator.
BOX 37
Utility Progrilm
a-Bit Music Data Generator
10 REM ** F'ROGFi AM TO GENER ,nc: 8 -0 I T MUSI C DATA NUMBERS **
F'RINT
319 PRINT "HOW MANY NOT C .-j ") " : TRAP ~I~
40 INPUT N
5121 DIM NTEDAT(N),NTE$ ( I ) ,NTETYPE$(l) ,FREO'(3) ,OPTIONS(I)
61D PRINT
70 PRINT " WHAT C LOC~:: FREQUENCY~ (' 15~ ' OR '64k')":T;;AP?ii1
80 INPUT FREQS
9121 IF FREQ '. &=" 15K" TI-'EN CL Cl [f :F(;EO= 15 69 9. 9 : GOTO 1 2 1~
Hl l" IF FREQ'="64 k " 1 HEiJ C LOCH;RE(.L~ 6392 1: GOT O 1 2QI
111, GOTO 6121
120 PRINT
1 3 ~1 PRINT " WHAT OCTA VE
(ID - ,)C''' :TRAP 1 31,1
140 INPUT OCTA V E
15 121 OCTAVE=OC TA VE+l
16121 ON OCTA VE GOSUB 570,580 ,590, 600 ,610,6 2 0,630,64121
171lJ PR I NT
1 8~ 1 PRINT
"WHAT NOTE ? ":TR AP 180
19 0 INPUT NTE$
201' IF NTE$~"C" THEN POWER~0:GOTO 28 121
2 10 IF NTE$="D" THEN P OWER = 2 :GOTO 2 80
2 20 IF NTE$=" E" THEN P OWER =4:GOT O 281"
2 3 1?i IF NTE'="F " THEN F'O WER=5:G OT O 2 8 1'
2 413 IF NTE'=" G " THEN POWER=7:!30TO 2 81 ~
250 IF NTE$= "A" THEN f'O WER=9 : GO T O ~80
IF NTE$="B" THEN P OWE R= II:GOTO 281~
:':70 (j OTO 1 81,1
28L~ PR [N T
2';>1,1 F'R HJT "N A TURAL ( :J) . S' IAFP (S) IJR FL ,~T (f' i" : TF'AP :~'71 ~
30 0 INPUT NTET YPE $
3 112' IF NTE T YF'E$="N" TI1i=N GCITIJ ':" 5 ,':
,3 = 1' IF NTETYPE$ = " S " TH E~ I F' m J ER~r'[) WERq: GO TO ~,S 0
:Y:, I~ JF N TE T YPE$="F"
TH OI PO WE' ,'-, r='Ot~E R- l: GUTU :-:5 13
3 41' GCI1 0 2'7 ,;,
21~
BOX 37. Utility program--8-bit music data generator
Sound 217
35111 FREGl2BASE* (1.
0~946 " ' PoWER)
360 NTE2INTCLoCKFREGl/(2*FRED) ) - 1)
370 K-I<+1
380 NTEDAT(K)-NTE
390 IF K( N THEN GO TO 130
400 PRINT :PRINT :TRAP 410
410 PRINT "PRINT TO SCREEN OR PRINTER
420 INPUT OPTION.
4 3 121 IF of.TION.="S" THEN GOTO 461:'
440 IF OPTION'~"F'" THEN GOTO 4 ' ,,1
431!l GOTO 41~1'\
,II ,,;, r 'h I NT
. :7,., For, f ~t TIJ N:f-'hlNl '~lEl'n1" I; " . " ; :
'l:. lI'l G() 1 r l
~,bt:'
490 OPEN 11 3 ,8.1"1, " P: "
TO ~ J
51121 P~INT 113:NTEDA T ( f
~:;:0 PRINT 113; "
:"\30 NEXT P
540 PRINT 11-,
:"\I!ll/l FOR P= t
I;
560 END
5 70
BASE=t t,3~:RETURN
BASE- 32.7 :RETURN
590 BAS E-65.4t : RE fUPN
6H BASE: t3 0. 0 t:RETUR iJ
610 BASC <> t. t, ~:nETIJRN
6~0 BASF=5 : ~.2 5 : RET ~ ~~
6~0 BA SE =t .1.l6.: : RF; ';."
6 41;\ E<A S F c. :I " 9~, : r.' F T'JI- i
~80
BOX 37. (Cont.)
(S.P)~"
'~f
xr
I>
218 Atari Assembly Language Programmer's Guide
,
BOX 38
8-Bit Music
Three Blind Mice
*.
10 REM
THREE BLIND MICE **
NUM8ER=' 1 "1 3
:25 REM
30 FOR 1=0 TO NUMBER:READ D
40 POKE 1536+I,D:NEXT I
4 5 REM
50 REM * INITIALIZE MACHINE *
61<1 DATA 104,169,1<1,141,14,212,
141 , 14, 21"', 1 41 , QI, 212, 141 , 8, 211<1, 169, 3, 141 . 15, 211<1
65 REM * PLAY NOTE AND LOAD THE DURATION *
70 DATA 162,0,189, 78,6,141,0,210,
169 ,168, 141,1 , 2JeI, 232, 189,78,6, 32,61<1,6
75 REM * TURN OFF SOUND 8ETWEEN NOTES *
81<1 DATA 169, 16QI, 141,1, 21Q1, lMI, 2QI, 136,208,25:',.231<1, 2Q13, 2Q18, 247
85 REM * CONTINUE OR RETURN TO 8ASIC *
90 DATA 232,224,96,208,219,96
95 REM * DELA Y -CONTROLS NOTE DUR AT ION *
100 DATA 160,200,136 ,208,253,230,
21~13,208,247~216, ' 56,233, 1,201,0,2Q I8.239,96
105 REM * NOTE TABLE *
tIl!! DATA 95~ .3 , ifl'?, 3,121,3,95,3, 1m?,
3, 121,3,80,3,9 0,2,90,3,95,4,80,3,90,2,90,2,95,4,8,~,3,60 ,2,60,
3,63,3,71,3
115 REM
1 2 1~ DATA 63,3 , 6r~',3 .81~,2 ,8 r~',4,8f~,3,
:21~
60,3,60,~,6Q',3,63,3,71,3,63,3.6~',3 , 8Q',2,81~1,3t8~), 3,80,3,60,3,6
f2J, .3 , 63,3,71,3
125 REM
130 DATA 63 , 3,60,3,80,3,80.2,80,3,
90,3,95,4,107,4,121,4
135 REM
21<11<1 X=USR (1536)
205 REM * RESTORE SCREEN *
210 PO KE 54272,34 :POKE 54286,64:POKE 53774,192
Box 38. 8-bit music "Three Blind Mice"
Sound 219
BOX 38A
Assembly Language Listing
for
Three Blind Mice
Section 1: Initialize the machine
PLA
LDA #0
STA NMIEN
STA IRQEN
STA DMACTL
STA AUDCTL
LDA #3
STA SKCTL
104
169,0
141,14,212
141,14,210
141 ,0,212
141,8,210
169,3
141,15,210
Remove parameter count
Turn off
interrupts
Turn off ANTIC
Initialize POKEY
Section 2: Play the notes and load the duration
START LDX #0
162,0
LOOPA LDA TABLE,X 189,78,6
STA AUDF1
141,0,210
LDA #168
169,168
STA AUDC1
141,1 ,210
INX
232
LDA TABLE,X
189,78,6
JSR DELAY
32,60,6
Initialize the index register
Load the note value
Store in frequency register 1
Load pure tone and 1f2 volume
Store in AUDC1
Increment X to point to duration
Load the duration value
Jump to the delay
Box 38A. Assembly language listing for Three Blind Mice
220 Atari Assembly Language Programmer's Guide
,
Section 3: Turn off sound between notes
LOA #160
169,160
Load pure tone 0 volume
STA AUDC1
LOOPB LDY#20
LOOPC DEY
BNE LOOPC
DEC DREG
BNE LOOPB
141,1 ,210
160,20
Store in AUDC1
A two loop delay routine
136
208,253
230,203
208,247
The value loaded in the Y
register helps to determine
the tempo by controlling
the pause between notes.
Section Four: Continue or return
INX
232
Increment X to next note
CPX TABLEND
BNE LOOPA
RTS
224,96
208,233
96
Check if finished
If not, continue
If yes, return to basic
Section 5: Delay routine
160,200
DELA Y LOY #200
136
LOOPD DEY
208,253
BNELOOPD
230,203
DEC DREG
208,247
BNE DELAY
\.
CLD
SEC
SBC #1
CMP#O
BNE DELAY
RTS
BOX 38A. (Cont.)
216
56
233,1
201,0
208,239
96
Load Y with delay value
for first loop . Change this
for precise timing
Second delay
loop
Third delay loop using
binary subtraction of 1
from the duration value
Loaded from the data table
Return from delay subroutine
Sound 221
The "Three Blind Mice" program can be used as a starting point
for other music programs. To play another song, just change the data
numbers in line 20 and the value of T ABLEND in section four of the
assembly listing. Of course there are other ways to modify the
program. You can introduce attack, sustain and decay or vibrato to
make the music richer. A straightforward way to modify the program
is to play chords. So far all of the program examples have used only a
single sound channel. The program in box 39 plays "Three Blind Mice"
using two sound channels.
BOX 39
Three Blind Mice with Chords
1~
2121
30
4@
50
60
REM ** THREE BLIND MICE WITH CHORD S
NUMBER= 23 4
FOR 1=0 TO NUMBER:RE AD D
POKE 1536+ I,D: NEXT j
REM * INITIALIZE MACHINE *
DATA 11214,169,121,141,14,21 :,
141, 14, 21 j!J, 141, I!I, 212, 141 , 8
21 f?l t 16 9 , '3, 141 , 1 5 ~ 210
65 REM * PLAY NOTES AND LOAD DUR AT10N
70 DATA 162.0,189,91,6,141, :'. ,21<,1,
2 .3 2, 189,91 ,6, 141, 2 ~ 21 Ql. 169 ~ 1 6!, 14 1 , 1 I 21 Q! , 141 ~ 3, 21@, 232, 189,91
,6,32,7.3 ,6
75 REM * TURN OFF SOUND BETWEEN NOTES
8121 DATA 169,160,141,1, 21121,141,3,
210,16~,20,136 , 208,253,23 0 . 203,2eI 8,247
85 REM * CONTINUE OR RETURN TO BA S IC.
90 DATA 232,224.144,208,206 ,96
95 REM * DELAY - CONTROLS NOTE DURATION.
1@0 DATA 160,20,~,136, ~08 . 253,231~1,
2~3,208,~47,216,5~,233~1 . :@ 1, 0,~08 ,23 9,96
105 REM * NOTE TAB LE
11121 DATA 95.162,3,107,18 2,3 ,121 ,
192,3,95, 162,3, lR17, 182,3, 1:: 1 , 1 '7~ .
:' .
Olil f 1:28. ::. 91!1. 14 L1 , 2,
91~,
144,3
,95, 16 2,4,80,128
120 DATA 3,9@,144.2,90.144.2,95.
162,4,8121, 162.3,60, 121. :;" . 60 . 121. 3 . 63, 1('17, .3 , 7 t ,95, .3 , 63,107,3,60
,9:5,3,81!1,128,2
13121 DATA 80.128,4,80.128. 3 . 6 0,95. : .
60.95,2,6~,95.3.63~1~17,~,71,95~ ~ . 63 ,1!~7,3. ~~ 1,95, 3 ,8,~,9~.2,80,
95,
3,81~,
128
140 DATA 3,80,
128. 3 .60, 95 . ~ . 60 . o5 . 3 ,
63, 11!17, .3 ,71 , 12 1 , 3,6"3. ! 1:1~1
-:"
QI~ .
95. :' .8111 , 1:21 : .
De'.
,9~',144,3
151~ DATA 95,162 .4,11,17 .1 132 .4.1 21.1'12 .4
201,1 X =U5R ( 15.3 6)
21~ 5 REM
RESTIJRE SCREFri
:' I t!l
F'O~
5/l~/2 .
-:-.4 : F-OLE
S ,, ~o ~ )
.~ ,'!
: rfH
Box 39. "Three Blind Mice" with chords
E 5--:- 7:' 'I, l9:
1:? 1 , 2 ,80, 1 :2 1 ':;'
222 Atari Assembly Language Programmer's Guide
Box 39A
Assembly Language Listing
for
Three Blind Mice with Chords
Section 1: Initialize the machine
PLA
LOA #0
STA NMIEN
STA IRQEN
STA OMACTL
STA AUOCTL
LOA#3
STA SKCTL
104
169,0
141,14,212
141,14,210
141,0,212
141,8,210
169,3
141,15,210
Remove parameter count
Turn off
interrupts
Turn off ANTIC
Initialize POKEY
Section 2: Play the notes and load the duration
START LOX #0
162,0
LOOPA LOA TABLE,X 189,91 ,6
STA AUOF1
141,0,210
INX
232
LOA TABLE,X
189,91,6
STA AUOF2
141,2,210
\...
LOA #168
STA AUOC1
STA AUOC2
INX
LOA TABLE,X
JSR DELAY
169,168
141 ,1,210
141 ,2,210
232
189,91 ,6
32,73,6
Box 39A. Assembly language listing for Three Blind Mice with Chords
Sound 223
Section 3: Turn off sound between notes
LDA #160
STA AUDC1
STA AUDC2
LOOPB LDY #20
LOOPC DEY
BNELOOPC
DEC DREG
BNE LOOPB
169,160
141,1,210
141,3,210
160,20
136
208,253
230,203
208,247
Section 4: Continue or return
INX
CPX TABLEND
BNELOOPA
RTS
232
224,144
208,206
96
Section 5: Delay Routine
LDY #200
\...
DEY
BNELOOPC
DEC DREG
BNE DELAY
160,200
136
208,253
230,203
208,247
CLD
SEC
SBC #1
CMP #0
BNE DELAY
RTS
216
56
233,1
201,0
208,239
96
Box 39A. (Cont.)
224 Atari Assembly Language Programmer's Guide
Sixteen Bit Music
At times music generated by eight bit data numbers will be
unsatisfactory because some of the notes will sound slightly flat or too
sharp . As the example earlier in this chapter showed, this is because
eight bits will not always give an adequate selection offrequencies. The
problem can be remedied by joining the sound channels into pairs with
channels 1 and 2 forming one pair and channels 3 and 4 the other.
Because the bytes in the paired AUDF registers are used together, the
numbers in the "divide by circuit" ranges from 0 to 65536.
The l6-bit music option is controlled by bits D3 and D4 of
ADDCTL (53768). Bit D 4joins channels 1 and 2; bit D3joins channels
3 and 4. Each note will have two data numbers - a Hi-Byte and a
Lo-Byte . If channels 1 and 2 are paired, the Lo-Byte goes into AUDFI
and the Hi-Byte into AUDF2. When channels 3 and 4 are paired, the
Lo-Byte goes into AUDF3 and the Hi-Byte into AUDF4. Data
numbers for octave 0 - 8 are given in Appendix H. The data numbers
are based on the system clock frequency, 1.79MHZ. This requires bit
D6 of AUDCT2 to be set.
A program to play "Three Blind Mice"using l6-bit music is given
in box 40 and the assembly language listing in box 40A. The program
pairs channels 1 and 2. While the program is similar to the previous
program in Box 39, there are some differences to note. In the
initialization section the value stored in A UDCTL sets bits D6 and D 4
AUDCl is set to zero since the choice of pure tone and volume are
controlled by A UDC2. In the section that loads the note data values
AUDFI is the target for the Lo-Byte and AUDF2 receives the Hi-Byte.
To summarize, for 16-bit music you:
Set bits 6 and 4 of AUDCTL to join
channels 1 and 2 or
Set bits 6 and 3 of AUDCTL to join
channels 3 and 4
Turn off AUDC of the lower numbered
channel
Store La-Byte of data number in lower
channel
Sound 225
Store Hi-Byte of data number in higher
channel
Store volume in AUDC3 or AUDC4 as
required
r
"'*
**'
10 REM
THREE BLIND MI CE
1 G BIT MUSIC
20 NUMBER= 235
30 FOR 1=0 TO NUMBER:READ D
40 POKE 1536 +I,D:NE XT I
50 REM
INI T IALIZE MACHINE
60 DATA
104, 169,0, 141, 14 , 2 12, 111, 14, 2 10, 141,0, 212, 169 , 1 G0 . 141, 1, 210, 1
69 , 80,141,8,21121,169,3,141,15,210
65 REM
PLAY NOTES AND LOAD DURATION ~:
70 DATA
162, 121, 189, 92, 6, 141, 0 , 21121 , 232, 189 , 92, 6, 141 , 2, 21 Ci, 16 9, 168, 14 J .
,210,232,1 89,92 ,6,32 ,74,6
75 REM
TURN OFF SOUND BETI'IEEN NOTES
80 DATA 169, 160,1 41 ,3,2 10,160,20, 136,208,25 J . 2 30 , 203,208,2 4 7
85 REM
CONTINUE OR RET URN TO BASIC *
90 DATA 232,224,144,208,212,96
95 REM
DELAY -CONTROLS NOTE DURATION
100 DATA
160,150, 136,208 ,253,23121 , 21213,208,247,216,56,233, 1 ,~ 01,0,208,23
9 , 96
105 REM
NOTE TABLE '"
1110 DATA
148,110,3 ,224 , 11,3,85,13,3,148,10,3,224,11,3,85, 13 ., 3 ., :)~~8, 8, 3, 2
51, 9, 2, 251, 9, 3, 148 , 10 , 4 , 228, 8, 3, 251 , g, 2
120 DATA
25 1, 9, 2, 148, 10, 4 , 228 , 8 ., 3 J 67 , 6 , 2, 167 6, 3, 13, 7 , 3 , 235, 7 , 3, 1 :-; . 'I.
3,167,6,3, 22e , 8, 2, 228 , e , 4, 228, 8, 3,167
130 DATA
6, 3, 167 , 6 2, 167 , 6.' 3 , 13, 7 , 3, ? 3 5 7 :3 13, 7 . 3 , 1 C7 . 6 . 3 ., ~::2 8 . S . 2 . ~ ~ 8
,8,3, 228 ,8 , 3,228,8,3, 167,6,3,167, 8 , 3
140 DATA
13 7 , 3, 235, 7 3 13, 7, 3 , ] 67 6 3 J 228, 8, 3, 228 I S, 2, 228 8 3, 2 fJ 1, ~J ., 3
, 14e, 1121,4,224,11,4,85,13,4
150 DATA 95, 162,4 , 107, 182,4 , 121,19 2 ,4
200 X= [JSR ( 15 36)
205 REM
RESTORE SCREEN
210 POKE 54272,34: POKE 54286,64: POKE 53774,192
*'
*
*
*'
*'
*'
*'
Box 40. 16-bit music "Three Blind Mice"
226 Atari Assembly Language Programme(s Guide
BOX 40A
16 Bit Music Program
Three Blind Mice
START LOX #0
162,0
LOOPA LOA TABLE,X 189,92,6
141,0,210
STA AUDF1
232
INX
LOA TABLE,X
189,92,6
STA AUDF2
141,2,210
169,168
LOA #168
STA AUDC2
141,3,210
INX
232
LOA TABLE,X
189,92,6
JSR DELAY
LOA #160
STA AUDC2
LOOPB LOY #20
LOOPC DEY
BNELOOPC
DEC DREG
BNELOOPB
Load counter
Load Lo-Byte of music data number.
Store it in AUDFI
Increment X to point to next value
Load Hi-Byte of music data no.
Store it in AUDF2
Load volume number
Store volume number in AUDC2
Increment X to point to delay value
Load delay value
32,74,6
Jump to delay (keep note playing)
169,160 Load zero volume
141 ,3,210 Store in AUDC2 to turn sound off
160,20
Start delay loop for
136
sound off
208,253
230,203
208,247 Is delay loop off? No, cont inue
\..
Box 40A. 16 Bit music program "Three Blind Mice"
Sound 227
r
INX
CPX TABLEND
BNE LOOPA
RTS
DELA Y LOY #200
232
224,144
208 ,212
96
160,200
Increment X to point to next value
Is the table ended?
No , branch back to beginning
Return from subroutine
Load initial delay value
First Delay
inner loop
Another inner
delay loop
Clear decimal mode
outer delay
set carry
LOOPD DEY
BNELOOPD
DEC DREG
BNE DELAY
136
208,253
230,203
208,247
CLD
SEC
SBC #1
CMP#O
BNE DELAY
216
56
233,1
201,0
208,239
subtract
} determines
is accumulator 0
length of
note
if not, recycle
RTS
96
Return from delay
\".
Box 40A. (Cont.)
Summary
In this chapter we have presented the fundamentals of music but
have only scratched the surface of what you can do. There are many
options available. We have mentioned tremolo, vibrato, and chords.
You can put in glides, attack, sustain, decay. The sound channels do
not have to be turned on and off at the same time as we did in our
simple programs. There is one option yet to go . That is to combine
music with the vertical blank interrupt. This option is the subject ofthe
next chapter.
6
Advanced Techniques
Introduction
As you now know, most of the sound and graphics features of the
Atari Home Computer are, to so me extent, accessible from BASIC.
However, there are situations in which the only satisfactory implementation
of sound or graphics comes through machine language subroutines.
Forexample, yo u can use BASIC to play music, but if you want to play
music as an integral part of your program, it can only be done in
machine language during the TV's vertical blank. You can detect
collisions, or write programs to go with a touch tablet in BASIC, but
these tasks are also done more satisfactorily in the vertical blank with
machine language.
The OS vertical blank routines a re among the more powerful and
ve rsa tile features of Atari co mputers. In this chapter we will focus on
describing what happens during the vertical blank and how to
integrate your own routine(s) into the regular OS protocols. We will
illustrate the general procedures with examples that demonstrate
scrolling, music, and input with a touch tablet.
229
230 Atari Assembly Language Programmer's Guide
The Vertical Blank Routines
When the electron beam that ge nerates the TV display comes to
the end of the last sca n line, the display hardware sends a nonmaskable interrupt to the CPU . In response, the CPU tests to see if the
interrupt was caused by a DLl , a Reset, or a Vertical Blank Interrupt
(VBI).
Figure 6-1 is a flowchart of the vertical blank routine. After
determining that the interrupt is a VBI, the OS jumps to the location
pointed to by VYBLKI (locations 546,547). Stored in these memory
locations are the Lo-Byte ansi Hi-Byte of the address of a subroutine
that is normally carried out during each vertical blank. In technical
jargon, locations such as 546 and 547 which store addresses of
subroutines are called pointers or vectors . Normally the 'vector' at
546,547 points to 58463 . This is the first of three places in the VB
routine where you can insert your own machine language program.
You do this by 'stealing the vector', ie. POKE the starting address of
your own routine into 546 ,547. Depending on your intent, your
routine should end with a JMP back to the operating system's
program at 58463 , or to exit the vertical blank program by a JMP to
XITVBL at 58466.
The routine at 58463 is called the Stage I or Vertical Blank
Immediate routine. During the Stage I routine, the OS:
increments the real time clock
decrements system timer one
performs color attracting
Once this is completed, the OS checks memory location 66 (CRITIC) .
If CRITIC has a non-ze ro value, then a time critical code section is
being executed and the program jumps to XITVBL. If the code is not
critical then Stage II of the vertical bla nk routine is processed. During
Stage II the OS takes care of the following 'housekeeping' chores:
Advanced Techniques 231
FLOWCHART
for
VERTICAL BLANK INTERRUPT ROUTINE
(VB
INTERRUPT
SIGNAL
~ump
throuQh ' USER RESET
WBLKI
540,:547
USER
STAGE I
ROUTINE
SB463
VBLANI<
St.aQ. I
PROCESSED
CRITICAL
/~CJ(
CRITIC
CODE
NOT
CR I TI CAL
VBLANK
St.aQ. II
PROCESSED
Jump
Through
:548,:549
USER RESET
USER
STAGE II
ROUTINE
XITVBL
58~66
Figure 6-1. Flowchart for vertical blank interrupt routine
232 Atari Assembly Language Programmer's Guide
system timers are decremented
color registers are updated
graphics registers such as CHBASE, PRIOR,
CHACTL, and DMACTL are updated
keyboard utilities are processed
game controller data is read from hardware to
RAM
After completing the Stage II tasks, the OS programjumps to the
location specified in 548 ,549 . Normally this vector points to XITVBL.
This is the second place to steal a vector and make it point to an
alternate routine.
The procedure to use vertical blank interrupts for your programs
can be summarized as follows .
Decide whether your routine is to be executed in Stage I or
Stage II. The general considerations that should enter into
your decision are: (I) if your routine must be mixed with time
critical functions such as disk I/ O , use Stage l. (2) If your
routine reads from , or writes to , OS shadow registers, use
Stage I I. (3) If your routine uses more than 3000 machine
cycles , use Stage 1I .
Make sure your routine ends with ajump to: (a) 58463 for a
Stage I rotuine. This allows the OS to continue its normal VB
chores or (b) 58466 for a Stage II routine . This allows the CPU
to exit from the vertical blank interrupt and go back to its
regular processing.
Place the routine in a safe area in memory.
Initialize any timers or memory locations necessary for the
implementation of your routines.
Link your routine to the proper vertical blank stage by a
short machine language program that stores the routine's
starting address at 546,547 for Stage I or 548,549 for Stage II.
Advanced Techniques 233
The linking mentioned in the last step is provided for in the
operating system. The OS contains a subroutine called SETVBV
(Set Vertical Blank Vector) which installs addresses in the Stage I and
Stage II pointers. To link a subroutine to Stage I, use a USR command
to call this short program.
BOX 41
Vertical Blank Linking Routine
PLA
LOY AOORLO
LOX AOORHI
LOA#7
JSR SETVBV
RTS
104
160,AOORLO Load Y with Lo-Byte of routines
address
162,AOORHI Load X with Hi-Byte of routines
address
169,7
7 indicates Stage" link .
32 ,92,228
Jump to SETVBV .
Return
96
AOORLO and AOORHI are the Lo-Byte/ Hi-Byte of the address
location where you store your routine.
Box 41. Vertical blank linking routine
In this program (Box 41) AODRLO and AODRHI of course
depend on where you store your routine. The 7 loaded into the
accumulator flags SETVBV that this is to be linked to Stage II. If you
want to link a routine to Stage I, load the accumulator with 6 (LOA #6)
instead.
The reason for the SETVBV subroutine is that it prevents system
lockup. The vertical blank vectors are two byte critters. Setting these
vectors with BASIC POKE statements runs the risk of an interrupt
occuring before both locations are updated and .. . that would crash the
program!
234 Atari Assembly La ng uage Prog rammer's Guide
So fa r we have menti o ned seve ral memo ry locati o ns in connection
with vertica l bla nk interrupt s. Table 6-1 lists several mo re. Actuall y
this just scratches th e surface since a ll the shadow ! ha rdwa re register
combina tions , co llisio n regis ters, priority reg isters, etc. are potenti a lly
useful. In a dditi o n to t he system reg isters that we have di scussed , ta ble
6- 1 lists timer registers.
TABLE 6-1
Memory Locations Useful With VBls
TIMERS
(a) 18,19,20 The real tim e clock . I nc remented each VB Stage I
(b) 536,537 (CDTMV1) System tim er 1. Wh en it rea c hes 0 it sets a
flag to jump through th e ad dresses in 550,551 . Used by
OS .
(c) 538,539 (CDTMV2) System tim er 2. Dec remented every Stage II.
Performs a JSR through location 552 ,553 when value
counts down to O. Very useful for VB routines .
(d) 540,541 (CDTMV3) System tim er 3. Sets a flag at 554 when
counts to O. Used for cassette I/ O.
(e) 542,543 (CDTMV4) System tim er 4. Sets a flag when
decremented to O.
(f) 544,545 (CDTMV5) System tim er 5. Sets a flag at 558 when
decremented to O.
SYSTEM REG ISTERS:
(a)
(b)
(c)
(d)
546,547
548,549
58460
58463
Vertical Blank Stage I Vector ex plained in text.
Vertical Blank Stage II vector ex plained in text.
SETBV routine to link in a user vertical blank routine.
SYSVBV Stage I VB entry point. A user Stage I routine
should end with a jump to this address .
XITVBV Exit from vertical blank . A Stage II routine
(e) 58466
should end with a jump to this address.
Table 6-1 . Memory loca ti ons useful with VB ls
Advanced Techniques
235
System timer 2 is the third place to add a machine language
routine to the vertical blank process. When a system timer 2 counts
down to zero the OS does a JSR to the memory location specified in
552 and 553. Routines that use system timer 2 do not have to be
installed with SETVBV. For them, read your program into memory,
put its starting address at 552 (Lo-Byte) and 553 (Hi-Byte). To start the
program, POK E a non-zero value in 538 (or 538 and 539 if you need a
long delay before it begins).
Scrolling
Our first programs that use the vertical blank will illustrate
horizontal and vertical scrolling. Scrolling in the Atari Home Computer
is best thought of as using the TV screen as a window on memory.
Using ANTIC's LMS instruction a rd two fine scroll registers, the
window can be moved smoothly from one part of memory to another.
Scrolling done this way is more versatile than scrolling in machines
that use a fixed area in memory for the screen display. In this case you
have to move information (bytes) through the screen memory,
sometimes moving thousands of bytes . With the Atari you can create a
large picture and scroll across it as if it were a panaroma .
The heart of scrolling is manipulating ANTIC's display list and
the two fine scroll registers, HSCROL (54276) and VSCROL(54277).
Recall that ANTIC's display list is a microprocessor program and as
such can be modified. Any mode line instruction can also have the load
memory scan option (LMS instruction). Suppose that the address for
each LMS instruction is changed during a vertical blank. Then what is
shown on the screen next will have shifted position, or changed
entirely, depending on the value(s) stored.
The ideas involved can be visualized with the help of some
diagrams. We commonly think of computer memory as organized
vertically:
236 Atari Assembly Language Programmer's Guide
page 135
page 134
page 133
page 132
page 131
page 130
For the purposes of discussion, it is better to think of memory as cut
into pieces that are lined up horizontally:
138-------------------------------------------
136--------~============~-----------134----------~--------------~r_---------------
132--------~~--------------_4----------------
====!::=====~======
130
128---------------------------------------------
Advanced Techniques 237
The square superimposed on the horizontal lines represents the screen
window. Move this window up or down and the display scrolls
vertically . Move the window left or right and the display scrolls
horizontally. Coarse movement requires proper configuration of the
display list and manipulating LMS address bytes. Fine movement is
accomplished by changing the value in HSCROL or VSCROL.
Extended smooth motion requires using a combination of both fine
and coarse scrolling during the vertical blank.
N ow that you know the general ideas , let's see how to put them
into action with a vertical scrolling program. The program in box 42
scrolls a yellow submarine up the screen. Since this program is more
complicated than previous examples in the book we will describe it in
detail.
The first consideration in designing the program is how to
organize memory. The submarine, constructed with redefined characters,
is displayed on a full Graphics 2 screen. Space must be put aside for the
character set and screen memory. The screen memory area should be
cleared and large enough so that if the display window is scrolled either
above or below the submarine no unwanted characters appear. Since a
full screen Graphics 2 uses 240 bytes, I K of memory set aside is
sufficient. Besides room for the character set and screen memory, we
also need space for a custom display list and the machine language
scrolling routine. To provide room for the above, the program starts
by lowering RAMTOP 12 pages to page 148 (37888). The character set
occupies I K bytes beginning at page 154, leaving 512 bytes below it
empty (pages 152,153) . By starting the display list at page 157, two
pages are left empty between screen memory and the next data in
memory. Finally, the scrolling routine occupies the lower part of page
158. Certainly this is rather loose use of memory since the full
character set is not needed , and neither the display list nor the scrolling
routine need a full page. However, it was written this way so that you
could use it as a skeleton for other, larger programs.
238 Atari Assembly Language Programme(s Guide
BOX 42
Vertical Scrolling
The Yellow Submarine
5 REM ** YELLOW S UBMI1,RINE SCROLL.. **
1@ REM * DIMENSION STRINGS THAT STORE ML ROUTINES *
20 REM
AND CHARACTER SET *
30 DIM CLEAR$(18),MOV$C20',REDEF$(14 ) ,SUB$C120),S$C32)
40 REM CLEARS
50 REM MOV$
60 REM REDEF$
70 REM SUB~
80 REM Sf
85 SUBS(LEN(SUBS ) +1)=S$
90 REM * SET UP RESERVED SPACE AND CLEAR *
100 POKE .106, 14S:POKE 2 03,0:POKE 204,148
110 CLEAR=USRCADR(CLEAR$
120 REM * SET GRAPHICS MODE AND COLORS *
130 GRAPHICS 1S:POKE 752,1:POKE 708,60:POKE 712,134
140 REM * MOVE STANDARD CHARACTERS/REDEFINE *
150 POKE 205,0:POKE 206,224
160 MOVE=USRCADRCMOV$
170 Q=ADRCSUBf)
18~ HIQ=INTCQ/256)
190 LOQ=Q-HIQ*256
200 POKE 205,LOQ:POKE 206,HIQ
210 POKE 203,24:POKE 204,148
220 R=USR(ADRCREDEF$) )
23~ REM * SET UP CUSTOM DISPLAY LIST *
24/ij FOR 1=0 TO 2:POKE 40192+1, 112:NEXT
250 POKE 40195,103
260 POKE 40196,0:POKE 40 197,154
271~ FOR I=@ TO 9:POKE 40198+I,39:NEXT
280 POKE 40212'8, 7
290 POKE 41i1212'9, 65
300 POKE 40210,0:POKE 40211,157
'"
Box 42. Vertical Scrolling The Yellow Submarine
Advanced Techniques 239
10 REM
21!'
F'(J~< E
TE LL ANTIC AND OS WHERE SCREE N MEMORY 1S
559,
30 POKE 560, 0 :PO ~E 5 6 1 , 15 7
40 POKE 88,0:POKE 89,154
50 F'mT 756,148
61~ F'mE 559, :34
70 REM * PUT SUBMARINE IN MEM ORY
81~ POS ITION 6, El : PRINT 1i6 : "jI"
91'1 F'OSITION 3,9:PRINT 116; " $'l. ,~, ' ()"
I~I'I POSITION ,3 , 11~ : F'RINT 11 6 : " .++>+ , "
11'1 F'O!:iITION :3,11 : PRII~T 11 6 : "-- . 11 1,11"
20 REM * LOAD IN SCROLL ROUTINE *
30 FOR 1=0 TO 7 0 : READ ML : P O~E 4044 8 +I,ML : NEXT
35 REM
240,19,132,205,
166,20 6,232~224,
16,24R', 11, 142,5,212,134
445 REM
450 DATA 206,169,6,141,26,2 ,96,
216,24,173,4,157, 105,2C2l, 1 76, 16, 141~4, 15 7 ~ 169,C!l, 1 41,5,21 2, 133
455 REM
460 DATA 206,169,6,141,26,2,96,
238,5, 15 7,141,4,157,169,12',141,5.212,13.3 , 21!l6, 169,6,14 1, 26,2, 96
465
470
480
490
50 0
510
520
5 31~
REM
REM * INS TALL ADDRESS OF THE S CROLLING PROGRAM *
POKE 55 2 , 0 : POKE 55 3 ,15 8
REM * SET REGISTER S USED BY SCROLLING ROUTINE *
PO KE 205 ,0 :POKE 206,0 :POKE 54277,0
REM S TART SYS TE M TIMER 2
PO KE 538, 10
GOTO 531~
Box 42. Vertica l scro lling The Ye llow S ubma rine
This program makes use of several things that we have referred to
in earlier chapters . For example, machine language subroutines that
clear the memory above RAMTOP, move and redefine the character
set. These subroutines are stored as strings. The data listing for the
CLEAR$ routine is given in box 42 A. The submarine is also stored as a
string of characters. Its listing is in box 42B. MOV$ and REDEF$ are
presented in box 24 and box 25. Box 42C is the assem bly la nguage
listing for the vertical scrolling routine.
240 Atari Assembly Language Programme(s Guide
BOX 42A
CLEAR$ Li sti nf~
1"
h
"
169
162
16i1
CLI,
[:J
CLIO
28:5
2H
2fJ8
2:51
"
G
14:5
ICLI, I
CLI,
ICL/Q
23.
2iJ4
21112
21118
246
96
GJ
GJ
CL/.
LEGEND
0
CLI
Around
= inverse
= Control
video
Key
Box 42A. CLEAR$ Listing
Advanced Techniques 241
BOX 42B
The Yellow Submarine
SUB$ Listing
1.
120
96
CLI.
2. ($) 0
(#)
120
96
96
96
96
96
127
127
127
ES/TAB
CLI,
3. (%)0
CLI,
4. (&) 15
5.
6.
(')
(')
17
49
63
?
CLIO
CLIO
248
40
40
CLI,
(cont. on next page)
127
248
63
255
CLIG
!ES/ CL> !
255
255
255
IES/ CL> I
254
255
255
255
IES/ BS! IES/ CL> I
224
254
CLI.
IES/BSI
255
242 Atari Assembly Language Programme(s Guide
7.
(,)
8. (*) 127
127
ES/TB
9.
(+)
255
192
Cl/,
255
15
31
63
255
255
255
255
252
254
252
252
248
ISH=I
IEs/cL/B~~H= I
63
31
15
ES/ Cl *CLlO
255
255
252
ISH=I
IEs/cL> \
10. (,) 224
248
ICLlI0
11 . (-) 255
255
255
13. (I) 255
127
63
15
ES/ TB ?
CLIO
CLI,
255
255
255
CLI,
IES/ CL> I
14. (0) 255
255
224
ISH=I
ICLII
CLI,
224
ICu.1
CLI,
IES/ CL> I
15. (1) 248
I~
Cl/ ,
[ES/CL> I
12. (.) 255
ISH=\
252
box around = inverse video
ES = Escape Key
BS = Back space
LEGEND
SH = Shift
Cli = Control Key
TB = Tab Key
Box 428. The Yellow Submarine SUB$ Listing
Advanced Techniques 243
BOX 42C
Vertical Scrolling Routine
The Yellow Submarine
205 (COUNT) keeps track of how far we 've scrolled
206 (SCRLREG) keeps track of value to put in VSCROL.
LOY COUNT
BEQ COARSE
164,205 First check to see if submarine
has sc rolled to top of screen
200
192,120 Here, the value 120 limits
240,19
the scrolling
132,205 Save Y for next pass thru routine
166,206 Get value to put in VSCROL
232
Increase it by 1 scan line
Have we reached the
224,16
maximum?
If so, do coarse scroll / reset
240,11
STX VSCROL
STX SCRLREG
LOA #6
STA TIMER
SCRLREG
142,5,212If not store value in VSCROL
134,206 Save value for next time around
169,6
Load and store a delay value. A
141,26,2 fine scroll each 6th VB .
RTS
96
INY
CPY #120
BEQ END
STY COUNT
LOX SCRLREG
INX
CPX
END
\..
1t-IG
(cont. on next page)
Return from subroutine
244 Atari Assembly Language Programmer's Guide
COARSECLO
CLC
LOA SCNLO
AOC #20
BCS AOOHI
STA SCNLO
LOA #0
STA
STA
LOA
STA
AOOHI
VSCROL
SCRLREG
#6
TIMER
RTS sc..NH;:..
INC...cNLD
1t-. ST A SCNLO
~ D:.
-:-=f"
LOA #0
~\ STA VSCROL
'j-
216
24
CLEAR decimal mode and carrY'
flag for binary addition
173,4,157 Get La-Byte of screen memory
add ress
105,20
Add the no . of bytes in Gr 2
mode line
176,16
If carry results , Increment
Hi-Byte
141,4,157 Get La-Byte of screen memory
address
169,0
141 ,5,212 Reset VSCROL and SCRLREG
133,206
169,6
141 ,26,2
96
238,5,157
Load and store a delay value
for a fine scroll each 6th VB
Return from subroutine
I ncrem ent Hi-Byte of screen
address
141,4, 157 update La- Byte of screen
address
169,0
141 ,5,212
STA SCRLREG 133,206
LOA #6
169,6
STA TIMER
14 1,26,2
96
RTS
Reset VSCROL and SCRLREG
Load and store a value for
a fine sc roll every 6th VB
Return from subroutine
Box 42C. Vertica l Scroll ing Routine T he Ye ll ow Subma rine
Advanced Techniques 245
The sequence of events in the submarine scrolling program is as
follows :
-The machine language strings are DIMensioned
and defined .
-RAMTOP is lowered and 8 pages of memory
above RAMTOP are cleared.
-The ROM character set is moved and redefined.
-A custom display list that includes setting the
fine scroll option is constructed.
-The machine language scrolling routine is read
into memory.
-The address of the scrolling routine is put into
locations 552,553.
-Finally, the scrolling routine is started by
POKEing a value into 538 so that when system
timer 2 counts down to 0, the OS will jump to the
scrolling routine.
Now let's look at the theory behind vertical scrolling and at the
machine language scrolling routine. Refer to figure 6-2. Each horizontal
line represents 20 bytes of screen memory - the number of pixels in a
Graphics 2 mode line. To begin with, the address specified in the
display list LMS instruction tells ANTIC to find the internal character
code for the top left-hand pixel at memory location 39424 (154 HiByte / O Lo-Byte). Suppose that during a vertical blank the LMS
address is changed to 154,20. This change moves the data that
determined the top mode line off the screen, shifts all mode lines up
one position and moves a new mode line in at the bottom. The effect
produced is that of a course vertical scroll.
246 Atari Assembly Language Programme(s Guide
153,236
1:54, (lJ - - - - -
1:54,2J2!
1:54, 4 ( l J - - - - -
..
1:54,22 (lJ
154,240-------~~~------------
Figure 6-2. Vertical scrolling
TV display
Advanced Techniques 247
Since the image moves one whole mode line at a time, coarse
scrolling is noticeably jerky, especially in Graphics 2, where a single
mode line has 16 scan lines. Using the vertical fine scroll option allows
you to move a mode line, a group of mode lines, or the entire screen up
or down in scan line increments. The number of scan lines to move the
display is determined by the number in VSCROL. By incrementing
VSCROL during the vertical blank, the display drawn is shifted up
slightly from the previous one. Fine scrolling is limited by the fact that
only the lowerfour bits of VSCROL are significant. Consequently, the
largest number of scan lines that a display can be moved with fine
scrolling alone is 15. To continue the scrolling beyond this limit
involves invoking a coarse scroll and resetting the fine scroll register.
The process in flowchart form is shown in figure 6.3. Vertical fine
scrolling can be done with the whole display or part of the display . All
that is required is to set bit 05 in each display list instruction by adding
32 to the normal mode line number (see chapter 3).
Now we are in a position to look at the assembly language listing
in box 42C. The program starts off with a check on how far the
scrolling has progressed. This is done with a page zero register count
called COUNT at location 20.6 which is incremented on each pass
through the program. After 120. passes, aRTS is performed without
resetting system timer 2, thus effectively ending program execution.
Without the check on the scrolling, the screen window would scroll
across the computer memory which would be interesting but not
necessarily desira ble . For an interesting experience , rep lace BEQ # 19
with two NOP's.
Once the check on scrolling is done , the program loads the current
value in VSCROL from a software register at 20.6, increments it, and
compares it with 16. A natural question is "Why do we need a software
register?"The answer is because VSCROL is a write only register. This
means that there are some things you can't do with it such as load
CPU registers from it or use the INC VSCROL instruction. If fine
scrolling is not complete, which is determined by the results of CPX
# 16, the new va lue is stored in VSCROL and back into SCRLREG .
Finally, a delay value of 6 is loaded into system timer 2. This value does
248 Atari Assembly Language Programme(s Guide
SET UP
DISPLAY
INCREMENT
VSCROL
NO
IS
FINE SCROLL
COMPLETE
YES
DO
COARSE SCROLL
RESET VSCROL
TOO
Figure 6-3. Vertical fine scrolling process
Advanced Techniques 249
two things . It makes sure the subroutine will be called again when
timer 2 counts down to 0 and it controls the speed of scrolling.
When SCRLREG increments to 16, it is necessary to shift the
LMS instruction to point to the next lower screen mode line by adding
20 to the low byte of the LMS address. The program section beginning
with the label COARSE does a binary add and resets VSCROL and
SCRLREG. A new wrinkle in this addition routine is that sometimes
we must perform two byte addition. That happens when adding 20 to
SCNLO ;the Lo-Byte in the LMS address gives a result greater than
255. The procedure for doing this should be evident from the assembly
listing.
Before going further, test your understanding of the concepts
covered by rewriting the program so that the submarine scrolls down
the screen. To do this you will want to decrement the value in
VSCROL. Since VSCROL does not use the upper four bits, one way
to proceed is to load both hardware and software registers with 255
and decrement down until bits Do-Ds are clear. Now since you are
scrolling down, you must subtract 20 from the Lo-Byte of the screen
address . Don't forget it may be necessary to borrow from the Hi-Byte .
Horizontal Scrolling
The idea behind horizontal scrolling is to allocate a portion of
screen memory for each mode line . If the memory allocated is larger
than necessary, and if each mode line has the LMS option, then by
changing the address in the instruction, the display can be moved left
or right. This concept is illustrated with a single mode line thusly:
130,19
130,0------+
I Graphics 2
\1
.
130,255....;::J
250 Atari Assembly Language Programmer's Guide
Change the Lo-Byte of the LMS from 0 to 20 and the display shifts:
nOIOngerShOWn~
The easiest way to organize memory for horizontal scrolling is to
set aside one page for each mode line. Then you need only increment or
decrement the Lo-Byte of the LMS instruction. Incrementing scrolls
the display to the left. Decrementing scrolls the display to the right.
The diagram above shows the effect of adding 20 bytes to the address,
which is coarse scrolling in a big way! Normal coarse scrolling
increments by one byte at a time. To smooth out the motion, the
horizontal equivalent of a vertical fine scroll must be done. Horizontal
fine scrolling is done in color clock units. The fine scrolling register
HSCROL is nominally 8 bits wide but only the lower four bits are
used. Thus, the maximum number of color clocks that an image can be
fine scrolled before resetting is 16. The actual number to use depends
in the number of color clocks in the characters of the graphics mode
being used.
Box 43 is a horizontal scrolling example using the submarine of
the previous program. This program and our succeeding example, in
box 44, are similar, in order to reduce the amount of typing you need to
do. In both programs the machine language routine is stored in a string
for reasons of efficiency and economy. To make space for the display
list, character set, and screen memory, RAMTOP is lowered 27 pages.
Memory is used in the following manner:
PAGE
133
134
135
LO-BYTE
128
o
o
FUNCTION
Start of display list
Start of character set
Start of screen memory
Advanced Techniques 251
The screen memory actually uses only eleven pages. The remaining
space, from page 149 to 160 is cleared to act as a buffer so that the
diagonal scrolling program in box 44 does not bring 'garbage' (actually
the BASIC cartridge) onto the screen.
The program outline is as follows. The strings are DIMensioned
and all but ML$ are defined . Then RAMTOP is lowered and all ofthe
space above RAMTOP is cleared. You can save some typing by
starting out with the previous program and modifying or changing the
appropriate lines. After the character set has been moved and
redefined, a custom display list is constructed . The display list,
112
112
112
LMS
ADDRLO
ADDRHI
LMS
ADDRLO
ADDRHI
has an LMS instruction at each mode line . The LMS instruction
opcode is 87 (64+ 16+7) which sets bits D 6 , D4and selects Graphics 2. The
Lo-Byte of each instruction specifies that the memory scan counter
starts at the half way point of each page. This allows the option of
scrolling either way - left or right.
With a custom display list such as this , it is much easier to POKE
the character codes for each of the redefined characters directly into
memory. The easiest way to figure out where to POKE the numbers is
to make a sketch such as:
252 Atari Assembly Language Programme(s Guide
~ ;;:
~ ~scr-een location
tI
page 144
145
&
146
147
Lines 330-400 put the display in memory. Lines 420-450 tell ANTIC
where to find the display list and the OS where to find the character set.
Finally, lines 460-560 define the scrolling routine and start things
gomg.
The assembly listing of the scrolling routine is in box 43A. The
listing is fully documented. However, a couple of comments are in
order. As in the previous program, a count value is used to keep from
scrolling beyond the page boundary. There are, of course, other ways
to do this check. One way is to load in a typical LMS address and test
to see if it is within bounds. Also note that there is a curious asymmetry
between what we do to the fine scroll register and the address bytes. To
scroll right, HSCROL is incremented and the address is decremented .
To scroll left, HSCROL is decremented and the address is incremented.
Once again, it would be a good idea for you to rewrite the
program so that the submarine scrolls to the left across the screen.
Never mind that submarines probably don't back up too well! Start
your changes by repositioning the submarine in screen memory and
decrement the screen address bytes. This time however, decrement the
fine scrolling number down from 15 and make use of the fact that the Z
flag is set when DEX results in a zero in the X-register. That will
shorten the routine so watch your branch!
Advanced Techniques 253
BOX 43
Horizontal Scrolling
Th. Y.llow Bub~arin.
REM ** YELLOW SUBMARINE SCROLL **
10 REM * DIMENSION STRINGS THAT STORE ML ROUTINES *
20 REM * AND CHARACTER SET *
30 DIM CLEARt(18),MOVt(20),
REDEFt(14),SUBS(120) ,SS(32),MLS(~2)
40 REM CLEARS
50 REM MOVt
60 REM REDEFS
70 REM SUBt
80 REM St (the rem.ind.r of SUB.)
8~ SUSS(LEN(SUBS)+l)=SS
90 REM * SET UP RESERVED SPACE AND CLEAR *
100 POKE 106, 133:POKE 203,0:POKE 204,133
110 CLEAR=USR(ADR(CLEARS
120 REM * SET GRAPHICS MODE AND COLORS *
130 GRAPHICS 18:POKE 7~2,1:POKE 708,60:POKE 712,134
140 REM * MOVE STANDARD CHARACTERS/REDEFINE *
150 POKE 20~,0:POKE 206,224
160 MOVEmUSR(ADR(MOV.
170 Q-ADR(SUB.)
180 HIQ-INT(Q/2~6)
190 LOQ-Q-HIQ*256
200 POKE 205,LOQ:POKE 206,HIQ
210 POKE 203,24:POKE 204,134
220 R=USR(ADR(REDEFS
230 REM * SET UP CUSTOM DISPLAY LIST *
240 FOR 1-0 TO 2:POKE 34176+I,112:NEXT
2~0 FOR 1-0 TO 10:POKE 34179+I*3,87:NEXT
260 FOR 1=0 TO 10:POKE 34180+1*3, 128:NEXT I
270 FOR 1=0 TO 10:POKE 34181+1*3, 138+I:NEXT
280 POKE 34212,65
290 POKE 34213,128
300 POKE 34214,143
~
continued on next page
254 Atari Assembly Language Programmer's Guide
REM * TELL ANTIC AND OS WHERE SCREEN MEMORY IS *
REM * PUT SU8MARINE IN MEMORY *
REM * POKE INTERNAL CHAR NUM8ERS DIRECTLY IN MEMORY
POKE 144*256+133,3
FOR 1"1 TO 6:POKE 145*256+(129+Il, (I+3):NEXT
POKE 146*256+130,10
FOR I-I TO 4:POKE 146*256+(130+I),II:NEXT I
POKE 146*256+135,12
FOR 1=0 TO 2:POKE 147*256+(130+I),13+I:NEXT
FOR 1=0 TO 2:POKE 147*256+(133+I),15+I:NEXT
REM * CHANGE CHAR8AS *
pm:E 559,0
POKE 560,128:POKE 561,133
POKE 756,134
POKE 559,34
ML.
REM * INSTALL ADDRESS OF THE SCROLLING ROUTINE *
Q=ADR(ML.)
HIGI'"'I NT (G!/256)
LOQ=G!-HIGI*256
POKE 552,LOG!:POKE 553,HIG!
REM * SET REGISTERS USED BY SCROLLING ROUTINE *
POKE 205,0:POKE 206,0:POKE 54276,0
REM * START SYSTEM TIMER 2 *
POKE 538,10
GOTO 560
\.
Box 43. Horizontal scrolling The Yellow Submarine
Advanced Techniques 255
BOX 43A
The Yellow Submarine
Assembly listing for Horizontal Scroll
COUNT (205) keeps track of number of passes thru routine.
SCRLREG (206) keeps track of fine scrolling value
LDY COUNT
INY
164,205
200
CPY LIMIT
192,100
BEQ END
240,19
STY COUNT
132,205
LDX SCRLREG 166,206
INX
232
CPX #16
224,16
BEQ COARSE 240,11
STX HSCROL 142,4,212
STX SCRLREG 134,206
LDA #4
169,4
STA TIMER
141 ,26,2
END RTS
96
COARSE LDX#O 162,0
LOOP DEC Dec., sc.fi'; _.'1'. :1
LOSeNMEM;-X- 222,132,133
INX ~~ 232
INX
INX
232
232
224 ,33
CpX#33
208,246
BNELOOP
169,0
LDA #0
STA HSCROL 141,4,212
STA SCRLREG 133,206
169,4
LDA #4
141,26,2
STA TIMER
96
RTS
Load number of current pass
increment and check if
is complete. If done branch to
RTS without setting timer
Otherwise store pass number
Load the fine scroll number
Increment it
Is fine scroll done?
Yes, then branch to coarse scroll
Store new scrolling value in hardware
and software registers
Reset system
timer 2
Return to VB processing
Load X-Reg for indexed addressing
Change SCN ADDR (coarse scroll)
Increment X-register to point
to next screen memory address
in the display list
Have all addresses been changed?
If not, loop back
If yes , reset fine scrolling
registers-hardware and
software
Reset system
timer 2
Return to VB processing
\..
Box 43A. The Yellow Submarine assembly listing for horizontal scroll
256 Atari Assembly Language Programmer's Guide
Bo)( 438
Th. V.llow Subaarin.
t1l.. Li sti nQ
DECIMAL ..
164
20:5
200
192
KEYSTROKE
[!]
[;]
DECIMAL ..
19
132
20:5
166
KEYSTROKE
Cl/SM
DECIMAL ..
224
KEYSTROKE
~Cl /P
DECIMAL ..
212
KEYSTROKE
GJ
16
134
240
Gl
206
232
GJ [UGJ GJ
11
GJ
Cl/K ICl/NI Cl / D
206
169
Cl / D FllMl
162
222
96
142
240
ICLlFI0
141
DECIMAL ..
26
KEYSTROKE
Cl/Z CLIB Cl / .
CJ
Cl/,
DECIMAL ..
132
133
232
232
224
KEYSTROKE
Hl0
JCLlDlbl/E!
--- DECIMAL ..
33
KEYSTROKE
DECIMAL II
4
Cl/D
DECIMAL
141
KEYSTROKE
GJ GJ GJ
246
212
133
141
Cl / , !ClIM]
169
[2J IcLl~GJ Q
26
.,
f 0 r- dlago n a I scroll
language 1 ist "ing in 80;< 44A.
contr-ol
2@6
Cl / D
96
ICl iM !Cl /Z Cl / B CLI.
NO TE: ML$
ell:
169
GJ GJ GJ
r; EYS TROKE
II
208
232
key
I
I
can be deri v ed
a round
Box 43B. The Yellow Submarine ML$ listing
f r-am
a3s emb l '
inverse vi deo
Advanced Techniques 257
Diagonal Scrolling
The final scrolling example, in box 44, shows how to program a
diagonal scroll. Except for the fact that both fine scrolling bits are set
in the LMS instruction, all of the interesting differences between this
program and the previous one occur in the scrolling routine which is
written out in detail in box 44A.
Diagonal scrolling involves simultaneous manipulation of both
fine scroll registers. N ow, because we are using Graphics 2, the vertical
fine scroll register goes from 0 to 15, while HSCROL is incremented
from 0 to 7. To keep things simple, we increment VSCROL twice for
each increment of HSCROL. Consequently, both registers reach their
limits together and by testing only HSCROL it is possible to choose
whether or not to branch to the coarse scroll segment. The vertical
coarse scroll differs from the example in box 42 because screen
memory is organized in one page per mode line. Here it is only
necessary to increment the address Hi-Byte to scroll one line .
BOX 44
Diagonal Scrolling
The Yellow Submarine
5 REM ** YELLOW SUBMARINE SCROLL **
10 REM * DIMENSION STRINGS THAT ST ORE ML ROUTINES *
20 REM * AND CHARACTER S ET *
31~ DIM
CLEAR$(lS',MOV$120',REDEF$ 114'.SUB$1 120',S$132' ,ML$ 169'
40 CLEARS
51~ MOV$
6Ql REDEF$
71~ SUBS
80 S$
85 SUBsILENISUB$'+l'=S$
90 REM * SET UP RESERVED SPACE AND CLEAR *
100 POKE 106, 133:POKE 203.0:POKE 204,133
110 CLEAR=USRIADRICLEAR$ ))
120 REM * SET GRAPHICS MODES AND COLORS *
130 GRAP HICS IS:PO KE 752. I:POVE 70 S.60:POVE 712,135
140 REM * MOVE STANDARD CHARACTERS/ REDEFINE *
150 ~OKE 205,0:POKE 206,::4
160 MOVE =US RIADRIMOV S))
(cont. on next page)
258 Atari Assembly Language Programme(s Guide
O=ADR(SUB$)
HID='INT (0/256)
LOO=Q--H I 0*256
POKE 205,LOO:POKE 206,HID
POKE 203,24:POKE 204,134
R=USR(ADR(REDEF$
REM * SET UP CUSTOM DISPLAY LIST *
FOR 1=0 TO 2:POKE 34176+1,1 2:NEXT
FOR 1=0 TO 10:POKE 34179+1* ,119:NEXT
FOR 1=0 TO 10:POKE 34180+[* ,128:NEXT
FOR [=QI TO 1111: F'm:E 34181+[* ,138+1: NEXT
pm~ E 3421:2, 65
F'm~E 34213,128
pm:E 34214,133
REM * TELL ANTIC AND OS WHERE SCREE N MEMORY IS *
REM * PUT SUBMARINE IN MEMOR Y *
REM * POKE INTERNAL CHAR NUMBERS DIRECTL Y TN MEMORY *
POKE 144*256+133,3
FOR 1=1 TD 6:POKE 145*256+ (I:~9+ I ) . (li- ~S ) :NE XT
POKE 146*256+130,10
FOR 1=1 TO 4:F'Of<E 146*256+-(1 31~I+ I) .l.l.:NEXT I
POKE 146 *256+135,12
FIJR 1=121 TO ~~:F'Of' E 147*256+-(13121+I>,l.3+I:I\IE~T
FOR [=0 TO 2:POKE 147* 2 56+(133+[) , 15+I:NEXT
REM * CHANGE CHAR BAS *
POfT 559, QI
POKE 560, 128:POKE 561.133
POf: E 756, 1 ~; 4
POI<E 559, :::4
ML$
REM * INSTALL ADDRESS OF THE SCROLLING ROUTINE *
O=ADR(ML$)
HIO=INT(Q /2 56)
LOQ=Q-HIQ* 256
POKE 552,LOQ:POkE 553,HIQ
REM * SET REGISTERS USED BY SCROLLING ROUTINE *
POKE 205,0:POKE 206,0:POKE 54276,0
POKE 2QJ'7, QI
REM * START SYSTEM TIMER 2 *
pm:: E 538, 10
(30TO 571~
Box 44. Diagonal scrolling The Yellow Submarine
Advanced Techniques 259
BOX 44A
The Yellow Submarine
Assembly Listing for Diagonal Scroll
COUNT (205) keeps track of number of passes thru routine
HSREG (206) keeps track of horizontal fine scrolling value
VSREG (207) keeps track of vertical fine scrolling value
LOY COUNT
INY
CPY LIMIT
SEQ ENO
STY COUNT
LOX HSREG
INX
CPX #8
SEQ COARSE
STX HSREG
STX HSCROL
LOX VSREG
INX
\...
(cont. on next page)
164,205
200
192,80
240,28
132,205
166,206
232
224,8
240,20
134,206
142,4,212
166,207
232
Load number of current pass
increment and check if
is complete . If done branch to
RTS without setting timer
Otherwise store pass number
Load the fine scroll number
Increment it
Is fine scroll done?
Yes, then branch to coarse scroll
No store horizontal scroll in hardware
and software registers
Load vertical fine scroll number
Increment it twice (fine scro ll
260 Atari Assembly Language Programmer's Guide
232
In 2 scan line increments)
Store value in software and
134,207
142,5,212 hardware registers
169,6
Reset system
141 ,26,2
timer 2
96
Return to VB Processing
COARSE LDX#O 162,0
Load X-reg for indexed addressing
LOOP DEC
LOSCNMEM,X
222,132, 133Change Lo-Byte of screen address
INX
232
I nc X-reg to point to Hi-Byte of
Screen Address
INC HISCNMEM,X254, 132, 1331ncrement Hi-Byte of screen address
INX
232
Increment X-reg to point to next
INX
232
Lo-Byte of the screen address
CPX#33
224,33
Are all screen addresses changed?
208,243
BNELOOP
No? Then branch back to do next one
169,0
LDA#O
If yes , reset
all software
133,206
STA HSREG
and
133,207
STA VSREG
STA HSCROL
141,4,212 hardware
STA VSCROL
141 ,5,212 registers
169,6
LOA #6
Reset system
STA TIMER
timer 2
141,26,2
RTS
Return to VB processing
96
Box 44A. The Yellow Subma rine assembly listing for diagonal scroll
Vertical Blank Music
So far , all of the examples have used system timer 2 to link the
subroutines into the vertical blank. This leaves the vector at 548,549
free to link in another program. Since the vertical blank is a fine place
to play music, let's add the appropriate song to our previous examples!
Up to this point the program in box 45 is the most ambitious program
that we have presented . It scrolls the submarine around the screen
Advanced Techniques 261
while playing - you guessed it - The Yellow Submarine! Again, the
program is structurally similar to the previous yellow submarine
programs, so that your typing chore will be reduced. However, there
are some changes. First, the scrolling routine is no longer in a string.
Because of its length, it is read in from data numbers. So eliminate
ML$ in line 30, but add VB$(ll) in its place. VB$ is the short routine
that links the music program to the regular VB processing by 'stealing'
the vector at 548,549. In line 100, RAMTOP is lowered to page 130 to
allow room for the scrolling routine and the music data numbers. In
line 130, Graphics 18 is changed to Graphics 2 so we can print a
message in the text window. Since ML$ is gone, lines 420 through 570
have been changed. These are the major changes. However, be sure to
compare this program carefully with the previous one before you start
typing.
N ow that we have discussed the changes, let's see how the
program is organized and how it works. Memory use is as follows:
RAMTOP is repositioned to page 130.
A one page buffer exists between RAMTOP and the
scrolling routine, which starts at page 13l.
Since the scrolling routine is 241 bytes long, it takes up most
of page 13l.
The music data is stored on page 132. The music program is
only 93 bytes and fits into the first half of page 133.
As before, the display list is in the second half of page 133.
When you plan out programs that are going to run during the
vertical blank, one important thing to remember is to make sure that
the machine language routines are in place before they are called up by
the BASIC program. Otherwise the computer will lock up.
The program in box 45 makes sure everything is in place by
going to a loading subroutine at line 420, right after the submarine has
been put in memory. Since this is a rather lengthy process, a message is
printed in the text window to let the user know what's happening.
After the machine language routines are in place, the registers they use
262 Atari Assembly Language Programmer's Guide
are set, the system timer is started, the music routine is linked, and the
action begins. Speaking of linking a subroutine to the VB, here is the
routine again: LDY with the Lo-Byte of the routine's address, LDX
with the Hi-Byte, LDA with a 6 for an immediate, or with a 7 for a
deferred vertical blank routine. Then JSR SETVBV. SETBV is at
92,228 (Lo-Byte, Hi-Byte).
In keeping with the format of the book, the entire assembly listing
of the scrolling routine is in box 45A and the assembly listing of the
music routine is in box 45B . However, because of the length and
complex nature of the programs we offer the following explanation.
Basically the scrolling consists of four sections:
A
A
A
A
vertical scroll up
horizontal scroll to the right
vertical scroll down and
horizontal scroll to the left.
The first thing the program must do is to decide in which direction to
move. This is the purpose of section 1 of the program. Associated with
each section is a COUNT register that keeps track of how far the
scrolling has progressed . The program tests each of these registers in
turn and will branch to the appropriate scrolling routine when it finds
a nonzero value. There is an interesting wrinkle at the end of secti.)Ol 1.
Because of the length of the program, it is not possible to re~? on
relative branching alone to go from the last COUNT test in section 1 to
the horizontal scroll-left (HORZLFT)in section 6. Recall that one can
branch forward only 127 bytes and backward 128 bytes. Consequently,
we branch to a JMP instruction that's conveniently tucked in after the
end of the vertical up (VER TUP) routine. The JMP then sends the
program to (HORZLFT).
Look at Sections 3,4,and 5 (VERTUP,HORZRT,VERTDN).
The first thing each of these segments do is to set up the COUNT and
fine scroll registers for the segment following it. That way when their
COUNT register is finally decremented to zero, the next one will be
ready to go. However, the very last segment, horizontal left (HORZLFT),
Advanced Techniques 263
can't do this . Why? Becau se the horizontal left routine is executed 100
times before it gets down to zero, and after the first time through,
COUNTI would be set. The program would read that, branch to
VERTUP , and never go back to HORZLFT. For every vertical scroll
up after the first, VERTUP is executed as the default routine when
section I finds only zero CO UNT registers. The register values needed
by VER TUP are provided in section 2.
Notice that the values stored in the COUNT registers for
VERTUP and VERTDN are different. Also, the initial values of the
software scrolling register, VSCLREG, are different in each case. The
reason for this is that it is necessary to use these numbers in order to
make sure that the scrolling rectangle closes and the submarine doesn't
slowly sink into the mud at the bottom of the sea.
Other than this, the scrolling routines are similar to the ones in the
previous programs. First, the program does a fine scroll until the limit
has been reached. Then it branches to a coarse scroll. As in diagonal
scrolling, in this program a coarse vertical scroll is done by in'crementing,
or decrementing the Hi-B yte of the screen address in the LMS
instruction . This reflects the allocation of one page of memory per scan
line. HORZRT is the same as before and HORZLFT is the answer to
the exercise we posed earlier.
The music routine, in Box 45B has three parts:
one which stores music frequency numbers in AUDFI and
AUDF2 (8 bit music)
one which turns the notes off so they do not run together
and
a section at the beginning which chooses between the
previous two.
The beginning section also controls the timing register at 1536. In
order to keep track of whether we're on a music cycle or a silent cycle,
there is a flag register called CYCLE at 1537. The program begins by
loading in the current timer va lue and decrementing it. Then it tests to
see if result is zero . If it is , the end of the current cycle has been reached
and then the program branches to see which cycle comes next. If the
cycle flag is 1, a new pair of frequencies is loaded in. If the cycle flag is
zero the sound is turned off. Each segment of the program sets the flag
to identify the next segment of the routine.
264 Atari Assembly Language Programmer's Guide
BOX 45
Fi n a l e
Scrol ling and Mus ic
2 REM ** FINALE PROGRAM **
5 REM ** YELLOW SUBMARINE SCROLL AND MU SIC **
10 REM * DIMENSION STRINGS THAT STORE ML ROUTINES *
20 REM * AND CHARACTER SET *
30 DIM CLEAR$(18),MOV$(20),
REDEF$(14),SUB$(1 20) , S$(32),VB$(II)
40 CLEAR$
50 MOV$
60 REDEF$
70 SUBS
80 S$
85 SUB$(LEN(SUB$)+I)=S$
90 REM * SET UP RE SE RVED SPACE AND CLEAR *
100 POKE 106, 130: POKE 203,0: POKE 20 4 , 130
110 CLEAR=USR(ADR(CLEAR$))
120 REM * SET GRAPHICS MODES AND COLORS *
130 GRAPHICS 2:POKE 752, I :POKE 708,60:POKE 712, 1 3~
140 REM * MOVE STANDARD CHARACTERS/REDEFINE 't.
150 POKE 205,0:POKE 206,224
160 MOVE=USR(ADR(MOV$))
170 Q=ADR(SUB$)
180 HIQ=INT(Q /256)
190 LOQ=Q-HIQ*256
200 POKE 205,LOQ:POKE 206,HIQ
2 10 POKE 203,24:POKE 204,134
220 R=USR(ADR(REDEF$))
230 REM * SET UP CUSTOM DISPLAY LIST *
240 FOR 1=0 TO 2 :POKE 34176+I,112:NEXT I
250 FOR 1=0 TO 10:POKE 34179+1*3, 119:NEXT I
260 FOR 1=0 TO 10:POKE 34180+1*3.020001, 128 :NEXT
270 FOR 1=0 TO 10:POKE 3418 1+1*3, 138+I:NEXT I
280 POKE 34212 ,6 5
290 POKE 34213 , 128
300 POKE 34214,133
320 REM * PUT SUBMARINE IN MEMORY *
330 REM * POKE INTERNAL CHAR NUMBERS DIRECTLY IN ME~1or,y "340 POKE 144*256+13 3,3
350 FOR 1=1 TO 6:POKE 145 *256"( 129+1), (J+3) :NEXT
360 POKE 146*256+130,10
370 FOR 1=1 TO 4:POKE 146*256+(130+1), 11: NEXT [
380 POKE 146*256+135, 12
390 FOR 1=0 TO 2:POKE 147 *2 56~(130+I) , 13+1:NEXT
400 FOR 1=0 TO 2:POKE 147*256+( 133 +1), 15+I:NEXT I
410 PRINT "LOADING MACHIN!, LANGUAGE ROUTINES AI',IIl 1~1I ~;rC"
420 GOSUB 700
430 VB$
440 REM * CBANGE CBARBAS *
450 POKE 559,O
(cont. on next page)
Advanced Techniques 265
460 POKE 560, 12B:POKE 561 , 133
470 POKE 756, 134:POKE 559,34
480 REM
INSTALL ADDRESSES OF VERTlCAL. BLANK ROliTINES
490 POKE 552,0:POKE 553,131
500 REM
SET REGISTERS USER BY ROUTINES
510 POKE 209,l:POKE 1,536,l:POKE 1537,0
520 POKE 203,80:POKE 204,0:POKE 205,0
530 POKE 206,0:POKE 207 , 0:POKE 208,0
550 REM
START TIMER AND MUSIC REGISTERS
560 POKE 538, 10
570 POKE 53768,0:POKE 53775,3
580 POKE 53761, 168:POKE 53763 , 168'POKE 5376!",168
590 X=USR(ADR(VB$))
600 GOTO 600
700 REM READ IN MACHINE LANGUAGE ROUTINE
710 FOR 1=0 TO 92:READ MUS
720 POKE 3404B+I,MUS:NEXT I
72 ,5 REM
730 DATA 174,0,6,202 , 142,0,6,224 ,
0, 240, 3, 76 , 98, 228 , 166, 209 , 224, 1, 240, 20, 169,0, 141,0, 210 " 141, 2,
210
735 REM
740 DATA 1 69,2,141,0,6,169, I , 133,
209 , 76,98, 228 , 174, I , 6, 189 , 0 " 13 2 , 141,0, 210, 232, 189 , 0, 132 , 141 , 2
,210
745 REM
750 DATA 232,189,0,132,141 , 0 , 6 ,
232,224,186 , 240 , 10 , 142, 1,6 , 16 9, 0,133, 20!), 76 , 98, 228,169,0,133,
209, 141. 1, 6
755 REM
760 DATA 169,20,141,0 , 6 , 76,98 , 228
765 REM
770 REM READ IN WISIC DATA
780 FOR 1 =0 TO 185:READ MUSDAT
790 POKE 33792+I,MlI SDAT:NEXT I
795 REM
800 DATA 63,5 3 ,22,71 , 53,22,80,53 ,
22,5,53,30,47,0, 12,85,71 , 30 , 85,71,8,85,71 , 30,85,71,8,85 , 71 , 50
,85,71,30
805 REM
810 DATA 85,71,8,85,71,30,85,71,8,
85,71,50,107,80,30,107 , 80,8 , 107,80,30, 107,80,8, 107,80,50,83 , 5
*
*
*
3,22
8 1 5 REM
820 DATA 71,53,22,80 , 53 , 22,85 , 53,
30, 47, 0, 12, 85, 7 I, 30, 85, 71, 8, 85, 7 I , 30 , 85, 7 1 , 8, 85, 71 , 50 , B5 , 71, 3
0 , 85,71,8
825 REM
830 DATA 85,71,30,85 , 71, 8 , 8 5,71,
50,107 , 80,30,107 , 80,8,107,80 , 30 , 107,80,B , 107,80,22,0 , 63 , 30,60
,0,8
835 REM
840 DATA 0,53,64,63 , 0,8 , 0, 7 1, 30,
63,0,8,0,B0 , 64,63,80,30,0,63,8,71, 121,30,0,80,8,95 , 12 1 ,48 , 80,
(cont. on next page)
266 Atari Assembl y Language Prog rammer's Guide
63,313
845 REM
8513 DATA 13,63,8,71,13,64,13,63,313,
613,13,8,13,53,64,63,13,12,13,71,313,63,13,8,13,813.72
8613 REM
8713 REM READ IN SCROLLING ROUTINE
8813 FOR 1=0 TO 2413:READ ML
8913 POKE 33536+I,ML:NEXT I
895 REM
91313 DATA 164,2133,192,13,2138,24,
164,2134,192,13,208 , 75,164,2135,192,13,2138,123 , 164, 2136,192.13,2138,
613
9135 REM
9113 DATA 169,8,133,2137,1613,913,
169,11313,133,2134 , 169,4,133,2138,136,.132,2133,166,207, 232, 224,16,
2413, 11
915 REM
9213 DATA 142,5,212,134,2137,169,6,
141,26,2,96,162 , 13,254,133,133,232,232,232,224, 33 ,. 2138 , 246 ,. lG9.
13,133,2137
925 REM
9313 DATA 141,5,212,169,6,141,26,
2,96, 76, 195, 131, 169, 85, 133, 2135, 169, 2, 133, 2137 , 136, 132, 2134, 166,
2138,232,224
935 REM
9413 DATA 8,240,11,142,4,212 , 134,
208 , IS9,6, 141,26,2,96, 162,0,222, 132 , 133,232,232,232,224, 3 3,20
8,246,169,13
845 REM
950 DATA 141,4,212,133,208 , 168,6.
14 1 ,26 , 2,86, 169,1013,133,2136,169 , 1 , 133,208,136,132, 205,166,2137
, 202,224,0
955 REM
9613 DATA 2413,11 , 142,5,212,134 ,
207, 168,6,141.26,2,96 , 162,0,222,133,133,232,232, 232. 224 . 33 , 20
8,2 46, 169,15 , 1 33
965 REM
8713 DA TA 207,14 1 ,5,212,169,6,141,
26, 2, 96, 136, 132 , 206, 166, 2138, 202, 224,13, 2413, 11, 142 , 4, 212, 134, 213
8, 169,6,141
975 REM
980 DATA 26,2 , 96,162,13,254,132,
133 , 232,232,232,224,33,2138,246,169,8,141,4.212 , 133,2138,169 . 6,
141,26,2,96
985 REM
890 RE TURN
Box 45. Finale Scrolling and Music
Advanced Techniques 267
BOX 45A
Assembly Language Listing
for
Yellow Submarine Scrolling
Register use:
COUNT1 = 203
COUNT2 204
COUNT3 205
COUNT4 206
=
=
=
VSCLREG = 207
HSCLREG = 208
SECTION 1: Determine which move to make
LOY COUNT1
CPY #0
BNE VERTUP
LOY COUNT2
CPY #0
BNE HORZRT
LOY COUNT3
CPY #0
BNE VERTON
LOY COUNT 4
Cpy #0
BNE HORZLFT
164,203
192,0
208,24
164,204
192,0
208,75
164,205
192,0
208,123
164,206
192,0
208,60
BOX 45A. Assembly language listing for Yellow Submarine Scrolling
268 Atari Assembly Language Programmer's Guide
SECTION 2: Initialize counters for vertical up move (ie next routine)
LOA #8
STA VSCLREG
LOY #90
169,8
133,207
169,90
SECTION 3: Vertical Scroll Up
VERTUP
COARSE1
LOOP
LOA #100
STA COUNT2
LOA #4
STA HSCLREG
DEY
STY COUNT1
LOX VSCLREG
INX
CPX #16
BEQ COARSE1
STX VSCROL
STX VSCRLREG
LOA #6
STA TIMER
RTS
LOX #0
INC HISCN,X
INX
INX
INX
CPX #33
BNELOOP
LOA #0
(cont. on next page)
169,100
133,204
169,4
133,208
136
132,203
166,207
232
224,16
240,11
142,5,212
135,207
169,6
141,26,2
96
162,0
254,133,135
232
232
232
224,33
208,246
169,0
Advanced Techniques 269
STA VSCLREG
STA VSCROL
133,207
141,5,212
LOA #6
STA TIMER
RTS
JMP HORZLFT
169,6
141,26,2
96
76,195 ,131
SECTION 4: Horizontal Scroll to the Right
HORZRT
COARSE2
LOOP
LOA#85
STA COUNT3
LOA #15
STA VSCRLREG
DEY
STY COUNT2
LOX HSCLREG
169,85
133,205
169,2
133,207
136
132,204
166,208
232
INX
CPX #8
BEQ COARSE2
STX HSCROL
STX HSCLREG
LOA #6
STA TIMER
RTS
96
LOA #0
DEC LOSCN,X
INX
INX
INX
CPX #33
BNE LOOP
162,0
222,132,133
232
232
232
224,33
208,246
(cont. on next page)
224,8
240,11
142,4,212
134,208
169,6
141 ,26,2
270 Atari Assembly Language Programmer's Guide
LOA #0
STA HSCROL
STA HSCREG
LOA #6
STA TIMER
RTS
169,0
141,4,212
133,208
169,6
141,26,2
96
SECTION 5: Vertical Down Scroll
VERTON
COARSE3
LOOP
LOA #100
STA COUNT4
LOA #1
STA HSCLREG
DEY
STY COUNT3
169,100
133,206
169,1
133,208
136
132,205
LOX VCSCLREG
OEX
CPX #0
BEQ COARSE3
STX VSCROL
STX VSCLREG
LOA #6
STA TIMER
166,207
202
224,0
240,11
142,5,212
135,207
169,6
RTS
LOX #0
DEC HISCN,X
INX
96
162,0
222,133,133
232
232
232
224,33
208,246
169,15
INX
INX
CPX #33
BNELOOP
LOA #15
(cont. on next page)
141,26,2
Advanced Techniques 271
STA
STA
LOA
STA
VSCLREG
VSCROL
#6
TIMER
RTS
133,207
141,5,212
169,6
141,26,2
96
SECTION 6: Horizontal Scroll Left
HORZLFT
DEY
STY COUNT4
LOX HSCLREG
OEX
CPX #0
BEQ COARSE4
STX HSCROL
STX HSCRLREG
LOA #6
STA TIMER
COARSE4
LOOP
136
132,206
166,208
202
224,0
240,11
142,4,212
134,208
169,6
141,26,2
RTS
LOX #0
INC LOSCN ,X
96
162,0
254,132,133
INX
INX
INX
CPX #33
BNELOOP
LOA #8
STA HSCROL
STA HSCLREG
LOA #6
STA TIMER
RTS
232
232
232
224,33
208,246
169,8
141 ,4,212
133,208
169,6
141,26,2
96
(cont. on next page)
272 Atari Assembly Language Programmer's Guide
r
BOX 45B
Assenbly Language Listing
for
Yellow Submarine Music
Register use:
MUSTIMER = 1536
DATACNT = 1537
CYCLE = 209
Section 1: Timing and Cycle Test
LOX MUSTIMR 174,0,6
DEX
202
STX MUSTIMR 142,0,6
224,0
CPX #0
BEQ CYTEST 240,3
JMP XITVBL
76,98,228
CYTEST LOX CYCLE
CPX #1
BEQ SOUND
(cant. on next page)
166,209
224,1
240,20
Load duration of note or silence
decrement and save. If done
then go see what happens
next
If not done leave vertical blank
Test flag to see if we're on
silence or sound
Advanced Techniques 273
Section 2: Sound Off to Separate Notes
LOA #0
169,0
Turn off
STA AUOF1
141,0,210 Sound
STA AUOF2
141,2,210 registers
LOA #2
169,2
Load duration of silence
STA MUSTIMR 141 ,0,6
and store in timer
LOA #1
169,1
Set cycle
STA CYCLE
133,209 Flag
JMP XITVBL
76,98,228 Leave vertical blank
Section 3: Sound On
SOUND LOX
LOY
STA
INX
LOA
STA
INX
LOA
OATACNT 174,1 ,6
TABLE,X 189,0,132
AUOF1
141 ,0,210
232
TABLE,X 189,0,132
AUOF2
141 ,2,210
Load notes and
duration from
the music data
table. Store in sound
Channels 1 and 2
232
and store duration in
189,0,132 MUSTIMR
STA MUSTIMR 141,0,6
TABLE ,X
INX
CPX TABLENO
BEQ REPEAT
STX OATACNT
LOA #0
STA CYCLE
JMP XITVBL
232
224,186
240,10
142,1,6
169,0
132,209
Test for end of data table
Save last X-reg for next note
Set flag for sound off
76,98,228 Leave vertical blank
REPEATLOA #0
169,0
STA CYCLE
133,209
STA OATACNT 141,1,6
LOA #20
169,20
STA MUSTIMR 141,0,6
JMP XITVBL
76.98.228
Restore registers and
set timer to hold
the last note a little
longer .. ..
Box 45B. Assembly language listing for Yellow Submarine music
274 Atari Assembly Language Programmer's Guide
Alternate forms of Input/Output
There is an area of programming, about which very little has been
written which has a lot of potential for new and innovative
programming. This area is the use of alternate forms of input such as
light pens, touch sensitive pads, or specialized switches designed for
handicapped computer users. We will discuss touch sensitive pads
because they are comparatively inexpensive, readily available, and
quite versatile. When one thinks of a touch sensitive pad like the Atari
Touch TableC" or Koala Pad T", one invariably thinks of drawing and
artwork. But there is absolutely no reason that either of these pads be
relegated to duty as a high-tech Etch-a-Sketch T". A touch pad can be
just as useful for input as a mouse and uses a lot less desk space.
The typical touch pad can be connected into any of the joystick
ports. As we shall see, which port you use depends on the program
written for it. The pad has two or three switches and the touch sensitive
surface. The touch sensitive surface works like a rectangular grid of
variable resistors, usually referred to as potentiometers. In its action
the pad mimics a pair of game paddles.
In the Atari Home Computer a pair of paddles connects into one
game port: paddles 0 and 1 into port 1, paddles 2 and 3 into port 2, etc.
A small current at +5 volts is sent from the computer through the
potentiometer in the paddle. Turning the knob on the paddle varies the
resistance and changes the voltage of the signal. The current returns to
the computer at pins 5 and 9 of the joystick port. Here the signal is
changed by an analog to digital converter into a number fromO to 228.
During each vertical blank, the OS reads the values from hardware
registers 53760 - 53767 and stores the values in the shadow registers
PADDLO - PADDL7 at 624 - 631.
Now it is easy to see how a touch pad works . For example,
suppose that the Atari Touch TableC" is plugged into game port 1 and
you touch the stylus to the surface. The number read into PADDLO
(624) gives a measure of the horizontal distance from the left side of the
tablet to the point of contact. The number in PADDLl (625) gives a
measure of the vertical distance from the bottom of the tablet to the
point of contact.
Advanced Techniques 275
PADDLE 0
Notice that the tablet is laid out the same as quadrant I of a normal
X-Y coordinate system with the origin in the lower hand corner. This is
different from how coordinates are laid out on the TV screen where the
origin is at the upper left hand corner. The Koala Pad, on the
other hand uses the same layout as the screen display with the origin in
the upper left hand corner and PADDLO giving the X values and
PADDLl giving the Y values.
In order to make use of a touch pad (digitizer) for input you need
to know how the PADDLO and PADDLl numbers are mapped on to
the pad. The program in box 46 will help you to do this. Cut a piece of
graph paper withY4inch squares the size of the sensitive surface and lay
it on the pad. Plug your digitizer into Port I. When run, the program
reads PADDLO and PADDLl every 1/ 6th second during the vertical
blank storing the values in page 158. It waits for a while at line 145 to
allow the reading to be completed and then prints out the values on the
screen. Reading the paddle values during the vertical blank is more
accurate than doing it from BASIC. This is particularly true for the
Atari Touch Tablet which has the quicker response and sensitivity of
the two digitizers. By running the program several times and making
contact with the pad at different places you can prepare a diagram with
the paddle values obtained.
As an example of what can be done with a digitizer, Box 47
contains a program to play music by simply moving the stylus around
the surface.
276 Atari Assembly Language Programmer's Guide
BOX 46
Reading tb e Atari Toucb Tabl e t
5 REM ** PROGRAM TO TEST TOUCH TABLETS **10 REM * Lm~ER RAMTOP TO RESERVE SPACE FOR DATA *
20 POKE 106, 158:GRAPHICS 0
30 REM * LOAD I N ROUTINE TO READ PADDL0 / PADDLl DURING VB t.
40 FOR 1=0 TO 37 :READ ML
50 POKE J536+ I ,ML:NEXT I
60 DATA 164,204,136,132,204,
192,0,208,26,160,10,132,204, 16 6, 203 ,22 4, 254,2 40 , 16,232,173, 11
2,2
70 DATA 157,0,158,232,173 , JJ 3,2, 157,0, J58,1 34.203 . 76,88.22 8
80 POKE 203,0: POKE 204, 10
90 REM '" LOAD IN VB LINKING ROUTINE *'
100 FOR 1=0 TO 10:READ ML
110 POKE 1684+1,ML:NEXT I
120 DATA 104,160,0,162,6,1 69 ,7, 32,92,228 , 96
130 X=USR(1684)
140 REM DELAY
DATA TO BE READ *
150 FOR 1=0 TO 6000
160 NEXT I
170 REM * PRINT OUT PADDL0 / PADDL1 DATA .t.
180 FOR 1= 1 TO 255
190 PRINT rEEK(40448~r);"
200 NE XT r
*'
Box 46. Reading the Atari Touch Tablet
Advanced Techniques 277
BOX 46A
A Simple Program to Read The
Atari Touch Tablet
Register Use :
204
203
= Timer for read
= Counter for storage
LOY TIMER
DEY
STY TIMER
CPY #0
BNE END
LOY TIMER
STA TIMER
164,204
Load timer value, decrement
136
132,204
192,0
208,26
160,10
132,204
don 't read paddles until its
down to zero . Thus, read
every 10th VB
LOX,COUNT
CPX FINAL
BEQ END
166,203
224,254
240,16
Load table offset called COUNT
Are we done?
If so , end
INX
LOA PAOOLO
STA TABLE,X
INX
LOA PAOOL 1
232
173,113,2
157,0,158
232
173,112,2
Increment offset
Get paddle 0 value
Store in Table
Incroment offset
Get paddle 1 value
STA TABLE,X
STX,COUNT
JMP,XITVBL
\...
157,0,158
134,203
76,98,228
Store in table
Save Offset
Leave vertical blank processing
Reset
Timer
BOX 46A. A simple program to read the Atari Touch Ta blet'"
278 Atari Assembly Language Programmer's Guide
BOX 47
Atari Touch Tablet Music
10 REM ** PROGRAM TO PLAY MUSIC WITH TOUCH PAD **
20 FOR I=0 TO 27:READ ML
30 POKE 1536+I,ML:NEXT I
4~ DATA 164,21214,136,132,204, 192,0,208,16,164,10,132
50 DATA 21214,173,112,2,141,0,
210,173,l13,2,141,2,210,76,98,228
60 FOR I=0 TO 10:READ ML
70 POKE 1664+I,ML:NEXT I
80 DATA 104,160,0,162,6,169,7, 32,92,228,96
9121 POKE 53768,0:POKE 53775,3:POKE 204,10
11210 POKE 53761, 168:POKE 53763,168
110 X=USR(1664)
121?J GOTO 12121
Box 47. Atari Touch Tablet Music
Once again the program reads PADDLO and PADDLl during the
vertical blank. However, this time it stores the values in AUDFI and
AUDF2 which have been initialized for pure tones. This is a simple
program which we have left for you to disassemble. It makes use of a
timer register on page 0 (204) and reads the paddles every 10th vertical
blank. As written, the program addresses the Atari Touch Tablet and
needs to be modified for the Koala Pad by shortening the delay value
used in the timer.
In addition to the touch sensitive surface which inputs paddle
numbers, the digitizers have either two (Koala Pad) or three (Atari
Touch Tablet) switches. The status of these switches can be monitored
by reading the STICK or STRIG registers. Table 6-2 lists the ports to
read and the values produced when each switch is closed. Additionally,
the hardware and shadow registers for the STICK and STRIG ports
are listed.
Advanced Techniques 279
Table 6-2. Switch summa ry
Left Switch
Right Switch
Probe Switch
Left switch afld probe
Right switch and probe
Left and right switch
(x)
Kaola Pad
Value
Atari
Value
Stick( x)
Stick(x)
11
7
Stick(x)
- - - - ----
--
--------
--
--------
--
Stick(x)
11
7
14
10
6
3
Stick(x)
Stick(x)
Stick(x)
Stick(x)
Stick(x)
= depends on the game port used
STRIG
Shadow Register
Hardware Register
STRIG(O)
STRIG(1)
STRIG(2)
STRIG(3)
644
645
646
647
53264
53265
53266
53267
STICK(O)
STICK(1)
STICK(2)
STICK(3)
632
633
634
635
54016
54016
54017
54018
Bits
Bits
Bits
Bits
Do - 0 3
04 - 07
Do - 0 3
04 - 07
280 Atari Assembly Language Programmer's Guide
When writing programs that use digitizer pads, there are several
ways to regard them as input devices. One common way is to think of
the pad surface as the primary input source, and use the switches to
control program branching between different program segments that
process this input. Another way to use them is to partition the surface
into areas, each of which is associated with some program action. This
is the sort of programming that is done when you use the stylus to pick
an icon for paint or draw. Another way to look at them is to consider
the geometry involved. The pad can be thought of as a grid of
approximately 220 horizontal and 220 vertical lines. Where these lines
meet defines a point. The total number of points is approximately
48400. Each point is labelled with two numbers and since order is
important, each point can be distinguished from every other point.
Thus, in principle a digitizer pad can be used to input 48400 separate
pieces of information . Combine this with the switches and you can
input up to 242 ,000 pieces of information. Granted this is a rather
abstract way in which to regard the touch pads , but it is one with many
possibilities that have not yet been explored in any depth.
Appendix A
6502 Microprocessor Instruction Set
ADC
AND
ASl
BCC
BCS
BEQ
BIT
BMI
BNE
BPl
BRK
BVC
BVS
ClC
ClD
CLI
ClV
CMP
Add memory to Accumulator with carry
Logical "AND" of memory with Accumulator
Shift left one bit [Accumulator or memory]
Branch on carry clear
Branch on carry set
Branch on result equal to zero
Test bits in memory with Accumulator
Branch on result minus
Branch on result not equal to zero
Branch on result plus
Force Break
Branch on overflow clear
Branch on overflow set
Clear the carry flag
Clear decimal mode
Clear the interrupt disable bit
Clear the overflow flag
Compare memory and Accumulator
281
282 Atari Assembly Language Programmer's Guide
CPX
CPY
DEC
DEX
DEY
EOR
INC
INX
INY
JMP
JSR
LOA
LOX
LOY
LSR
NOP
ORA
PHA
PHP
PLA
PLP
ROL
ROR
RTI
RTS
sec
SEC
SED
SEI
STA
STX
STY
TAX
TAY
TSX
TXA
TXS
TYA
Compare memory and X-Register
Compare memory and Y-Register
Decrement memory by one
Decrement X-Register by one
Decrement Y-Register by one
Logical "Exclusive-OR", memory with Accumulator
Increment memory by one
Increment X-Register by one
Increment V-Register by one
Jump to new location
Jump to subroutine
Load the Accumulator
Load the X-Register
Load the V-Register
Shift right one bit [Accumulator or memory]
No operation
Logical "OR", Memory with Accumulator
Push Accumulator onto stack
Push Processor Status Register onto stack
Pull value from stack into Accumulator
Pull vlaue from stack into Processor Status
Rotate one bit left [Accumulator or Memory]
Rotate one bit right [Accumulator or Memory]
Return from interrupt
Return from subroutine
Subtract memory from Accumu lator with borrow
Set carry flag
Set decimal mode
Set interrupt disable
Store Accumulator in memory
Store X-Register in memory
Store Y -Register in memory
Transfer Accumulator to X-Register
Transfer Accumulator to Y-Register
Transfer Stack Pointer to X-Register
Transfer X-Register to Accumulator
Transfer X-Register to Stack Pointer
Transfer Y-Register to Accumulator
Appendix B
Acknowledgement: We thank D. Kassabian for writing the
disassembler and assembler programs that follow.
The assembler in Appendix B and the disassembler in Appendix
C are included to make your machine language programming easier.
They may be used as either stand alone utilities or in combination.
Both programs are written in a straight forward manner so that you
can modify them if you wish. They can be obtained by sending $20.00
to: Weber Systems Inc., Box 413, Gates Mills, OH 44040. Visa,
Mastercard and American Express are accepted.
The assembler begins by asking for a starting address . The most
common address to use is 1536 (page 6). However, for longer programs
you might want to lower RAMTOP before RUNing the program by
typing
POKE(106),PEEK(106)-8:GRAPHICS 0
and use pages 156 through 159 (39936-40960). Remember that you
need a buffer above RAMTOP since each time the screen is cleared the
OS clears beyond RAMTOP. The program will next give you the
option to continue , quit, list or print. If you choose to continue, an
input prompt is displayed on the screen. The input asked for is a string
283
284 Atari Assembly Language Programmer's Guide
of characters organized into five fields: mnemonic, prefix, data, data,
suffix. If the mnemonic doesn't require the full set of fields (for
example, R TS) , the program automatically pads out the input with
blanks.
The prompt on the screen defines the fields as follows:
MNE
PR
DAT
DAT SUF
t
1
1
Field
Field
Field
Field
Field
5
4
3
2
1
Spaces or any characters typed between the fields are ignored .
Once the input string is constructed it is broken down into its
components. These components are used to select the proper OP
CODE to go with the mnemonic. The program is relatively forgiving in
that it allows you two chances to edit your input. The first is right after
the initial input. The second opportunity to edit comes after the OP
CODE is determined and a summary has been displayed on the screen.
If the mnemonic entered does not correspond to a legal OP CODE, ???
is echoed back to the user and the input must be edited. Assembled
code can be either listed on the screen (L) or printed out by the printer
(P). This task can be done at any time and assembly continued
afterwards.
This is a simple single pass assembler and no provision has been
made for labels and relative branching. You can work around this by
using the assembler in conjunction with the disassembler and doing the
branching calculations yourself. The way to do this is to have both the
assembler and disassembler on the same disk saved under convenient
names such as ENCODE and DECODE respectively. Now suppose
you are assembling some code and come to a branch instruction. Enter
a 'dummy number' from 0 to 255 - one that you will easily recognize
-for the branch data. List the assembled code on the screen and write
down the address of the data number. Now continue on with assembly
until you reach a convenient stopping point or have finished. Then
Appendicies 285
"quit" the assembler and type RUN "D:DECODE". If you were
careful and stored your assembled code in a protected area of memory
such as page 6, the disassembler will load and run leaving your code
intact. You may use the disassembler to print out the assembly listing
from which you can quickly calculate the proper branching number.
All that remains is to POKE the correct branching number into the
address you wrote down. Just as you can run the disassembler from the
assembler you can return to assembly by typing RUN "D:ENCODE".
Just be sure to keep track of what your starting address should be.
Both the assembler and disassembler use standard notations to
indicate the addressing modes. These are as follows:
MNEMONIC + no data
addressing
= implied or accumulator
MNEMONIC + 1 data number = 0 page or relative
addressing
MNEMONIC + # data
= immediate addressing
MNEMONIC +2data numbers
=absolute addressing
MNEMONIC + 1 data,X = 0 page,X indexed
addressing
MNEMONIC + 1 data,Y
0 page,Y indexed
addressing
MNEMONIC + 2 data nos,X
addressing
= absolute,X indexed
MNEMONIC + 2 data nos,Y
addressing
= absolute,Y indexed
MNEMONIC+ (data,X)
=indexed indirect addressing
MNEMONIC + (data),Y
JSR + (
= indirect indexed
) = absolute indirect
286 Atari Assembly Language Programmer's Guide
APPENDIX B
ASSEMBLER
1000
10111'
1020
1030
1040
1~9~
REM SIMPLE INTERPRETATIVE ASSEMBLER
REM
OPEN .l,4,0,"K:"
OPEN .2,8,0,"S:"
DIM PRES(2),SUFS(3),CODES(19),ML(128),A$(1)
DIM SS(1),ANS$(1),MNS(3),DAT1$(3),DAT2S(3)
PRINT :PRINT "ENTER STARTING ADDRESS"
TRAP 1IZ'7~
INPUT ST
PcaT
11~~
Z-0:CODES"":DAT1-0:DAT2-~
10~~
107~
1~7~
1~B~
PRINT CHRS(12~)
112111 PRINT "PRESS (RETURN> TO CONTINUE":PRINT "PRESS [Q] TO
IiIUIT":PRINT "PRESS [Pl TO PRINT"
112~ PRINT "PRESS [Ll TO LIST"
113~ INPUT AS
114111 IF A'-"" THEN GOTO 117111
11~1II IFA "Q" THEN END
116111 IF A. .. P" OR A."L" THEN OOTO 163~
116~ GOTO 112f/J
117f/J PRINT CHR.(12~):POSITION 4,4:POKE 7~2,1
llB~ PRINT "MNE PR DAT DAT aUF
PC-", PC
119~ POSITION 4,6:PRINT .2, "?"
12~0 GET .1,S:S CHR.(S):ZZ+1
121~ POSITION 3+Z,6:PRINT .2,SS
122~ CODES(LEN(CODES)+1)-S$
1230 IF Z.19 THEN GOTO 1290
1240 IF Z(19 AND as.CHR.(1~~) THEN GO TO 126~
12~" POSITION 4+Z,6:PRINT .2,"?":GOTO 12~~
126~ FOR I.LEN(CODE.) TO 18
127~ CODES(I,I)-" "
12B~ NEXT I
1290 POSITION 4,B:PRINT .2, "CHANGE ?? (YIN)"
13~0 INPUT ANS$
131~ IF ANSS"Y" THEN GOTO 110111
1320 IF ANS .... N" THEN GOTO 134111
1330 GOT a 129111
134111 MNS.CODES(l,3):PRES-CODES(~,6)
13~0 DAT1SCODES(S,10):DAT2S-CODE$(12,14)
1360 SUF CODES(16,1B)
13'70 IF DATU."
"AND DAT2$-"
"THEN DC'"I1I:GOTO 141110
13B0 IF DATU< >"
"AND DAT2$-"
"THEN DC-l: GOTO 1400
1390 DC-2
1400 GOSUB 1900
1410 PRINT CHR$(12~)
1420 PRINT :PRINT
143111 POKE 7~2,0
1440 PRINT "MNEMONIC:
",MNS;"
"; "!liP CODE:
";OP
1450 PRINT "ADDR MODE: "IPRES;" ";SUFS
1460 PRINT "DATA CNT:
";DC
111~
Appendicies 287
1470 PRINT "DATA:
"; DATlS; " II;DAT2S
148121 "PRINT :PRINT
149121 PRINT "THIS WILL BE ENTERED AT: ";PC
1:5111121 PRINT
1:51111 PRINT "PRESS RETURN TO CONTINUE, 'E' TO EDIT"
1:52121 INPUT A.
1:53121 IF A.-"" THEN GO TO 1:56121
1:54121 IF A.-"E" THEN GOTO 11111121
1:5:5121 GOTO 1:51~
1:5:5:5 REM **POKE PROGRAM INTO MEMORY**
1:56121 TRAP 1441ZJ
.. THEN DATl-VAL (DATa)
1:57121 IF DATl.< >"
.. THEN DAT2-VAL(DAT2.)
1:57:5 IF DAT2.<>"
1:58121 POKE PC,OP
1:59121 IF DATa<>"
" THEN PC=PC+l:POKE PC, DATI
.. THEN PC-PC+I:POKE PC,DAT2
1618 IF DAT2.<>"
1618 PC-PC+l
162111 130 TO 111118
163111 REM **PRINT OUT**
163:5 IF A "P" THEN OPEN .3,8,/ll,"P:"
164111 FOR I-ST TO PC-l:X-PEEK(I)
16:5111 IF A "P" THEN PRINT .3ixl:PRINT .31 ", "I
16:5:5 IF A "L" THEN PRINT II" : "IX
166. NEXT I
166:5 IF A "P" THEN CLOSE .3:LPRINT
167111 IF A.-"L" THEN PRINT "PRESS CRETURNJ":INPUT A.
1688 GOTO 111111
191. REM **STANDARDIZE PRE. AND SUF.**
1918 IF PRE.-" ... THEN PRE.-". "
1921 IF SUF " ,X" THEN SUF.-",X "
193111 IF SUF." ,Y" THEN SUF.-",Y "
1948 IF SUF." ) .. OR SUF.-" )" THEN SUF$"")
21111111 REM **LOOK-UP TABLE**
281111 IF MN."STA" AND DC-I AND SUF ... " , X) " THEN OP .. 129:GOTO
361111
" THEN OP-132:GOTO
21212111 IF MN$-"STY" AND DC-l AND SUF.""
361111
" THEN OP"133:GOTO
211138 IF MN.-"STA" AND DC-1 AND SUF.="
36/ll121
" THEN OP=-134:GOTO
21114111 IF MN.-"STX" AND DC-1 AND SUF.="
36/ll121
211.1:5121 IF MN."DEY" AND DC-III THEN OP-136:GOTO 3600
21116121 IF MN."TXA" AND DC-IZJ THEN OP-138:GOTO 361210
21217121 IF MN."STY" AND DC-2 THEN OP-141ZJ:GOTO 3600
"THEN OP=141:GOTO
21118121 IF MN."STA" AND DC-2 AND SUF.....
36111111
21119121 IF MN ..... STX" AND DC-2 THEN OP"'142:GOTO 3600
211111ZJ IF MN.="BCC" THEN OP-144:GOTO 3600
211121 IF MN."STA" AND DC-I AND SUF.="),Y" THEN OP=145:GOTO
361111ZJ
2120 IF MN.-"STY" AND DC"1 AND SUF.=",X " THEN OP-148:GOTO
361110
213111 IF MN ... "STA" AND DC=1 AND SUF.=",X " THEN OP=149:GOTO
3600
288 Atari Assembly Language Programme(s Guide
2140 IF MN.="STX"
3600
2150 IF MN$="TYA"
2160 IF MN$=-"STA"
36"121
217121 IF MN.=-"TXS"
218" IF MN.-"STA"
360121
219121 IF MN.-"LDY"
36"0
22"" IF MN'-"LDA"
36""
221" IF MNt-"LDX"
222" IF MN.-"LDY"
OP-164:GOTD 36121121
223" IF MN.-"LDA"
OP-165:GOTO 36"121
224" IF MNt-"LDX"
OP-166:GOTO 36""
225" IF MNt-"TAY"
226" IF MNt-"LDA"
227" IF MNt-"TAX"
228" IF MNt-"LDY"
36""
229" IF MNt-"LDA"
36""
23121" IF MNt""LDX"
36""
231" IF MN. .. BCS"
2320 IF MNt-"LDA"
360"
233" IF MN.-"LDY"
3600
234" IF MN.-"LDA"
36"0
235" IF MN.-"LDX"
360121
236" IF MN.""CLV"
2370 IF MNt-"LDA"
3600
238" IF MN.="TSX"
2390 IF MN.-"LDY"
361210
24121" IF MN."'''LDA''
36121"
2410 IF MN.="LDX"
36121121
2420 IF MN.="CPY"
243121 IF MN.'" "CMP ",
36121121
244" IF MN.="CPY"
OP-196:GOTO 361210
2450 IF MN."'''CMP''
OP=197~GOTO 3600
AND DC=l AND SUF.=" ,Y " THEN DP=150:GDTD
AND DC=12I THEN OP-l~2:GOTD 3600
AND DC-2 AND SUF.-",Y " THEN DP-153:GOTO
AND DC-I2I THEN OP-154:GOTO 36121~
AND DC"2 AND SUF'E" , X " THEN OP-157:,GOTO
AND DC-l AND PRE ...... " THEN OP-16":GDTO
AND DC-l AND SUFt- .. , Xl " THEN OP-161:GOTO
..
AND PREt-".
THEN OP-162:GOTO 36"121
AND DC-l AND PRE.-". " AND SUFt-"
" THEN
AND DC-l AND PRE.-"
" AND SUF.-"
" l'HEN
AND DC-l AND PREt- ...
..
" THEN
AND
AND
AND
AND
AND SUFt- ..
DC-" THEN OP-168:GOTO 36"0
PREt-". " THEN OP-169:GOTO 36""
DC-" THEN OP-17":GOTO 36""
DC-2 AND SUFt- ..
" THEN OP-172:GOTO
AND DC-2 AND SUFt-"
" THEN OP-173:GOTO
AND DC-2 AND SUF.-"
" THEN OP"174:GDTO
AND DC-" THEN OP-176:GOTO 3600
AND DC-l AND SUF.-"I,Y" THEN OP-177:GOTO
AND DC-l AND SUF.-",X " THEN OP-180:GOTD
AND DC-l AND SUF.-", X
THEN OP-181:GOTO
AND DC-l AND SUF.-",Y " THEN OP"182:GOTO
AND DC-0 THEN OP-184:GOTO 3600
AND DC-2 AND SUF."",Y " THEN OP=185:GOTO
AND DC-" THEN OP-186:GDTO 361210
AND DC-2 AND SUF."" , X " THEN OP-188:GOTO
AND DC-2 AND SUF.-", X " THEN OP-189:GDTD
AND DC=-2 AND SUF.-",Y " THEN DP=19121:GDTD
AND PRE.",". " THEN OP-192:GOTO 3600
AND DC-l AND SUF.-",X'" THEN DP=193:GDTO
AND DC"l AND PRE."'''.
AND DC"'! AND PRE.= ....
..
AND SUF.="
" THEN
AND SUF.="
..
THEN
Appendicies 289
246121
36130
2470
2480
249t11
2:5"tII
2:51t11
36"tII
2:52t11
36"tII
2:53/11
2:54/11
36
2:5:5/11
36"0
2:56/11
36111/11
2:578
2:58l1li
IF MNS"'''DEC'' AND DC"l AND SUFS="
IF
IF
IF
IF
IF
MNS""INY"
MN$-"CMP"
MNS-"DEX"
MN$-"CPY"
MN$-"CMP"
AND
AND
AND
AND
AND
" THEN OP=l98:GOTO
DC.,12I THEN OP-200:GOTO 361210
PRE.-". " THEN OP-201:GOTO 36121121
DC-! THEN OP-202:GOTO 3600
DC-2 THEN OP m 2"4:GOTO 3600
DC-2 AND SUFS-"
"THEN OP"'2I21S:GOTO
IF MN$-"DEC" AND DC-2 AND SUFS-"
" THEN OP-206:GOTO
IF MN$-"BNE" THEN OP-2t118:GOTO 360t11
IF I1N$-"CI1P" AND DC-l AND SUF$-"),Y" THEN OP-2t119:GOTO
IF I1N$-"CMP" AND DC-I AND SUF'.-",X " THEN OP-213:GOTO
IF MN$-"DEC" AND DC-I AND SUF$-",X " THEN OP-214:GOTO
IF MN$-"CLD" AND DC-til THEN OP-216:GOTO 36t11t11
IF I1N$-"CI'IP" AND DC-2 AND SUF$-",Y " THEN OP-217:GOTO
368
2:59. IF MN$-"C/'1P" AND DC-2 AND SUF$-",X " THEN OP-221:GOTO
36H
26 IF I1N$-"DEC"
361.
261. IF MN$-;'CPX"
262t11 ~F MN$-"SBC"
36"l1li
263" IF I1N$-"CPX"
OP-228:GOTO 36"0
264" IF MN$-"SlBC"
OP-229: GOTO 36111"
26:5l1li IF MN$-"INC"
361118
266l1li IF MN$-"INX"
267l1li IF MN$-"SBC"
268l1li IF I1N$-"NOP"
269" IF I1N$-"CPX"
27"tII IF MN.-"SBC"
36"0
271t11 IF MN$-"INC"
36121t11
272" IF MN$-"BEQ"
273J1 IF MN$ .. "SBC"
36"tII
274t11 IF MNS-"SBC"
361210
27:5121 IF MN.-"INC"
361210
2760 IF MNS","SED"
277121 IF MNS-"SBC"
361ill1'
278r!1 IF MNS-"SBC"
361210
27911l IF MNS-"INC"
AND DC-2 AND aUF$-" , X " THEN OP-222:GOTO
AND PRE$-". " THEN OP-224: GOTO 36t110
AND DC-I AND SUF$-",X)" THEN OP-22:5:GOTO
AND DC-I AND PRES-". " AND SUF$-"
" THEN
AND DC-l AND PRES-". " AND SUF.="
" THEN
AND DC-I AND SUF ... "
AND
AND
AND
AND
AND
" THEN OP"23121:GOTO
DC-til THEN OP-232:GOTO 36t110
PRE.-". THEN OP-233:GOTO 360121
DC-I2I THEN OP-234:GOTO 361210
DC-2 THEN OP-236:GOTO 360"
DC-2 AND SUF.-"
"THEN OP"'237:GOTO
AND DC-2 AND SUFS="
" THEN OP-238:GOTO
AND DC-1 THEN OP-240:GOTO 3600
AND DC-I AND SUFS-"),Y" THEN OP"241:GOTO
AND DC-I AND SUFS-",X " THEN OP-24:5:GOTO
AND DC-l AND SUF.=",X " THEN OP=246:GOTO
AND DC"11I THEN OP=248: GOTO 36r1:l0
AND DC-2 AND SUFS-",Y " THEN OP=249:GOTO
AND DC"'2 AND SUFS=",X " THEN OP-2:53:GOTO
AND DC=2 AND SUFS=",X " THEN OP=254:GOTO
290 Atari Assembly Language Programme(s Guide
361/.1~1
280'" IF MN$="8RK"
2810 IF MN$"'''ORA''
2820 IF MN$="ORA"
283" IF MNS""ASL"
2840 IF MN.="PHP"
28:50 IF MN$ .. "ORA"
2861!J IF MN$ .. "ASL"
287f2! IF MN ... "ORA"
36"0
2880 IF MN$-"ASL"
36f/:10
2890 IF MN.-"BPL"
291210 IF MNS .. "ORA"
2910 IF MNS-"ORA"
36f/:10
292111 IF MNs-"ASL"
36f/:10
293111 IF MNs-"CLC"
2940 IF MNS-"ORA"
36f/:10
29:5/11 IF MNS-"ORA"
36121121
296111 IF MNS .. "ASL"
36/11/11
297f2! ~F MNs="JSR"
298121 IF MN.-"AND"
360111
2990 IF MN.-"BIT"
30f/:10 IF MN$ .. "AND"
OP-37:GOTO 36013
3f/:110 IF MN.-"ROL"
36f/:1f2!
302" IF MNS-"PLP"
303f2! IF MNS.. "AND"
3040 IF MN ... "ROL"
30:50 IF MN$","BIT"
3060 IF MN$="AND"
3600
3070 IF MN$="ROL"
3600
3f2!80 IF MN$="BMI"
309f2! IF MNS .. "AND"
36f2!0
311210 IF MN$="AND"
36f2!0
3110 IF MN$="ROL"
36f2!1ZI
312" IF MNS="SEC"
3130 IF MNS""AND"
36f2!0
3140 IF MN$="AND"
361210
31512' IF MN$="ROL"
AND
AND
AND
AND
AND
AND
AND
AND
DC"f2! THEN OP="':GOTO 3601~
DC=-l AND SUF$=",X)" THEN OP=l GO TO 36f211~
DC=l AND SUF.""
" THEN op-s GOTO 3600
DC=l AND SUF$ .. "
" THEN OP=6 GOTO 3600
DC-f2! THEN OP-8:GOTO 36f2!0
PRE$-"" " THEN OP-9:GOTO 3600
DC'"'f2! THEN OP-10:S0TO 360f2!
DC-2 AND SUFs-"
" THEN OP-13: GO TO
AND DC"2 AND SUFs-"
" THEN OP-14:GOTO
AND DC-I2I THEN OP-16:GOTO 3600
AND DC-l AND SUF.. -") Y" THEN OP-17: SOTO 361~0
AND DC-l AND SUFS-'), X " THEN OP=21:GOTO
AND DC-l AND SUFS-",X " THEN OP"22:GOTO
AND DC-I2I THEN OP-24:GOTO 3600
AND DC-2 AND SUFS-",Y " THEN OP-2:5:GOTO
AND DC-2 AND SUF.-" , X " THEN OP-29:GOTO
AND DC-2 AND SUF.-" , X " THEN OP-30:S0TO
AND Dc .. f2! THEN OP-32:GOTO 36f2!0
AND DC-l AND SUF."" , X) " THEN OP"33:GOTO
AND DC-I THEN OP-36:GOTO 361!Jf2!
AND DC-l AND PREs-"" " AND SUF.="
AND DC-l AND SUFS-"
AND
AND
AND
AND
AND
" THEN
" THEN OP"38:GOTO
DC-f2! THEN OP-4f2!:GOTO 3600
PRES-".
THEN OP-41:GOTO 36"'"
DC-I2I THEN OP-42:GOTO 3600
DC-2 THEN OP-44:GOTO 3600
DC"'2 AND SUFs="
" THEN OP=45:GOTO
H
AND DC=2 AND SUF.=-"
" THEN OP=46:GOTO
AND DC-0 THEN OP-48:GOTO 3600
AND DC-l AND SUF.-"l,Y" THEN OP=49:GOTO
AND DC-l AND SUF$=-" , X " THEN OP=53:GOTO
AND DC=1 AND SUF$=",X " THEN OP=54:GOTO
AND DC=0 THEN OP=56:GOTO 3600
AND DC=2 AND SUFS=",Y " THEN OP=57:GOTO
AND DC=2 AND SUF$=",X " THEN OP=61:GOTO
AND DC=2 AND SUF$=",X " THEN OP=62:GOTO
Appendicies 291
3600
3160 IF MN$="RTI" AND DC=l~ THEN OP=64: GO TO 361~1'
3170 IF MN$="EOR" AND DC=l AND SUF$=",X)" THEN OP=65:GOTO
36121121
3180 IF MN$="EOR" AND DC=l AND SUF$="
" THEN OP=69:GOTO
360121
" THEN OP=70:GOTO
3190 IF MN$="LSR" AND DC=l AND SUF$="
3611111)
3200 IF MNt-"PHA" AND DC"0 THEN OP=72:GOTO 360~
3210 IF MN$-"EOR" AND PRE$=". " THEN OP=73:GOTO 3600
32211.1 IF MNt-"LSR" AND DC=0 THEN OP=74: GOTO 36121121
3230 IF MNt-"JMP" AND DCz2 AND SUFS="
"THEN OP=76:GOTO
3600
3240 IF MNS-"LSR" AND DC-2 AND SUF$~"
"THEN OP=78:GOTO
3600
32:50 IF MNt-"BVC" AND DC"111 THEN OP'"80:GOTO 3600
32611.1 IF MNt-"EOR" AND DC-l AND SUF$;"""), Y" THEN OP e 81: GOTO
36111111
32711.1 IF MNt-"EOR" AND DC-l AND SUFS-",X " THEN OP-85:GOTO
3600
328' IF MNt-"LSR" AND DC-l AND SUFS-", X " THEN OP=86:GOTO
361110
32911.1 IF MNt-"CLI" AND DC-11l THEN OP=88:GOTO 36111~
3300 IF MNt-"EOR" AND DC-2 AND SUFt-",Y " THEN OP"89:GOTO
360f.1
33UJI IF MlI!t-"EOR" AND DC-2 AND SUFS-", X " THEN OP-93: GOTO
360111
3320 ~F MNt-"LSR" AND DC-2 AND SUF$=" , X " THEN OP=94:GOTO
3600
33411.1 IF MNt-"RTS" AND DC-III THEN OP"96:GOTO 360111
33:50 IF MNt."ADC" AND DC-l AND SUF$=",X)" THEN OP=97:GOTO
3600
336' IF MNt-"ADC" AND DC"l AND PRES-". " AND SUFt"'''
"THEN
OP-101:GOTO 360121
337111 IF MNS-"ROR" AND DC-l THEN OP .. 102:GOTO 3600
3380 IF MNt-"PLA" AND DC-0 THEN OP"'104:GOTO 3600
3390 IF MNt-"ADC" AND PREt-". " THEN OP-10:5: GOTO 361iJ12I
3400 IF MNt-"ROR" AND DC-0 THEN OP"106:GOTO 3600
3411' IF MNt-"JMP" AND DC-2 AND SUFt"''')
"THEN OP-=108: GO TO
360111
3420 IF MN$="ADC" AND DC=2 AND SUF$="
"THEN OP=109:GOTO
36111111
343111 IF MNS="BVS" AND DC=III THEN OP=112: GOTO 36fi)0
3440 IF MNt="ADC" AND DC=l AND SUF$="),Y" THEN OP=113:GOTO
3600
34:50 IF MNt-"ADC" AND DC"l AND SUFt=" , X " THEN OP"117:GOTO
361110
3460 IF MNS="ROR" AND DC-l AND SUF$=", X " THEN 118: GOTO 361210
3470 IF MN$="SEI" AND DC=0 THEN OP=120:GOTO 3600
3480 IF MNt="ADC" AND DC=2 AND SUF$=",Y " THEN OP=121:GOTO
3600
3490 IF MN$-"ADC" AND DC=2 AND SUF$=",X " THEN OP=125:GOTO
3600
3:500 IF MNS="ROR" AND DC=2 AND SUF$=",X " THEN OP=126:GOTO
3600
3:510 MN$="???":OP=666:GOT0360i!1
3600 RETURN
Appendix C
BASIC Disassembler
The BASIC disassembler is an example of a simple look-up table
translator. By PEEKing consecutive memory locations and comparing
their contents to the OP CODES of the 6502 instruction set, it is able to
generate a list of mnemonics and operands. Operand is a general term
used to refer to the addresses or data numbers following an OP CODE.
As mentioned in the previous appendix, the disassembler can be used
in conjunction with the assembler or, to disassemble someone else's
machine language routine. To use the disassembler in this manner you
should add the following lines to the beginning of the program:
100 FOR 1=10 TO NUMBER
120 READ ML:POKE MEMORY+I,ML
130
140
150
160
NEXT 1
REM DATA NUMBERS HERE
REM DATA NUMBERS HERE
REM DATA NUMBERS HERE
293
294 Atari Assembly Language Programmer's Guide
NUMBER in line 100 is 1 less than the total data numbers in the
program you are disassembling. MEMORY in line 120 is the place
where you want to store the data numbers. This is usually page 6
(1536), but you could store them above RAMTOP. If that is your
choice add lines:
80 POKE 106,PEEK(106)-8
90 GRAPHICS 0
to lower RAMTOP eight pages and set NUMBER accordingly. If you
do this keep in mind that each clear screen call wipes out memory
above RAMTOP, so leave a buffer.
The program allows you to print out the disassembled code that
has been displayed on the screen. The line that allows this is:
100PEN#2,5,0,"E:"
This is a forced read command and must be used with some care. It
should precede all other lines in the program.
When you run this program you will find that the addresses are
listed in hexadecimal. In this book we have not made use of hex
numbers beyond the introduction to number systems in chapter one.
That was a deliberate choice on our part since all of the machine
language routines we have discussed were meant to be called by
BASIC, and BASIC requires decimal numbers. However, many
programmers use hexadecimal numbers and so it is useful to become
familiar with them. By exposing you to hex numbers here we believe
that you can begin to get used to them without being forced into
innumerable conversions between number systems. Of course, if you
wish, you can modify the program to output the addresses in decimal.
Appendicies 295
APPENDIX C
4000
41211121
4020
412130
412140
412150
411J611J
4070
411J811J
411J911J
4111J11J
41111J
4120
4130
41411J
4150
41611J
41711J
4180
4190
4211J11J
4210
42211J
42311.1
4240
42:511.1
42611J
4270
42811J
42911.1
4300
4310
43211J
4330
43411J
4350
43611J
43711J
438121
43911J
4412111.1
44111J
44211J
44311J
444121
44!5121
446121
44711J
448121
4490
450121
451111
OPEN #2,5,0,"E:"
REM DISASSEMBLER VERSION 1.0
REM
PRINT CHR$ (125)
REM
DIM HEX$(16),AS(5),ADDR$(5),PRE$(2),SUF$(3),LINE$(120)
DIM MNS(3),OP$(3),B$(1),HEX2$(1),HEX3$(1),HEX4$C1)
HEXS .. "12I123456789ABCDEF"
PRINT
PRINT "6502 IN-MEMORY DISASSEMBLER"
PRINT
PRINT
REM
PRINT "ENTER STARTING ADDRESS IN DECIMAL"
INPUT AS
IF AS-"" THEN END
A-VAL CAs)
PRINT CHRs C125)
PRINT
PRINT" ADDR
MNEM
OP CODE
DATA"
PRINT
REM DISPLAY ONLY 18 LINES AT A TIME
CNT--1:LINE--1
eNT-CNT+1:LINE=LINE+1
IF LINE-18 THEN GOTO 4470
ADDR-CNT+A
BOSUS 4550
REM READ MEMORY
P-PEEKCADDR)
OPS-STRSCP)
MNS-"???":PRE$=" ":SUFs="
DC-IIJ:R-II.I:RL=11J
B06US 46711J
REM PRINTOUT SECTION
IF DC-1 THEN GOTO 4380
IF DC-2 THEN GOTO 441121
PRINT" "IADDRs;"
";MN$;"
";OP$
ADDRS-"":GOTO 4230
PRINT" ";ADDR$;"
";MN$;"
";OPS;"
";PRE$;
CNT-CNT+1:ADDR~CNT+A:DTA=PEEKCADDR):PRINT DTA;SUF$
ADDRS-"":GOTO 4230
";PRE$;
PRINT" "IADDR$;"
";MNS; '"
";OP$;"
CNT=CNT+1:ADDR=CNT+A:DTA=PEEKCADDR)
PRINT DTA;
CNT=CNT+1:ADDR=CNT+A:DTA=PEEKCADDR)
PRINT ", "; DTA; SUF$
ADDRS=" " : GO TO 4231~
REM PAUSE SECTION
P FOR PRINT"
' N' FOR NEXT
PRINT "( RETURN > TO END
TRAP 4500
INPUT B.
IF BS="" THEN END
296 Atari Assembly Language Programmer's Guide
4520
4530
4540
4550
IF BS=" N" THEN A=ADDR+ 1 : GOTO 41 71~
IF BS="P" THEN GOTO 619121
GOTO 44819
HEX1=INT(ADDR/4096)
456~ ADDR$=HEX$(HEX1+1,HEX1+1)
4570 HEX2=INTADDR-HEX1*4096)/256)
458~ HEX2$=HEX$(HEX2+1,HEX2+1)
459~ ADDR$(LEN(ADDRS)+1)=HEX2S
46~~ HEX3=INTADDR-HEX1*4096-HEX2*256)/16)
4610 HEX3$-HEX$(HEX3+1,HEX3+1)
462~
ADDR$(LEN(ADDR$)+1)~HEX3$
463~
HEX4mINT(ADDR-HEX1*4~96-HEX2*256-HEX3*16)
HEX4$=HEXS(HEX4+1,HEX4+1)
465~ ADDR$(LEN(ADDRS)+1)-HEX4$
466~ RETURN
4670 REM LOOK-UP TABLE
468~ IF P-129 THEN MN$="STA":DC ml:PRE$"'''
(":SUF$-",X)":GOTO
6180
4690 IF P-132 THEN MNS""STY":DC-l:GOTO 6180
471211Z' IF P-133 THEN MN$""STA":DC-1:GOTO 6180
471121 IF P-134 THEN MN$-"STX":DC-l:GOTO 6180
472121 IF P-136 THEN MN$""DEY":GOTO 6180
473121 IF P-138 THEN MN$="TXA":GOTO 618~
474121 IF P-140 THEN MN$-"STY":DC-2:GOTO 6180
47:5121 IF P-141 THEN MN$-"STA":DC-2:GOTO 618~
4760 IF P-142 THEN MN$-="STX":DC-2:GOTO 6180
4770 IF P"144 THEN MN$-"BCC":DC-l:GOTO 6180
4780 IF P-145 THEN MN$-"STA":DC-l:PRE$-" (":SUF$-"),Y":GOTO
6180
4790 IF P .. 148 THEN MNS="STY":DC-l:SUFS-",X ":GOTO 6181~
4800 IF P-149 THEN MN$-"STA":DC-l:SUFS-",X ":GOTO 618121
48U' IF P-l:5121 THEN MNS-"STX":DC-l:SUFS-",Y ":GOTO 6180
4820 IF P"1:52 THEN MN$-"TYA":GOTO 6180
4830 IF P"153 THEN MN$-"STA":DC-2:SUF$"",Y "
4840 IF P-154 THEN MN$-"TXS":GOTO 6180
4850 IF P-l:57 THEN MN$""STA":DC-2:SUFS=",X ":GOTO 6180
4860 IF P-160 THEN MNS="LDY":DC-=l:PRES-"* ":GOTO 6180
4870 IF P-161 THEN MNS="LDA":DC"'l:PRE$=" (":SUFS=",X) ":GOTO
6180
4880 IF P=162 THEN MN$="LDX":DC=l:PRE$="* ":GOTO 6180
4890 IF P=164 THEN MN$="LDY":DC-1:GOTO 6180
4900 IF P=165 THEN MN$="LDA":DC=1:GOTO 6180
4910 IF P"166 THEN MN$="LDX":DC-1:GOTO 6180
4920 IF P=168 THEN MNS="TAY":GOTO 6180
4930 IF P=169 THEN MN$="LDA":DC-=1:PRE$="# ":GOTO 6180
4940 IF P=170 THEN MN$="TAX":GOTO 6180
4950 IF P=172 THEN MN$="LDY":DC-2:GOTO 6180
4960 IF P=173 THEN MN$="LDA":DC=2:GOTO 6181~
4970 IF P=174 THEN MN$="LDX":DC=2:GOTO 6180
4980 IF P=176 THEN MN$="BCS":DC=1:GOTO 6180
4990 IF P=177 THEN MN$="LriA":DC=1:PRE$=" (":SUFS="),Y":GOTO
6180
51111210 IF P=180 THEN MNS="LDY":DC=l:SUF$=",X ":GOTO 618(1)
5010 IF P=181 THEN MNS="LDA": DC=l: SUF$=". X ": GOTO 618f!I
464~
Appendicies 297
502'11 IF
503~1 IF
510410 IF
5105~1 IF
512'60 IF
5070 IF
5080 IF
5090 IF
5100 IF
6180
5110 IF
5120 IF
5130 IF
5140 IF
~150 IF
5160 IF
5170 IF
5180 IF
519. IF
520121 IF
521111 IF
618111
5220 IF
523111 IF
524111 IF
5250 I.F
52611.1 IF
5270 IF
5280 IF
5290 IF
6180
5300 IF
5310 IF
5320 IF
5330 IF
5340 IF
5350 IF
5360 IF
53712' IF
53812' IF
5390 IF
541210 IF
61812'
541117 IF
54212' IF
54310 IF
54412' IF
54510 IF
5460 IF
5470 IF
:5480 IF
618117
5490 IF
55f!'!!} IF
P=182
P=184
P=185
P=186
P=188
P=189
P=-190
P=192
P=193
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
MN$="LDX":DC=l:SUF$=",Y ":GOTO 6181,
MN$="CLV":GOTO 6180
MN$="LDA":DC=2:SUF$=",Y ":GOTO 6180
MN$="TSX":GOTO 6180
MN$="LDY":DC=2:SUF$=", X ":GOTO 6180
MN$="LDA":DC=2:SUF$=",X ":GOTO 61810
MNS="LDX":DC=2:SUFS-",Y ":GOTO 6180
MN$="CPY":DC=1:PRE$="tI ":GOTO 6180
MNS="CMP":DC=l:PRE$z" (":SUF$=",X)":GOTO
p c 196
P"197
P"198
P=200
P"21171
P"21172
P=204
P-21215
P-21216
P"208
P-21219
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
MNS-"CPY":DC~l:GOTO 6180
MN$""CMP":DC"l:GOTO 6180
MNS-"DEC":DC=l:GOTO 61811.1
MN$=" I NY" : GOTO '618.0
MN$="CMP":DC=1:PRES-"tI ":GOTO 618117
MN$="DEX":GOTO 6180
MNS-"CPY":DC=2:GOTO 618121
MNS""CMP":DC"2:GOTO 6180
MNs-"DEC":DC-2:GOTO 6180
MNS-"BNE":DC-1:GOTO 618121
MNS="CMP":DC=l:PRES=" (":SUF.-"),Y":GOTO
P-213
P-214
P-216
P-217
P-221
P-222
P=224
P"'225
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
MNS="CMP":DC"'l:SUFS-",X ":GOTO 618111
MNS-"DEC":DC-1:SUFS-",X ": GOrO 618121
MN$="CLD":GOTO 618121
MNS="CMP":DC=2:SUF$-",Y ":GOTO 6180
MNS""CMP":DC-2:SUFS-",X ":GOTO 618121
MNS="DEC":DC=2:SUFS-", X ":GOTO 61810
MN$="CPX":DC=l:PRES="tt ":GOTO 618121
MNS="SBC":DC=1:PRE$=" (":SUF$=",X)":GOTO
P=228
P-229
P-23121
P-232
P=233
P=234
P=236
P=237
P=238
P=240
P=241
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
MN$="CPX":DC-1:GOTO 6180
MNS="SBC":DC-1:GOTO 6180
MN$-"INC":DC-1:GOTO 618121
MN$-"INX":GOTO 618121
MN$="SBC":DC-1:PRES-"tt ":GOTO 6180
MNS="NOP":GOTO 618121
MNS="CPX":DC=2:GOTO 6180
MN$="SBC":DC=2:GOTO 61812'
MN$="INC":DC=2:GOTO 6180
MN$="BEQ":DC=l:GOTO 61812'
MNS="SBC":DC=1:PRE$=" (":SUF$="),Y":GOTO
P=245 THEN MN$="SBC":DC=1:SUF$=",X ":GOTO 618117
P=246 THEN MN$="INC":DC=1:SUF$-",X ":GOTO 6180
P=248 THEN MN$="SED":GOTO 6180
P=249 THEN MN$="SBC":DC=2:SUF$=",Y ":GOTO 6180
P=253 THEN MN$="SBC":DC=2:SUF$=",X ":GOTO 6180
P=254 THEN MN$="INC":DC=2:SUF$=",X ":GOTO 6181~
P=0 THEN MN$="BRK":GOTO 6181~
P=l THEN MN$="ORA" :'DC=l: PRE$=" ( " : SUF$=" , X) " : GOTO
P=5 THEN MN$="ORA":DC=l:GOTO 6181~
P=6 THEN MN$="ASL":DC=l:GOTO 6180
298 Atari Assembly Language Programmer's Guide
5511~
552@
5530
5540
5550
5560
557111
6180
5580
5590
5600
561111
5620
5630
5640
5650
618111
5660
5670
5680
5690
5700
5710
5720
5730
5740
5751J
5760
6180
577111
578111
579111
581110
5810
582111
5830
584111
6180
585el
5860
587117
5880
5890
59117117
5910
5920
5930
6180
5940
5950
596el
5970
5980
5990
IF
IF
IF
IF
IF
IF
IF
P=8 THEN MN$="PHP:GOTO 4 1,1 iii 13 "
P=9 THEN MN$="ORA":DC=1:PRE$="* ":GOTO 6180
P=10 THEN MN$="ASL:GOTO 400~1"
P=13 THEN MN$:"ORA":DC=2 : GOTO 6180
P-14 THEN MN$="ASL":DC= 2 :GOTO 6180
P'"'16 THEN MNS="BPL":DC=1:GOTO 61812'
P=17 THEN MN$-"ORA" : DC=1:PRE $ =" (":SUFS="l,Y":GOTO
IF
IF
IF
IF
IF
IF
IF
IF
P"21
P-22
P-24
P-25
P"29
P-30
P-32
P-33
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
MN$="ORA":DC- 1:SUF$=",X
MNSc"ASL":DC = l:SUFS=",X
MNS-"CLC":GOTO 6180
MNS""ORA":DC=2:SUF$=",Y
MNS:"ORA":DC-2:SUFS-",X '
IF
IF
IF
IF
IF
IF
IF
IF
IF
IF
IF
P-36
P-37
P-38
P-4111
P-41
P-42
P-44
P-45
P-46
P-48
P-49
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
THEN
MNS-"BIT":DC-1:GOTO 6180
MNS-"AND":DC-1:GOTO 6180
MNS-"ROL":DC-l:GOTO 6180
MNS-"PLP":GOTO 6180
MNS-"AND":DC-1:PRE$a:"4t ":GOTO 6180
MNS"ROL":GOTO 6180
MNS-"BIT":DC-2:GOTO 61813
MNS-"AND":DC-2:GOTO 6180
MNS"ROL": DC=2: GO TO 6180
MNS-"BMI":DC-l:S0TO 6180
MNS-"AND":DC-l:PRE$-" ( " : SUFS=" l , Y" : GO TO
IF
IF
IF
IF
IF
, IF
IF
IF
P-53
P-54
P-56
P-57
P-il1
THEN
THEN
THEN
THEN
THEN
P~62 THEN
P-64 THEN
P-65 THEN
MNS="AND":DC"'1:SUF$=",X ":GOTO 6180
MN$-"ROL":DC-1:SUFS=",X":GOTO 6180
MNSa"SEC":SOTO 6180
MNS-"AND":DC-2:SUF$-",Y ":GOTO 6180
MNS-"AND":DC-2:SUFS=",X ":GOTO 61812J
MN~-"ROL":DC-2:SUFS=".X ":GOTO 618117
MNS"'"RTI":GOTO 618el
MNS-"EOR":DC-1:PRES-" (":SUF$=",Xl":GOTO
MNS:"ASL":DC - ~:SUFS=",X
":GOTO 6181~
":GOTO 61812'
":GOTO 6180
":GOTO 6180
":GOTO 6180
MNS-"JSR":DC-2:GOTO 6180
MNS-"AND": DC'"' 1: PRE$=" ( " : SUF$=" , x l
":GOTO
IF
IF
IF
IF
IF
IF
IF
IF
IF
P-69 THEN MN$="EOR":DC=1:GOTO 6180
P-7el THEN MNS-"LSR":DC-l:GOTO 6180
P=72 THEN MNS="PHA":GOTO 6180
P-73 THEN MN$="EOR":DC=1:PRE$="4t ":GOTO 6180
P-74 T.HEN MNS""LSR:GOTO 40 el 117 "
P-76 THEN MNS="JMP":DC=2:GOTO 6180
P-78 THEN MNS="LSR":DC=2:GOTO 6180
P=8el THEN MNS=" BVC" : DC= 1 ': GOTO 61813
P=81 THEN MNS="EOR":DC"1:PRE$=" (":SUF$="l,Y":GOTO
IF
tF
IF
IF
IF
IF
P=85
P=86
P=88
P=89
P=93
P=94
THEN
THEN
THEN
THEN
THEN
THEN
MNS"'"EOR"
MNS="LSR"
MNS-"CLI"
MN$=';EOR"
MN$="EOR"
MN$="LSR"
DC=l: SUF$=", X
DC=1:SUF$=",X
GOTO 6181<1
DC=2 SUF$=",Y
DC=2 SUF$=",X
DC=2 SUF$=",X
":GOTO 6181!!
": GOTO 6181!!
"
GOTO 6180
" GO TO 6181!!
" GO TO 618'"
Appendicies 299
60013
61l' 113
6180
6020
6030
6041!1
61!1:'.51!1
6061!1
61!171!1
6181!1
6f2181!1
6f2191!1
611!1"
6111!1
618"
612"
6131!1
6141!1
61:511'
61611'
61711'
61811'
61911'
62f2111'
62111'
6221!1
6231!1
6241!1
IF P=96 THEN MNS="RTS": GO TO 6181~
IF P=97 THEN MNS=" ADC" : DC= 1: PRES="
THEN
THEN
THEN
THEN
THEN
THEN
(":SUF$=",X)":GOTO
MNS="ADC":DC=l:GOTO 6181~
MNS="ROR":DC-l:GOTO 6180
MN$=" PLA" : GOTO 61811'
MNS-"ADC":DC-l:PRE$","tI ":GOTO 6180
MN$="ROR":GOTO 6180
MNS-"JMP":DC-l:PRE$=" (":SUF$-")
":GOTO
IF
IF
IF
IF
IF
IF
P-1I2'1
P"102
P-104
P-ll!1:5
P-106
P-1I2'8
IF
IF
IF
IF
P-109 THEN MNS-"ADC":DC-2:GOTO 6180
P-110 THEN MN$-"ROR":DC-2:GOTO 6180
P-112 THEN MN$-"BVS": DC"l; .GOTO 6180
P-113 THEN MN$-"ADC": DC'" 1 i'PRES"''' (": SUF$-"), Y": GO TO
IF P-117 THEN MN$-"ADC":DC=1:SUF$=",X
IF P-118 THEN MN$-"ROR":DC-1:SUFS"''',X
IF P-120 THEN MN$-"SEI":GOTO 6180
IF P-121 THEN MN$-"ADC":DC-2 SUF$-",Y
IF P-12:5 THEN MNS.. "ADC":DC-2 SUFS-",X
IF P-126 THEN MN$-"ROR":DC-2 SUF$-",X
RETURN
POSITION PEEK(82),1!I
FOR 1-1 TO 2f21
INPUT *2,LINE$
LPRINT ,LINE$
NEXT I
GOTO 4480
":GOTO 6180
":GOTO 6180
" GOTO 6180
" GOTO 6180
" GOTO 6181!1
Appendix D
Memory Map
This memory map is arranged to give you an overview of the
organization of Atari memory . We have given emphasis to the specific
memory locations that are directly useful in terms of sound and
graphics as explained in the text of this book. See the end of the
memory map for sources of the complete memory allocations.
LABEL
DECIMAL I HEX I FUNCTION
Page zero is found at locations zero to 255 ($O-$FF). These locations
are accessed faster and easier by the machine. On page 0 locations 0
to 127 are observed forthe OS, While locations 128 to 255 are for BASIC
and the programmer's use .
Locations 2 to 7 are not cleared out by any of the startup routines.
Locations 16 - 127 are cleared on warmstart and coldstart.
301
302 Atari Assembly Language Programmer's Guide
POKMSK
BRKKEY
16
17
RTCLOCK
18,19,20
10
11
POKEY interrupts
Indicates status of the
BREAK key
12,13,14 Realtime clock
Locations 32 to 47 are the Page 0 Input/ Output Control Block.
CRITIC
66
42
ATRACT
DRKMSK
COLRSH
LMARGN
77
78
79
82
4D
4E
4F
52
RMARGN
ROWCRS
COLCRS
83
84
53
54
55 ,56
DINDEX
SAVMSC
87
88,89
57
58,59
LDROW
90
5A
OLDCOL
91 ,92
5B ,5C
OLDCHR
93
5D
ADRESS
100,101
64,65
RAMTOP
106
6A
Critical I/O region flag
used in ML Vertical Blank
routines
Attract mode timer and flag
Dark attract mode
Attract color shifter
Column of left margin of
text, GR 0 or text window
Right margin of text screen
Current cursor row, 0-191
Current cursor column
0-319
Current screen mode
Lo-Byte/ Hi-Byte of the start
of screen memory
Previous graphics cursor
row
previous graphics cursor
column
Data under graphics
window cursor
Temporary storage holds
contents of SA VMSC
Top of RAM memory
Appendicies
303
Locations 128-210 arefor programmer's use and BASIC page 0 RAM.
Locations 128-145 are the site of BASI C program pointers; 146 to 202
is for BASIC RAM; 203-209 are not used by BASIC. Locations 146 to
202 are reserved for use by 8K BASIC. Locations 176 to 207 are
reserved for Assembler Editor Cartridge. Locations 212 to 255 are
reserved for the floating point package.
LOMEM
128,129
80,81
MEMTOP
144,145
90,91
STOPLN
186,187
BA ,BB
ERRSAVE
195
C3
------
203-207
-----
208-209
210-211
-----
BASIC low memory pointer
token output address
BASIC top of memory
pointer
Line number where a STOP
or TRAP occured
Error number causing the
STOP or TRAP to occur
CB-CF Unused by BASIC or
Assembler Cartridge
00-01 Unused by BASIC
02- 03 Reserved for BASIC or
other cartridge
Page 1 - The Stack are at locations 256 - 511 . Machine language , JSR,
PHA and interrupts result in data bei ng written to page I; R TS , PLA,
and R TI instructions read data from page I.
VOSLST
VPRCEO
VINTER
VBREAK
VKEYBO
VTIMR1
VTIMR2
VTIMR3
VIMIRQ
512,513
514,515
516,517
518,519
520,521
528,529
530,531
532,533
534,535
200 ,201
202,203
204,205
206,207
208,209
210,211
212 ,213
214,215
216,217
NMI OLi vector
Serial proceed
Serial interrupt
Break instruction vector
Keyboard interrupt vector
POKEY timer 1 vector
POKEY timer 2 vector
POKEY timer 3 vector
General IRQ immediate
vector
304 Atari Assembly Language Programmer's Guide
Locations 536 - 558 are used for the system software timers and are
accessed by assembly language. T hese timers count backwards every
sixtieth or thirtieth of a second until ~hey r~ac1!zero.
CDTMV1
CDTMV2
CDTMV3
CDTMV4
System
System
System
System
System
timer
timer
timer
timer
timer
1 value
2 value
3 value
4 value
5 value
536,537
538,539
540,541
542,543
544,545
218,219
21A,21 B
21 C,21 D
21 E,21 F
220 ,22 1
546,547
222,223 VB immediate jump
VVBLKD
CDTMA1
CDTMA2
CDTMF3
SRTIMR
CDTMF4
548,549
555
556
224,225
226,227
228,229
22A
22B
22C
INTEMP
557
22D
CTMF5
SDMCTL
SDLSTL
558
559
560,561
CDTMV5
VVBLKI
550,551
552,553
554
SSKCTL
SPARE
LPENH
562
563
564
LPENV
BRKKY
565
566,567
568,569
581
623
GPRIOR
address
VB deferred jump address
System timer 1 jump addr
System timer 2 jump addr
System time 3 flag
Software repeat timer
System timer 4 flag
Temporary register used by
SETVBL
22E
System timer 5 flag
22F
DMA enable
230,231 Hi-Byte/ Lo-Byte of the
starting address of the
display list
232
Serial port control
233
No OS use
234
Horizontal value of light
pen
235
Vertical value of light pen
236,237 Break key interrupt vector
238,239 Two spare bytes
245
Spare byte buffer
26F
Priority selection register shadow of 53275.
Appendicies 305
Locations 624 - 647 are paddles, joysticks a nd lightpen controls .
PADDLO
PADDL 1
PADDL2
PADDL3
PADDL4
PADDL5
624
625
626
627
628
629
271
272
273
274
275
PADDL6
PADDL7
630
631
276
277
STICKa
STICK1
STICK2
STICK3
632
633
634
635
278
279
27A
278
Value
Value
Value
Value
PTRIGO
636
27C
Determines if trigger or
button on paddle has been
pressed
PTRIG1
PTRIG2
637
638
27D
27E
PTRIG3
PTRIG4
PTRIG5
PTRIG6
PTRIG7
639
640
27F
280
641
642
643
281
282
283
STRIGO
644
284
STRIG1
STRIG2
STRIG3
645
646
647
285
286
287
270
Value
Value
Value
Value
Value
of
of
of
of
of
paddle
paddle
paddle
paddle
paddle
a
1
2
3
4
Value of paddle 5
Value of paddle 6
Value of paddle 7
of
of
of
of
joystick
joystick
joystick
joystick
a
1
2
3
Determines if the stick
button has been pressed
306 Atari Assembly Language Programmer's Guide
------ -- --------
651
652,653
654,655
288
Spare byte
28C,28D OS ROM interrupt handler
28E,28F Spare bytes
Locations 656 - 703 are used for screen RAM display handler and
depends on the Graphics Mode.
TXTROW
TXTCOL
TINDEX
656
657,658
659
TXTMSC
660,661
Text cursor row 0-3
290
291,292 Text cursor column 0-39
Current split-screen text
293
window
294,295 Upper left corner of the text
window
Locations 704-712 are color registers for playfield, players, and
missiles. They are the RAM shadow registers for 53266-53274.
PCOLRO
PCOLR1
PCOLR2
PCOLR3
COLORO
704
405
406
707
708
2CO
2C1
2C2
2C3
2C4
COLOR1
709
2C5
COLOR2
710
2C6
COLOR3
711
2C7
COLOR4
712
2C8
Color of player/ missile 0
color of player/ missile 1
Color of player/ missile 2
Color of player/ missile 3
Color register 0
Playfield 0
Color register 'I
Playfield 1
Color register 2
Playfield 2
Color register 3
Playfield 3
Color register 4
8ackg round/Border
Appendic ies
307
713-735
736-739
740
2C9-2DF Spare bytes
2EO-2E3 Miscellaneous use
2E4
Top of RAM address
CRSINH
741,742
745
752
2E5,2E6 OS top of memory pointer
2E9
Spare byte
2FO
Cursor inhibit
KEYDEL
CH1
753
754
CHAT
CHABAS
CHAR
755
756
757-761
762
ATACHR
763
CH
764
FILDAT
DSPFLG
765
766
SSFLAG
767
-----------
RAMSIZ
MEMTOP
------
------
2F1
2F2
Key debounce counter
Prior keyboard character
code
2F3
Character mode register
Character base register
2F4
2F5-2F9 Spare bytes
2FA
Internal value for last
character written or read
2FB
Last ATASCII character
read / write and DRAWTO
value
2FC
I nternal code for last key
pressed
2FD
Color for XIO
2FE
Display flag used for
control characters
2FF
Start/stop flag to halt
scrolling and CNTL2
Page three: The locations 768 to 831 are the device handler and vectors
to the handler routines.
Locations 832 - 959 are used for the eight Input j Output control
blocks. These are the channels for the transfer of data into and out of
the computer, or between devices.
308 Atari Assembly Language Programme(s Guide
PRNBUF
960-999
3CO-3E7 Printer buffer
Locations 1000 - 1020 are a reserved spare buffer area.
CASBUF
1021-1151
3FD-47F cassette buffer
Locations 1152 - 1791 are for user RAM requirements. There are 128
spare bytes available at location 1152 - 1279 if you don't use the
floating point package at locations 1406 - 1535.
Locations 1536 - 1791 are on page six and are not used by the OS.
These locations may be used safely for machine language routines,
redefined character sets and whatever the programmer can fit into this
space.
Locations 1792 - 2047 (page 7) are the user boot area. Locations 1792
to the address of LOMEM at 128, 129 are also used by DOS and the
File Management System.
CTRDGE. B
CTRDGE. A
32768
40960
8000
AOOO
Used by right slot on 800
Used by the left slot
Locations 49152 - 53247 unused; reserved for future expansion. This
4K area of memory can NOT be written to by the programmer.
Appendicies
GTIA
53248-53505
0000
HPOSPO
53248
DOFF
0000
53249
0001
MOPF
HPOS1
53250
0002
53251
0003
53252
0004
M3PF
HPOSMO
collision
(W) horizontal position of
(W) horizontal position of
player 3
(R) missile-playfield
collision
(W) horizontal position of
missile 0
(R) player to playfield
POPF
HPOSM1
(W) horizontal position of
player 0
(R) missile-playfield
collision
(W) horizontal position of
player 2
(R) missile-playfield
collision
M2PF
HPOSP3
processes the video signal
player 1
(R) missile-playfield
M1PF
HPOSP2
309
53253
0005
collision
(W) horizontal position of
missile 1
P1PF
HPOSM2
53254
0006
53255
0007
P2PF
HPOSM3
P3PF
MOPL
53256
0008
(R) player to playfield
collision
(W) horizontal position of
missile 2
(R) player to playfield
collision
(W) horizontal position of
missile 3
(R) player to playfield
collision
(R) missile 0 to player
collision
310 Atari Assembly Language Programmer's Guide
SIZEPO
M1PL
53257
0007
SIZEP1
M2PL
53258
OOOA
SIZEP2
M3PL
53259
0008
SIZEP3
POPL
53260
oooe
SIZEM
GRAFPO
53261
0000
53262
OOOE
53263
OOOF
GRAPFP3
53264
0010
TRIGO
(644)
GRAPFPM
TRIG1
eOLPMO
53265
0011
53266
0012
P1PL
GRAPFP1
P2PL
GRAPFP2
P3PL
TRIG2
(646)
(W) size of player 0
(R) missile 1 to player
collision
(W) size of player 1
(R) missile 2 to player
collision
(W) size of player 2
(R) missile 3 to player
collision
(W) size of player 3
(R) player 0 to player
collision
(W) size for all missiles
(W) graphics shape for
player 0
(R) player 1 to player
collisions
(W) graphics shape for
player 1
(R) player 2 to player
collisions
(W) graphics shape for
player 2
(R) player 3 to player
collisions
(W) graphics shape for
player 3
(R) joystick trigger 0
(W) graphics for all missiles
(R) joystick trigger 1
(704) color/ luminance of
player/ missile 0
(R) joystick trigger 2
Appendicies 311
COLPM1
53267
0013
TRIG3
(647)
COLPM2
(705) color/ luminance of
player/ missile 1
(R) joystick 3 trigger
53268
0014
COLPM3
53269
0015
COLPFO
53270
0016
COLPF1
53271
0017
COLPF2
53272
0018
COLPF3
53273
0019
COLBK
53274
001A
PRIOR
VOELAY
GRACTL
53275
53276
53277
001B
001C
0010
HITCLR
CONSOL
53278
53279
001E
001F
(706) color/ luminance of
player/ missile 2
(707) color/ luminance of
player/ missile 3
(708) color/ luminance of
playfield 0
(709) color/ luminance of
playfield 1
(710) color/ luminance of
playfield 2
(711) color/ luminance of
playfield 3/ missile 4
(712) color/ luminance of
background
Priority selection
(W) vertical delay
(W) use with OMACTL:
latch triggers
turn on players
turn on missiles
(W) clear collision registers
(R/ W) check for OPTIONSELECT-START buttons
pressed
Locations 53280 - 53503 are repeats of locations 53248 - 53279.
Programmers cannot use these locations.
Locations 53504 - 53759 are unused . However they are not empty. If
you are interested you can PEEK these locations to see their contents.
312 Atari Assembly Language Programmer's Guide
POKEY: Locations 53760 - 54015 are the 110 chip that controls audio
(requency registers and audio control registers, frequency dividers,
polynoise counters, paddle controllers, random number generation,
keyboard scan, serial port 110 and IRQ interrupts .
AUOF1
POTO (624)
AUOC1
53760
0200
53761
0201
53762
0202
53763
0203
AUOF3
POT4 (628)
53764
0204
AUOC3
53765
0205
POT1 (625)
AUOF2
POT2 (626)
AUOC2
POT3 (627)
POT5 (629)
AUOF4
POT6 (630)
AUOC4
POT7 (631)
AUOCTL
ALLPOT
STIMER
KBCOOE (764)
SKREST
RANDOM
POTGO
------
SEROUT
53766
0206
53767
0207
53768
0208
53769
0209
53770
020A
53771
020B
53722
53773
020C
0200
(W) Audio channel 1 freq .
(R) POT 0
(W) Audio channel 1
control
POT1
(W) Audio channel 2 freq .
(R) Pot 2
(W) Audio channel 2
control
(R) Pot 3
(W) Audio channel 3 freq .
(R) Pot 4
(W) Audio channel 3
control
(R) Pot 5
(W) Audio channel 4 freq .
(R) Pot 6
(W) Audio channel 4
control
(R) Pot 7
(W) Audio control
(R) 8 line pot port state
(W) Start POKEY timers
(R) Keyboard code
(W) Reset serial port status
Random number generator
(W) Start pot scan
sequence
unused
(W) Serial port output
Appendicies 313
SERIN
IRQEN
IRQST
SKCTL
SKSTAT
53774
020E
53775
020F
(R) Read serial port status
(W) Interrupt request
enable
(R) Interrupt request status
(W) Serial port control
(R) Reads serial port status
Locations 53776 to 54015 are a repeat of locations 53760 to 53775. As
of this writing these locations have no use.
PIA: 6520 Chip is located at addresses 54016 to 54271 . These locations
are used for control ports , controller jacks one through four and to
process VINTER and VPRCED.
PORTA
54016
0300
PORTB
54017
0301
PACTL
PBCTL
54018
54019
0302
0303
R/W data from controller
jacks one and two
R/ W data to/from jacks
three and four
(W/ R) Port A controller
(W/ R) Port B controller
Locations 54020 to 54271 are a repeat of locations 54016 to 54019.
ANTIC resides at locations 54727 to 54783 and controls GTIA, screen
display and other screen functions. NMI interrupts are also processed
here.
,
314 Atari Assembly Language Programme(s Guide
OMACTL
C HACTL
54272
54273
54274,5
HSCRO L
54276
VSCROL
54277
54278
54279
0405
0406
0407
54280
54281
54282
0408
0409
040A
- - --- -
PMBASE
-- ----
CHBASE
WSYNC
(W) OMA control (559)
(W) Character mode
co ntrol (755)
0402,3 Disp lay li st po inter
(560,561 )
0404 (W) Horizonta l scroll
enab le
OLi STL/H
I
0400
0401
(W) Vert ica l scro ll enab le
Unused
(W) Player/missile base
address
Unused
(W) Character base addr.
(W) Wait for horizontal
synchronization
VCOUNT
PENH
54283
040B
(R) Vertica l li ne counter
54284
040C
PEN V
54285
0400
(R) Horizontal posit ion of
lightpen
(R) Vertica l posit ion of
lightpen
NM IEN
54286
040E
NMIRES
54286
040F
NMIST
(W) Non- Maskab le
interrupt enable
(W) Reset for NMIST:
clears i nterru pt req uest
register
(R) NMI status
Locations 54288 to 54303 are a repeat of locations 54272 to 54287.
Locations 54784 to 55295 are unused. However they are not empty and
therefore are not programmable. If you are interested you can PEEK
into these locations and find out what is there .
. .
Locations 59310 to 59628 are the Operating System ROM.
Appendicies 315
,- -- -- - - -- - - - - -- - - -- - - - - - - - -- Locations 55296 to 57343 are used for the ROM 's Floating Point
Mathematics Package, The FP Package also uses page 0 locations
212-245 and page 5 locations 1406 - 1535, BASIC Trigonometric
functions which use the FP routines are located at 48549 to 49145,
Locations 57344 to 58367 contain the standard Atari character set.
57344
57600
57856
58112
EOOO
E100
E200
E300
Special characters
Punctuation, numbers
Capital letters@
Lowercase letters
~----------~---L------------- I
Locations 58368 to 58477 ace vector tables . These are base addresses
't
d ISP
' Iay
W h'IC h are use d b y th e resl'd en t h an dl ers ( screen e d lor,
handler, keyboard handler, printer and cassette handler) and are
stored in Lo-Byte / Hi-Byte form,
Locations 58448 to 58495 are jump vectors, Locations 58496 to 58533
are the initial RAM vectors ,
SETVBV
SYSVBV
XITVBV
58460
58463
58466
E45C
E45F
E462
Set system timers routine
Stage 1 VBLANK entry
Exit VBLANK entry
Locations 58534 to 59092 are the addresses for the Central Input / Output
routines
ILoc~tions 59093 to 59715 are the addresses for the interrupt handler
routines
316 Atari Assembly Language Programme(s Guide
'---59123
E6F3
SYSVBL
59310
E7AE
PNMI
59316
E7B4
SETVBL
59629
E8ED
PIRQ
Start of I RQ interrupt
service routine
Start of the VBLANK
routines
(JSR) interrupt service
routine
Subroutines to set the
VBLANK timers/ vectors
Locations 59716 - 60905 are the addresses for the serial Input / Output
routines.
Locations 61667 - 62435 are the addresses for the monitor handler
routines.
Sources of memory locations:
(1)
(2)
(3)
(4)
(5)
DE RE ATARI
Technical Users Notes
ANTIC Magazine
Master Memory Map, Santa Cruz Educational Software (1981)
Mapping The Atari, COMPUTE! Publications (1983)
Appendix E
CHARACTER CODES
ATASCI I
DECIMAL
I)
KEYSTROKE
CHARACTER
CNTRL
CNTRL A
CNTRL B
CNTRL C
..
CNTRL 0
04
CNTRL E
CNTRL F
CNTRL G
CNTRL H
CNTRL
10
CNTRL J
,
/
INTERNAL CODE
64
65
66
67
68
69
70
71
72
73
74
11
CNTRL
12
CNTRL L
13
CNTRL M
14
CNTRL N
79
15
CNTRL 0
16
CNTRL
79
F'
80
17
CNTRL
81
18
CNTRL R
19
CNTRL S
83
20
CNTRL T
84
I<
75
76
77
82
317
318 Atari Assembly Language Programme(s Guide
21
CNTRL U
22
CNTRL V
23
CNTRL W
24
CNTRL X
25
CNTRL Y
26
CNTRL Z
27
ESC ESC
28
ESC CNTRL -
29
ESC CNTRL -
30
ESC CNTRL +
31
ESC CNTRL
32
SPACE BAR
33
SHIFT
34
SHIFT 2
85
...
87
...
I
.~
l'
86
88
89
90
91
92
...
93
94
95
0
3~
SHIFT 3
II
36
SHIFT 4
37
SHIFT
Yo
38
SHIFT 6
&c
39
SHIFT 7
40
SHIFT 9
41
SHIFT 0
42
10
43
11
44
12
45
13
46
14
Appendicies 319
47
48
15
16
17
49
:50
18
:51
19
:52
20
:53
:5
:5
21
:54
22
:5:5
23
:56
24
:57
2:5
:58
26
SHIFT!
27
:59
60
<
<
61
62
>
28
29
>
30
63
SHIFT
31
64
SHIFT 8
(I
32
6:5
33
66
34
67
3:5
68
36
69
37
70
38
71
39
72
40
320 Atari Assembly Language Programmer's Guide
73
41
J
42
7!5
43
76
44
77
4!5
78
46
79
47
80
48
81
CI
CI
49
82
!50
83
~1
84
~2
8~
~3
86
~4
87
~~
88
~6
89
~7
90
~8
74
91
SHIFT
92
SHIFT
93
SHIFT
94
SHIFT
62
9~
SHIFT -
63
96
CNTRL
~9
60
61
96
97
97
98
98
Appendicies 321
99
99
100
00
101
101
102
102
103
103
104
104
10~
10~
106
106
107
L07
108
108
109
109
110
110
111
111
112
112
113
113
114
114
11~
11~
116
116
117
117
118
118
119
119
120
120
121
121
122
122
123
CNTRL
124
SHIFT
123
124
322 Atari Assembly Language Programme(s Guide
<
125
ESC CNTRL
126
ESC BACK S
127
ESC TAB
"'.
.,
~
125
126
127
[.-...J
Inverse Vi .dec
128
[A.JCNTRL.
129
[~JCNTRL
130
[A-JCNTRL B
131
[AI.]CNTRL C
132
192
193
194
[.h-JCNTRL D
a
a
196
133
[ A-JCNTRL E
CI
197
134
[A-JCNTRL F
198
13~
[ft,JCNTRL G
199
136
[ .....JCNTRL H
!J
200
137
[A.]CNTRL
It
201
138
[A-JCNTRL J
139
["'JCNTRL K
140
[""JCNTRL L
m
m
19:5
202
203
141
[..+JCNTRL M
142
[A-JCNTRL N
"e
143
[AlCNTRL 0
II
207
144
[A-JCNTRL P
Qg
208
14:5
["'JCNTRL tl
17
209
146
[A'-JCNTRL R
147
[NCNTRL S
148
[",JCNTRL T
149
[A\JCNTRL U
ii
D
0
204
20:5
206
21<)
211
212
213
Appendicies 323
150
[J
[AJCNTRL V
214
151
[4]CNTRL W
152
[.A]CNTRL X
153
[-4.]CNTRL Y
154
[ ....]CNTRL Z
II
&:I
155
[~RETURN
156
ESC SHIFT BACK S
157
ESC SHIFT
1;58
ESC CNTRL TAB
)59
ESC SHIFT TAB
160
[A]SPACE BAR
161
[~
SHIFT 1
129
162
["-]
SHIFT 2
ii
13(1
163
[..+.J
SHIFT 3
131
164
CA-.]
SHIFT 4
132
165
C.AJ
SHIFT :5
133
166
CAJ
SHIFT 6
fl
134
167
CA]
SHIFT 7
r.
135
168
CA\.]
SHIFT 9
136
169
CA]
SHIFT 0
tJ
137
170
CA]
138
171
CA.]
172
CA]
173
[ft.]
174
[A]
175
CA.]
215
216
217
2'8
219
>
220
221
C
:l
222
223
128
...
139
140
;;
141
II
142
143
324 Atari Assembly Language Programmer's Guide
176
[AJ
(I
ill
144
177
[ A. J
(!
145
178
[ -1-.J
146
179
[ ".J 3
147
180
[ 1'3 4
148
181
[AJ 5
149
182
[A-J 6
150
183
[AJ
fj
184
[AI.J 8
[;J
185
[4J
153
186
[AJ SHIFT;
154
187
[A.J
155
188
~..-N
<
156
189
[;\.J
Iii
157
190
u,J
158
191
[ "-J SHIFT I
159
192
C~J
SHIFT 8
[g
160
193
[.,f.J
161
193
[ A. J
l!)
162
195
[ A. J C
[ A-. J
l!J
l!l
163
196
197
CAl E
165
198
["'J F
La
166
199
[~
Ul
167
200
[ -+-J H
t:J
201
4J
>
151
152
164
168
'169
Appendicies 325
202
(..j.
J J
!J
17(>
203
(AJ K
171
204
CA.J L
172
20~
(.lJ M
(i)
173
206
(A.J N
l!l
174
207
(4.J 0
[!l
175
208
(..f..J P
176
209
( ...... J
til
177
210
CA.J R
[3
178
211
CA.J S
179
212
(..,.J T
il
180
213
C-+.J U
214
CA.J V
L!J
L!J
182
215
CA'-J W
I!l
183
216
UJ X
184
217
C.... J Y
185
218
(-'" J Z
186
219
( ... J SHIFT
187
220
C+J SHIFT +
188
221
C... J SHIFT
lJ
189
222
(~J
SHIFT
223
C-"'J SHIFT
224
(~J
225
CAJ
226
( ... J b
227
(~'J
228
( ....1
181
190
I!!
191
CNTRL
224
225
m
[;
rn
226
227
Z'2a
326 Atari Assembly Language Programmer's Guide
229
[ A. J e
230
[ .... J f
231
229
1 30
[ "'J 9
231
232
[AJ h
232
233
[-1-J i
m
n
234
[ I).J
1I
234
23:5
[ f'J k
235
236
[~J
237
0
CJ
236
[",J m
238
[-1'J n
!i]
238
239
[.+J
239
240
[hJ p
rn
m
241
[.A.J q
Ci1
241
242
[ -l'J r
[j1
24~
243
[4J
f12
243
244
UJ.J t
24 ..
24:5
[-lJ u
[!]
24~
246
[~J
t!l
246
247
[AJ
...
247
248
[ II-J
248
249
[.A.J Y
249
2~O
[~J
2~O
251
[I)..J CNTRL
251
252
[A..J SHIFT
II
252
253
ESC CNTRL 2
1a
..::..; .,j
254
CU ESC CNTRL BACK S
254
2!l"5"
CAW ESC. CN,RL )
255"
II
233
237
240
-.C'~
Appendix F
Instructions and Flags
Flag
Instruction
ADC
AND
ASL
x
x
x
x
x
x
x
BIT
BRK
CLC
CLD
CLI
CLV
CMP
CPX
CPY
DEC
DEX
DEY
C
x
0
0
0
0
x
x
x
x
x
x
x
x
x
x
x
x
327
x
x
x
x
328 Atari Assembly Language Programmer's Guide
EOR
INC
INX
INY
LOA
LOX
LOY
LSR
ORA
PLA
PLP
ROL
ROR
RTI
SBC
SEC
SEO
SEI
TAX
TAY
TSX
TXA
TYA
x
x
x
x
x
x
x
0
x
x
x
x
x
x
x
x
x
x
x
x
From Stack
x
x
x
x
From Stack
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
Appendix G
Values for
Decim~l
6502
Instructions
I~
..
~ I
~
..,
u
III
L.
'tI
c:
<I:
11)1
11)5
ADC
1 109
117
1:;:5
121
197
113 1
~A--N-D-+---~1-4-1--+-3-7--~5-3--~--~~ -5-7--+-----~--+3-3--}-4-9~~~
ASL
8CC
10
14
22
-+,---I
i-----r- _.
!
-'j---i-!I --+--+-
-r;
I~-~t---'--- 136
i
144
~5-t- --'---1 ---1--/
BEQ
.3 0
176
240
-1---,-----144-+I---+-j_1+--!-------!----l---+-!- i!f---"
!~~-:---I I :~ --+i----+--+I----;!---l1-1-6-+I!
I::, I I :
-iC-----'I'----l
I
~ ._~. ___ .
1-----.--,--
-l-.-_:__
~~~- ---r-----l---,: --+-I-+--t---t---OO-t---+--j'---'----I
BVC
avs
--;!__+-_+-_-+-_ _
+-8_0- +__-+-_-+___
I
: j
112
CLC
1 -I - j-'-,---+1---t---+----t-- 2- 4- 1 - - l -- + ----If------j
1
CLD
1
!
I
I 216 I
I
------~I-----+----+--------~
I --~----}---~----~--~--~---+---j
~----,----;-----r--_+----r---~--~-----+--~--_+-----i---___j
I~L I
CL V
+ ____
+-__ lr-__--+1____+-__+-__-+_____+-__--+-__. .; ___+---1
88
j __
329
184
330 Atari Assembly Language Programmer's Guide
E
.
u
u
<i
CMF
I-~
CPY
DEC
.,
>-
Cl
'"
'"a.
Cl
''""
'"a.
Cl
.0
<i
r
_ -__ 11-2-2-4- --LF
:?-88
-:[I
, . __ ._ 192
,----
.0
<i
<i
217
209
T - 1 ---+----1
2l)4
2c)2
136
DEY
73
EOR
INC
69
85
77
93
:23 0
246
238
254
65
89
81
,I
232
lNX
INY
JMP
\
\ 76
JSR
32
200
LOA
169
16:=> 1 181
LOX
162
166
160
164
f----.LOY
LSR
119:-
! 2 -1-4-+---l-2-0-6-~112-2-2-+-- --T
DEX
- -
-+_--l _:?_:,6_1:--_ _ 1-_---l ---
1196
198
.,;
.0
:?~_~~ -~--l---+i' :?__<:_'5_ 1~2 1
"0
."!
Ci
>-
.,;
'"
a.
'
70
74
--
NOP
-- I---ORA
..- -
182 11 174
--
I 21
78
1 86
I
--
172
180
.,
189
173
I 13
190
I
94
I
-I
:--188
29
I 25
il l
17
1 0 4 f l1- - + - - + - - - 1
1--.--tI
I
ROL
4:?
ROR_
1')6I---H --=-~.
RTI
RTS
234
PHP
-;~I--I--+
I
-- -~-
177
t---I--T--~'
--r--~'-::~
I
PHA
PLP
-161
185
38
54
40
I
461. 62-
~t_--~I~~i~r--t_-_+-4_-~-~~
t--,-~,
__
LllO ~j...
I
I
I
iI
I
I,
___ _ _
-+_-+_-+_ __-1--1
64
96 -:1- - -.
I
Appendicies 331
5 8C
J~
2:9
~37
:!45
253
STA
133
STX
134
STY
132
TXA
TYA
120
SEI
TSX
291
248
SED
TAY
'::' _..J
56
SEC
TAX
~ .., ~
249
141
149
j15(1
148
157
129
153
142
140
170
168
186
138
152
1~:'
Appendix H
FREQUENCY VALUES
To Generate Notes Using Registers as Pairs
NOTE AUDF LOBYTE . H I BYTE
OCTAVE 0
C 5tf720 192
193
0 48750 110
0 . . . . . . . . . . . . . . . . . . 4601~ . . . . . . . . . . . . . . 191
E 43430 166
F 40992 32
F . . . . . . . . . . . . . . . . . . 38691 35
G 36519 167
GtI 34469 165
A 32~3:5 23
A. . . . . . . . . . . . . . . . . . 30708 244
B 28984 56
e .................. 51649
213
201
190
179
169
160
151
142
134
127
119
113
OCTAVE 1
e ........... " ..... 27357 221 - 106
eft ..... 2:5821 221 100
0 24372 52 . 95
Ott 23003 , .219 89
E 21712 208 84
F 20493 13 80
F . . . . . . . . . . . . . . . . . . 19342 142 7~
G 182:57 81 71
G. . . . . . . . . . . . . . . . . . 17231 79 67
A 16264 136 63
A. . . . . . . . . . . . . . . . . . 15351 247 ~9
B 14489 153 56
333
334 Atari Assembly Language Programmer's Guide
OCTAVE 2
C 1367~ 107 53
ett 12907 107 50
O 12182 150 47
Ott 11498 234 44
E 10852 100 42
F 10243 .. 3 40
F . . . . . . . . . . . . . . . . . . . 9668 196 37
G 9125 165 35
8ft 8612 164 33
A 8128 192 31
Aft 7672 248 29
B 7241 73 28
OCTAVE 3
c ..... 6834 178 26
Cft 64:50 50 25
O 6088 200 23
Oft :5746 11 4 22
E ~423 47 21
F 5118 . 254 19
Fft 4830 222 18
G 4559 207 17
Gft 4303 207 16
A 4061 . 221 15
A. . . . . . . . . . . . . . . . . . . 3832 248 14
B 3617 33 14
OCTAVE 4
e .................. 3413 . 85 13
eft 3222 150 12
O 3040 224 11
Oft 2869 . 53 , 11
E 2708 , 148 10
F 2555 251 9
F . . . . . . . . . . . . . . . . . . . 2412 108 9
G 2276 228 8
Gft 21 48 100 8
A 2027 235 7
Aft 1913 121 7
B 180:5 13 7
Appendicies 335
OCTAVE :5
c 1703 167 6
Cft 1607 71 6
O 1:517 237 5
Ott 1431 1:51 :5
E 13:50 70 5
F 1274 250 4
Fft 1202 178 4
G 1134 110 4
Gtt 1070 46 4
A 1010 242 3
A.. 962 ' .' 194 3
B 899 131 ~
OCTAVE 6
c ..... 848 80 3
Ctt 800 32
O 755 243
Oft . 712 200
E 672 160
F 634 122
F . . . . . . . . . . . . . . . . . . . . 598 86
G 564 52
Gtt 532 20
A :501 245
A. . . . . . . . . . . . . . . . . . . . 473 217
B . 446 190
3
2
2
2
2
2
2
2
1
1
1
OCTAVE 7
C 421 165
Cft 397 141
O 374 118
Ott 3:53 97
E . 332 76
F 313 57
F . . . . . . . . . . . . . . . . . . . . 295 39
G ' .' . 278 22
G. . . . . . . . . . . . . . . . . . . . 262 6
A 247 247
A. . . . . . . . . . . . . . . . . . . . 233 233
B 219 219
1
1
1
1
1
1
1
1
1
0
0
0
336 Atari Assembly Language Programmer's Guide
OCTAVE B
c ................... 207 207 0
c .................... 195 195 0
D 183 183 0
D. . . . . . . . . . . . . . . . . . . . 173 173 0
E 163 163 0
F 153 153 0
Ft! 144 .
a .... ............. 136.
aft ... 128
A 120
A . . . . . . . . . . . . . . . . . . . . 113
B 106
144 0
1 36 0
128 0
120 0
113 0
106 0
Index
BNE 50
BPL 50
Branching
BRK 55
BYC 55
BYS 50
Accumulator 37
ADC 52
Addressing Modes 55-61
Immed iate 57
Accumulator 58
Absolute 57
Zero Page 57
Indirect 57
Implied 58
Relative 58
A bsolu te Indexed 60
Zero Page Indexed 60
I ndirect Inde xe d 60
I ndexed I nd i rect 61
Amplitude 181
AND 53
ANTIC 40
Instructions 66-71
Multicolored Characters 112-115
Artifacting 106
Arithmetic Instructions 52, 53, 168
ATASCII 35
ASCII 35
ASL 53
c
C haract er Set Graphics
CLC 52, 145
CLD 52
107-112
CLI 51
CMP 49
Codes
ATASCII 35
Binary Coded Decimal
Collisions 129
Color 97-104
CPU 36-37,40
Cpy 49
CPX 49
D
Data-Moving 155
DEC 49
Decimal System 22
DEX 49
DEY 49
Diagonal Scrolling 257
Display List 66, 76
Custom DL 80
DL from scratch 88
Display Modes 72-76
DL Interrupts 69,70, 136
B
BBC 50
BSC 50
BEQ 50
Binary System 22-30
Binary Coded Decimal
BIT 55
BMI 50
49-50,161
36
337
36
338 Atari Assembly Language Programmer's Guide
JjK
Eight-bit Music
EOR 53, 145
215
F
F lags 39
Frequency
181, 188
G
Graphics 2 DL 78
Graphics 8 DL 83
GTiA 41. 101-104
H
Half-step 188
Harmonics 183
Hexadecimal System 31-35
Hi-Byte 27,34
Horizontal Blank 64
Horizontal Scroll in g 70,249
INC 49
International Pitch Standard 188
I nstruction Set 45-51
Load / Store 48
Register Transfer Operations 49
I ncrement / Decrement 49
Compare / Branch 49-50
Jump / Return 50-51
Interrupt 51
Stack Operations 51 -52
Arithmetic 52-53
Logical / Miscellaneous 53-55
INY 49
INX 49
JMP
JSR
JVB
Koala
71
51
71. 77, 78, 84
Pad 274
L
LDA 48,112
LDX 48
LDY 48
LMS 57, 59,67, 70
Lo-Byte 27,34
LSR 53
Luminance 97, 99, 102
M
Machine Language
Comments On 44
Instructions 48
Program Listing Conventions
Map Modes 8 1
Memory 41-43
Lowering RAMTOP 87,88
Screen 66
M icroseco nd 64
Mnemonic 45
Music 215,260
Missiles 172
N
NOP 55
Number Systems
Binary 22-30
Binary Coded Decimal
Decimal 22
Hexadecimal 31-35
36
149
Index 339
SEC 52 , 142
SED 52
SE I 5 1
S ixtee n-bit Music 224
So und 179
Theory 180
Ha rdware 189
Pro gra m Exa mples 197-2 17
S ta ck Pointer 38
STA 48
STU 48
STX 48
Sta IUs Register 38
S trings 152
Octave 187,188
ORA 53
p
Page Flipping 95-97
Parameter Passing 162
Parameter Passing 162
Period 181
PHA 51
PHP 51
PIA 4 1
Pixel 64, 75
PLA 51, 112, 114
P laye r Missi le Gra phics 115
Registers 121-125
Collisions 129
Priority 133
Memory 127
PLP 41
POKEY 41, 163
Priority 133
Program Counter 38
Program Listing Convention
R
R AMTOP 87 ,88
Recursive Rule 23
ROL 53
ROR 53
RTI 51
RTS 51
s
SAVMCS 80,81, 84
SBC 52
Screen Memory 66
Sc rolling 235
149
TAX 49
TAY 49
Timbre 183
Touch Tablet 274
Tremolo 187
TSX 49
TV 64-66
Two's Co mplement Arithmetic
TXA 49
TXS 49
TYA 49
U/V/W
USR 15 1
Vertical Blank 66
Vertical Blank Int e rrupts 230
Ve rti ca l Blank Music 260
Vertical Scro lling 235
Vibrato 185
X/V/Z
X-reg iste r
Y-register
38
38
169
More Computer Books from Weber Systems Inc.
Instant Lotus 1-2-3
Turbo Pascal: Programming Ex . & Sub rout ines
Turbo Prolog Programmer's Guide
Amiga Programmer's Guide
Alari ST Programmer's Guide
Excel: Using Macros
Work ing With 0 & A
Commodore 128 Programmer 's Gu ide
dBASE III Plus: Thi ngs the Manual Didn 't Tell You
Working with MS-DOS v. 3-2
Working with Reflex
Microsoft Basic 3rd Edition
Alar i XE User's Handbook
Alari XL U ser's Handbook
IBM PC AT User's Handbook
Okidata Printer User's H andbook
Sanyo MBC 550/555 User's Handboo k
AppleWorks User's Han dbook
Working With Multimate
The Applewriter II Handbook
The WordStar Handbook
Lotus t -2-3 Models
$ 7.95
$15.95
$17.95
$19.95
$19.95
$19.95
$19 .95
$17.95
$19 .95
$19.95
$19.95
$17.95
$15.95
$17.95
S 9.95
$15.95
$17 .95
$ 9.95
$17 .95
$19.50
$19.95
$15.95
Inventory Managemen t for Sma ll Compu ters
Programs for Electronic Circuit Design
The Model 100 Prog ram Book
IBM PC Business Software
Sanyo MBC Business Software
32 BASIC Programs fo r the Apple
More Than 32 BASIC Programs fo r the IBM PC
32 BASI C Programs for Ata ri 800XL and 130XE
Computers, Teaching and Learn ing
Electronic No tebook
Computers for Everybody 3rd Edition
Bit , Bytes . and Buzzwords
Atari Assembly Language Programmer's Guide
6502, 65C02, and 65816 Handbook
Inside th e TRS-80 Model 100
Baron 's Used Computer Price Guide
Speech Systems for Your Microcomputer
Logo and More fo r the Commodo re 64/ 128
T he Programmer's Too lbox
Sanyo BASIC User's Handbook
Nailing Jelly to a Tree
Shaping Logo on Your Apple
Symphony Command Language Programmer Guide $17 .95
How to Bui ld a Program
Supercalc Models
All About 1-2-3
1-2-3 Manager ial Worksheets
Beyond Beginning BASIC
Beginnin g FORTRAN
BASIC: Step-by-Step Programm ing
Beginning FORTH
Beginning COBOL
$15.95
$ 5.95
$ 7.95
Cont rollin g Financial Pe rformance for Higher Profits S17.S0
Planning and Budgeting for Higher Profits: 1-2-3
Business Probl em Solving: 1-2-3
$17.50
$19.95
Analyzing Your Financial Statem ents with
Symphony: 1-2-3
$19.95
Business Decision Making for Higher Profits: 1-2~3
$19 .50
Business Graphics for Analysis & Presentation: 1-2-3 $ 19.95
How to Get Sta rted with MS-DOS
CPI M Simpli fied
Work ing with PICK
The World of PC-DOS
$ 7.95
$13.95
519.95
$ 7.95
Introduction to Structured FORTRAN
Lisp
Pascal: Step-by -Step Prog rammi ng
Introduction to C
Introduction to Madu ra 2
Introduction to Ada
Turbo Pascal Prog rammer's Guide
Xen ix User's H andbook
THEOS/OASIS User's Handbook
Title
Price
Quantity
$ 5.95
$14.95
$12.95
$17.95
$11 .95
$ 5.95
$ 5.95
$ 5.95
$12.95
$ 9.95
$ 4.95
$ 3.95
$14.95
$14.95
$19.95
$ 7.95
$14.95
$ 7.95
$ 9.95
$17.95
$ 7.95
$ 7.95
$ 9.95
$ 7.95
$15.95
$15.95
$16.95
$ 9.95
$19.95
$15.95
$16.95
519.95
$19.95
$19.95
$17.95
$17.95
$17.95
Total
NC
Catalogue
Book Subtotal
Shipping & Handling ($2. 50 per item)
Oh io Resi dents Add 6'1,% Sal es Tax
GRAND TOTAL
Method of Payment:
Card Number
0 Check
Charge my:
0 VI SA
0 Master Card
0 Am erican Express
Exp. Date
Cardhold er Name
Ship To
Name
Address
City
State
Z ip
Send to: Web er Sys tems Inc. , 8437 Mayfield Road, Ches terland, OH 44026
TOil-free order number 800-851-6018
$19.95 US
$28.95 Canada
ISBN 0-938862-54-5
WEBER SYSTEMS, INC.
8437 Mayfield Road, Chesterland, Ohio 44026