A Sprite of Your Own
A sprite is a small picture the hardware draws over the background, on its own, wherever you point it. No bitplane, no blitting — you hand the chips a shape and a position and they put it on the glass and keep it there. This is how you make a player.
The Blitter draws into the bitplane — it changes the picture. A sprite is different: it's a small object the hardware draws over the picture, independently, without disturbing a single pixel of the background. You give it a shape and a position; the chips composite it onto the screen as the beam sweeps past.
This is exactly what you want for a player, an enemy, a bullet — something that moves around freely on top of a scene. Move a sprite and the background underneath is untouched, so there's nothing to redraw. The Amiga has eight of them, each with its own little palette.
A sprite is just data in memory: two control words that say where (a vertical start, a horizontal start, a vertical stop), then the image itself — two bits per pixel, picking one of three colours or transparent. You point the sprite hardware at that data, switch on sprite DMA, and it appears.
What you'll see by the end
A deep blue screen with an orange diamond near the middle. The background is a flat colour with no bitplane at all; the diamond is a sprite, drawn over the top by the hardware from the shape you hand it.
A shape and a position
;──────────────────────────────────────────────────────────────
; Meet the Machine (Amiga) - Unit 17: A Sprite of Your Own
;
; A sprite is a small picture the hardware draws OVER the background, on its own,
; wherever you tell it. No bitplane, no drawing into memory - you hand the chips
; a shape and a position and they put it on the glass. Here: one diamond.
;──────────────────────────────────────────────────────────────
CUSTOM equ $dff000
DMACON equ $096
INTENA equ $09a
INTREQ equ $09c
COP1LC equ $080
COPJMP1 equ $088
DIWSTRT equ $08e
DIWSTOP equ $090
DDFSTRT equ $092
DDFSTOP equ $094
BPLCON0 equ $100
SPR0PTH equ $120
SPR0PTL equ $122
COLOR00 equ $180
COLOR17 equ $1a2 ; sprite 0, colour 1
section code,code_c
start:
lea CUSTOM,a5
move.w #$7fff,INTENA(a5)
move.w #$7fff,INTREQ(a5)
move.w #$7fff,DMACON(a5)
; --- tell the Copper where the sprite data lives (patch pointer) ---
lea sprite_data,a0
move.l a0,d0
swap d0
move.w d0,sprhi
swap d0
move.w d0,sprlo
lea copperlist,a0
move.l a0,COP1LC(a5)
move.w d0,COPJMP1(a5)
move.w #$82a0,DMACON(a5) ; DMA on: master + Copper + sprites
forever:
bra.s forever
;──────────────────────────────────────────────────────────────
; Sprite 0 data: two control words (position), then 16 lines of
; image (plane A, plane B per line), then a zero terminator.
; VSTART=$7c, HSTART=$100, VSTOP=$8c -> on screen around (128,80).
;──────────────────────────────────────────────────────────────
even
sprite_data:
dc.w $7c80,$8c00 ; VSTART/HSTART, VSTOP/control
; plane A plane B
dc.w %0000000110000000,0 ; every set bit -> sprite colour 1
dc.w %0000001111000000,0
dc.w %0000011111100000,0
dc.w %0000111111110000,0
dc.w %0001111111111000,0
dc.w %0011111111111100,0
dc.w %0111111111111110,0
dc.w %1111111111111111,0
dc.w %1111111111111111,0
dc.w %0111111111111110,0
dc.w %0011111111111100,0
dc.w %0001111111111000,0
dc.w %0000111111110000,0
dc.w %0000011111100000,0
dc.w %0000001111000000,0
dc.w %0000000110000000,0
dc.w $0000,$0000 ; end of sprite
;──────────────────────────────────────────────────────────────
; Copper list: a blank background plus sprite 0 switched on.
;──────────────────────────────────────────────────────────────
copperlist:
dc.w DIWSTRT,$2c81
dc.w DIWSTOP,$2cc1
dc.w DDFSTRT,$0038
dc.w DDFSTOP,$00d0
dc.w BPLCON0,$0200 ; no bitplanes - just colour and sprites
dc.w SPR0PTH
sprhi: dc.w $0000 ; sprite data address, high (patched)
dc.w SPR0PTL
sprlo: dc.w $0000 ; sprite data address, low (patched)
dc.w COLOR00,$0008 ; background: deep blue
dc.w COLOR17,$0f80 ; sprite colour 1: orange
dc.w $ffff,$fffe
A sprite is two parts. First the data — control words, then image rows:
sprite_data:
dc.w $7c80,$8c00 ; VSTART/HSTART, VSTOP/control
; plane A plane B
dc.w %0000000110000000,0 ; every set bit -> sprite colour 1
dc.w %0000001111000000,0
...
dc.w $0000,$0000 ; end of sprite
The two control words encode the position — $7c80/$8c00 places the sprite around (128, 80) on screen. The packing is fiddly (vertical start and stop, horizontal start, split across the words), which is why real code writes a helper to work them out; here they're filled in directly so you can see the shape. Each image row is two words — plane A and plane B — and the two bits for each pixel choose its colour: 00 is transparent, so the background shows through, and 01 is sprite colour 1.
Then the code points the hardware at the data and switches it on:
lea sprite_data,a0
move.l a0,d0
... patch the Copper's SPR0PT pointer with this address ...
move.w #$82a0,DMACON(a5) ; DMA on: master + Copper + sprites
The Copper holds the sprite's pointer (SPR0PT) and reloads it every frame; $82a0 to DMACON switches on sprite DMA. From then on the hardware fetches the shape and paints it over the background every frame, with no further help from the CPU. The two sprite colours are set in the Copper list — COLOR17 is the orange.
Assemble, master, and run
make
An orange diamond floating on blue.
Try this: move it
The position is in the first control word. Change $7c80 — the high byte is the vertical start, so $5080 moves the diamond up, $a080 down. (Move the vertical stop in the second word to match, or the diamond stretches or vanishes.) Nudge that number every frame inside Unit 9's vblank loop and the sprite glides — and the background never needs redrawing.
Try this: redraw the shape
The image is sixteen rows of bits. Edit them — every 1 is a lit pixel, every 0 transparent. Draw a ball, a ship, a letter. Keep plane B at 0 and every lit pixel is colour 1; set bits in plane B too and you unlock colours 2 and 3 for a three-colour sprite.
If it doesn't work
- No sprite, just background. Sprite DMA isn't on —
DMACONneeds the sprite bit ($82a0here), and the Copper must pointSPR0PTat your data. - The sprite is a torn smear. The vertical start and stop in the control words don't bracket the image height. Stop minus start should equal the number of image rows.
- It's in the wrong place or off-screen. The position packing is unforgiving — keep the control words as shown until the diamond appears, then move it one step at a time.
What you've learnt
A sprite is a small picture the hardware draws over the background, from data in memory: two control words for the position, then image rows of two bits per pixel. You point SPR0PT at the data (through the Copper, so it reloads each frame), switch on sprite DMA, and the chips composite it every frame. Moving it costs nothing — the background is never touched. This is the natural way to put a player on screen.
What's next
You've used the Copper, the bitmap, the Blitter, and now sprites — everything you can see. One chip is left, and it's the one you hear. Next — Paula Makes a Sound — hand the sound chip a waveform and she plays it.