Monday, October 13, 2014

More work on sprites

I don't have any nice screen shots to put in here (but I might add some in later), but I have been working on VIC-II sprites.

These sprites are now displaying properly, apart from the lack of border/foreground priority and hardware collision detection.  Sprite positions are now correct with regard to the text/bitmap screen.

Unfortunately, adding the extra logic to the VIC-IV memory access paths has thrown FPGA timing closure out the window for now.

The 192MHz pixel clock requires timing within about 5.1ns, but is currently sitting around 7.3ns. It is an amazing testimony to the Artix7 FPGAs that the system still seems to run flawlessly.  This is partly because the FPGA is speed rated for operation at 85 degrees Centigrade and an operating voltage of 0.95 Volts instead of the nominal 1.00 Volt supply.

In any case, I want to get the timing at least close to meeting closure (i.e., being fast enough), so that I can avoid problems later, and also to make sure that everything else that I want to add will still fit.

My approach to this at the moment is to unify the VIC-II compatibility sprite data fetches so that there is only one extra data stream that has to be plugged into the chipram/fastram.  I am part way through this, and have already improved timing to about 6.6ns, and it looks like it shouldn't be too hard to further improve on this.

I have also started thinking about the design for the new sprites.  This is all subject to change, but here is what I am thinking about at the moment:

The basic design of the new VIC-IV sprites, is that each sprite will have a dedicated 4KB memory buffer, and will be strictly one byte per pixel.  This allows for sprites of up to 64x64 256 colour pixels.

Like with the VIC-II, one physical sprite can be used multiple times on a frame without reloading the data by altering the data offset within the 4KB block, and possibly the height and width of the sprite.  I am also thinking about allowing sprites to be much wider.

Foreground/background priority will be by applying a bit mask to the character/bitmap data to decide whether it should appear in front of the sprite or behind the sprite.  This will allow sprites and the background to perform many of the functions of Amiga-style bit planes, although the way it will be done will be rather different.

Bit masks are also provided to allow modification of the colours of sprites.  For example applying and AND mask of $1f and an OR mask of $80 will translate all colours to $80-$9F.  This can be used to allow a common image to be used for different characters in a game, with selected colours being altered.  The 256 colour sprite palette can be separated from the bitmap palette, so there is improved flexibility compared to just applying bit masks to a flat 256 colour palette shared by all on-screen elements.  If I get really excited it might even be possible to use the other two 256 colour palettes for different sprites.

Finally, I intend to provide hardware scaling and rotation support.  I thought about having simple angle and zoom factor settings, but currently I am thinking that I will simply provide a linear 2D transformation matrix per sprite so that other effects can also be used.

The registers for the VIC-IV sprites are currently planned to live at $D710-$D7FF, allowing for up to 15 of these sprites, but there may end up being less than these depending on how many I can wrangle in.

All this is subject to change, as is the register map, but here is the structure I am currently looking at:

$D7x0-$D7x1 - Enhanced sprite X position in physical pixels (lower 12 bits)
$D7x1.4-7   - Enhanced sprite width (4 -- 64 pixels)
$D7x2-$D7x3 - Enhanced sprite Y position in physical pixels (16 bits)
$D7x3.4-7   - Enhanced sprite height (4 -- 64 pixels)
$D7x4       - Enhanced sprite data offset in its 4KB SpriteRAM (x16 bytes)
$D7x5       - Enhanced sprite foreground mask
$D7x6       - Enhanced sprite colour AND mask (sprite not visible if result = $00)
$D7x7       - Enhanced sprite colour OR mask
$D7x8-$D7x9 - Enhanced sprite 2x2 linear transform matrix 0,0 (5.11 bits)
$D7xA-$D7xB - Enhanced sprite 2x2 linear transform matrix 0,1 (5.11 bits)
$D7xC-$D7xD - Enhanced sprite 2x2 linear transform matrix 1,0 (5.11 bits)
$D7xE-$D7xF - Enhanced sprite 2x2 linear transform matrix 1,1 (5.11 bits)

The attentive reader will note that nowhere does this address the 4KB data blocks for each sprite.  This will be direct mapped in the 28-bit address space.  I am tossing around the idea of over-mapping it with the 64KB colour RAM at $FF80000 (the first 1KB of which is also available at $D800 for C64 compatibility).  The reason for this is that the 4KB sprite RAM will probably be write-only to simplify the data plumbing.  However, to allow for freezing (and hence multi-tasking), I really do want some way to read the sprite data.  The trade-off of course is that this means that you wouldn't be able to use all 64KB for colour RAM if it also being used as a proxy to the sprite RAM data.


  1. Looks quite a powerfull sprite system. One of the major drawbacks of 256 colour VGA modes on the PC was that while 256 colours do allow photo-realism, photo-realism was not possible in games, because the palette had to have colours to allow for any software-sprite that could appear on the screen. Once sprites have their own palettes, there might be enough space left in the main graphics palette to allow for photo-realism. If you succeed, your little C65 based computer might be able to compete with PC's of several 100 MHz.

  2. How do you apply the rotate/scaling transform without getting gaps between the original pixels?

    1. Hello,
      Rotation and scaling are not yet implemented, but my plan is to use a 2D transform matrix, which implicitly works out which pixel is required for a given point on the display. Thus a single pixel may get drawn many times.