amiga-bootcamp/08_graphics/blitter_programming.md
Ilia Sharin 21751c0025 docs(amiga): complete AmigaOS 3.1/3.2 developer reference — 172 files across 17 sections
Comprehensive technical documentation covering:
- Hardware: OCS/ECS/AGA custom chip registers, Copper & Blitter deep dives
- Boot sequence: cold boot through startup-sequence
- Binary format: HUNK executable spec, relocation, debug info
- Linking & ABI: .fd files, LVO tables, register calling conventions
- Exec kernel: tasks, interrupts, memory, signals, semaphores
- AmigaDOS: file I/O, FFS/OFS layout, CLI/Shell scripting
- Graphics: planar bitmaps, Copper programming, HAM/EHB modes
- Intuition: screens, windows, IDCMP, BOOPSI
- Devices: trackdisk, SCSI, serial, timer, audio, keyboard
- Libraries: utility, expansion, IFFParse, locale, ARexx
- Networking: bsdsocket API, SANA-II, TCP/IP stack comparison
- Toolchain: GCC, vasm/vlink, SAS/C, NDK, debugging
- Reverse engineering: IDA/Ghidra setup, compiler fingerprints, case studies
- CPU & MMU: 68040/060 emulation libs, PMMU, cache management
- Driver development: SANA-II, Picasso96/RTG, AHI audio

All files include breadcrumb navigation. No local paths or proprietary content.
2026-04-23 12:17:35 -04:00

7.9 KiB
Raw Blame History

← Home · Graphics

Blitter Programming — Deep Dive

Overview

The Blitter (Block Image Transfer) is a DMA engine that performs raster operations on rectangular blocks of memory. It operates on up to 4 channels (A, B, C → D) using programmable minterm logic and can work independently of the CPU. The Blitter is the workhorse for screen clearing, scrolling, cookie-cut sprites, line drawing, and area fill.


Channel Architecture

Channel A ──→ ┐
Channel B ──→ ├──→ Minterm Logic ──→ Channel D (output)
Channel C ──→ ┘

A = mask/pattern (e.g., cookie shape, font glyph)
B = source image data
C = background / destination read-back
D = output destination

Each channel reads (or writes, for D) from a different memory pointer with independent modulo.


Minterm Logic

The minterm is an 8-bit truth table encoding the logical function of A, B, C:

Bit 7: ABC = 111  →  bit value
Bit 6: ABC = 110  →  bit value
Bit 5: ABC = 101  →  bit value
Bit 4: ABC = 100  →  bit value
Bit 3: ABC = 011  →  bit value
Bit 2: ABC = 010  →  bit value
Bit 1: ABC = 001  →  bit value
Bit 0: ABC = 000  →  bit value

Common Minterms

Minterm Hex Operation Use Case
D = A $F0 Copy A to D Simple block copy
D = B $CC Copy B to D Simple block copy
D = C $AA Copy C to D Read-back
D = A·B + (¬A)·C $CA Cookie-cut Masked sprite blit (B through A mask onto C)
D = 0 $00 Clear Clear a memory region
D = $FFFF $FF Set all Fill with 1s
D = A XOR C $5A XOR Cursor blink, highlight
D = A OR C $FA OR Overlay
D = ¬A AND C $0A Mask out Erase through mask
D = A·B $C0 AND (A,B) Masked pattern
A = mask (1 = sprite pixel, 0 = transparent)
B = sprite image data
C = background
D = result

Minterm $CA:
  Where A=1: D = B  (show sprite)
  Where A=0: D = C  (show background)

Register Reference

Reg Offset Description
BLTCON0 $040 Control: channels enabled (bits 118), ASH (bits 1512), minterm (bits 70)
BLTCON1 $042 Control: BSH (bits 1512), line mode (bit 0), fill mode (bits 32)
BLTAFWM $044 First word mask for channel A
BLTALWM $046 Last word mask for channel A
BLTAPT $050 Channel A pointer (high+low)
BLTBPT $04C Channel B pointer
BLTCPT $048 Channel C pointer
BLTDPT $054 Channel D pointer
BLTAMOD $064 Channel A modulo
BLTBMOD $062 Channel B modulo
BLTCMOD $060 Channel C modulo
BLTDMOD $066 Channel D modulo
BLTSIZE $058 Blit size + START (write triggers blit)

BLTCON0 Encoding

Bits 1512: ASH (A shift, 015 pixels)
Bit  11:    USEA (enable channel A)
Bit  10:    USEB (enable channel B)
Bit   9:    USEC (enable channel C)
Bit   8:    USED (enable channel D, almost always 1)
Bits  70:  Minterm

BLTSIZE Encoding (OCS/ECS)

Bits 156: Height in lines (11024, 0 means 1024)
Bits  50: Width in words (164, 0 means 64)

Writing BLTSIZE starts the blit!


Complete Examples

Example 1: Clear Screen (320×256, 1 bitplane)

    lea     $DFF000,a5

    ; Wait for blitter idle:
.bwait:
    btst    #14,$002(a5)    ; DMACONR bit 14 = BBUSY
    bne.s   .bwait

    ; D channel only, minterm $00 (clear):
    move.l  #$01000000,$040(a5)  ; BLTCON0: USED=1, minterm=$00
    clr.w   $042(a5)             ; BLTCON1: 0
    move.l  #ScreenMem,$054(a5)  ; BLTDPT
    clr.w   $066(a5)             ; BLTDMOD: 0 (contiguous)
    move.w  #(256<<6)|20,$058(a5) ; BLTSIZE: 256 lines × 20 words (320/16)
    ; Blit is now running!

