Skip to content

BOBs: Blitter Objects

Software sprites on the Amiga

A BOB is an image the Amiga's blitter draws into the playfield itself, through a mask, after saving the background it covers. BOBs can be any size and use every colour of the screen, which the eight 16-pixel hardware sprites cannot, but each one costs three blits a frame for every bitplane.

The Amiga has eight hardware sprites, and each is 16 pixels wide with three colours. That is enough for a player’s ship, not for a screen full of large, colourful enemies. For those, Amiga programmers drew the objects into the screen’s own bitplanes with the blitter, the custom chip that copies and combines rectangles of memory. Commodore called these Bobs, “blitter objects”.

The name comes from Commodore’s own animation system. Its ROM Kernel Manual explains that “the system uses the blitter to move the playfield objects, while it saves and restores the background. The objects controlled by the blitter are called Bobs”. Game programmers, who usually drove the hardware directly, kept the word for their own routines. Dave Jones, explaining his shoot-’em-up Menace in Amiga Format in February 1990, wrote that “many people refer to software sprites on the Amiga as BOBS, short for Blitter OBjectS, as they tend to be drawn using the blitter”, and that “the main ship in Menace is made up of hardware sprites, but all of the aliens are software sprites”. On screen, he added, “there is no visual way to tell the difference”. The series went further than most programming articles: each month it documented a part of the game “accompanied by the source code for that section”.

BOBs and hardware sprites

Hardware sprites BOBs
How many 8 on any one line; each can be reused further down the screen As many as the blitter has time to draw
Width 16 pixels Any
Colours 3 plus transparent; 15 plus transparent for an attached pair Every colour of the playfield
Drawing cost None: the display hardware overlays them Three blits per bitplane per frame
Background Untouched Must be saved and restored
Order on screen Fixed priority between sprites; BPLCON2 sets their priority against the playfields The order the program draws them in

A Bob is “physically a part of the playfield”, as the ROM Kernel Manual puts it. The program has to clear it away before moving it, and the last one drawn “appears to be in front of all other Bobs”.

The three blits

Commodore’s Hardware Reference Manual teaches the method with a car driving past some buildings, in three steps:

  1. Save the rectangle of background the object will cover, with a plain copy: channel A to channel D, the copy function $F0.
  2. Draw the object through a mask. Channel A fetches the mask, B the image, C the background, and D writes the result.
  3. Restore the saved background next frame, with the same copy, before drawing the object somewhere else.

The drawing step uses what the manual calls “the cookie-cut function”. Wherever the mask has a bit set, the result takes the image from B; wherever it does not, it keeps the background from C. In logic terms that is AB + (not A)C, and the blitter’s function code for it is $CA. The background has to be read even though most of it is written back unchanged, because, the manual explains, “only a portion of a destination word might need to be modified, and there is no way to do a write to only a portion of a word.”

The mask is one bitplane deep, with a bit set wherever any plane of the image is coloured. On a screen of several bitplanes, the program repeats the draw once for each plane, using the same mask every time. Jones described Menace’s aliens this way: “To draw an alien BOB requires three separate blits, one for each plane of the screen”, with “Blitter A channel = mask, Blitter B channel = data, Blitter C channel = screen, Blitter D channel = screen”.

Drawing at any pixel

The blitter works in 16-bit words, so an object that does not start on a 16-pixel boundary has to be shifted. The blitter does that as it copies: bits 12 to 15 of BLTCON0 shift channel A and the same bits of BLTCON1 shift channel B, by 0 to 15 pixels. Both must be set, or the image and its mask fall out of line.

A shifted object spills into one more word. Jones explains that a 32-pixel BOB is two words wide only “if the BOB is not shifted”, and “as soon as we want to place a BOB on ANY pixel position we will be affecting THREE words”. His solution is to blit three words while the image and mask are stored two words wide: “the last word will be masked to 0, and the modulo will be -2 for the mask and data channel.” The negative modulo steps the source back a word at the end of each row, and the blitter’s last-word mask, BLTALWM, clears whatever channel A fetched in that third word, so the background shows through there.

The routine below draws one bitplane of a 32×32 BOB in that way. It assumes a6 holds the custom-chip base address $DFF000 and that the register names come from Commodore’s include files.

