michielvoo / Super Public
Sprites
The Super Nintendo supports up to 128 independent sprites. Sprite tables (metadata) is stored in Object Attribute Memory (OAM). The sprites in the sprite tables refer to locations in VRAM and CGRAM for pixel data (stored as characters, see Characters) and color data respectively (stored as palettes, see Colors).
Sprite tables in OAM can be read from the OAMDATAREAD port and written through the OAMDATA port, using the OAMADDL and OAMADDH addressing registers. The address auto-increments after each read or write. Writes are buffered until the high order byte of the double byte is written.
Sprite tables
The sprite data are 544 bytes stored in 2 tables in OAM. The first table contains 128 records of 4 bytes each (512 bytes total). The second table contains 128 records of 2 bits each (32 bytes total).
To write a sprite record to table 1, first select table 1 by writing 0 to OAMADDH, then write the sprite number multiplied by 2 to OAMADDL, and then double-write the first double-byte to OAMDATA, followed by a double-write for the second double-byte. The address in OAMADDL will be auto-incremented after each double-write.
To write 4 sprite records to table 2, first select table 2 by writing 1 to OAMADDH, then write the first (of the 4) sprite's number divided by 4 to OAMADDL, and then write the byte to OAMDATA. The address in OAMADDL will not be auto-incremented when writing only 1 byte.
Sprite data records in table 1 (low to high):
- x-coordinate byte
- y-coordinate byte
- character number (9 bits)
- palette number (3 bits)
- priority (2 bits)
- horizontal flip bit
- vertical flip bit
Sprite data record in table 2 (low to high):
- x-coordinate most-significant bit
- size toggle bit
Sprite palettes consist of 16 colors and start at address 128 in CGRAM.
Characters
The character number is used to calculate the address of the sprite's (first) character in the VRAM. This is calculated relative to the sprite character segment, which is set in OBSEL.0-1. For the purpose of referring to characters for sprites the VRAM can be divided into 4 segments of 16KiB each. These character segments are numbered from 0 to 3. To obtain the corresponding VRAM address the segment number is shifted left by 13.
(Example: sprite character segment 1 corresponds to address 8192, and byte offset 16384.)
Each sprite in the OAM table can be set to 1 of 2 sizes. The sizes that are available for selection by a sprite are determined by the sprite size mode in OBSEL.5-7:
- mode 0: 8× 8 and 16×16
- mode 1: 8× 8 and 32×32
- mode 2: 8× 8 and 64×64
- mode 3: 16×16 and 32×32
- mode 4: 32×32 and 64×64
Sprites have a color depth of 4 (16 color) so each character is 32 bytes (8 rows and 4 planes). Sprites use color palettes 8 through 15 (starting at color address 128 in CGRAM, see Colors).
Sprites that consist of more than 1 character arrange their characters in the following fashion, where A represents top-left, B represents top-right, C represents bottom-left, and D represents bottom-right.
16×16 32×32 64×64
----- ------------- ---------------------------------
Row 0 - A | B AA AB | BA BB AAA AAB ABA ABB | BAA BAB BBA BBB
--+-- | |
Row 1 - C | D AC AD | BC BD AAC AAD ABC ABD | BAC BAD BBC BBD
------+------ + | +
Row 2 - CA CB | DA DB ACA ACB ADA ADB | BCA BCB BDA BDB
| |
Row 3 - CC CD | DC DD ACC ACD ADC ADD | BCC BCD BDC BDD
----------------+----------------
Row 4 - CAA CAB CBA CBB | DAA DAB DBA DBB
|
Row 5 - CAC CAD CBC CBD | DAC DAD DBC DBD
+ | +
Row 6 - CCA CCB CDA CDB | DCA DCB DDA DDB
|
Row 7 - CCC CCD CDC CDD | DCC DCD DDC DDD
The characters are stored in VRAM, per row, and the rows of multiple sprites are interleaved such that row n starts at 16 characters past the start of row n-1.
Interleaving pattern for 16×16 sprites:
Sprite 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 0 ...
Part A B . . . . . . . . . . . . . . C ...
Character 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...
Interleaving pattern for 32×32 sprites:
Sprite 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 0 ...
Part AA AB BA BB . . . . . . . . . . . . AC ...
Character 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...
Interleaving pattern for 16×16 sprites:
Sprite 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 ...
Part AAA AAB ABA ABB BAA BAB BBA BBB . . . . . . . . AAC ...
Character 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...
Every character is 32 bytes (at 4bpp). The address in VRAM of the first character of row n is:
16×16 sprite: addressof(A) + n × 16 × 8 × 2
32×32 sprite: addressof(AA) + n × 16 × 8 × 2
64×64 sprite: addressof(AAA) + n × 16 × 8 × 2
Or, every sprite's row starts at $0100 from where the previous row started.
See also: Characters, Tiles, Colors.