Difference between revisions of "Sprite Attribute Upload"

From SpecNext official Wiki
Jump to: navigation, search
(further details from Jim in forum post)
(Core 2.00.23 changes (relative sprites added and sprite-index link with NextReg $34))
Line 7: Line 7:
 
|Subsystem=Sprites
 
|Subsystem=Sprites
 
}}
 
}}
Uploads attributes of the sprite slot selected by {{PortNo|$303B}}. Attributes are in 4-5 byte blocks sent in the following order; after sending 4 or 5 bytes the address auto-increments to the next sprite. This auto-increment is independent of other sprite ports. The 4-5 bytes are as follows:
+
Uploads attributes of the sprite slot selected by {{PortNo|$303B}}. Attributes are sent in 4-5 byte blocks. After sending 4 or 5 bytes block the sprite-index (slot) auto-increments to the next sprite. This auto-increment is independent of other sprite ports, but may be interlinked with {{NextRegNo|$34}} (see details there). The auto-increment from value 63 is officially "undefined behaviour" and index must be explicitly reset back to 0..63 after such auto-increment to make the SW predictable in future.
 +
 
 +
The 4-5 bytes sprite-attribute structure is as follows:
  
 
Byte 1 is the low bits of the X position. The MSB is in byte 3.
 
Byte 1 is the low bits of the X position. The MSB is in byte 3.
Line 46: Line 48:
 
| 7 || If 1, the pattern will be treated as 4-bit colour one (128 bytes), 0 is for 8-bit colour patterns (256 bytes)
 
| 7 || If 1, the pattern will be treated as 4-bit colour one (128 bytes), 0 is for 8-bit colour patterns (256 bytes)
 
|-
 
|-
| 6 || Chooses top/bottom part of pattern slot (for 4-bit colour patterns)
+
| 6 || (if bit 7 = 1): Chooses top/bottom part of pattern slot when 4-bit colour pattern
 
0 will target bytes 0..127 of pattern "Name" (byte 4), 1 will target bytes 128..255 of pattern "Name".
 
0 will target bytes 0..127 of pattern "Name" (byte 4), 1 will target bytes 128..255 of pattern "Name".
 +
 +
(if bit 7 = 0): make this sprite "relative" one: 1 = relative, 0 = normal (anchor) type
 
|-
 
|-
| 5 || Reserved, use always 0
+
| 5 || (if bit 7-6 = %01) for "relative" sprite, this bit chooses top/bottom part of pattern slot for 4-bit colour mode (4 or 8 bit mode is set by anchor sprite, relative sprite can't switch the colour mode). See Bit 6 description above, if anchor sprite is in 4-bit mode. If anchor sprite is in 8-bit mode, use always 0
 +
(else) For normal (anchor) sprites this is reserved, use always 0
 
|-
 
|-
 
| 4-3 || x-axis scale factor: %00 = 1x (16 pixels), %01 = 2x, %10 = 4x, %11 = 8x (128 pixels)
 
| 4-3 || x-axis scale factor: %00 = 1x (16 pixels), %01 = 2x, %10 = 4x, %11 = 8x (128 pixels)
Line 57: Line 62:
 
| 0 || MSB of Y coordinate
 
| 0 || MSB of Y coordinate
 
|}
 
|}
 +
 +
=== Normal (= anchor) sprites ===
  
 
About [X,Y] coordinates: 9 bit values allow for 0..511 coordinate. The top-left ULA pixel ("paper" area) is at [32,32] and bottom-right ULA pixel is at [287,223] (256x192 pixel area).
 
About [X,Y] coordinates: 9 bit values allow for 0..511 coordinate. The top-left ULA pixel ("paper" area) is at [32,32] and bottom-right ULA pixel is at [287,223] (256x192 pixel area).
Line 63: Line 70:
  
 
All coordinates beyond these act as wrap-around 0..511 coordinate system, with sprite getting outside of drawing area, i.e. [X,Y]=[511,510] will render sprite in top left corner over "border" area, with left-most column already not visible (511 works as "-1" X coordinate) and two top-most rows not visible (510 works as "-2" Y coordinate), only remaining 15x14 pixels of sprite pattern are visible in top-left corner. Similarly sprite at coordinates [310,250] will render only 10x6 pixels of pattern in bottom right corner, rest of pattern being already outside of rendering area and not visible (assuming the over-border is enabled and not clipped by sprite clip-window).
 
