Codetapper's Amiga Site

Brian the Lion

Brian the Lion from Psygnosis is an Amiga game running in 4 bitplane (16 colour) mode. The game fakes a parallax layer using a couple of sprites multiplexed across the screen. Sprites are heavily used in the game too:

Brian the Lion with sprites enabled

Sprites enabled.

Brian the Lion with sprites disabled

Sprites disabled.

If we turn on the 8 sprites in sequence, we can see how the sprites are re-used by the game. Each odd numbered sprite has an attach bit that means it will be attached to the previous sprite to create a 16 colour sprite. The first 2 sprites are re-used extensively in attach mode:

Sprite 0 enabled.

Sprites 0-1 enabled.

Sprites 2 and 3 form the middle section of Brian, plus the right part of the life image, and the blue jewel counter is made using only sprite 2:

Sprites 0-2 enabled

Sprites 0-3 enabled

Sprites 4 and 5 form the right part of Brian, and the life counter and red thing are created using only sprite 4.

Sprites 0-4 enabled

Sprites 0-5 enabled

Sprites 6 and 7 tidy up the blue jewel graphic, and add the parallax palm trees, and the small ball in the score panel. Note that sprite 7 by itself is repeated horizontally in the same line to form very wide clouds.

Sprites 0-6 enabled

Sprites 0-7 enabled

As you can see above, sprite 7 is reused extensively to add clouds and palm trees to the background. You may wonder how this is possible when you don't have enough DMA time with the copper to change the sprite data (2 words) and re-position it horizontally?

If we investigate the copperlist, the trick is revealed. Because the cloud is only 2 colours, SPR7DATA is changed every 8 pixels, but SPR7DATB is left alone to retain it's previous value. In 4 bitplane (16 colour) mode, the copper can write a word of data every 8 pixels, so the sprite is positioned and then the cloud data is written. Immediately the sprite is repositioned 16 pixels further to the right, and the next word of data is written into the sprite. This happens 4 times to create the 64 pixel wide cloud. Here is the copperlist for the 3rd to last line of the big cloud:

Address   Copperlist   Comment
-------   ----------   -----------------------------------------
0000ed42: 683f fffe    ; Wait for vpos >= 0x68 and hpos >= 0x3e.
                       ; VP 68, VE 7f; HP 3e, HE fe; BFD 1
0000ed46: 0180 09ff    ; COLOR00 := 0x09ff
0000ed4a: 0178 6850    ; SPR7POS := 0x6850    Start small sprite
0000ed4e: 017c 1000    ; SPR7DATA := 0x1000   (1 pixel wide)
0000ed52: 68a9 fffe    ; Wait for vpos >= 0x68 and hpos >= 0xa8.
0000ed56: 0178 68b0    ; SPR7POS := 0x68b0    Start big cloud sprite
0000ed5a: 017c 0175    ; SPR7DATA := 0x0175   (64 pixels wide)
0000ed5e: 0178 68b8    ; SPR7POS := 0x68b8
0000ed62: 017c 7f5f    ; SPR7DATA := 0x7f5f
0000ed66: 0178 68c0    ; SPR7POS := 0x68c0
0000ed6a: 017c ffff    ; SPR7DATA := 0xffff
0000ed6e: 0178 68c8    ; SPR7POS := 0x68c8
0000ed72: 017c dc00    ; SPR7DATA := 0xdc00
0000ed76: 68dd fffe    ; Wait for vpos >= 0x68 and hpos >= 0xdc.
0000ed7a: 0180 0000    ; COLOR00 := 0x0000

At the start of the line, the background is changed to the correct colour in the gradient, then a small cloud sprite is rendered on the left of the screen. The copper waits on the same line for position 0xa8, then starts frantically changing the position of the sprite and pushing data directly into the SPR7DATA register. At the end of the line, the background is switched back to black.

If we examine the next 2 lines, they are very similar:

