Exploring the ATARI® Frontier

The Player/Missile Connection: Part II


At the end of last month's article I presented a short PMG demo program to pique your interest (reprinted this month as Listing 1). Although it doesn't do much, it demonstrates a simple use of PMGs. This month, I'll dissect that demo to show how it works. PMGs are versatile because of the many options which affect the PMG display. Knowing what these options are and when to use them is important to understanding the entire PMG concept.

To select any particular option, you use a RAM location, known as a hardware register and its counterpart, called a shadow register. The hardware registers are wired directly into the ANTlC and GTIA processor chips for immediate use, while the shadow registers contain data accessible to and necessary for the Operating System (OS). This usually takes the form of a copy of all the data written into the hardware registers (for more on shadow/hardware registers, see Frontier in Issue 40). From BASIC you access these registers with PEEK and POKE commands. If you looked at the demo listing at any length you should have noticed a few strange POKE commands. To understand what each of these POKEs does, we'll take them one at a time and explain what their corresponding registers do. Table One is a list of the registers used in the demo program's POKEs.


Table 1


IMPORTANT PMG SHADOW REGISTER LOCATIONS


HexHexTitleRegister Description

006A00106RAMTOPTop of RAM pointer.
022F00559SDMCTLDirect Memory Access Control
02C000704PCOLR0Player 0 color.
02C100705PCOLR1Player 1 color.
02C200706PCOLR2Player 2 color.
02C300707PCOLR3Player 3 color.

IMPORTANT PMG HARDWARE REGISTER LOCATIONS


HexHexTitleRegister Description

D00053248HPOSP0Player 0 horizontal position.
D00153249HPOSP1Player 1 horizontal position.
D00253250HPOSP2Player 2 horizontal position.
D00353251HPOSP3Player 3 horizontal position.
D01D53277GRACTLGraphics control.
D40754279PMBASEMemory page for PM data.

Setting Up A PMG



In Listing One, the first line GOSUBs to line 500, where it sets up the PMG. Line 500 shows a particularly important setup procedure. Since the PMG structure is like a screen, it has its own set of screen RAM, called PMG RAM. The OS takes care of setting aside memory for the screen, but for PMGs, the programmer must do it. You need to find a section of memory not already used by the OS or BASIC, and protect it from outside interference. In a sense the OS already does this at power up or whenever the system reset key is pressed. The location called RAMTOP (see Table One) tells the system where the top of memory is. RAMTOP prevents the OS from occasionally putting important information like screen memory or the Display List in a nonexistent area of RAM. The OS also uses this location to protect itself from using an area of memory that should never be used. Thus we can fool the OS into thinkng it has a different amount of memory available by modifying this location. To tell the OS "hands-off," determine how much memory you need, and adjust this pointer.

The value stored in this location is in the form of a one byte absolute page number. A page in computer terms is 256 bytes, so four pages equals 1K of memory. A full 64K (including ROM and RAM) Atari has 256 pages numbered 0-255 . What line 500 does is set the Top-of-RAM-Pointer back eight pages from whatever it was previously. I later discovered that only four pages were needed. How to select the proper amount of memory will be covered later. Another important PMG POKE is in line 510. ANTIC and GTIA need to know the PMG RAM's location. Table One has a location marked PMBASE, which must contain the absolute page number of the PMG memory location. Since you have specified this address through the RAMTOP, all you have to do is POKE in the currently residing value.

Sometimes the location in RAMTOP is not pointing to the beginning of PMG data. This can happen when more memory has been reserved for such things as machine language subroutines, etc. In that case you should keep track of what page the PMG data is on with a separate variable. Once this location has been given a value, ANTIC and GTIA will use it for all of the processing for PMGs.



