Sprite table reference
Sprite table format
The location of the sprite table in VRAM is determined by VDP register $85xx
.
The sprite table consists of either 80 or 64 entries (depending on whether the horizontal resolution is H40 or H32, respectively). Each entry is 8 bytes long:
Offset | Size | Description |
---|---|---|
+0 | 2 bytes | Y coordinate |
+2 | 1 byte | Sprite size |
+3 | 1 byte | Sprite link |
+4 | 2 bytes | Tile ID and flags |
+6 | 2 bytes | X coordinate |
X and Y coordinates
These two fields indicate the position of the top-left corner of the sprite on screen. The origin is at -128;-128, i.e. you should add 128 to both coordinates to match their position on screen.
These fields are only 9-bit (the rest of the bits are ignored) so the coordinates will wrap around every 512 pixels. This is only relevant if you don't clip out the sprites at the screen boundaries.
Tile ID and flags
This is the field that indicates which graphic the sprite uses and whatever effects are applied to it (flipping, palette, etc.):
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | |
---|---|---|---|---|---|---|---|---|
1st byte | PRI
| CP1
| CP0
| VF
| HF
| SN10
| SN9
| SN8
|
2nd byte | SN7
| SN6
| SN5
| SN4
| SN3
| SN2
| SN1
| SN0
|
PRI:
1 for high priority, 0 for low priorityCP1-0:
which palette to useVF:
1 to flip vertically, 0 to notHF:
1 to flip horizontally, 0 to notSN10-0:
first tile ID
Sprites use consecutive tile IDs, i.e. if your sprite is 3×2 tiles and the first tile ID is 100, then it'll use tiles 100, 101, 102, 103, 104 and 105.
The flip flags apply to the whole sprite, not each individual tile. Coordinates still refer to the top-left corner of the already flipped sprite, so you will need to adjust them if this is not what you wanted.
To make things easier, you can OR these flags with the tile ID to set the respective effects (you may OR up to one of each group):
NOFLIP: equ $0000 ; Don't flip
HFLIP: equ $0800 ; Flip horizontally
VFLIP: equ $1000 ; Flip vertically
HVFLIP: equ $1800 ; Flip both ways
PAL0: equ $0000 ; 1st palette
PAL1: equ $2000 ; 2nd palette
PAL2: equ $4000 ; 3rd palette
PAL3: equ $6000 ; 4th palette
LOPRI: equ $0000 ; Low priority
HIPRI: equ $8000 ; High priority
Sprite size
This field indicates the size of the sprite (in tiles). It has the following format:
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
---|---|---|---|---|---|---|---|
0
| 0
| 0
| 0
| HS1
| HS0
| VS1
| VS0
|
HS1-0
: sprite widthVS1-0
: sprite height
Both width and height are measured in tiles minus one (i.e.
00
is 1 tile and 11
is 4 tiles), any
combination is allowed. The remaining bits are ignored. You may use the
following constants to make your life easier:
; Name is SPR_*x# where * is the
; width and # is the height
SPR_1x1: equ %0000 ; 1x1 tiles
SPR_2x1: equ %0100 ; 2x1 tiles
SPR_3x1: equ %1000 ; 3x1 tiles
SPR_4x1: equ %1100 ; 4x1 tiles
SPR_1x2: equ %0001 ; 1x2 tiles
SPR_2x2: equ %0101 ; 2x2 tiles
SPR_3x2: equ %1001 ; 3x2 tiles
SPR_4x2: equ %1101 ; 4x2 tiles
SPR_1x3: equ %0010 ; 1x3 tiles
SPR_2x3: equ %0110 ; 2x3 tiles
SPR_3x3: equ %1010 ; 3x3 tiles
SPR_4x3: equ %1110 ; 4x3 tiles
SPR_1x4: equ %0011 ; 1x4 tiles
SPR_2x4: equ %0111 ; 2x4 tiles
SPR_3x4: equ %1011 ; 3x4 tiles
SPR_4x4: equ %1111 ; 4x4 tiles
Sprite link
The sprite table is not linear but actually a linked list. This means that each sprite which one follows in the list. This field indicates which sprite follows (1 = second entry, 2 = third entry, etc.). If this field is 0, it indicates the end of the list.
The list always starts with sprite 0. Bits 6-0 are used (bit 7 is ignored).
128k VRAM mode
In 128k VRAM mode, there's room for 4096 unique tiles, but only 2048
can be addressed at once. The VDP deals with this by splitting VRAM into
two "banks" of 2048 tiles. VDP register $86xx
determines
which of the two banks is used by all sprites:
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
---|---|---|---|---|---|---|---|
0
| 0
| AP16
| 0
| 0
| 0
| 0
| 0
|
AP16
is 0 to use the lower 64KB of VRAM and 1 to use the
upper 64KB of VRAM.
The sprite table is not affected by this register, but rather the sprite table address simply gains an extra bit. This means you can place the table in the opposite bank if you wish.