Address   Copperlist   Comment
-------   ----------   -----------------------------------------
0000ed9e: 693f fffe    ; Wait for vpos >= 0x69 and hpos >= 0x3e.
0000eda2: 0180 09ff    ; COLOR00 := 0x09ff
0000eda6: 0178 6951    ; SPR7POS := 0x6951
0000edaa: 017c 1000    ; SPR7DATA := 0x1000
0000edae: 69a9 fffe    ; Wait for vpos >= 0x69 and hpos >= 0xa8.
0000edb2: 0178 69b0    ; SPR7POS := 0x69b0
0000edb6: 017c 17ff    ; SPR7DATA := 0x17ff
0000edba: 0178 69b8    ; SPR7POS := 0x69b8
0000edbe: 017c ffff    ; SPR7DATA := 0xffff
0000edc2: 0178 69c0    ; SPR7POS := 0x69c0
0000edc6: 017c ffea    ; SPR7DATA := 0xffea
0000edca: 0178 69c8    ; SPR7POS := 0x69c8
0000edce: 017c feb0    ; SPR7DATA := 0xfeb0
0000edd2: 69dd fffe    ; Wait for vpos >= 0x69 and hpos >= 0xdc.
0000edd6: 0180 0000    ; COLOR00 := 0x0000
  ...
0000edfa: 6a3f fffe    ; Wait for vpos >= 0x6a and hpos >= 0x3e.
0000edfe: 0180 0aff    ; COLOR00 := 0x0aff
0000ee02: 6aa9 fffe    ; Wait for vpos >= 0x6a and hpos >= 0xa8.
0000ee06: 0178 6ab0    ; SPR7POS := 0x6ab0
0000ee0a: 017c afa5    ; SPR7DATA := 0xafa5
0000ee0e: 0178 6ab8    ; SPR7POS := 0x6ab8
0000ee12: 017c 4b4b    ; SPR7DATA := 0x4b4b
0000ee16: 0178 6ac0    ; SPR7POS := 0x6ac0
0000ee1a: 017c a555    ; SPR7DATA := 0xa555
0000ee1e: 0178 6ac8    ; SPR7POS := 0x6ac8
0000ee22: 017c 577a    ; SPR7DATA := 0x577a
0000ee26: 6add fffe    ; Wait for vpos >= 0x6a and hpos >= 0xdc.
0000ee2a: 0180 0000    ; COLOR00 := 0x0000
0000ee2e: 0178 0000    ; SPR7POS := 0x0000

Here is a zoomed version of the last 3 lines of data from the cloud. If you associate blue in the image as the background (a 0 bit), and the white as the cloud foreground (bit 1) you would get hex values of $0175, $7f5f, $ffff and $dc00 respectively for the first line of data, $17ff, $ffff, $ffea and $feb0 for the 2nd line, and $afa5, $4b4b, $a555 and $577a for the final line. Look familiar?

The palm trees are done by alternating loading of the DATA registers for sprites 6 and 7 in sequence:

Address   Copperlist   Comment
-------   ----------   -----------------------------------------
0000f52a: 892f fffe    ; Wait for vpos >= 0x89 and hpos >= 0x2e.
                       ; VP 89, VE 7f; HP 2e, HE fe; BFD 1
