Skip to content
Hardware

Blitter: The Amiga's Graphics Accelerator

Hardware-powered block transfers

The Blitter moved, combined, and transformed graphics data faster than any CPU could—making the Amiga's smooth scrolling and complex visuals possible.

commodore-amigacustom-chipsgraphicsdmacommodore1985–present

The Blitter (block image transferrer) was a DMA engine inside Agnus that performed graphics operations in hardware. It could copy memory, combine multiple sources with logic operations, fill areas, and draw lines—all while the CPU worked on game logic. This division of labour gave the Amiga its characteristic smooth, fast graphics.

Fast facts

  • Location: integrated into Agnus chip.
  • Sources: up to 3 inputs (A, B, C) plus 1 output (D).
  • Operations: copy, logic combine, area fill, line draw.
  • Speed: not a fixed figure — Commodore states bus cycles are “dynamically allocated” and declines to guarantee its own timing chart.

256 ways to combine three sources

The blitter’s central trick is not copying but combining. Three source channels go in, one destination comes out, and what happens between them is chosen from every possible answer:

The blitter can combine the data from the three source DMA channels in up to 256 different ways to generate the values stored by the destination DMA channel.

The 256 is not a designer’s list of useful operations. Three source bits have eight possible combinations, and for each the programmer says whether the destination bit is 0 or 1 — eight yes/no answers, so 2⁸ = 256, and every one of them is available. The eight answers are written as a single byte into BLTCON0, and that byte is the operation.

The manual works the standard case: the “classic cookie-cut function of AB+AC”, which is the byte $CA. Masked sprite blitting — the thing the Amiga is famous for — is not a mode the hardware provides. It is one value out of 256 in a control register.

Blitter channels

Channel Purpose
A Source data, often used as mask
B Source data
C Destination read (for combining)
D Destination write

Not all channels need be active for every operation.

Blitter nasty

DMACON bit 10 carries a name Commodore printed in its own manual:

BLTPRI Blitter priority. Also known as “blitter-nasty.” When this is a 1, the blitter has full (instead of partial) priority over the 680x0.

The register description elsewhere gives the mechanism: setting it “disables /BLS pin, preventing micro from stealing any bus cycles while blitter DMA is” running. Normally the processor may take slots the blitter is not using. With this bit set, it cannot — the blitter holds the bus until it is finished, and the CPU stops.

This is the Amiga’s contention argument in one bit. The machine’s other components negotiate for memory; the blitter can be told to stop negotiating.

Speed, which Commodore would not promise

The figure usually quoted for blitter throughput is a fixed number of cycles per word. The Hardware Reference Manual prints a timing table and then disclaims it:

Bus cycles are dynamically allocated based on blitter operating mode; competing bus activity from processor, bitplanes, and other DMA channels; and other factors. Commodore Amiga does not guarantee the accuracy of or future adherence to this chart.

A blit’s cost depends on how many bitplanes the display is fetching, what else holds DMA slots, and which blitter mode is running. There is also a pipeline to account for: “typical operation involves fetching all sources twice before the first destination becomes available”, with the warning that overlapping source and destination regions therefore need care.

Basic operations

Copy (A to D)

    move.w  #$09f0,BLTCON0(a6)  ; A->D, no shifts
    move.w  #$0000,BLTCON1(a6)  ; No special modes
    move.l  #source,BLTAPT(a6)  ; Source address
    move.l  #dest,BLTDPT(a6)    ; Destination address
    move.w  #$0000,BLTAMOD(a6)  ; Source modulo
    move.w  #$0000,BLTDMOD(a6)  ; Dest modulo
    move.w  #64*64+40,BLTSIZE(a6) ; 64 lines × 40 words

Masked copy (A masks B to D)

Cookie-cutter operation for sprites:

    move.w  #$0fca,BLTCON0(a6)  ; A=mask, B=source, C=bg, D=output

Minterm $CA: D = (A AND B) OR (NOT A AND C)

Fill

Fill enclosed areas:

    move.w  #$0001,BLTCON1(a6)  ; Fill mode enabled

Draw outline first, then fill—Blitter toggles fill state at each edge pixel.

Line drawing

Draw lines in hardware:

    move.w  #$0001,BLTCON1(a6)  ; Line mode + octant
    move.w  #dx,BLTBMOD(a6)     ; Delta X
    move.w  #dy,BLTAMOD(a6)     ; Delta Y
    ; ... additional setup
    move.w  #1*64+width,BLTSIZE(a6) ; Start line draw

Minterm logic

The Blitter combines sources using an 8-bit minterm:

Bit Condition
7 A AND B AND C
6 A AND B AND NOT C
5 A AND NOT B AND C
4 A AND NOT B AND NOT C
3 NOT A AND B AND C
2 NOT A AND B AND NOT C
1 NOT A AND NOT B AND C
0 NOT A AND NOT B AND NOT C

Common minterms

Minterm Operation
$F0 D = A (copy A)
$CC D = B (copy B)
$AA D = C (copy C)
$CA D = (A∧B)∨(¬A∧C) (cookie cut)
$5A D = A XOR C
$0A D = A AND C

Shifting

The Blitter can shift data horizontally:

    move.w  #$n9f0,BLTCON0(a6)  ; n = shift count (0-15)

Essential for pixel-precise positioning in planar graphics.

Blitter registers

Register Address Purpose
BLTCON0 $DFF040 Control: minterm, shift, channels
BLTCON1 $DFF042 Control: fill, line mode
BLTAFWM $DFF044 First word mask for A
BLTALWM $DFF046 Last word mask for A
BLTCPT $DFF048 Channel C pointer
BLTBPT $DFF04C Channel B pointer
BLTAPT $DFF050 Channel A pointer
BLTDPT $DFF054 Channel D pointer
BLTSIZE $DFF058 Size and start operation
BLTCMOD $DFF060 Channel C modulo
BLTBMOD $DFF062 Channel B modulo
BLTAMOD $DFF064 Channel A modulo
BLTDMOD $DFF066 Channel D modulo
BLTCDAT $DFF070 Channel C data
BLTBDAT $DFF072 Channel B data
BLTADAT $DFF074 Channel A data

Modulo explained

Modulo values handle non-contiguous memory:

Source width = 320 pixels = 40 bytes = 20 words
Screen width = 320 pixels = 40 bytes = 20 words
Blit width = 32 pixels = 4 bytes = 2 words
Modulo = screen width - blit width = 20 - 2 = 18 words

Waiting for Blitter

Always wait before using Blitter results:

wait_blit:
    btst    #6,$dff002          ; Check BLTBUSY in DMACONR
    bne.s   wait_blit           ; Loop until done

The btst #6,$dff002 idiom is the classic Amiga form. It works because btst with a memory operand is byte-sized: it reads the high byte of DMACONR (which is at $dff002) and tests bit 6 of that byte — which is bit 14 of the full 16-bit register, the BBUSY flag. Equivalent and more obvious if you prefer: btst #14,$dff002 with a word read also works but compiles to a longer instruction.

See also

Not yet fact-checked. This entry was drafted by an AI and nobody has verified it. The dates, figures and technical details may be wrong. Use it to find your bearings, then confirm anything that matters against a primary source.