All coordinates beyond these act as wrap-around 0..511 coordinate system, with sprite getting outside of drawing area, i.e. [X,Y]=[511,510] will render sprite in top left corner over "border" area, with left-most column already not visible (511 works as "-1" X coordinate) and two top-most rows not visible (510 works as "-2" Y coordinate), only remaining 15x14 pixels of sprite pattern are visible in top-left corner. Similarly sprite at coordinates [310,250] will render only 10x6 pixels of pattern in bottom right corner, rest of pattern being already outside of rendering area and not visible (assuming the over-border is enabled and not clipped by sprite clip-window).
 +
 +
=== Relative sprites ===
 +
 +
Every normal sprite works as "anchor" sprite for all following relative sprites (i.e. sprite 12 is anchor for relative sprites 13 and 14, etc, until another normal sprite sets up new anchor - when rendering in normal order) (when order of rendering is reversed by bit 6 in {{NextRegNo|$15}}, the ordering of sprites is descending (i.e. normal sprite 15 is new anchor for relative sprites 14 , 13, etc, until another normal sprite sets up new anchor).
 +
 +
Every anchor sprite sets temporarily '''anchor.x''', '''anchor.y''' (coordinates), '''anchor.H''' (4-bit or 8-bit colour pattern mode) and '''anchor.visibility''' variables in sprite engine. All following "relative" sprites then:
 +
* use '''(anchor.visibility AND relative.visibility)''' to determine visibility status of relative sprite
 +
* use '''[(anchor.x + x), (anchor.y + y)]''' coordinates (i.e. relative.x = 510 works as "-2": X = (anchor.x - 2), and relative.x = 5 works as X = (anchor.x + 5))
 +
* use '''anchor.H''' to select 4 or 8 bit colour rendering mode for pattern (relative sprite can't have different colour mode than anchor has)
 +
* if '''anchor.H''' is set (4-bit colour mode), then bit 5 in fifth attribute byte of relative sprite determines the top/bottom part of pattern to draw (instead of bit 6 having this function for anchor sprites)
 +
 +
This allows to create "clusters" of sprites where the last processed "normal" (non-relative) sprite is "anchor", providing global display position, visibility-master and colour mode - followed by one or more "relative" sprites which are positioned relatively against the last "anchor" sprite. To move such cluster of sprites on the screen, you need to update only the anchor position in attributes data (or to hide whole cluster, set anchor.visibility to 0). The relative sprites are always drawn above anchor (as they are defined "after" anchor in whichever direction of sprite list is used),

Revision as of 14:39, 28 December 2018

Number $xx57
Decimal
Short desc. Uploads sprite positions, visibility, colour type and effect flags.
Bit Mask %---- ---- 0101 0111
Readable No
Writable Yes
Subsystem Sprites

Uploads attributes of the sprite slot selected by Sprite Status/Slot Select ($303B / 12347). Attributes are sent in 4-5 byte blocks. After sending 4 or 5 bytes block the sprite-index (slot) auto-increments to the next sprite. This auto-increment is independent of other sprite ports, but may be interlinked with Sprite port-mirror Index Register ($34) (see details there). The auto-increment from value 63 is officially "undefined behaviour" and index must be explicitly reset back to 0..63 after such auto-increment to make the SW predictable in future.

The 4-5 bytes sprite-attribute structure is as follows:

Byte 1 is the low bits of the X position. The MSB is in byte 3.

Byte 2 is the low bits of the Y position. The MSB is in optional byte 5.

Byte 3 is bitmapped:

Bit Description
4-7 Palette offset, added to each palette index from pattern before drawing
3 Enable X mirror
2 Enable Y mirror
1 Enable rotation
0 MSB of X coordinate

Byte 4 is bitmapped:

Bit Description
7 Enable visibility
6 If 1, the optional 5th attribute byte should follow fourth one.

If 0, only four attribute bytes are expected (accidental fifth byte send to port will be treated as first byte of next sprite attributes), and all extra sprite features (not covered by 4 byte block) will be reset to zero (as if 5th byte equal to value zero was explicitly sent).

5-0 Pattern index ("Name")

Optional (when bit 6 is set in byte 4) byte 5 is bitmapped:

Bit Description
7 If 1, the pattern will be treated as 4-bit colour one (128 bytes), 0 is for 8-bit colour patterns (256 bytes)
6 (if bit 7 = 1): Chooses top/bottom part of pattern slot when 4-bit colour pattern

0 will target bytes 0..127 of pattern "Name" (byte 4), 1 will target bytes 128..255 of pattern "Name".

(if bit 7 = 0): make this sprite "relative" one: 1 = relative, 0 = normal (anchor) type

5 (if bit 7-6 = %01) for "relative" sprite, this bit chooses top/bottom part of pattern slot for 4-bit colour mode (4 or 8 bit mode is set by anchor sprite, relative sprite can't switch the colour mode). See Bit 6 description above, if anchor sprite is in 4-bit mode. If anchor sprite is in 8-bit mode, use always 0

(else) For normal (anchor) sprites this is reserved, use always 0

4-3 x-axis scale factor: %00 = 1x (16 pixels), %01 = 2x, %10 = 4x, %11 = 8x (128 pixels)
2-1 y-axis scale factor: %00 = 1x (16 pixels), %01 = 2x, %10 = 4x, %11 = 8x (128 pixels)
0 MSB of Y coordinate

Normal (= anchor) sprites

About [X,Y] coordinates: 9 bit values allow for 0..511 coordinate. The top-left ULA pixel ("paper" area) is at [32,32] and bottom-right ULA pixel is at [287,223] (256x192 pixel area).

When sprites are configured to be drawn "over border", there is fixed-size 32 pixels wide area around pixel area (so called "border" in BASIC terms), i.e. coordinates [0,0] to [319,255] are coordinates of visible over-border sprite area.

All coordinates beyond these act as wrap-around 0..511 coordinate system, with sprite getting outside of drawing area, i.e. [X,Y]=[511,510] will render sprite in top left corner over "border" area, with left-most column already not visible (511 works as "-1" X coordinate) and two top-most rows not visible (510 works as "-2" Y coordinate), only remaining 15x14 pixels of sprite pattern are visible in top-left corner. Similarly sprite at coordinates [310,250] will render only 10x6 pixels of pattern in bottom right corner, rest of pattern being already outside of rendering area and not visible (assuming the over-border is enabled and not clipped by sprite clip-window).

Relative sprites

Every normal sprite works as "anchor" sprite for all following relative sprites (i.e. sprite 12 is anchor for relative sprites 13 and 14, etc, until another normal sprite sets up new anchor - when rendering in normal order) (when order of rendering is reversed by bit 6 in Sprite and Layers System Register ($15), the ordering of sprites is descending (i.e. normal sprite 15 is new anchor for relative sprites 14 , 13, etc, until another normal sprite sets up new anchor).

Every anchor sprite sets temporarily anchor.x, anchor.y (coordinates), anchor.H (4-bit or 8-bit colour pattern mode) and anchor.visibility variables in sprite engine. All following "relative" sprites then:

  • use (anchor.visibility AND relative.visibility) to determine visibility status of relative sprite
  • use [(anchor.x + x), (anchor.y + y)] coordinates (i.e. relative.x = 510 works as "-2": X = (anchor.x - 2), and relative.x = 5 works as X = (anchor.x + 5))
  • use anchor.H to select 4 or 8 bit colour rendering mode for pattern (relative sprite can't have different colour mode than anchor has)
  • if anchor.H is set (4-bit colour mode), then bit 5 in fifth attribute byte of relative sprite determines the top/bottom part of pattern to draw (instead of bit 6 having this function for anchor sprites)

This allows to create "clusters" of sprites where the last processed "normal" (non-relative) sprite is "anchor", providing global display position, visibility-master and colour mode - followed by one or more "relative" sprites which are positioned relatively against the last "anchor" sprite. To move such cluster of sprites on the screen, you need to update only the anchor position in attributes data (or to hide whole cluster, set anchor.visibility to 0). The relative sprites are always drawn above anchor (as they are defined "after" anchor in whichever direction of sprite list is used),