0000f52e: 0170 893f    ; SPR6POS := 0x893f    Prepare sprite 6
0000f532: 0174 00f0    ; SPR6DATA := 0x00f0
0000f536: 0178 8947    ; SPR7POS := 0x8947    Prepare sprite 7
0000f53a: 017c 0000    ; SPR7DATA := 0x0000
0000f53e: 0180 0cff    ; COLOR00 := 0x0cff    Set background colour
0000f542: 0174 0000    ; SPR6DATA := 0x0000   Begin switching data!
0000f546: 0170 894f    ; SPR6POS := 0x894f
0000f54a: 017c 1c00    ; SPR7DATA := 0x1c00
0000f54e: 0178 8957    ; SPR7POS := 0x8957
0000f552: 0174 0000    ; SPR6DATA := 0x0000
0000f556: 0170 895f    ; SPR6POS := 0x895f
0000f55a: 017c 0000    ; SPR7DATA := 0x0000
0000f55e: 0178 8967    ; SPR7POS := 0x8967
0000f562: 0174 0000    ; SPR6DATA := 0x0000
0000f566: 0170 896f    ; SPR6POS := 0x896f
0000f56a: 017c 0000    ; SPR7DATA := 0x0000
0000f56e: 0178 8977    ; SPR7POS := 0x8977
0000f572: 0174 0000    ; SPR6DATA := 0x0000
0000f576: 0170 897f    ; SPR6POS := 0x897f
0000f57a: 017c 6000    ; SPR7DATA := 0x6000
0000f57e: 0178 8987    ; SPR7POS := 0x8987
0000f582: 0174 00f0    ; SPR6DATA := 0x00f0
0000f586: 0170 898f    ; SPR6POS := 0x898f
0000f58a: 017c 0000    ; SPR7DATA := 0x0000
0000f58e: 0178 8997    ; SPR7POS := 0x8997
0000f592: 0174 0000    ; SPR6DATA := 0x0000
0000f596: 0170 899f    ; SPR6POS := 0x899f
0000f59a: 017c 1c00    ; SPR7DATA := 0x1c00
0000f59e: 0178 89a7    ; SPR7POS := 0x89a7
0000f5a2: 0174 0000    ; SPR6DATA := 0x0000
0000f5a6: 0170 89af    ; SPR6POS := 0x89af
0000f5aa: 017c 0000    ; SPR7DATA := 0x0000
0000f5ae: 0178 89b7    ; SPR7POS := 0x89b7
0000f5b2: 0174 0000    ; SPR6DATA := 0x0000
0000f5b6: 0170 89bf    ; SPR6POS := 0x89bf
0000f5ba: 017c 0000    ; SPR7DATA := 0x0000
0000f5be: 0178 89c7    ; SPR7POS := 0x89c7
0000f5c2: 0174 0000    ; SPR6DATA := 0x0000
0000f5c6: 0170 89cf    ; SPR6POS := 0x89cf
0000f5ca: 017c 6000    ; SPR7DATA := 0x6000
0000f5ce: 0178 89d7    ; SPR7POS := 0x89d7
0000f5d2: 89dd fffe    ; Wait for vpos >= 0x89 and hpos >= 0xdc.
0000f5d6: 0180 0000    ; COLOR00 := 0x0000

The next line of palm tree data is much the same:

Address   Copperlist   Comment
-------   ----------   -----------------------------------------
0000f5fa: 01ba 00ee    ; COLOR29 := 0x00ee
0000f5fe: 8a2f fffe    ; Wait for vpos >= 0x8a and hpos >= 0x2e.
0000f602: 0170 8a3f    ; SPR6POS := 0x8a3f
0000f606: 0174 007e    ; SPR6DATA := 0x007e
0000f60a: 0178 8a47    ; SPR7POS := 0x8a47
0000f60e: 017c 0000    ; SPR7DATA := 0x0000
0000f612: 0180 0dff    ; COLOR00 := 0x0dff    Set background colour
0000f616: 0174 0000    ; SPR6DATA := 0x0000   Begin switching data
0000f61a: 0170 8a4f    ; SPR6POS := 0x8a4f
0000f61e: 017c 071c    ; SPR7DATA := 0x071c
0000f622: 0178 8a57    ; SPR7POS := 0x8a57
0000f626: 0174 1020    ; SPR6DATA := 0x1020
0000f62a: 0170 8a5f    ; SPR6POS := 0x8a5f
0000f62e: 017c 0000    ; SPR7DATA := 0x0000
0000f632: 0178 8a67    ; SPR7POS := 0x8a67
0000f636: 0174 0000    ; SPR6DATA := 0x0000
0000f63a: 0170 8a6f    ; SPR6POS := 0x8a6f
0000f63e: 017c 0001    ; SPR7DATA := 0x0001
0000f642: 0178 8a77    ; SPR7POS := 0x8a77
0000f646: 0174 8000    ; SPR6DATA := 0x8000
0000f64a: 0170 8a7f    ; SPR6POS := 0x8a7f
0000f64e: 017c 39f0    ; SPR7DATA := 0x39f0
0000f652: 0178 8a87    ; SPR7POS := 0x8a87
0000f656: 0174 007e    ; SPR6DATA := 0x007e
0000f65a: 0170 8a8f    ; SPR6POS := 0x8a8f
0000f65e: 017c 0000    ; SPR7DATA := 0x0000
0000f662: 0178 8a97    ; SPR7POS := 0x8a97
0000f666: 0174 0000    ; SPR6DATA := 0x0000
0000f66a: 0170 8a9f    ; SPR6POS := 0x8a9f
0000f66e: 017c 071c    ; SPR7DATA := 0x071c
0000f672: 0178 8aa7    ; SPR7POS := 0x8aa7
0000f676: 0174 1020    ; SPR6DATA := 0x1020
0000f67a: 0170 8aaf    ; SPR6POS := 0x8aaf
0000f67e: 017c 0000    ; SPR7DATA := 0x0000
0000f682: 0178 8ab7    ; SPR7POS := 0x8ab7
0000f686: 0174 0000    ; SPR6DATA := 0x0000
0000f68a: 0170 8abf    ; SPR6POS := 0x8abf
0000f68e: 017c 0001    ; SPR7DATA := 0x0001
0000f692: 0178 8ac7    ; SPR7POS := 0x8ac7
0000f696: 0174 8000    ; SPR6DATA := 0x8000
0000f69a: 0170 8acf    ; SPR6POS := 0x8acf
0000f69e: 017c 39f0    ; SPR7DATA := 0x39f0
0000f6a2: 0178 8ad7    ; SPR7POS := 0x8ad7
0000f6a6: 8add fffe    ; Wait for vpos >= 0x8a and hpos >= 0xdc.
0000f6aa: 0180 0000    ; COLOR00 := 0x0000

