Players and missiles (called sprites on some computers) are movable
objects which are independent of the normal graphics.
Player and missile graphics are fairly straight forward. Once the
computer is set-up for PM graphics, five 8-pixel-wide columns can be
displayed on the screen. The horizontal resolution (width of each
pixel) and the vertical resolution (number of scan lines per pixel)
are variable. The horizontal position of each column is determined by
it's horizontal position register. Each column is simply a
representation of a bit map in a certain block of memory. If you want
to draw an object on the screen, you simply put a bit map representing
it in the proper memory block. The vertical position of an object is
determined by the location of it's bit map in memory. For example, if
you want to draw a happy face in the middle of the screen, you put a
happy face bit map in the middle of one of the memory blocks
controlling one of the columns.
One column (player) displayed on the screen
---------- first byte of a block
| |
| |
------------------------------
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | ++++ | visible |
| | + + | |
| |+ + + +| |
| |+ +| area |
| |++ ++| |
| |+ ++++ +|--object |
| | + + | bit map |
| | ++++ | |
| | | |
| | | |
| | | |
------------------------------
| |
| |
---------- last byte of a block
Horizontal positions
$00 $30 $CE $FF
(0) (48) (206) (255)
| | | |
| Left edge right edge |
| |
Far left far right
To move the happy face vertically you would move the entire bit map in
memory. To move the happy face horizontally you change the number in
the horizontal position register for the proper player.
One of the players can be (and often is) split into four columns of
two pixels wide each. These columns are then called missiles. In
this case, each missile has it's own horizontal position register.
SETTING UP PM GRAPHICS
PM graphics are enabled by the direct memory access control register,
DMACTL [$D400 (54272)]. The program using PM graphics will usually
use the shadow register, SDMCTL [$022F (559)].
DMACTL (SDMCTL)
7 6 5 4 3 2 1 0
-----------------
|0|0| control |
-----------------
bits
5 1 = enable display list reading
4 0 = one line player resolution
1 = two line player resolution
3 1 = enable four players
2 1 = enable fifth player or missiles
1 & 0 00 = no background
01 = narrow background (128 color clocks,
1 color clock equals 2 GRAPHICS 8 pixels)
10 = normal background (160 color clocks)
11 = wide background (192 color clocks)
Normally, bits 5 and 1 are set to 1. Bits 4, 3 and 2 are used to
enable players and/or missiles accordingly.
Once DMACTL is set up for the type of PM graphics to enable, the
graphics control register, GRACTL [$D01D (53277)], is used to actually
enable the PM graphics.
GRACTL
7 6 5 4 3 2 1 0
-----------------
|not used | | | |
-----------------
Bits
2 1 = latch paddle triggers
1 1 = enable four players
0 1 = enable fifth player or missiles
If only DMACTL is set up, the ANTIC chip will access memory for PM
graphics but will not display them.
Next, the memory area used for the PM bit maps must be set. This
block must start on a 2K (8 page) boundary if single line resolution
is used and a 1K (4 page) boundary for two line resolution.
The page number where the bit map starts is stored in the PM base
register, PMBASE [$D407 (54279)]. For one line resolution this number
will be a multiple of 8. For two line resolution it will be a
multiple of 4. PMBASE holds the MSB of the address of the PM bit map.
The LSB will always be 0 so it need not be specified.
The PM bit maps
2 line resolution
128 bytes (1/2 page)
per player
----------------- start + 0
| |\
+---------------+ 1-1/2 page
| | (384 bytes)
+===============+ unused
| |/
+---------------+ +$180 (384)
|M3 |M2 |M1 |M0 | fifth player or missiles
+===============+ +$200 (512)
| player 0 map |
+---------------+ +$280 (640)
| player 1 map |
+===============+ +$300 (768)
| player 2 map |
+---------------+ +$380 (896)
| player 3 map |
+===============+ +$400 (1024)
1 line resolution
256 bytes (1 page)
per player
----------------- start + 0
| |\
+ +
| |
+===============+
| | 768 bytes
+ +
| | (3 pages)
+===============|
| | unused
+ +
| |/
+===============+ +$300 (768)
| | | | | fifth player
+M3 |M2 |M1 |M0 | or missiles
| | | | |
+===============+ +$400 (1024)
| |
+ player 0 map +
| |
+===============+ +$500 (1280)
| |
+ player 1 map +
| |
+===============+ +$600 (1536)
| |
+ player 2 map +
| |
+===============+ +$700 (1792)
| |
+ player 3 map +
| |
+===============+ +$800 (2048)
Example of using P/M graphics in BASIC
0 REM ---LABEL REGISTERS ETC
10 LINES=2
20 VERT=120
22 IF LINES=2 THEN VERT=VERT/2
30 PM0=1024
32 IF LINES=2 THEN PM0=PM0/2
40 HORIZ=120
50 PCOLR0=704
60 SDMCTL=559
70 SIZEP0=53256
80 HPOSP0=53248
90 SDMCTL=559
100 PMRAM=PEEK(106)-16
110 PMBASE=54279
120 GRACTL=53277
130 PMSTART=PMRAM*256+PM0
200 REM ---SET REGISTERS
210 POKE SDMCTL,62
212 IF LINES=2 THEN POKE SDMCTL,46
220 POKE SIZEP0,1
230 POKE HPOSP0,HORIZ
240 POKE PCOLR0,88
250 POKE PMBASE,PMRAM
260 POKE GRACTL,3
300 REM ---DRAW PLAYER
310 POKE PMSTART+VERT,60
320 POKE PMSTART+VERT+1,66
330 POKE PMSTART+VERT+2,165
340 POKE PMSTART+VERT+3,129
350 POKE PMSTART+VERT+4,195
360 POKE PMSTART+VERT+5,189
370 POKE PMSTART+VERT+6,66
380 POKE PMSTART+VERT+7,60
The above program will draw a happy face in about the middle of the
screen using player 0. To move the player horizontally, poke a
different number into HPOSP0. To draw the player in a different
vertical position, change VERT. To use a different player or missile,
use the memory maps above to find the starting address of the player
you want to use. For example, to use player 1 change line 40 to
PM1=1280. Then change line 130 to PMSTART=PMRAM*256+PM1. The
variable "LINES" determines the vertical resolution. The number poked
into SIZEP0 determines the width.
P/M PRIORITY
The priorities of players, missiles and non-P/M graphics can be
controlled by the PRIOR register [$D10B (53275)] and its shadow
register, GPRIOR [$26F (623)]. Objects with higher priority will
appear to move in front of lower priority objects. The format of
PRIOR is as follows:
PRIOR bit assignment
7 6 5 4 3 2 1 0
-----------------
| | | | | | | | |
-----------------
1 6 3 1 8 4 2 1
2 4 2 6
8
Bits
7-6 Control the GTIA graphics modes.
00 = normal
01 = mode 9
10 = mode 10
11 = mode 11
5 1 = multiple color player enable. Permits
overlapping of players 0 and 1 or
2 and 3 with a third color in the
overlapped region.
4 1 = fifth player enable. All missiles
will assume the color controlled by
COLOR3 [$2C7 (711)]. missiles are
positioned together to make the fifth
player.
3-0 Controls the priorities of players, missiles
and other graphics. Objects with higher priority will appear to move
in front of those with lower priority.
The following chart may need some clarification. In the chart:
PM0 = player 0 and missile 0
C0 = COLOR0, plotted graphics controlled
by color register 0 in the SETCOLOR
command.
P5 = all four missiles when combined
into one player.
BAK = the background, known as COLOR4 or color
register 4 in the SETCOLOR command.
Etc.
Bits 0-3 of PRIOR and P/M priorities
Bit 3=1 2=1 1=1 0=1
C0 C0 PM0 PM0 highest
C1 C1 PM1 PM1 priority
PM0 C2 C0 PM2
PM1 C3+P5 C1 PM3
PM2 PM0 C2 C0
PM3 PM1 C3+P5 C1
C2 PM2 PM2 C2
C3+P5 PM3 PM3 C3+P5 lowest
BAK BAK BAK BAK priority
Only one priority bit can be set at a time. If more than one priority
bit is 1, overlapping areas of conflicting priorities will turn
black.
COLLISIONS
Each player or missile has a register showing overlap (collisions)
with other objects. Each player has two registers assigned to it; one
to detect collisions with other players and one to detect collisions
with plotted objects. Likewise each missile has two registers; one to
detect collisions with players and one to detect collisions with
plotted objects. Careful use of these 16 registers can detect any
type of collision.
Each register uses only the lower 4 bits. The bits which equal 1 tell
what the associated object has collided with. For example, to detect
collisions of player 1 to other players examine P1PL [$D00D (53261)].
P1PL, player 1 to player collisions
7 6 5 4 3 2 1 0
-----------------
P1PL |unused | | | | |
-----------------
8 4 2 1
3 = 1 collision with player 3
2 = 1 collision with player 2
1 = 1 invalid
0 = 1 collision with player 0
Etc.
When looking for collisions with plotted objects, the bit number tells
what color register is assigned to the object the collision was with.
For example, to detect collisions between player 1 and plotted objects
(officially called the play field), P1PF [$D005 (53253)] is used.
P1PF, player 1 to ploted object collisions
7 6 5 4 3 2 1 0
-----------------
P1PF |unused | | | | |
-----------------
8 4 2 1
3 = 1 collision with COLOR3
2 = 1 " COLOR2
1 = 1 " COLOR1
0 = 1 " COLOR0
Etc.
Once a collision occurs it remains indicated in its collision
register. To clear out all collision registers, write anything to
HITCLR [$D01E (53278)]. STA HITCLR or POKE 53278,0 will do.
Useful database variables and OS equates
HPOSP0 $D000 (53248): write: horizontal position of player 0
M0PF " " : read: missile 0 to plotted graphics collisions
HPOSP1 $D001 (53249): write: horizontal position of player 1
M1PF " " : read: missile 1 to plotted graphics collisions
HPOSP2 $D002 (53250): write: horizontal position of player 2
M2PF " " : read: missile 2 to plotted graphics collisions
HPOSP3 $D003 (53251): write: horizontal position of player 3
M3PF " " : read: missile 3 to plotted graphics collisions
HPOSM0 $D004 (53252): write: horizontal position of missile 0
P0PF " " : read: Player 0 to plotted graphics collisions
HPOSM1 $D005 (53253): write: horizontal position of missile 1
P1PF " " : read: Player 1 to plotted graphics collisions
HPOSM2 $D006 (53254): write: horizontal position of missile 2
P2PF " " : read: Player 2 to plotted graphics collisions
HPOSM3 $D007 (53255): write: horizontal position of missile 3
P3PF " " : read: Player 3 to plotted graphics collisions
SIZEP0 $D008 (53256): write: size of player 0
M0PL " " : read: missile 0 to player collisions
SIZEP1 $D009 (53257): write: size of player 1
M1PL " " : read: missile 1 to player collisions
SIZEP2 $D00A (53258): write: size of player 2
M2PL " " : read: missile 2 to player collisions
SIZEP3 $D00B (53259): write: size of player 3
M3PL " " : read: missile 3 to player collisions
SIZEM $D00C (53260): write: widths for all missiles
P0PL " " : read: player 0 to other player collisions
GRAFP0 $D00D (53261): write: player 0 graphics (used by OS)
P1PL " " : read: player 1 to other player collisions
GRAPF1 $D00E (53262): write: player 1 graphics
P2PL " " : read: player 2 to other player collisions
GRAFP2 $D00F (53263): write: player 2 graphics
P3PL " " : read: player 3 to other player collisions
GRAPF3 $D010 (53264): write: player 3 graphics
GRAFM $D011 (53265): write: missile graphics (used by OS)
COLPM0 $D012 (53266): color for player/missile 0
COLPM1 $D013 (53267): color for player/missile 1
COLPM2 $D014 (53268): color for player/missile 2
COLPM3 $D015 (53269): color for player/missile 3
COLPF0 $D016 (53270): color register 0
COLPF1 $D017 (53271): color register 1
COLPF2 $D018 (53272): color register 2
COLPF3 $D019 (53273): color register 3
COLBK $D01A (53274): background color (register 4)
PRIOR $D01B (53275): priority select, GTIA modes
GRACTL $D01D (53277): graphics control
HITCLR $D01E (53278): writing anything clears all collision bits
DMACTL $D400 (54272): direct memory access (DMA) control
PMBASE $D407 (54279): start of P/M memory
Shadow registers
SDMCTL $022F (559): DMACTL
GPRIOR $026F (623): PRIOR
PCOLR0 $02C0 (704): COLPM0
PCOLR1 $02C1 (705): COLPM1
PCOLR2 $02C2 (706): COLPM2
PCOLR3 $02C3 (707): COLPM3
COLOR0 $02C4 (708): COLPF0
COLOR1 $02C5 (709): COLPF1
COLOR2 $02C6 (710): COLPF2
COLOR3 $02C7 (711): COLPF3
COLOR4 $02C8 (712): COLBK