Program Listing 1
10 RESTORE:GOSUB 500
20 FOR X=0 TO 35 STEP 2
30 A=A+1:IF A=4 THEN A=1
40 COLOR A
50 PLOT 79-X,Y+6:DRAWTO 79-X,47-Y
60 PLOT 78-X,Y+6:DRAWTO 78-X,47-Y
70 DRAWTO X,47-Y:DRAWTO X,Y+6
80 PLOT X+1,47-Y:DRAWTO X+1,Y+6
90 Y=Y+1:NEXT X:GOSUB 400
100 IF Z>50 THEN GOSUB 400
110 W=INT(RND(0)*2)
120 Z=Z+1:POKE 53248,122+W
130 POKE 704,INT(RND(0)*16)*16+10
200 AZ=PEEK(708):POKE 708,PEEK(709)
210 POKE 709,PEEK(710):POKE 710,AZ
300 FOR X=0 TO 26:NEXT X:GOTO 100
400 X=INT(RND(0)*16)*16:Z=0
410 POKE 708,X:POKE 709,X+4
420 POKE 710,X+8:RETURN
500 P=PEEK(106)-8:POKE 106,P
510 POKE 54279,P:GRAPHICS 21
520 POKE 559,46:POKE 53277,3
530 POKE 704,0:FOR X=512 TO 768
540 POKE P*256+X,0:NEXT X
550 FOR X=578 TO 584:READ D
560 POKE P*256+X,D:NEXT X
570 POKE 53248,124:FOR X=708 TO 712
580 POKE X,0:NEXT X:RETURN
700 DATA 34,65,93,119,93,65,34

Memory Manager


After PMBASE, in line 520, the next important location is 559 decimal. It is listed in Table One with the name SDMCTL. This is the DMA (Direct Memory Access) control register. In simple terms, this technique allows more than one part of the computer to read different sections of memory. Normally, the 6502 microprocessor reads and writes memory over a set of internal wires called the data bus. To avoid confusion and communication conflicts when another computer circuit wants to use these data lines at the same time, DMA tells the 6502 to wait until the other circuit is finished. It literally means that other microprocessors like ANTlC and GTIA have a Direct Memory Access priority over the 6502 CPU.

SDMCTL contains a wide variety of crucial information pertaining to the other DMA functions of the OS, so be careful of what you POKE here. To pack so much information into a small place they use a technique called bitmapping. This is useful when a condition can be either true or false, yes or no, on or off. Each individual bit represents one of two possibilities. If the bit is zero, this usually means the condition is not valid. If the bit is one, the condition is true. This method allows up to eight individual condition flags (bits 0 through 7) in one byte. In SDMCTLs case, only bits two and three implement PMG DMA. Figure 1 is a representation of the SDMCTL register's bit map. Normally from Atari BASIC this register contains the value 34 decimal (22 hex); bits 1 and 5 are set (equal to 1) and all others reset (equal to 0).

Figure 1.

SDMCTL - DIRECT MEMORY ACCESS CONTROL ($022F)
A shadow register for DMACTL ($D400) which writes data into the DMA control
register in hardware.

Bit Map:
       ┌───┬───┬───┬───┬───┬───┬───┬───┐
Bit:   │ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │
       └───┴───┴───┴───┴───┴───┴───┴───┘

     B7, B6 - Not used
         B5 - 1 Enables antic DMA instruction fetch.
         B4 - 1 Enables single line PMG resolution.
              0 Enables double line PMG resolution.
         B3 - 1 Enables player DMA.
         B2 - 1 Enables missile DMA.
     B1, B0 - 0, 0 No playfield DMA.
              0, 1 Enables narrow playfield DMA. (128 color clocks wide)
              1, 0 Enables narrow playfield DMA. (160 color clocks wide)
              1, 1 Enables wide playfield DMA. (192 color clocks wide)

Bit by Bit


Bits 0 and 1 are the playfield select bits. The Atari has the ability to make the playfield screen (the area where normal text and graphics are displayed) one of four possibilities. When bits 0 and 1 are both zero, the screen display is off. This technique has been used in many SoftSide programs. Whenever a program has to modify the Display List, it can get the video sync hardware confused . The screen flips and flickers and when it finally stops, the Display List can be totally messed up. POKEing 559 with a number that has both of these bits off (0 is standard) will cause the screen to "go away" so the user doesn't have to see the mess. This method is useful for setting up a display on the screen when the programmer doesn't want the user to see the setup procedure. To re-enable the normal play field (turn the standard screen display back on) use a POKE that has bit 0 reset and bit 1 set (34 is standard).