Example 2: Block Copy (No Shift)

    ; Copy 64×64 pixel block from source to dest (1 bitplane)
    ; Source and dest are in contiguous bitmap, 320 pixels wide

    ; Width = 64 pixels = 4 words
    ; Modulo = (320 - 64) / 16 = 16 words = 32 bytes

    lea     $DFF000,a5

.bwait:
    btst    #14,$002(a5)
    bne.s   .bwait

    move.l  #$09F00000,$040(a5)  ; BLTCON0: USEA+USED, minterm=$F0 (A→D)
    clr.w   $042(a5)             ; BLTCON1
    move.w  #$FFFF,$044(a5)      ; BLTAFWM = all bits
    move.w  #$FFFF,$046(a5)      ; BLTALWM = all bits
    move.l  #SourceAddr,$050(a5) ; BLTAPT
    move.l  #DestAddr,$054(a5)   ; BLTDPT
    move.w  #32,$064(a5)         ; BLTAMOD = 32 bytes
    move.w  #32,$066(a5)         ; BLTDMOD = 32 bytes
    move.w  #(64<<6)|4,$058(a5)  ; BLTSIZE: 64 lines × 4 words → GO!
    ; Blit a 16×16 masked sprite onto background
    ; A = mask, B = sprite data, C = background, D = destination

    lea     $DFF000,a5

.bwait:
    btst    #14,$002(a5)
    bne.s   .bwait

    move.l  #$0FCA0000,$040(a5)  ; BLTCON0: A+B+C+D, minterm=$CA
    clr.w   $042(a5)             ; BLTCON1
    move.w  #$FFFF,$044(a5)      ; BLTAFWM
    move.w  #$FFFF,$046(a5)      ; BLTALWM
    move.l  #MaskData,$050(a5)   ; BLTAPT = mask
    move.l  #SpriteData,$04C(a5) ; BLTBPT = sprite imagery
    move.l  #ScreenPos,$048(a5)  ; BLTCPT = background (read-back)
    move.l  #ScreenPos,$054(a5)  ; BLTDPT = same as C (overwrite)
    clr.w   $064(a5)             ; BLTAMOD = 0 (mask is 16px = 1 word wide)
    clr.w   $062(a5)             ; BLTBMOD = 0
    move.w  #38,$060(a5)         ; BLTCMOD = (320-16)/8 = 38 bytes
    move.w  #38,$066(a5)         ; BLTDMOD = 38
    move.w  #(16<<6)|1,$058(a5)  ; BLTSIZE: 16 lines × 1 word → GO!

Example 4: Line Drawing

    ; Draw a line from (x1,y1) to (x2,y2) using blitter line mode
    ; This is complex — blitter line mode uses a Bresenham-style algorithm
    ; implemented in hardware

    ; BLTCON1 bit 0 = LINE mode
    ; Channel A = single word (texture pattern)
    ; Channel C/D = destination bitmap

    ; See HRM for the full algorithm; here's the concept:
    move.l  #$0B4A0000,$040(a5)  ; BLTCON0: A+C+D, minterm=$4A (XOR), ASH=dx
    move.w  #$0001,$042(a5)      ; BLTCON1: LINE=1, octant bits set per slope
    move.w  #$8000,$074(a5)      ; BLTADAT: single pixel pattern
    move.w  #$FFFF,$044(a5)      ; BLTAFWM
    move.l  #StartPos,$048(a5)   ; BLTCPT: line start position in bitmap
    move.l  #StartPos,$054(a5)   ; BLTDPT: same
    move.w  #Modulo,$060(a5)     ; BLTCMOD
    move.w  #Modulo,$066(a5)     ; BLTDMOD
    move.w  #(len<<6)|2,$058(a5) ; BLTSIZE: length × 2 → GO!

System-Friendly Blitter (via graphics.library)

/* BltBitMap — the safe, OS-friendly way: */
BltBitMap(srcBitmap, srcX, srcY,
          dstBitmap, dstX, dstY,
          width, height,
          0xC0,     /* minterm: A AND B */
          0xFF,     /* all planes */
          NULL);    /* temp buffer */

/* BltMaskBitMapRastPort — cookie-cut with mask: */
BltMaskBitMapRastPort(srcBM, srcX, srcY,
                       rp, dstX, dstY,
                       width, height,
                       (ABC | ABNC | ANBC),  /* minterm for cookie */
                       maskPlane);

/* BltClear — fast memory clear: */
BltClear(memory, byteCount, 0);

/* OwnBlitter / DisownBlitter — exclusive access: */
OwnBlitter();    /* wait for and lock blitter */
/* ... direct register programming ... */
DisownBlitter(); /* release */

Performance Notes

Operation Speed
Word copy 4 DMA cycles per word (1 µs at 3.58 MHz)
Full 320×256 clear ~1280 µs (~1.3 ms)
Cookie-cut blit 4 channels = 4 cycles/word (same as copy)
CPU vs blitter Blitter wins for moves > ~40 words
Nasty mode BLTPRI in DMACON: blitter gets priority, CPU stalls

References

  • HRM: Blitter chapter — complete register descriptions
  • 01_hardware/ocs_a500/blitter.md — hardware reference
  • 08_graphics/blitter.md — graphics.library BltBitMap API