68000 assembly
; Draw one bitplane of a 32x32 BOB at pixel column d0.
; a0 = mask (2 words x 32 lines), a1 = this plane of the image (2 x 32),
; a2 = screen address of the word containing column d0 on the BOB's top line.
SCREEN_BYTES = 40                ; 320-pixel low-resolution bitplane

draw_bob_plane:
        bsr     wait_blitter
        move.w  d0,d1
        and.w   #15,d1           ; pixel offset within the word, 0-15
        ror.w   #4,d1            ; move it to bits 12-15
        move.w  d1,BLTCON1(a6)   ; BSH: shift the image
        or.w    #$0fca,d1        ; use A, B, C and D; cookie-cut $CA
        move.w  d1,BLTCON0(a6)   ; ASH: shift the mask by the same amount
        move.l  #$ffff0000,BLTAFWM(a6) ; first-word mask all ones, last-word mask 0
        move.w  #-2,BLTAMOD(a6)  ; sources are 2 words wide, the blit is 3
        move.w  #-2,BLTBMOD(a6)
        move.w  #SCREEN_BYTES-6,BLTCMOD(a6)
        move.w  #SCREEN_BYTES-6,BLTDMOD(a6)
        move.l  a0,BLTAPT(a6)
        move.l  a1,BLTBPT(a6)
        move.l  a2,BLTCPT(a6)
        move.l  a2,BLTDPT(a6)
        move.w  #(32<<6)|3,BLTSIZE(a6) ; 32 lines, 3 words: starts the blit
        rts

; Save the background under the BOB before drawing it: copy A to D.
; a2 = screen address as above, a3 = save buffer (3 words x 32 lines).
save_background:
        bsr     wait_blitter
        move.l  #$09f00000,BLTCON0(a6) ; BLTCON0 = $09F0 (use A and D, D = A), BLTCON1 = 0
        move.l  #$ffffffff,BLTAFWM(a6)
        move.w  #SCREEN_BYTES-6,BLTAMOD(a6)
        move.w  #0,BLTDMOD(a6)
        move.l  a2,BLTAPT(a6)
        move.l  a3,BLTDPT(a6)
        move.w  #(32<<6)|3,BLTSIZE(a6)
        rts

; Restoring is the same copy the other way: A = save buffer with modulo 0,
; D = screen with modulo SCREEN_BYTES-6.

wait_blitter:
        btst    #6,DMACONR(a6)   ; bit 14 of DMACONR, blitter busy; test twice,
.wait   btst    #6,DMACONR(a6)   ; as early chips may not have set it yet
        bne.s   .wait
        rts

Writing BLTSIZE starts the blit, so it goes last. Its upper ten bits hold the height in lines and its lower six bits the width in words. The program must not touch the blitter’s registers while a blit is running. The Hardware Reference Manual warns that the busy flag may not yet be set in the first moments of a blit on the original chips, and recommends reading a chip register before testing it, which the double test does.

Order matters

Bobs that overlap need two rules:

  • Draw from back to front. The last one drawn appears in front.
  • Restore in the reverse order. A Bob drawn over another saves a background that includes part of the first Bob. Restoring the later one first puts that part back, and then restoring the earlier one leaves a clean screen. Commodore’s animation system keeps track of the drawing order so that, in the manual’s words, it “restores the backgrounds in the correct sequence”.

Double buffering

Drawing into the screen being displayed lets the viewer see a Bob half erased. Jones called double buffering “fairly essential for smooth animation”: the program draws into one copy of the screen while the other is on show, then swaps them. It “cuts out all forms of ‘flickering’ caused by changing a screen while we are looking at it”, at the cost of being “quite hungry on memory”.

Double buffering changes the bookkeeping. Each screen needs its own saved backgrounds, because the copy of the screen being drawn into last held the Bobs where they were two frames ago, not one. Commodore’s system asks for a second save buffer for every double-buffered Bob and records where the object was in each buffer.

68000 assembly
; Once per frame:
;   1. wait for the vertical blank and show the buffer drawn last frame
;   2. in the other buffer, restore the backgrounds saved two frames ago,
;      in reverse drawing order
;   3. move the objects
;   4. save the new backgrounds and draw the Bobs, back to front

What a Bob costs