The Atari has two special playfield modes that are normally unavailable from BASIC. If bit 0 is set and bit 1 is reset, the narrow play field appears. Normally in GRAPHICS 0, the screen is 40 by 24 characters. Two POKEs change the position of the right and left margins within the playfield area (in GRAPHICS 0 the play field is a blue box tailed the text window). Location 82 controls the left margin in the text window while location 83 controls the right. Both require that a number between 0 and 39 be POKEd into them. If you set the right margin to less than the left, strange things can happen. Normally location 82 defaults to a value of 2 to make up for overscan on some older or low-cost TV sets. The right margin is set to 39. Even though only 38 characters on the display are used from BASIC when these margins are set, the playfield under all 40 positions continues to have the blue background displayed.

When the narrow play field option is specified, the playfield shrinks by a predetermined size. In the case of GRAPHICS 0, this makes the blue text window become thinner when displayed on the screen and takes less screen memory. When both bits are set, the wide play field mode is selected. Now the text window expands to stretch all the way to the right and left edges of the screen. Note that in both cases the actual number of bytes per line is also modified, and that the playfield does not apply only to text modes such as GRAPHICS 0.


Enabling Players and Missiles


Bit 2 is the Missile enable bit. If you plan to use Missile graphics, set this bit to 1, otherwise reset it. We haven't discussed Missiles, and won't until the subject of Players is well under way. Bit 3 is the Player enable bit, which in the demo is set to 1.

If either bit 2 or 3 is set, then bit 4 is the PMG thickness. Players and Missiles can have two different vertical resolutions - 256 or 128 separate lines in the Y coordinate. In the 128 line mode, the memory size of all the PMGs is half the normal amount and the height of a PMG "pixel" doubles. In the 256 line format (256 bytes, since one line uses one byte), each line is the thickness of a single horizontal scan line of a standard TV raster display.

If you look closely at the screen, you will see that the display actually consists of many horizontal lines of dots. Each row of dots is called a scan line because the electrons that strike the phosphor are scanned or traced onto the front of the picture tube in consecutive rows. In the 128 byte resolution mode, each line of the PMG is two scan lines thick. In most cases, this is enough, so why waste the extra memory?

Bit 5 is ANTIC's instruction fetch DMA flag. This bit acts on ANTIC the same way that setting the halt line on a 6502 microprocessor does. When the halt line is set, the 6502 freezes and all data flow ceases within the computer. Similarly, bit 5 is a holding flag for ANTIC's halt line equivalent. However when ANTIC halts, all screen memory processing going to GTIA ceases. Remember that GTIA is still sending out a video signal based on the data coming from ANTIC. The net result is a screen made up entirely of the default background color. The background is a colored border provided by the processor circuitry to fill in the unused portions on the video display.

If the GRAPHICS 0 background is set to red and ANTIC is disabled by resetting bit 5, the entire screen fills with the default red background color. Note that even if playfield select bits 0 and 1 are set, the status of bit 5 takes precedence. In general, if you want to see anything meaningful on the video display, bit 5 must be set. Bits 6 and 7 have no function at present.


Resolution and RAM


Single line resolution takes more PMG RAM than double line resolution. But just how much memory is needed and how is it mapped out? Figures 2a and 2b show a memory map for each resolution. PMBASE is the reference for the starting point of the map, since this varies depending on where it points to. The numbers along the left-hand sides of the diagram are a relative offset from the start of PMBASE. Remember that PMBASE is a page number, so multiply it by 256 to get an absolute memory address location.

Figure 2a.

      Double Line

┌───────────────────┐ PMBASE
│                   │
│                   │
│      Unused       │
│                   │
├────┬────┬────┬────┤  +384
│ M3 │ M2 │ M1 │ M0 │
├────┴────┴────┴────┤  +512
│     Player 0      │
├───────────────────┤  +640
│     Player 1      │
├───────────────────┤  +780
│     Player 2      │
├───────────────────┤  +896
│     Player 3      │
└───────────────────┘ +1024

Figure 2b.

      Single Line

