Overview
Amiga sprites have two control words at the start of their data that define vertical start/stop positions and horizontal position. Update these each frame to move sprites around the screen. The encoding packs multiple values into 16-bit words.
Code
; =============================================================================
; SPRITE CONTROL WORDS - AMIGA
; Calculate sprite position from X/Y coordinates
; Taught: Game 1 (Signal), Unit 2
; CPU: ~40 cycles | Memory: ~30 bytes
; =============================================================================
SPRITE_HEIGHT equ 16 ; Sprite height in pixels
; Update sprite control words (simple version)
; ASSUMES: even X coordinate (loses HSTART bit 0) and Y < 256
; (no VSTART[8] / VSTOP[8] support). Use update_sprite_full for those cases.
;
; Input: A0 = sprite data address
; frog_pixel_x, frog_pixel_y = coordinates
update_sprite:
move.w frog_pixel_y,d0 ; D0 = Y position (VSTART)
move.w frog_pixel_x,d1 ; D1 = X position (HSTART)
; === Control word 1: VSTART and HSTART ===
; Format: VSTART[7:0] in high byte, HSTART[8:1] in low byte
move.w d0,d2 ; D2 = VSTART
lsl.w #8,d2 ; Shift to high byte
lsr.w #1,d1 ; HSTART / 2 (lose bit 0)
or.b d1,d2 ; Combine
move.w d2,(a0) ; Write control word 1
; === Control word 2: VSTOP and control bits ===
; Format: VSTOP[7:0] in high byte, control bits in low byte
add.w #SPRITE_HEIGHT,d0 ; VSTOP = VSTART + height
lsl.w #8,d0 ; Shift to high byte
; Low byte contains: ATTACH, unused, VSTOP[8], VSTART[8], HSTART[0]
; Zero here means: not attached, even X, Y < 256
move.w d0,2(a0) ; Write control word 2
rts
frog_pixel_x: dc.w 160 ; Screen X coordinate
frog_pixel_y: dc.w 100 ; Screen Y coordinate
Extended version with all control bits:
; Full control word calculation with all bits
; Handles sprites in lower screen area (Y > 255)
update_sprite_full:
move.w sprite_y,d0 ; VSTART
move.w sprite_x,d1 ; HSTART
move.w d0,d2
add.w #SPRITE_HEIGHT,d2 ; VSTOP
; Control word 1
move.w d0,d3 ; VSTART[7:0]
lsl.w #8,d3
move.w d1,d4
lsr.w #1,d4 ; HSTART[8:1]
or.b d4,d3
move.w d3,(a0)
; Control word 2
move.w d2,d3 ; VSTOP[7:0]
lsl.w #8,d3
; Build low byte: bit 7=ATTACH, bit 2=VSTOP[8], bit 1=VSTART[8], bit 0=HSTART[0]
moveq #0,d4
btst #8,d2 ; VSTOP bit 8?
beq.s .no_vstop8
bset #2,d4
.no_vstop8:
btst #8,d0 ; VSTART bit 8?
beq.s .no_vstart8
bset #1,d4
.no_vstart8:
btst #0,d1 ; HSTART bit 0?
beq.s .no_hstart0
bset #0,d4
.no_hstart0:
or.b d4,d3
move.w d3,2(a0)
rts
Trade-offs
| Aspect | Cost |
|---|---|
| CPU | ~40 cycles |
| Memory | ~30 bytes |
| Limitation | Must update every frame for moving sprites |
When to use: Any program using hardware sprites.
When to avoid: Never - sprites always need valid control words.
Control Word Format
Word 1 (offset 0):
Bit 15-8: VSTART[7:0] - Vertical start position (low 8 bits)
Bit 7-0: HSTART[8:1] - Horizontal position (bits 8-1, divided by 2)
Word 2 (offset 2):
Bit 15-8: VSTOP[7:0] - Vertical stop position (low 8 bits)
Bit 7: ATTACH - Attach to previous sprite (for 15-colour sprites)
Bit 6-3: Unused
Bit 2: VSTOP[8] - Vertical stop bit 8
Bit 1: VSTART[8] - Vertical start bit 8
Bit 0: HSTART[0] - Horizontal position bit 0
Position Ranges
| Axis | Hardware register | Visible area |
|---|---|---|
| X | 9 bits (0-511) | ~64-448 in lowres (depends on display window) |
| Y | 9 bits (0-511, but used 0-312 PAL / 0-262 NTSC) | ~44-300 PAL / ~21-260 NTSC |
Setting HSTART[0] (bit 0 of word 2) lets you position to odd-pixel X. Without it, sprites can only sit on even X coordinates. Setting VSTART[8] (bit 1 of word 2) and VSTOP[8] (bit 2 of word 2) extends Y past 255 — required for sprites in the lower half of an interlaced or PAL screen.
Sprite attach (15-colour sprites)
Setting bit 7 of word 2 on an odd sprite (sprite 1, 3, 5, or 7) attaches it to the previous even sprite. The pair then displays one combined 15-colour sprite:
- Each pixel uses 2 bits from sprite N + 2 bits from sprite N+1 = 4 bits total
- 4 bits = 16 entries, of which entry 0 is transparent → 15 visible colours
- The pair must have matching VSTART/VSTOP/HSTART; only sprite N+1 needs ATTACH set
Practical use: bosses, rich playfield characters, status bars where 3-colour sprites look cheap.
; Setting ATTACH on sprite 1 (the odd partner of sprite 0)
; ... compute control word 2 in D3 as usual ...
bset #7,d3 ; ATTACH = 1
move.w d3,2(a0) ; A0 = sprite 1's data
Related
Patterns: Copper List Basics
Vault: Commodore Amiga