Post your comment

Comments

  • Gravatar for Elliott Savva

    The Wikipedia page for OCS reckons that sprite data can only be changed between lines? Is this incorrect?

    Elliott Savva 03/10/2020 1:06am (4 years ago)

  • Gravatar for Gzegzolka

    I wonder about aga version too. It would be interesting if You could investigate tricks in that one too. While I have no skills in games development I like how with simple language You explain those impressive stuff.

    Gzegzolka 23/09/2017 9:26am (7 years ago)

  • Gravatar for Bren McGuire

    what about the A1200 version? It shows much more colours and an insane number of parallax layers. Sprites or something else?

    Bren McGuire 27/06/2017 8:56pm (7 years ago)

  • Gravatar for kier

    There is the mistake in the text above.
    Brian is not dual playfield 6 bitplanes game. It uses normal 4 bitplanes 16colour frontplane and second layer of parallax trees which uses sprites 6 and 7 which is described above.
    Using 6 bitplane lowres screen copper can execute single instruction every 16 pixels, so you dont have enough dma to change sprites data. You can do it only using 4 or 5 bitplanes.

    kier 20/04/2016 8:59pm (9 years ago)

  • Gravatar for Visitor

    Great technic, great article - awesome!

    Visitor 23/12/2013 6:36pm (11 years ago)

  • Gravatar for Tom M.

    Interesting. Seems similar to Atari 2600 style of coding. But why did they use only 8 hardware sprites to make things that complicated for coders...

    Tom M. 19/02/2012 4:03pm (13 years ago)

RSS feed for comments on this page | RSS feed for all comments

Popular Sprite Tricks

Brian the Lion

Jim Power

2 sprites are displayed then repositioned horizontally right across the screen to create the colourful static background. The remaining sprites are used for the main character, the status bar and player bullets.

Brian the Lion

Risky Woods

The 16-colour background layer was created by using all 8 hardware sprites and repositioning them across the screen. The same 64 pixel wide graphics are repeated across the entire play area.

Brian the Lion

Shadow of the Beast

One of the first jaw-droppingly beautiful Amiga games that still looks great today. Sprites were heavily re-used on the screen, along with priority changes to make them appear between the playfields.

Brian the Lion

Stardust

The amazing tunnel sequence was created with a 6 frame animation sequence made with only 4 colours and mirrored vertically. The asteroid layer sits on top of this, with a status panel and player ship made of sprites sitting on top.