┌───────────────────┐ PMBASE
│                   │
│                   │
│                   │
│                   │
│                   │
│      Unused       │
│                   │
│                   │
├────┬────┬────┬────┤  +768
│ M3 │ M2 │ M1 │ M0 │
│    │    │    │    │
├────┴────┴────┴────┤ +1024
│     Player 0      │
│                   │
├───────────────────┤ +1280
│     Player 1      │
│                   │
├───────────────────┤ +1536
│     Player 2      │
│                   │
├───────────────────┤ +1792
│     Player 3      │
│                   │
└───────────────────┘ +2048

Double line resolution takes lK of memory while single line needs 2K. The Players always start halfway into the PMG RAM. Notice that a large portion of PMG RAM is not used at the start of PMBASE. This is a good place to put the data from a short machine language program or subroutine. If you use the single line resolution mode and you don't need Missiles, then the first 1024 bytes are perfect for holding the data for a redefined character set.

The next POKE is in line 520 also. This location (shown in Table One as GRACTL) is the other half of the PMG DMA enable bits. Even if all other POKEs have been set up, PMGs will not appear on the screen until these bits are set. Figure 3 is the bit map for GRACTL. Bit 0 enables PMG DMA for Missiles. Bit 1 enables Player DMA. If both bits are reset, then no PMGs appear. If both are set then both Players and Missiles are displayed. In the demo program, the value 3 sets bit 0 and 1.

Figure 3.

GRACTL - GRAPHICS CONTROL ($D01D)
Writes data to the graphic control register in hardware.

Bit Map:
       ┌───┬───┬───┬───┬───┬───┬───┬───┐
Bit:   │ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │
       └───┴───┴───┴───┴───┴───┴───┴───┘

     B7, B6
 B5, B4, B3 - Not used
         B2 - 1 Enables input latches for TRIG0-TRIG3 registers.
              0 Resets latches and TRIG0-TRIG3 act as normal.
         B1 - 1 Enables player DMA for player graphic registers.
         B0 - 1 Enables missile DMA for missile graphic registers.

Bit 2 has nothing whatsoever to do with PMGs, but it does something never documented anywhere, to the best of my knowledge. It deals with the way the hardware handles trigger inputs. When bit 2 is reset (its default condition) trigger inputs from BASIC (STRIG or PTRIG commands) return binary values. If you press the trigger, the hardware returns a value of 0 (Boolean false). When the trigger is not depressed, the hardware returns a 1 (Boolean true). The value of 0 is returned only as long as the button is held down. In hardware terms, when bit 2 is reset the trigger input latching circuits are disabled. If bit 2 is set, the latch is activated.

A latch is a device that acts like a door - it is either open or closed. In this example, normally the door is closed. Now and then people walk through and leave it open. Eventually someone sees the open door and closes it, after making a note that it was opened. The latch holds a value of 1 normally, but when some 0's walk through (trigger pressed), it changes to 0 and tells the program what has happened. To reset the latch to its initial state, reset bit 2. With this POKE a program can tell if a trigger has been pressed within a specific length of time. Normally you can only check if it is currently being pressed. When this bit is enabled, the trigger ports function just like the normal keyboard port at memory location 764 decimal which must also be reset between inputs.

The secret of putting color into PMGs is in the first part of line 530. Table One has four consecutive registers starting with 704 decimal (2C0 hex) named PCOLR0 through PCOLR3. POKE these locations with the color number multiplied by 16, plus the luminance number, for each Player. In the demo's line 130 I POKEd 704 (Player color 0) with a random color plus a luminance of 10.

The remainder of line 530 plus line 540 zero the PMG RAM. The reason for doing this is simple. The memory location chosen for PMGs may be filled with old data from other programs, other PMGs, or just plain old scrudge. If you position a PMG on the screen before erasing it with zeros (to turn the entire PMG off), you would see a vertical bar of randomly set bits. The variable P points to PMBASE and (referring to Figure 2a) Player 0 starts at an offset of 512 bytes from the begining of PMG RAM. Lines 550 and 560 read in the PMG shape from data statements and POKE them into the appropriate place within the Player 0 PMG RAM. To find out where any Player or Missile is located, use Figures 2a and 2b, substituting the real address of the PMBASE page number and adding the offsets.


