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:
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:
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 4 and 5 form the right part of Brian, and the life counter and red thing are created using only sprite 4.
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.
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
Popular Sprite Tricks
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.
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.
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.
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.
Post your comment
Comments
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)
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)
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)
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)
Great technic, great article - awesome!
Visitor 23/12/2013 6:36pm (11 years ago)
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)
No one has commented on this page yet.
RSS feed for comments on this page | RSS feed for all comments