Skip to content

Sprite Control Words

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

Code status: illustrative code. Adapt the listing to your program and check it on your target machine. This page links no assembly or execution record for the listing itself.

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

68000 assembly
; =============================================================================
; SPRITE CONTROL WORDS - AMIGA
; Calculate sprite position from X/Y coordinates
; Taught: Game 1 (Signal), Unit 2
; Cost depends on the assembled caller and memory placement.
; =============================================================================

SPRITE_HEIGHT   equ 16          ; Sprite height in pixels

; Update sprite control words (simple version)
; ASSUMES: even beam X in0..510 and Y+SPRITE_HEIGHT <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:

68000 assembly
; Full control word calculation with all bits
; Handles sprites in lower screen area (Y > 255)
update_sprite_full:
            move.w  frog_pixel_y,d0         ; VSTART
            move.w  frog_pixel_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 Not measured for this illustrative listing; include the caller and hardware scheduling costs
Memory Assemble the selected routines and caller to obtain code and state sizes
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):

Code
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):

Code
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.

68000 assembly
; 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

With height16 the simple routine accepts beam Y in0–239. The full version accepts9-bit beam coordinates only while the end Y also fits0–511. These are beam positions, not window-relative pixel coordinates: apply the display origin separately. A0 points to a word-aligned sprite buffer in Chip RAM. The simple routine changes D0–D2/CCR; the full one D0–D4/CCR. Both clear ATTACH unless the caller sets it afterwards. Update an inactive buffer and publish its pointer at an agreed beam point; live two-word writes can otherwise be observed half-updated.

Explore the cross-platform sprite family for software drawing, hardware limits, restoration and overload policies.