Chapter 6 Vertical Blank & Display List Interrupts
In this chapter you will learn to use Vertical Blank and Display List
Interrupts. These interrupts are a powerful aid to the game programmer,
who can use them to smooth animation, to enable players to be re-used in
the bottom portion of the frame, to allow character sets and color
registers to be changed mid-screen, and of course much more.
As you learned in the first chapter, "Vertical Blank" refers to the
period of time the television set takes to reposition the electron beam
back to the top left edge of the screen after raster scanning or drawing
one television frame. Since television frames are generated every 1/60th
of a second, there are sixty Vertical Blank periods a second, one for each
frame.
Since nothing is happening on the television screen during the Vertical
Blank period, it presents an ideal opportunity for a program to change the
positions of objects on the screen in order to animate them. If you only
knew when the Vertical Blank period occurred, you could take advantage of
this time to create smooth and flicker-free animation.
The ANTIC chip in the computer lets you do just that. Since it and the
GTIA/ CTIA chip generate the television image, they need to know what is
happening on the screen at all times. When Vertical Blank occurs, an
interrupt is generated on the Atari's 6502 CPU.
An interrupt is simply a way of telling the computer to stop what it is
doing, handle something more important, then return to what it was
previously doing. The 6502 checks the interrupt status after executing an
instruction. If an interrupt occurred, it saves the Program Counter
(marking its current place in the program) and the processor status
register onto the stack. It then jumps through one of a number of preset
vectors, depending on the type of interrupt that occurred. Once the
interrupt has been handled, the program will RTI (return from interrupt
instruction) back to the instruction that was to be executed before the
interruption.
ANTIC also generates Display List Interrupts. If you recall the
discussion on display lists, you remember that the display list is really
a program for ANTIC. Each byte in the display list is part of a series of
instructions that lets ANTIC know what type of information is to be
displayed. Setting the high bit in an instruction in the display list will
trigger an interrupt when it is time for the television beam to display
the information for the last scan line in that graphics mode line. This
type of interrupt is sometimes called a "Raster Interrupt." Remember that
the interrupt does not stop the TV raster process but causes the 6502 to
execute a series of instructions at this specific time.
Vertical Blank and Display List Interrupts (DLI's) are sent to the 6502
NonMaskable Interrupt (NMI) vector at $FFFA. It is called non-maskable
because these interrupts cannot be disabled on the 6502 CPU as can other
types of interrupts. Three interrupts go to the NMI vector. They are
Vertical Blank, DLI's, and System Reset. Although these interrupts cannot
be masked off on the 6502, ANTIC filters the first two. A memorymapped
hardware register in ANTIC, NMIEN ($D40E), allows the programmer to enable
or disable Vertical Blank and Display List Interrupts. Another register,
NMIST ($D40F), shows which interrupt actually occurred. When an NMI
occurs, the 6502 goes to an OS routine to find out what caused the
interrupt. If a DLI occurred, this routine vectors through page-two
vectors to a DLI service routine that changes one or more graphics
registers which control display. On the other hand, if a VBI occurred, the
OS routine saves the Accumulator, X and Y registers on the stack, then
jumps through the appropriate page-two vector to the Vertical Blank
routine. And if System Reset was pressed, it goes directly to the OS warm
start vector for system reset ($E474).
Vertical Blank InterruptsThe Atari computers use the Vertical
Blank Interrupt for many housekeeping chores. When the Atari is first
powered up under normal conditions, the Vertical Blank Interrupt is
enabled. A special list of vectors is placed in page two of memory. The
operating system places the list of vectors in page two because these are
RAM locations and the user can change their contents to point to his own
interrupt service routine. System Reset is the only interrupt that cannot
be routed through page two.
The operating system's Vertical Blank Interrupt (VBI) service routine
is a twostage process. When an interrupt occurs, the computer is sent to a
vector in the operating system, which in turn sends it to a routine to
determine what type of interrupt has occurred. It then jumps through the
appropriate vector on page two. It is called two-stage because it goes
through two vectors on page two. This allows the programmer to use either
his own VBI routine or that of the OS, or both.
The OS uses the VBI routine to transfer data from some of the special
hardware registers in Atari's custom chips to shadowed locations in RAM
and vice versa. For example, it reads the color register information, the
location of the display list, and other graphics control information
placed in RAM by the user, and writes them to their hardware addresses. It
also reads many hardware registers such as game controllers and light pen
and places them in RAM for the user. It updates the clock at locations
18-20 ($12-$14), and updates the timer for the attract mode which cycles
the colors if a key has not been pressed for several minutes. It even
takes care of the repeat action on the keyboard keys. Because the VBI
routine updates many registers that are used by the average program, most
programmers don't wish to replace it entirely by their own routine, since
in many cases it would mean duplicating at least some of the procedures
that are handled automatically by the OS.
The vectors are called Immediate VBlank and Deferred VBlank. Atari
engineers split the Vertical Blank period into two separate sections
because a VBI can extend for about 20,000 cycles or nearly all the time
available before the next VBI. The Immediate VBlank portion refers to the
time critical period when the electron beam is actually offscreen. It is
here that shadowing and hardware registers are updated. Once the OS VBI
routine has completed its housekeeping chores, it jumps through the
Deferred VBlank vector, which is set by the OS to point to a routine that
will restore the registers and return the computer to its position before
the interrupt. The OS VBI routine will abort if the computer was in the
middle of a time critical I/0 routine such as sending data to a cassette
or disk drive. In such a case, the Deferred VBlank vector is bypassed.
Unless you are using disk 1/0 where your code must be short enough not to
delay shadowing updating, you can use Deferred VBlank without being
concerned.
A major question asked by many programmers is: How much time do I have
in the VBI routine to execute my code? To answer this we must examine the
TV process again.
A television image is composed of 525 lines. Because of what is called
interlacing, only half are drawn per frame, and some of these are
offscreen due to normal vertical overscan. It takes the TV 63.5
microseconds to draw a single line. This includes the time it takes to
shut the electron beam off and reposition it back on the left edge one
scan line below. The length of Vertical Blank is equivalent to 22 scan
lines or roughly 1400 microseconds. With the Atari's 6502B CPU running at
1.79 MHz, 1400 microseconds is equivalent to approximately 2500 machine
cycles (1400 X 1.79 = 2506). So, how much can you do "inside" the Vertical
Blank period? Not very much, if you are trying to accomplish things like
moving players and scrolling the screen solely inside the Vertical Blank
period. The important thing to remember is that one television frame is
1/60th of a second, which is equivalent to 16,666 microseconds or just
about 30,000 machine cycles. This means that there is a maximum of
approximately 30,000 machine cycles BETWEEN Vertical Blanks. ANTIC delays
processor time in order to fetch screen data and look up character data
during the screen drawing process. A programmer using an extensive
Vertical Blank Interrupt routine will want to be sure that the routine is
finished before the next VBI occurs; otherwise, his routine will be
aborted in the middle unless very special precautions are taken. A
programmer will also want to be sure that his VBlank routine is not so
long that it causes serious delays to the program code that is running
outside VBlank.
Programmers often ask if the 2500 cycle VBlank time constraint
seriously limits the amount of time for smooth offscreen animation and
updating. The answer is No! True, all of the graphics updating must be
performed while the beam is offscreen, but you can also gain some
additional time. Remember what a normal display list looks like. It begins
with 24 blank lines. That gives 24 by 63.5 microseconds/line or another
2728 cycles that can be considered offscreen. High scores, player scores
and messages generally cover the top few lines too. This adds additional
time offscreen. Obviously if your Vertical Blank routine is even longer,
you should be OK as long as you do all of your graphics updating within
the first 5200 cycles of your routine. Figure that you have a maximum of
20,000 cycles (4500 instructions) in Deferred VBlank, but you must finish
before the next VBI or your program will crash.
While programmers have written entire games in Deferred VBlank, only
certain operations should be put in VBlank. All graphics updating,
including scrolling the screen, moving player-missile objects, and
changing color registers, should definitely be done in VBlank. In
addition, collisions should be checked, and joysticks or paddles should be
read. This is also the best place to implement time critical sound
routines. Everything else, including calculations, should be in your main
code outside VBlank.
Setting up a Vertical Blank Interrupt is a simple process since the OS
has a routine to set up the vector for you. All it involves is storing the
address of your VBI routine in the vector table on page two of RAM. If a
VBI has occurred between the time the two bytes that make up the vector
were stored in the table, the 6502 would jump through an erroneous
address, and the program would become erroneously lost. The OS setup
routine automatically assures this never happens.
Setting up the routine is simple. Load the Accumulator with 7 if you
are setting a Deferred VBlank routine, and 6 if you are setting an
Immediate VBlank routine. The X register is loaded with the high order
byte of your routine, the Y register with the low order byte. You then JSR
to the OS SETVBV routine at $E45C.
Example: SETVBV .EQ $E45C
LDA #$07 ;DEFERRED
LDX /VBLANK ;HIGH BYTE OF USER ROUTINE
LDY #VBLANK ;LOW BYTE
JSR SETVBV
There are two possible exit points from a VBlank routine depending on
whether Immediate or Deferred VBlank is used. If the programmer uses the
Immediate one and still desires to use the OS VBI routine, the vector is
$E45F (SYSVBV). If the Deferred VBlank is used or the programmer does not
want the OS VBI routine to execute the vector, then it is $E462 (XITVBV).
The XITVBV routine pulls the registers off the stack and does a RTI
(Return from Interrupt).
Display List InterruptsDisplay list interrupts are generally used
to change the color registers midscreen or switch character sets in use.
These changes can be made very rapidly since they are short and usually
modify only a few bytes. Take care so that changes of this type are
offscreen during Horizontal Blank, or they will appear crude and annoying.
When ANTIC encounters the DLI instruction, it completes the last scan line
for the mode it is drawing, then services the interrupt. This means in
effect that the interrupt must be set during the mode line above the one
you want the interrupt to effect.
The period of Horizontal Blank is seven microseconds. Horizontal
Overscan is another 3.31 microseconds. These 10.31 microseconds mean
approximately eighteen machine cycles offscreen. In order for an interrupt
routine to synchronize with Horizontal Blank, a special hardware register
in ANTIC freezes the 6502 until Horizontal Blank occurs. Thi's register at
$D40A is known as WSYNC. Writing to this location pulls down the ready
line on the CPU until Horizontal Sync. If you insert a STA WSYNC
instruction, then change the value in a color register, color won't be
changed in The Middle of the current line but will go into effect when the
beam is off the left edge of the screen one scan line lower.
What if eighteen cycles are not enough time to make all the changes you
need? There are several approaches that can be taken, and the proper one
depends of course upon the situation.
As with the VBI, you need not worry about crashing the program because
the code does not fit in the Horizontal Blank time or even within the time
it takes to do the entire scan line. Only if the code is so long that
another DLI occurs before the previous one has finished would you be
likely to run into problems and crash the program. There is no reason to
believe that you must complete the interrupt routine by the end of the
scan line. There are some programs that have one DLI set at the top of the
screen and do not return from the interrupt until the entire screen has
been drawn, hundreds of scan lines and thousands of machine cycles later.
The interrupt routine is used to control graphics information to the
screen, line by line. A DLI routine written in this manner is called a
kernel.
Programmers using DLI's for simple screen changes should decide if all
of them must be made on a single line. Perhaps only a few changes need be
made immediately. The rest can be made on the next line by waiting again
for Horizontal Sync. All the changes must be made on a single line, if
there is a major screen division between the score line and the playfield
requiring different colors and character set. In this case, it might be
practical to insert a zero in the display list. A zero is the blank line
instruction in a display list. Changes could be made past Horizontal Blank
on this line while the raster beam is drawing it and still be invisible to
the viewer.
There is one more important point for those readers who still need to
count cycles. Although a horizontal line takes 63.5 microseconds, you do
not have 113 cycles per line (63.5 x 1.79 = 113.6). This is because
ANTIC's Direct Memory Access (DMA) ability allows it to freeze the 6502
CPU and steal cycles in order to get screen data from screen memory,
player/missile data from player/missile memory, and to look up character
set data. It even steals cycles to look at the display list so it knows
what type of information to display. The amount of time stolen per scan
line can vary. ANTIC steals a cycle for each byte in memory it must
access. This DMA is controlled by a hardware register called DMACTL at
$D400 (54272 decimal). The OS VBlank routine rewrites the value found at
its shadow (SDMCTL) at $22F (559 decimal) every VBI. By setting bits in
SDMCTL, the program can control screen width from either 128, 160, or 228
color clocks. Selecting screen width tells ANTIC it may steal cycles from
the 6502 to access the display list and screen memory in order to display
information. Bits are also set here so that ANTIC may steal cycles to look
up player and/or missile data in memory.
If you want an idea of how much time you lose from DMA, try the
following example in BASIC.
10 FOR LI=1 TO 1000:NEXT LI
Then try:
10 POKE 559,0:FOR LI=1 TO 1000:NEXT LI:POKE 559,32
The second example is approximately 30% faster. The first POKE disables
ANTIC's DMA, and the screen becomes black. The second POKE restores DMA
after the loop is completed so we know how long it takes. If you were to
try the first example in different graphic modes, you would find Graphics
8 the worst case, This is because Graphics 8 uses much more memory, so
ANTIC must steal more cycles in order to access more screen memory.
However, the Graphics 0 text mode isn't much faster because ANTIC also
steals cycles while retrieving the characters set.
Display List Interrupts are even simpler to set up than Vertical Blank
Interrupts. Since there is no DLI enabled when the program takes control,
the program simply has to store the low byte-high byte address of the
routine into the vector on page two (VDSLST-$200,$201). Once the vector
has been stored and the display list is set for an interrupt, NMIEN is set
to enable DLI's. Bit 7 of NMIEN enables DLI's. Bit 6 enables VBI's.
Storing a $CO (192 decimal) is all that is needed to enable the DLI.
Example: VDSLST .EQ $200 ;DISPLAY LIST INTERRUPT VECTOR
NMIEN .EQ $D40E
LDA #VBI ;LOW BYTE OF DLI ROUTINE
STA VDSLST
LDA /VBI ;HIGH BYTE OF DLI ROUTINE
STA VDLIST+1
LDA #$CO
STA NMIEN ;ENABLE DLI'S
;WITHOUT DISABLING VBI'S
Since the OS does not save the Accumulator, X and Y registers for a DLI
as it does for a VBI, the user must save any registers used in the DLI
routine on the stack upon entering the interrupt routine and restore them
before exiting. If this is not done, the program will unquestionably
crash.
The power of DLI's is obvious. With a DLI, a program can easily switch
character bases from the standard ROM text set to a redefined character
graphics set. Without a DLI, the programmer could only redefine characters
that would not be used in the text display. DLI's enable you to change
color registers mid-screen. A good example is a game like Sea Wolf (a
submarine game) in which the background color changes from sky blue to
ocean blue partway down the screen. Without a DLI to change the background
color, one other playfield color register would have to be used for either
the sky or ocean, thus limiting further the amount of color available for
the screen. Multiple DLI's can be used to control screen scrolling in
games like Frogger in which different bands on the screen scroll in
different directions at different speeds.
DLI's can change player/missile horizontal positions and colors so
players can be reused down the screen as long as vertical positions do not
need to overlap in the same player. A player, which is actually a long
vertical stripe, can have several different smaller images. The DLI allows
you to snip the strip apart and reposition those pieces in the lower
portion by changing the player's horizontal position register. If vertical
movement is required, you must be careful that the different images don't
cross the boundary. Since collision registers are set by the hardware when
collision occurs, collision registers can be read within the interrupt
routine so that hardware collision detection is not lost by reusing the
players. A good example of reusing the players is the Atari Galaxian
cartridge.
BASIC can use a DLI to change one or more color registers at a
particular spot mid-screen, if a short Machine language routine is added.
The example below changes the background color register in the text mode
to orange and darkens the color of the characters so they show up against
the background. This is controlled by the color in playfield 2. The change
occurs in line 12 so that the interrupt is set in the mode line preceding
the change. The modified display list is as follows. 112
112 Blank 24 scan lines
112
66 |LMS for BASIC 0 (ANTIC 2) (64+2)
64 |Low byte of screen memory
156 |High byte of screen memory
2 second mode line
2
2
2
2
2
2
2
2
130 Eleventh mode line + DLI (128+2)
2
2
.
.
Since the display List is virtually identical, except for the
modification in the eleventh mode line, we need only change that byte to
activate our DLI. This is at the DLIST+15 byte.
5 REM FIND DISPLAY LIST
10 DLIST=PEEK(560)+256*PEEK(561)
15 REM INSERT INTERRUPT INSTRUCTION
20 POKE DLIST+15,130
25 REM READ IN DLI SERVICE ROUTINE
30 FOR I=O TO 19
40 READ A:POKE 1536+I,A:NEXT I
50 REM POKE IN INTERRUPT VECTOR
60 POKE 512,0:POKE 513,6
70 REM ENABLE DLI
80 POKE 54286,192
90 DATA 72,138,72,169,38,162,90
100 DATA 141,10,212,141,26,208
110 DATA 141,24,208,104,170,104,64
The actual Machine language DLI service routine is as follows: D01A: 00010 COLBK .EQ $DO1A
D018: 00020 COLPF2 .EQ $D018
D40A: 00030 WSYNC .EQ $D40A
4000: 48 00040 PHA ;SAVE ACCUMULATOR
4001: 8A 00050 TXA
4002: 48 00060 PHA ;SAVE X-REGISTER
4003: A9 52 00070 LDA #$52 ;DARK COLOR FOR CHARACTERS
4005: A2 26 00080 LDX #$26 ;ORANGE BACKGROUND
4007: 8D OA D4 00090 STA WSYNC ;WAIT
40OA: 8D 1A DO 00100 STA COLBK ;STORE COLOR
40OD: 8D 18 DO 00110 STA COLPF2 ;STORE COLOR
4010: 68 00120 PLA
4011: AA 00130 TAX
4012: 68 00140 PLA
4013: 40 00150 RTI
Care must be taken when using multiple DLI's. There is only one vector
for a DLI Setting NMIEN enables DLI's immediately and therefore does not
wait for the next frame. Your program must insure that the proper routine
will be executed. Three methods are available. The first method is to use
a variable as an index that is incremented by each DLI The program then
branches to the appropriate routine depending on the value of the index.
The second method is to read the vertical line counter and branch to the
appropriate routine. The third method is the cleanest. Each DLI routine
resets the DLI vector on page two (VDSLST) to point to the next. The DLI
is enabled within Vertical Blank and VDSLST is reset to point to the first
DLI routine in VBlank.
The following example is a simple DLI routine to change the background
color of a text screen similar to the Sea Wolf example. 00010 VDSLST EQ $200 ;DISPLAY LIST INTERRUPT VECTOR
00020 SDLSTL EQ $230 ;STARTING ADDRESS OF DISPLAY LIST
00030 WSYNC EQ $D40A
00040 NMIEN EQ $D40E
00050 COLPF2 EQ $DO18
00060 PAGEO EQ $FO
00070 LDA SDLSTL ;FIND DISPLAY LSIT
0080 STA PAGEO ;DISPLAY LIST LOW BYTE
00090 LDA SDLSTL+1
00100 STA PAGE0+1 ;SAVE HIGH BYTE
00110 LDY #$08 ;3RD TEXT LINE INA A GRAPHICS 0 DISPLAY LIST
00120 LDA (PAGEO),Y ;GET DISPLAY LSIT INSTRUCTION
00130 ORA #%10000000;TURN ON HIGH BIT ($80)
00140 STA (PAGEO),Y ;AND STORE IT BACK IN THE DISPLAY LIST
00150 LDA #DLI ;DLI LOW BYTE
00160 STA VDSLST ;STORE LOW BYTE OF OUR ROUTINE IN DLI VECTOR
00170 LDA /VBI ;GET HIGH BYTE OF OUR DLI ROUTINE
00180 STA VDSLST+l ;STORE HIGH BYTE OF VECTOR
00190 LDA #%11000000; ENABLE DLI AND KEEP VBI ($CO)
00200 STA NMIEN
00210 RTS ;AN RTS SHOULD RETURN THE PROGRAM
00220 ;BACK TO THE DEBUGGER WHEN RUN
00230 DLI PHA ;SAVE ANY REGISTER THAT WILL BE USED
00240 LDA #$A2 ;DEEP BLUE
00250 STA WSYNC ;WAIT FOR SYNC FOR NEXT LINE
00260 STA COLPF2
00270 PLA ;RESTORE ACCUMULATOR
00280 RTI ;RETURN TO MAIN PROGRAM
Binary representation was used for clarity in this example.
KernelsA kernel is a special DLI routine designed to control
graphics information on a line-by-line basis for the entire screen. It
does this by monitoring the VCOUNT (vertical line counter) register. The
most frequent use is for producing multi-colored players. Even the player
width can be changed on a line-by-line basis. For example, a cowboy image
could be made out of one player; a broad white hat defined at double width
changes a few scan lines down to a slim pink face, then changes a few scan
lines down to a brown cowboy suit and finally to black boots; four colors
and two different resolutions in a single player. Another example is the
players in Atari's Basketball cartridge. You cannot create multi-colored
players like these without Display List Interrupts because DLI's are keyed
to playfield vertical positions, not player positions.
Kernels are difficult to use because graphics information changes only
during Horizontal Blank. Kernels also drastically reduce the amount of
time available for program logic, since most of the 6502's time is spent
writing graphics information and waiting for Horizontal Sync on the next
line. Since virtually no computation time is available during display
time, and only about 4000 cycles are available during Vertical Blank and
overscan time, kernels are limited to simple skill and action games.
Multi-Colored Joystick Controlled PlayerThe following example
illustrates the use of a kernel to produce a joystickmovable,
multi-colored player. The player is 15 bytes high, but it also includes
two zero bytes on each side so that it erases itself as it moves. There is
no actual erase feature in this example. The player is controlled by a
joystick. This is not the standard routine but an alternate one that uses
table lookup to determine its horizontal and vertical movement. The
formulas are as follows:
PLAYRH = PLAYRH + HOFF(STICK) PLAYRV = PLAYRV + VOFF(STICK)
For example, if the joystick points to the right and up, STICK has the
value 6. HOFF(6)=$02, and VOFF(6)=$FE or a -2. The player position changes
to a location two scan lines up and two pixels right.
The kernel itself is designed to change the player's color four
different times. To accomplish this it must wait for the vertical line
counter to reach the player's position. Since this counter, called VCOUNT,
actually increments every other scan line, we divide the player's vertical
position by two. We add one because we actually want to start one line
later. We have to wait for each horizontal scan to test for whether VCOUNT
has reached our player's position. If it has, we then begin fetching color
to put in the player's color register. Since the color changes every three
scan lines, we must wait for three more horizontal scan lines before
changing colors. The fact that we have to do a WSYNC for each scan line
prevents us from doing any calculations outside of Vertical Blank.
Download
MULTI.EXE (Executable program) Download
MULTI.OBJ (Object code) Download
/ View
MULTI.LST (Assembler listing) Download
/ View
MULTI.S (Source file) Download
/ View
MULTI.RAW (As printed in book)
Splitting Screen Horizontally Using DLIsOur second example of a
kernel produces a split color screen, but this time the split is across
the vertical axis with the left portion of the screen black and the right
pink. The kernel takes advantage of a careful timing loop after a WSYNC
instruction. It waits until the beam is offscreen for each scan line, so
the beam always reaches the same horizontal position before changing the
background color register to pink. The loop is a simple countdown from six
to zero. The background is restored to black for the next scan line
immediately after the WSYNC. Notice that the color change is fed directly
to the hardware color register. Remember that the kernel operates outside
of VBlank, and the shadowed background color register doesn't get copied
until VBlank. Thus, color changes must feed directly to hardware. We do
have a joystick-controlled player-missile routine operating in VBlank in
order to show that the kernel and it are entirely independent.
Download
MIDSCRN.EXE (Executable program) Download
MIDSCRN.OBJ (Object code) Download
/ View
MIDSCRN.LST (Assembler listing) Download
/ View
MIDSCRN.S (Source file) Download
/ View
MIDSCRN.RAW (As printed in book)
Using DLIs to Create AnimationThe third example shows a motorboat
crossing water. A kernel controls an eight-scan line segment at the
surface so that it appears that the water has waves. The interrupt occurs
on the fourth text line. Essentially, each bit of an eight-bit random
number is sequentially shifted right into the carry bit while in a loop.
If the bit is set, the routine changes the background color register to
light blue. If it isn't, it remains dark blue. Once the eight scan lines
aye drawn, the routine sets the background color to dark blue for the
remainder of the screen. A new wave pattern is picked every eight VBlanks:
otherwise, the waves would change too quickly.
The white motorboat consists of two players, get side by side. It is
moved in the VBlank interrupt routine which also provides the new random
number every eighth cycle. The sequence is clocked through the internal
clock at $14 called RTCLOC. ANDing the value with #$07 produces a positive
value if you. don't have an exact even multiple of eight because some
combination of the lowest three bits (1 -7) is set. In that case, the
routine branches to a new random number.
There are many other possible examples using kernels. Advanced
programmers might attempt to modify the second example so that a
non-joystick-controlled player might have its horizontal position changed
during the horizontal scan for each line. It is possible, using tight
timing loops, to reuse the player on the same scan line.
Download
WAVES.EXE (Executable program) Download
WAVES.OBJ (Object code) Download
/ View
WAVES.LST (Assembler listing) Download
/ View
WAVES.S (Source file) Download
/ View
WAVES.RAW (As printed in book)
Return to Table of
Contents | Previous
Chapter | Next Chapter
|