A while back, while reading the forums over at eab.abime.net, I came across several posts mentioning the game Mega Typhoon, which used a clever system to have more bobs on screen. The game ran in Dual Playfield mode and used the back playfield as its background image and the foreground playfield solely for bobs. This method intrigued me and so I started experimenting with other ways to use the foreground playfield to get more bobs on screen.
Now, Mega Typhoon uses a pretty standard technique for drawing bobs: cookie-cut mode bobs are drawn into the bitmap and later cleared. However, if the front playfield is used just for blitting bobs, it is also possible to skip the clearing altogether and use the much cheaper copy mode of the blitter (as long as some restrictions are accepted and some care is taken while blitting).
Dual Playfield ‘Fast Bobs’
Now, Mega Typhoon uses a pretty standard technique for drawing bobs: cookie-cut mode bobs are drawn into the bitmap and later cleared. However, if the front playfield is used just for blitting bobs, it is also possible to skip the clearing altogether and use the much cheaper copy mode of the blitter (as long as some restrictions are accepted and some care is taken while blitting).
Dual Playfield ‘Fast Bobs’
Above: testing the Dual Playfield ‘Fast Bobs’ program in WinUAE
The basic idea of not needing to clear any pixels is based on how the Blitter deals with data when doing a copy. It very simply overwrites all data present with the data that is copied to the bitmap. Also, when shifting this data to pixel boundaries, normally empty pixels are shifted in. What this means is that as long as the given data contains some empty space around it in all directions, just copying the data over shifted by a few pixels will automatically also clear the background.
This is very good as it increases performance by quite a bit. Both due to the copy mode being twice as fast as the cookie-cut mode and because the clear step is skipped altogether. Normally, this is not very useful however, because blitting in this way also deleted any pixels present that show the background. However, if Dual Playfield mode is used, the background can be kept on the second playfield so the Blitter doesn’t overwrite those pixels.
This is very good as it increases performance by quite a bit. Both due to the copy mode being twice as fast as the cookie-cut mode and because the clear step is skipped altogether. Normally, this is not very useful however, because blitting in this way also deleted any pixels present that show the background. However, if Dual Playfield mode is used, the background can be kept on the second playfield so the Blitter doesn’t overwrite those pixels.
- Method
- Minimum space
- Overlap
- Performance
Tab 1
Above: visual example of copy mode blit onto a background and a copy mode blit using the foreground playfield.
The basic method for blitting copy mode bobs is to work around the restrictions of a copy blit. Which are:
By keeping some empty space in the bob definition, it is possible to move a bob around on the screen, while clearing the parts of the screen it previously occupied at the same time. Naturally this limits the speed of the bob - if more pixels are moved than there is empty space, part of the previous copy will remain on screen. For a more visual example, see the picture above and the schematic below:
- Any data present at the target location in the bitmap will get overwritten
- All data is blit in 16 pixel horizontal increments
- Pixel perfect positioning requires an extra 16 pixels horizontally
By keeping some empty space in the bob definition, it is possible to move a bob around on the screen, while clearing the parts of the screen it previously occupied at the same time. Naturally this limits the speed of the bob - if more pixels are moved than there is empty space, part of the previous copy will remain on screen. For a more visual example, see the picture above and the schematic below:
Old frame New location ResultWhen using this method, coupled with Dual Playfield mode, it is possible to draw bobs this way using just one Blitter operation (the straight A-D copy). Note that this does mean bobs will be limited to 7 colours + transparant and that the background will be limited to 8 colours using the OCS chipset. Using this method on an AGA machine increases the amounts of colours that can be used to 15 + transparant for the bobs and 16 for the background.
......... ......... .........
..xxx.... .. xxx... ...xxx...
..x.x.... .. x.x... ...x.x...
..x.x.... .. x.x... ...x.x...
..xxx.... .. xxx... ...xxx...
......... ......... .........
. = colour 0 pixel (screen)
" " = empty space (in bob source data)
x = coloured pixel
Tab 2
In order to prevent two copy mode bobs overlapping and erasing part of an already drawn bob or leaving behind a trail while moving, there is a certain minimum space needed between any two bobs drawn this way and an amount of minimum empty space needed in the bob definition. This distance is determined by the Blitter only blitting in 16 pixel increments and the amount of empty space in the bobs. Determining how much empty space is needed in the bob is done the following way:
For example, suppose we want to draw an object that can move 1 pixel to the left, 2 pixels to the right, 3 pixels up and 2 pixels down per frame. For this, the bob definition would then need 2 pixels empty space in the left columns, 1 pixel empty space in the right columns, 2 pixels empty space in the top rows and 3 pixels empty space in the bottom rows. If this bob is drawn as a 32x32 pixel square, the resulting space left for graphics data in the bob is 29x27 pixels (or 26x22 pixels when double buffering).
After determining empty space in the bob as above, the minimum distance between two bobs drawn can be established. To prevent horizontal overlap, a minimum distance of the bobs’s total horizontal size including empty pixels, plus 16 pixels and minus the minimum of the empty space on opposite sides of the two drawn bobs. Vertically, the minimum distance to prevent overlap is equal to the bob’s total vertical size including empty pixels, minus the minimum of the empty space on opposite sides of the two drawn bobs.
For example, if two bobs sized as the example bob above are drawn side to side, the minimum distance would be: horizontally 32+16-1 (=47 pixels) and vertically 32-2 (=30 pixels).
- Determine maximum speed in pixels per frame the bob will move in all four directions (left, right, up, down)
- Add this as empty space on the opposite sides of the bob to the directions (so, add the maximum speed the bob moves to the left on the right side of the bob)
- Double the amounts if using a double buffered bitmap
- If movement in a direction is not required, no empty space is needed for it on the opposite side of the bob either
For example, suppose we want to draw an object that can move 1 pixel to the left, 2 pixels to the right, 3 pixels up and 2 pixels down per frame. For this, the bob definition would then need 2 pixels empty space in the left columns, 1 pixel empty space in the right columns, 2 pixels empty space in the top rows and 3 pixels empty space in the bottom rows. If this bob is drawn as a 32x32 pixel square, the resulting space left for graphics data in the bob is 29x27 pixels (or 26x22 pixels when double buffering).
After determining empty space in the bob as above, the minimum distance between two bobs drawn can be established. To prevent horizontal overlap, a minimum distance of the bobs’s total horizontal size including empty pixels, plus 16 pixels and minus the minimum of the empty space on opposite sides of the two drawn bobs. Vertically, the minimum distance to prevent overlap is equal to the bob’s total vertical size including empty pixels, minus the minimum of the empty space on opposite sides of the two drawn bobs.
For example, if two bobs sized as the example bob above are drawn side to side, the minimum distance would be: horizontally 32+16-1 (=47 pixels) and vertically 32-2 (=30 pixels).
Tab 3
As stated before, it is not possible to overlap two copy mode bobs as the one would overwrite parts of the other. However, it is perfectly possible to mix copy mode bobs and normal cookie-cut mode bobs together. To achieve this, a procedure somewhat like the one below can be used.
Preventing overlap or dynamically blitting overlapping bobs using cookie-cut mode is extra work, but most of that should be avoidable - as designer of the game/demo/program using this method, you can choose to prevent this from happening too much. In many games for instance, enemies move on predictable paths. These paths could be chosen to prevent overlap. By adding a number of normal overlapping bobs and drawing the player as a sprite, such a game would look like overlap is always possible, but in fact only allow limited overlap to happen.
- Clear all cookie-cut bobs drawn the previous frame
- Blit all copy mode bobs
- Blit all cookie-cut mode bobs
Preventing overlap or dynamically blitting overlapping bobs using cookie-cut mode is extra work, but most of that should be avoidable - as designer of the game/demo/program using this method, you can choose to prevent this from happening too much. In many games for instance, enemies move on predictable paths. These paths could be chosen to prevent overlap. By adding a number of normal overlapping bobs and drawing the player as a sprite, such a game would look like overlap is always possible, but in fact only allow limited overlap to happen.
Tab 4
Performance of this method is pretty good, a normal Dual Playfield setup as the one in the example program would have been able to draw roughly 20 32x32 pixel bobs on screen per frame. The program as is could draw 58 28x28 bobs per frame* - but that didn’t fit on the screen, so the number was lowered to 42.
The theoretical performance limit (assuming zero CPU and Copper use) is somewhere around 70 28x28 bobs drawn per frame*, so using better blitting routines or using the Copper to blit could up performance further. Roughly speaking, my tests show that you should be able to blit around 2.5x3.0 times the copy mode bobs that could’ve been drawn using the cookie-cut/clear mode.
Performance is even greater when compared to the memory-friendly blitting method of having a separate restore buffer per bob. In this case, a program could achieve up to 4.0x the copy mode bobs compared to the copy/cookie-cut/restore mode bobs, without needing any more memory.
*) Assuming a basic A500
The theoretical performance limit (assuming zero CPU and Copper use) is somewhere around 70 28x28 bobs drawn per frame*, so using better blitting routines or using the Copper to blit could up performance further. Roughly speaking, my tests show that you should be able to blit around 2.5x3.0 times the copy mode bobs that could’ve been drawn using the cookie-cut/clear mode.
Performance is even greater when compared to the memory-friendly blitting method of having a separate restore buffer per bob. In this case, a program could achieve up to 4.0x the copy mode bobs compared to the copy/cookie-cut/restore mode bobs, without needing any more memory.
*) Assuming a basic A500
Now, the program I made is not perfect (which you can see by looking at the source code), but it works. There are several spots in which code could’ve been much more compact (such as the title page code), more legible (the tile blitting code) or more optimal. However, it is not intended to be the fastest or best ever code, it is intended to show this method of blitting in action and hopefully help Amiga developers achieve nice things for their games or demos.
Above: the Dual Playfield ‘Fast Bobs’ program running in WinUAE
As such, I hope it is useful or at least inspires coders to look for new ways to push the old OCS chipset ever further. All code, apart from the Startup code (which was made by Photon of Scoopex) and the joystick code (which was found on eab.abime.net) was written by me and is (C) 2017 Jeroen Knoester.
That said, please do use any part of my code or this idea you find useful. A credit/mention would be nice but is not required in any way. The program, source code and a bootable .ADF can be found in the downloads section.
If you have any questions, be sure to contact me through the contact form!
That said, please do use any part of my code or this idea you find useful. A credit/mention would be nice but is not required in any way. The program, source code and a bootable .ADF can be found in the downloads section.
If you have any questions, be sure to contact me through the contact form!