The Hardware Reference Manual gives the blitter’s speed in clock ticks per word. “The minimum blitter cycle is four ticks; the maximum is eight ticks”: channel B adds two ticks and using both C and D adds two more, so a cookie-cut with all four channels takes eight ticks a word and an A-to-D copy four. A blit takes n × H × W / 7.09 microseconds on a PAL machine, where n is the ticks per word and H and W are the height in lines and the width in words. The manual notes that this ignores setup time and “DMA contention”, the memory cycles the display and the processor take.

For a 32×32 Bob at an arbitrary pixel position on a five-bitplane screen, each blit is three words wide and the five planes make 160 lines:

  • Draw: 8 × 160 × 3 = 3,840 ticks, about 540 microseconds.
  • Save and restore: 4 × 160 × 3 = 1,920 ticks each, about 270 microseconds.
  • In all, about 1,080 microseconds, or 5.4% of a 20 ms PAL frame.

On those figures the blitter could handle about eighteen such Bobs a frame before the display, the processor and the rest of the game take their share. Menace’s aliens were smaller: at most 32×24 pixels on three planes. The same sums give about 490 microseconds each, which is how the game could put a screenful on at once. Jones gave the memory cost of each frame of alien animation as “384 bytes per anim”: 96 bytes for each of the three planes and 96 for the mask.

The blitter runs on its own, so the processor does not have to wait. The manual notes that “the processor does not stop while the blitter is working”, which lets a game start a blit, get on with its own logic, and check the busy flag only before it sets up the next one.

Menace also avoided clipping, the work of trimming a Bob that crosses the edge of the screen. Jones wrote that “no clipping of BOBs … is carried out in Menace”. Instead he made “the physical screen size larger than the one that is being displayed”, adding a margin as wide as the largest alien around the visible area, so that a Bob half off the screen is drawn into memory nobody sees.

Sprites and Bobs together

Most Amiga action games used both. Menace is the plain case, with hardware sprites for the player’s ship and Bobs for the aliens. Later games often turned it round. Codetapper’s analyses of Amiga sprite tricks record that Risky Woods built its 16-colour background layer from “all 8 hardware sprites” repositioned across the screen, R-Type II used the eight sprites for “a 64 pixel wide repeating pattern for the backgrounds on most levels”, Brian the Lion reused a single sprite for a parallax layer of clouds and palm trees, and Rod-Land used all eight for its score panel. In those games the moving characters were Bobs, and the sprites became scenery.

Sources

  • Commodore-Amiga, Amiga ROM Kernel Reference Manual: Libraries and Devices (Addison-Wesley, 1986), “Animation”: p. 105, Bobs as “blitter objects”, the save and restore of the background, and drawing order as priority; pp. 149–150, double-buffered Bobs, the second save buffer and restoring “in the correct sequence”.
  • Commodore-Amiga, Amiga Hardware Reference Manual (Addison-Wesley, 1985): p. 94, reuse of sprite channels; p. 97, sprite width; p. 99, sprite colours; pp. 102–103, the sprite data structure; p. 112, sprite priority; p. 117, attached sprites; chapter 7, BPLCON2 and sprite–playfield priority; pp. 169–170, the three-step car example and the cookie-cut function $CA; pp. 173–174, first- and last-word masks; p. 176, descending mode; pp. 180–181, the blitter done flag, the double test and concurrent working; p. 188, blitter speed; Appendix A, p. 261, the BLTCON0 and BLTCON1 bit tables.
  • Dave Jones, “The Menace Within”, Amiga Format issue 7, February 1990, pp. 63–64, the first part of his series on programming Menace: the monthly source code, hardware and software sprites in Menace, the name BOBS, masking and double buffering.
  • Dave Jones, “The Whole Truth about Games Programming Part 5: Aliens 2”, from the same Amiga Format series (1990), as republished on Codetapper’s site (web, secondary): three blits per alien, the channel assignments, the three-word shifted blit with -2 modulos, no clipping and the enlarged screen, 384 bytes per frame. https://codetapper.com/amiga/diary-of-a-game/menace/part-5-aliens-2
  • Codetapper, “Sprite Tricks” (web, secondary): Risky Woods, R-Type II, Brian the Lion and Rod-Land. https://codetapper.com/amiga/sprite-tricks/

See also

Checked. Verified against primary sources and signed off by a person.