The Spectrum Next/TBBlue have a new hardware sprites system, enabling easier programming of sprites and their manipulation on screen. The characteristics of the sprites are:
- Total 64 sprites in 64 attribute slots and 64 pattern slots;
- Size 16 by 16 pixels;
- 256 colors per pixel;
- 256-color palette where each sprite can define an offset from the palette;
- Pink color reserved for transparent color;
- Maximum of 12 sprites per scanline;
- Collision detection of sprites;
- Rotate and X/Y mirror flag;
- Possibility to display sprites over the ZX Spectrum border.
The memory used for the sprites is separated from the main memory of the ZX Spectrum, being implemented in the internal memory of the FPGA and accessible via I/O ports.
Some options are configured via the TBBlue port system, reproduced here:
Port 0x243B is write-only and is used to set the registry number.
Port 0x253B is used to access the registry value.Register: (R/W) 21 => Sprite system bits 7-2 = Reserved, must be 0 bit 1 = Over border (1 = yes) bit 0 = Sprites visible (1 = visible)
To turn on the sprites, bit 0 of register 21 must be set. If bit 1 is on, the sprites may be displayed over the default ZX Spectrum border.
Port 0x303B, if read, returns some information:
- Bits 7-2: Reserved, always 0.
- Bit 1: max sprites per line flag.
- Bit 0: Collision flag.
Port 0x303B, if written, defines the sprite slot to be configured by ports 0x57 and 0x5B, and also initializes the address of the palette.
Port 0x53 is write-only and is used to send the palette, the palette index is auto-incremented each write. The palette is initialized at the reset with colors from 0 to 255.
Port 0x57 is write-only and is used to send the attributes of the selected sprite slot, being the address is auto-incremented each writing and after sending the 4 bytes of attributes the address points to the next sprite. The description of each byte follows below:
- 1st: X position (bits 7-0).
- 2nd: Y position (0-255).
- 3rd: bits 7-4 is palette offset, bit 3 is X mirror, bit 2 is Y mirror, bit 1 is rotate flag and bit 0 is X MSB.
- 4th: bit 7 is visible flag, bit 6 is reserved, bits 5-0 is Name (pattern index, 0-63).
Port 0x5B is write-only and is used to send the pattern of the selected sprite slot, with the address being auto-incremented with each write and after sending the 256 bytes of the pattern the address points to the next sprite slot. Each pattern byte represents the offset of the palette and the order is left to right and top to bottom.
Addresses from Ports 0x57 and 0x5B are independent and configured together in the write port 0x303B however the increment of the address is done separately, can be sent the pattern of 10 sprites, for example, and then sent the attributes of the 10 sprites without having to rewrite in the port 0x303B.
Because sprites can be displayed on top of the ZX Spectrum border, the coordinates of each sprite can range from 0 to 319 for the X axis and 0 to 255 for the Y axis. For both axes, values from 0 to 31 are reserved for the Left or top border, for the X axis the values 288 to 319 is reserved for the right border and for the Y axis values 224 to 255 for the lower border.
If the display of the sprites on the border is disabled, the coordinates of the sprites range from (32,32) to (287,223).
The priority of the sprites is from 0 (least priority) to 63 (highest priority) and all sprites have a highest priority over all spectrum screens.
Each sprite has the Name attribute that defines which pattern it will display, and more than one sprite can display the same pattern. Each byte of the pattern defines the index of the palette with the 4 most significant bits being summed with bits 7-4 of the third byte of the atributes, allowing the programmer to display the same pattern with different colors.
As an example of the palette offset, if the byte of the pixel pattern (0,0) is 0x14, and the palette offset is 0x00, the color will be of the palette index 0x14, but if the palette offset is set to 0x20, The palette index will be 0x34.
In the palette each byte represents the colors in the RRRGGGBB format, and the pink color, defined by standard 11100011, is reserved for the transparent color.
Collisions of 2 or more sprites only happen if at least 2 non-transparent pixels are drawn in the same position on the screen.
As an example of a sprite, let’s check the pattern below:
Using the default palette, which is initialized at the reset for colors 0 through 255, the hexadecimal values for this pattern follow below, divided into 16 bytes per line with 16 rows in total:
04040404040404E3E3E3E3E3E3E3E3E3 04FFFFFFFFFF04E3E3E3E3E3E3E3E3E3 04FFFBFBFBFF04E3E3E3E3E3E3E3E3E3 04FFFBF5F5FBFF04E3E3E3E3E3E3E3E3 04FFFBF5A8A8FBFF04E3E3E3E3E3E3E3 04FFFFFBA844A8FBFF04E3E3E3E3E3E3 040404FFFBA844A8FBFF04E3E3E3E3E3 E3E3E304FFFBA84444FBFF04E304E3E3 E3E3E3E304FFFB444444FBFF044D04E3 E3E3E3E3E304FFFB44444444FA4D04E3 E3E3E3E3E3E304FFFB44FFF54404E3E3 E3E3E3E3E3E3E304FF44F5A804E3E3E3 E3E3E3E3E3E3E3E304FA4404A804E3E3 E3E3E3E3E3E3E3044D4D04E304F504E3 E3E3E3E3E3E3E3E30404E3E3E304FA04 E3E3E3E3E3E3E3E3E3E3E3E3E3E30404
The value in hexadecimal 0xE3 points to index 227 of the palette containing the color 0xE3 that represents the transparent color.
To set this pattern for some sprite, we must set the slot number of the patterns through port 0x303B and then send the 256 bytes in sequence to port 0x5B. In the following example we will choose slot #2:
OUT 0x303B, 2: REM Select pattern #2 OUT 0x5B, 0x04: OUT 0x5B, 0x04........... : REM Send pattern data
To display the sprite at some screen position, we must set up some sprite to be visible by setting its attributes, pointing to pattern #2 and turning on the sprites display. In the following example we will choose sprite slot #9:
OUT 0x303B, 9: REM Select sprite #9 OUT 0x57, 32: REM X position in 32 OUT 0x57, 32: REM Y position in 32 OUT 0x57, 0: REM no palette offset and no rotate and mirrors flags OUT 0x57, 130: REM Sprite visible and show pattern #2 OUT 0x243B, 21: REM Select register #21 OUT 0x253B, 1: REM All sprites visible
The Next screen should be displayed as below: