Skip to content

Sprite Control Words

Calculate and update Amiga sprite control words from X/Y coordinates. Position sprites anywhere on screen.

Taught in Game 1, Unit 2 spritespositioningcontrol-wordsrendering

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

AspectCost
CPU~40 cycles
Memory~30 bytes
LimitationMust 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

AxisHardware registerVisible area
X9 bits (0-511)~64-448 in lowres (depends on display window)
Y9 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

Patterns: Copper List Basics

Vault: Commodore Amiga