Moving Pictures


Vertical movement is not used in the demo, since I will cover it in another installment. Briefly, two methods are available. The first is to zero out the old Player and put the PMG shape data back in a different place. This is effective if the Player makes large leaps in vertical position. The other simple technique is effective for moving a Player slowly up or down the screen. It involves rotating the contents of an entire page of memory. You have to move 255 of the 256 bytes up or down one byte within the page, and then take the byte at the end of the page and wrap it around to the beginning - but more on this in a later installment.

For horizontal positioning, each PMG has a register assigned to it that governs where it appears on the screen display. In Table One, these locations are HPOSP0 through HPOSP3. The registers require a number between 0 and 255 to tell GTIA at what color clock to put the left edge of a PMG shape.


Color Clocks


What is a color clock, you ask? First, make the distinction between a color clock and the color clock. Each scan line takes a small amount of time to travel across the screen. The GTIA knows where to draw information (or more correctly, at what time to draw it) because of a circuit called the color clock. The color clock rate (also called the oscillator or counter) is synchronized with the sweep frequency of the horizontal scan rate (the time required to draw one scan line), and provides timing signals to the video processing circuits (see "Where Has All the Resolution Gone?" by Tom Flynn in Issue 40) . A color clock is a single pulse within the color clock, and it determines if the pixel should be lit as the beam passes by. Each scan line has 228 color clocks, but the maximum practical limit is about 176.

Watching the color clock counter is the only way to know exactly where the electron beam is positioned on the scan line at any specific time. If you wanted to plot a GRAPHICS 8 dot on the far right edge of the screen, GTIA would watch the color clock until the time was right to put the graphics dot information into the video signal to make it appear at the right location on the screen.

With PMGs, the position registers correspond to a specific time in the color clock. GTIA watches the clock and compares it to the PMG's horizontal position registers for a match. Since some of the pulses do not occur in time to appear on the screen, PMGs seem to have the ability to move on and off screen. Depending on the overscan of your TV or monitor, color clock pulses 0 through 44 will be too far left of the screen to see and positions 220 through 255 will be too far to the right. The visible portion is from 44 to 220. This figure varies, so a range of 60 to 200 is more practical. In the demo program you'll see that line 570 sets the position of Player 0 at 124, about halfway into the screen.


One Last Detail


Previously, I promised to explain why you must reserve lK of memory when you POKE 106 to set RAMTOP. For PMGs with double line resolution, lK is the required amount of memory. However, certain special cases cause complications that need to be checked for.

With RAMTOP, you are near the area where the OS constructs the screen memory for the GRAPHICS modes. If you recall from older Frontier columns, the ANTIC chip has one restriction as to where screen memory is placed. ANTIC can never address more than 4K at one time because of the width of its address bus. When it has to work with screen memory longer than 4K (such as GRAPHICS 8) or memory that overlaps a 4K boundary, it must execute a separate DLI instruction with the LMS option set between processing ANTIC's machine language mode lines.

If the technical explanation doesn't make sense to you, try this one. In the high resolution graphics modes, screen memory has to start at the beginning of a 4K boundary in RAM. The Atari's RAM can have as many as sixteen 4K boundaries. If you accidentally move the screen memory down too far when you reserve space with RAMTOP, the computer will ask you to reserve extra RAM to make screen memory start where it is required. Atari DV subscribers can load the cover program to see a working example of PMGs, and the special case I have mentioned . Though the program uses double line resolution PMGs, I had to reserve sixteen pages (4K) to allow the GRAPHICS 8 screen to work correctly. Whenever a memory conflict arises, bump the RAMTOP pointer back a page at a time until you find the amount that works. Remember though, that this is the exception and not the rule. In general, reserve four pages for double line resolution PMGs and eight pages for single. Look again at Listing One. See if you can understand how the walls are made to appear as if they are moving. It's done with a technique known as color indirection. Experiment with it and if you find anything interesting, write in and tell us, or send a disk with some examples. Until next time....