Many of the superb graphic displays
of which we all know the Atari is capable depend on altering a set
of instructions in RAM called the display list. This article is
devoted to the display list (DL) and how to modify it for our own
purposes. The article contains a number of demonstration programs
which are explained in the text and in REM statements in the program
itself. When typing them in, always type in the lines with REMs
in them (at least the line number plus REM, if not the whole line)
as in some cases these lines are used for GOTO and GOSUB statements.
I would recommend that when reading the article the program listings
are studied along with the text.
THE TV-SCREEN DISPLAY
Virtually every display list article
I have ever seen starts off with a discussion of how the TV display
is produced. This one is no exception, so those readers who already
know how this works can skip to the next section.
An image is produced on a television
screen by a stream of electrons which strike a phosphor coated surface
causing it to glow. The electron beam starts from the top left-hand
corner of the screen and moves horizontally from left to right.
When it reaches the right-hand edge, it is switched off, moved back
to the left side and down a fraction {this is the 'horizontal blank'
period). It is then switched back on and the process repeated, until
the beam reaches the bottom right-hand comer of the screen. At that
point, it is switched off and brought back to the start position.
Thus, the screen image is continually being redrawn (or 'refreshed')
- 50 times per second in the UK PAL system. This is much too fast
for the eye to follow and the image appears to us to be stable.
However, some flicker does occur and may account for the eyestrain
suffered by some people after long periods at their machine.
The picture is therefore built
up from a stack of horizontal lines across the screen, these are
usually termed 'scan lines'. The Atari can generate 262 scan lines,
but not all of these are used in order to ensure the image appears
on the screen of all makes of television. In fact, 192 scan lines
are used to create the image. It is no coincidence that the maximum
vertical resolution of the Atari is 192 (in Graphics 8-11 and Antic
modes 12 and 14). In these modes, each horizontal row is one scan
line high. The rows (or 'mode lines') of other graphics modes are
composed of more than one scan line (e.g. one mode line of Graphics
0 is eight scan lines high). Table 1 shows how the mode lines of
each graphics mode are made up, plus the resolution and memory requirements
for each mode.
Table 1: The ATARI Graphics modes
BASIC
mode
|
ANTIC
mode
|
Resolution (max)
|
Colours
|
Scan
lines/
mode lines
|
Bytes/
line
|
Memory
|
Type
|
0 |
2
|
40x24
|
1
|
8
|
40
|
960
|
T
|
-
|
3
|
40x19
|
1
|
10
|
40
|
760
|
T
|
12
|
4
|
40x24
|
5
|
8
|
40
|
960
|
T
|
13
|
5
|
40x12
|
5
|
16
|
40
|
480
|
T
|
1
|
6
|
20x24
|
5
|
8
|
20
|
480
|
T
|
2
|
7
|
20x12
|
5
|
16
|
20
|
240
|
T
|
3
|
8
|
40x24
|
4
|
8
|
10
|
240
|
G
|
4
|
9
|
80x48
|
2
|
2
|
10
|
480
|
G
|
5
|
10
|
80x48
|
4
|
4
|
20
|
960
|
G
|
6
|
11
|
160x96
|
2
|
2
|
20
|
1920
|
G
|
14
|
12
|
160x192
|
2
|
1
|
20
|
3840
|
G
|
7
|
13
|
160x96
|
4
|
2
|
40
|
3840
|
G
|
15
|
14
|
160x192
|
4
|
1
|
40
|
7680
|
G
|
8
|
15
|
320x192
|
1
|
1
|
40
|
7680
|
G
|
9-11
|
15
|
80x192
|
var.
|
1
|
40
|
7680
|
GTIA modes
|
Notes
1)
GTIA modes have identical DLs
to Graphics 8.
2)
Total memory requirements shown
are for full-screen modes (no text window) without any added unused bytes or for the DL. See ‘Mapping the ATARI’ pp. 17-21.
3)
BASIC modes 12-15 are not available
on the 400/800 series.
4)
T = Text mode, G = Graphics
mode.
The fundamental unit of horizontal
measurement on the screen is the colour clock. This is actually
a hardware limitation in that a colour clock is the length of the
smallest possible dot on the screen whose colour can be controlled
independently of adjacent dots. The Atari can display a screen 228
colour clocks wide, but only 160 of these are used on a normal screen
to ensure the sides of the picture are not cut off on the television.
(Although this produces a border at each side, at least the care
taken by the Atari's designers ensures the machine will work with
virtually any TV - unlike some inferior machines, which won't).
The machine can also light each
half of a colour clock independently, producing a maximum horizontal
resolution of 160 x 2 = 320 points, although this sacrifices additional
colour for the reasons given above. Incidentally, a pixel (picture
element) is the basic graphics unit which varies in size from one
mode to another. In text modes, one pixel is usually taken to mean
one character, although the individual dots making up each character
are also sometimes called pixels - very confusing!
THE ANTIC CHIP
Discussion of TV screen displays
is all very well but what has this to do with the display list?
Well the TV display is under control of a separate microchip inside
the Atari called Antic. Being a separate microprocessor, it needs
a program to run it, which is in fact the purpose of the DL. The
Display List is located in RAM, although its exact location depends
on the graphics mode in use and the amount of memory installed in
your machine. The Atari therefore has a pointer to the first byte
of the DL at locations 560 and 561. The start of the DL is stored
here in LSB/MSB format, so that in BASIC the start can be found
by:
DL= PEEK(560)+256*PEEK(561)
Before we go on, take a look at
Table 2. This contains some additional important memory locations
I shall be referring to in this article.
Table 2: Summary of memory locations
Location |
Name |
Description |
88, 89 |
SAVMSC |
Location of the first byte
of screen memory in low and high byte format (i.e.
SCREENMEM=PEEK(88)+256*PEEK(89)).
The first byte is displayed in the top left-hand corner
of the screen. |
87 |
DINDEX |
Contains the current Graphics
mode number (the BASIC/O.S. number, not the ANTIC number). |
660, 661 |
TXTMSC |
Identical to 88, 89, but for
the text window memory area. |
659 |
TINDEX |
Identical to 87 for the text
window. |
560, 561 |
SDLSTL |
Location of the first byte
of the display list in low and high byte format. Change
these locations to point to your own DL if you set up a
new one elsewhere in memory. |
512, 513 |
VDSLST |
Location of the first byte
of a DLI service routine in low and high byte format. |
559 |
SDMCTL |
Direct Memory Access Control.
Controls playfield width and Player-missile graphics enabling.
POKEing with zero turns off ANTIC; POKE with 34 (or press
System Reset) to turn it back on with a standard width playfield
and no PMG. |
54276 |
HSCROL |
Horizontal fine scroll register.
Will fine scroll up to 16 colour clocks horizontally; bit
four of the display list mode line instruction must be set
to enable this register (add 16). |
54277 |
VSCROL |
Vertical fine scroll register;
scrolls up to 16 sca lines vertically. Bit five of the DL
mode line code must be set (add 32). |
106 |
RAMTOP |
Top of useable RAM (in pages)
in the computer. Can be user-altered to reserve space for
character sets, Player-missile graphics, etc. Initialised
to 160 in a 48K system. |
Listing 1
|
|
|
At this point, type in and run
Listing 1. I suggest you save this program, as it will allow you
to examine the DL for any Graphics mode. The program will ask if
you want a printout as well as screen display. Type the letter N
if you don't have a printer. As an example, on being asked which
mode type '1' and press RETURN. After a second or two, you should
see something like this:
Display List for Graphics 1
112,
112, 112, 70, 128, 157, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 66, 96, 159, 2, 2, 2, 65, 94, 157
This is the DL for Graphics 1.
Some of the numbers may be different in your machine. These are
memory locations which depend on the amount of memory fitted in
your computer. Let us now examine the meaning of the various numbers
present in this DL.
The first three numbers are 112
(decimal). Each 112 is an instruction to Antic to leave eight blank
scan lines, making a total of 24 blank lines at the top of the screen.
No data can be displayed on these lines, which take the border colour
as default.
Why put blank lines there at all?
This is to prevent picture cut-off or 'overscan' at the top of the
screen. To see this, press Break and then type in direct mode:
DL=PEEK(560)+256*PEEK(561): POKE
DL,0: POKE DL+1,0: POKE DL+2,0
You will see the picture move up,
and on some TVs the top may actually be cut off. What this means
is that when designing your own DLs, you should always start with
24 blank lines. However, you can display less than 24 if absolutely
necessary. Table 3 shows the instructions needed to display from
one to eight blank lines.
Table 3: Blank line instructions
Instruction code |
Number of blank lines |
0 |
1 |
16 |
2 |
32 |
3 |
48 |
4 |
64 |
5 |
80 |
6 |
96 |
7 |
112 |
8 |
You are not restricted to putting
blank lines at the top of the screen. Listing 3 below shows how
blanks can also be used in the middle of the DL. This program is
explained more fully below.
The next number (70) is one of
the most important in the DL. It is in fact made up of two instructions:
64 (Load Memory Scan) plus 6 (Graphics Mode 1 instruction - see
Table 1). The LMS instruction is a very simple one in spite of its
name, since its function is to tell Antic the location of the first
byte of memory to be displayed on the screen. The LMS code should
always be present added to the code for one mode line of one of
the various graphics modes. If this is not done, blank scan lines
will be displayed instead. In addition, the LMS code must always
be followed by two bytes (128 and 157 in the above DL - this may
vary in your machine). These two bytes are the location, in conventional
low- and high-byte format of the start of display memory, and unless
deliberately altered will be the same as in locations 88 and 89.
By altering just these two bytes, you can cause your Atari to display
the contents of any area of memory on the screen! Would you like
to see what is happening in the very low RAM area? Type:
DL= PEEK(560)+ PEEK(561)*256: POKE
DL+4,0: POKE DL+5,0
You are now looking at what is
going on in Page 0 and succeeding Pages 1 to 3. If you wish, you
can set an LMS instruction on every mode line, so that each line
displays a different area of memory.
Following the LMS code and its
two operand bytes, there are a series of 6' s. These are the Antic
instruction codes for Graphics 1 (remember that Antic uses different
code numbers to BASIC and the Operating System). If you count them,
you will see that there are 19 '6' codes, which together with the
one incorporated in the LMS code makes a total of 20 mode lines
of Graphics 1.
Following these is another LMS
instruction with a Graphics 0 code added. This directs Antic to a
different memory area for the text window, which is of course in
Graphics 0. The following two bytes are the start of the text window
memory area and are followed by three lines of Graphics 0.
The final three bytes are an instruction
to Antic to go back to the start of the DL and repeat the program
over again. The code 65 means 'jump and wait for vertical blank',
this is telling Antic not to start drawing the screen until the
electron beam has returned to the top left-hand corner and the vertical
blank period is over. The two bytes following the Jump instruction
are the starting memory location for the DL itself, and are therefore
the same as in locations 560 and 561. Your DL must always end with
this instruction.
Simple arithmetic shows that we
have 20 lines of Graphics 1 each eight scan lines high, and four
lines of Graphics 0, also eight scan lines high. This makes a total
of 20 x 8 + 4 x 8 = 192 scan lines. When designing your own DL,
you should always approach this magic figure as closely as possible.
Having less than 192 scan lines doesn't matter - you merely have
a slightly smaller picture - but exceeding 192 does matter, since
it may cause the picture to roll unpleasantly. If you must exceed
192, compensate by reducing the number of blank lines at the top
- but remember that you may get picture cut-off as a result.
Now rerun Listing 1, and this time
examine the DL for Graphics 8. You will see that as well as the
LMS at the start of the DL and the one for the text window, there
is a third in the middle of the DL. This must be present because
of a limitation of Antic's memory counter, which cannot count past
a 4K memory boundary. The practical meaning of this is that any
Graphics mode displaying more than 4K of screen memory (e.g. Graphics
8-11) will need an additional LMS instruction in its display list
in order to reset the memory counter and cross the 4K barrier.
There are three final instructions
to consider, which don't appear in the 'built-in' DLs. These are:
128 call Display List Interrupt
16 horizontal fine scroll
32 vertical fine scroll
Any or all of these can be added
to to any mode line (together with the LMS code if you wish). They
are discussed more fully overleaf.
CUSTOM BUILT DISPLAY LISTS
There is no need for the Atari
programmer to be restricted to the 'official' DLs and Graphics modes
programmed into the Atari. By modifying the DL you can format the
screen in virtually any way you wish. It is easiest to explain how
this is done by means of examples.
Before we start I should point
out that there are two ways of going about creating your customised
DL. The first is to modify an existing DL, set up by a GRAPHICS
statement, and the second is to create an entirely new one somewhere
in a protected memory area. In general I would recommend the second
approach, except for very small changes, since you can then bring
your new DL into effect simply by changing the pointer at locations
560 and 561. Changing an existing DL may take a noticeable amount
of time, and may be impossible if your new DL is longer than the
existing one.
Example 1: Graphics 8 is fine in
terms of resolution, but sadly lacking in colour. What is worse,
the text window is in the same colour as the main part of the screen.
However, we can improve this by changing the text window to Graphics
1, allowing four colour text. Listing 2 does this.
Listing 2
|
|
|
This program is very straightforward,
it finds the start of the Graphics 8 DL and then POKEs the appropriate
locations with the Antic code for Graphics 1. Line 40 may need some
explanation however. The Operating System thinks that the text window
is in Graphics 0 - but Antic must now display it as Graphics 1.
This is a potential conflict, since the 0.S. allocates 40 bytes
per line for the text window, whilst Antic only uses 20 bytes per
line. This would alter the position of text PRINTed in the window.
We resolve this by telling the 0.S. that the window is now in Graphics
1 by POKEing location 659 with 1.
Example 2: I indicated earlier
that it was possible to insert blank scan lines in the middle of
a DL. This is demonstrated by Listing 3. This effect gives rather
an attractive 'ruled page' appearance which could be useful in long
text displays to break up the text (for example, in text adventures).
Notice that the screen editor entirely ignores the blank lines -
the cursor jumps from one mode line to the next. Unfortunately,
putting in the blanks means that we can only put 21 Graphics 0 lines
on the screen - this makes it difficult to use this screen for typing
in a BASIC program for example (try it, and see what happens when
you reach the bottom of the screen).
Listing 3
|
|
|
However, this program also demonstrates
how to set up a new DL from scratch. It must be placed in a suitable
memory area - such as page six. Display lists are not relocatable
due to the jump instruction at the end. The first three lines of
the program READ the DATA for the new DL and POKE it into page six.
Remember that zero is the code for one blank line and two is the
code for Graphics 0. We must then allocate some memory space for
the screen - in this case, done easily by the Graphics 0 call in
line 70. We then need to know the starting memory location for the
screen memory, which can be found from locations 88 and 89. These
values are POKEd into the appropriate locations in page six. Space
was reserved for these by the two zeroes following the LMS instruction
(fourth number in line 50). If other LMS codes were present in our
new DL we would of course have had to reserve space for the two
bytes following each one. The final three bytes are the Jump instruction
followed by the starting location of our new DL - the beginning
of page six.
To bring our new DL into effect,
we first turn off Antic by POKEing 559 with zero (you don't have
to do this, but if you don't then the DL may be changed while Antic
is 1 actually drawing a screen, making the picture jerk - which
at best looks unprofessional). The DL pointer is then directed to
our new DL in line 90 by POKEing 560 and 561 with the low and high
bytes of the start of the new DL. Finally, Antic is turned back
on again with a POKE 559,34. You can get out of the new DL by any
GRAPHICS call. To get back again, simply repeat the steps in this
last paragraph.
Example 3: The final example (Listing
4) is a little more complex, but nicely demonstrates a problem encountered
when printing or drawing on a mixed-mode screen. Let us suppose
that we want to design an attractive title page for a new game.
We want to start off with giant text at the top of the screen, then
decrease in size towards the middle, where we will print a message.
The text will then enlarge again, and lastly there will be a text
window for displaying messages and inputting replies. We'll call
the program by some sort of dramatic name - say, ‘INVADERS', in
honour of those little green men who started it all.
Type in Listing 4. Lines 10 to
90 should now be straightforward. Memory is assigned for our screen
in line 70, and then the new, mixed-mode, DL is set up. The starting
memory location for the text window is obtained from locations 660
and 661 (see Table 1). The method for plotting giant text in Graphics
4 comes from John Hulme in Page 6 issue 8.
Listing 4
|
|
|
The real problem is, how do we
PRINT or PLOT to the mixed graphics modes when the O.S. thinks we're
in Graphics 0? There are two ways around this. The first is to treat
each group of identical mode lines (or more generally, groups of
lines with identical memory requirements) as a sort of graphics
'window'. For each window, we would then POKE the screen memory
locations 88 and 89 with its starting memory location and to be
on the safe side do a POSITION 0,0 to return the cursor to the top
left-hand corner of the window. We then POKE 87 with the appropriate
BASIC (not Antic) mode number and can now use the normal BASIC printing
and drawing commands. Alternatively - especially for character graphics
- we could calculate the offset from the start of screen memory
and POKE the internal character codes (not the ATASCII codes) directly
into the screen memory.
So much for the Display List itself.
I suggest you experiment with the above examples and create your
own DLs. In the next part of this article, I want to concentrate
on some further applications of display list manipulation - the
'hidden' graphics modes, page flipping, the Display List Interrupt,
and scrolling.
top