Loading...
Searching...
No Matches
sprite.h File Reference

SNES Sprite (Object) Management. More...

#include <snes/types.h>

Go to the source code of this file.

Classes

struct  MetaspriteItem
 Metasprite item structure (PVSnesLib compatible) More...
 
struct  OamDynamicConfig
 Configuration for the dynamic sprite engine. More...
 
struct  t_sprites
 Dynamic sprite state structure (16 bytes, PVSnesLib compatible) More...
 

Macros

#define MAX_SPRITES   128
 Maximum number of hardware sprites.
 
#define MAXSPRTRF   (7 * 6)
 Maximum sprite transfers per frame (7 sprites * 6 bytes each)
 
#define METASPR_ITEM(dx, dy, tile, attr)   { (dx), (dy), (tile), (attr), 0 }
 Metasprite item macro (PVSnesLib compatible)
 
#define METASPR_TERM   { -128, 0, 0, 0, 0 }
 End marker for metasprite data (dx = -128)
 
#define metasprite_end   (-128)
 Legacy end marker value.
 
#define OAM_ATTR(_tile, _pal, _prio, _fl)
 Pre-compute OAM attribute byte (vhoopppc)
 
#define OAM_BUFFER_SIZE   544
 Total OAM buffer size in bytes (512 main + 32 extension)
 
#define OAM_DEFAULT_SIZE   OBJ_SIZE8_L16
 Default sprite size mode — small=8×8 / large=16×16.
 
#define OAM_DEFAULT_TILE_BASE   0
 Default sprite tile base — 0 = tiles at VRAM word $0000.
 
#define OAM_EXT_OFFSET   512
 OAM extension table offset in bytes (starts after 128*4 main entries)
 
#define OAM_EXT_SIZE   32
 OAM extension table size in bytes (2 bits per sprite, 128 sprites)
 
#define OAM_SET_GFX(id, gfx)
 Set sprite graphics address (bank $00 only)
 
#define OAM_SET_GFX_BANK(id, gfx, bank)
 Set sprite graphics address with explicit bank byte.
 
#define OAM_XHI_MASK(_slot)
 X-high-bit mask for a sprite slot (0-3 within a high-table byte)
 
#define OAM_Y_OFFSCREEN   0xE0
 Y coordinate that hides a sprite below the NTSC visible area.
 
#define oamSetFast(_id, _x, _y, _tile, _pal, _prio, _fl)
 Set sprite properties with zero function-call overhead.
 
#define oamSetXYFast(_id, _x, _y)
 Update sprite position only (most common per-frame operation)
 
#define OBJ_BASE(vram_addr)   (((vram_addr) >> 13) & 0x07)
 Convert VRAM word address to OBJSEL name base bits (0-2)
 
#define OBJ_CGRAM_BASE   128
 CGRAM base offset for sprite palettes (sprites use colors 128-255)
 
#define OBJ_CGRAM_PAL(n)   (OBJ_CGRAM_BASE + (n) * 16)
 CGRAM color index for sprite palette n (0-7)
 
#define OBJ_FLIPX   0x40
 Metasprite horizontal flip flag.
 
#define OBJ_FLIPY   0x80
 Metasprite vertical flip flag.
 
#define OBJ_HIDE   0
 
#define OBJ_HIDE_Y   240
 Y position to hide sprite.
 
#define OBJ_LARGE   1
 
#define OBJ_NAMETABLE_HIGH   0x01
 OAM attribute bit 0: second name table select (tile numbers 256+)
 
#define OBJ_PAL(pal)   ((pal) << 1)
 Metasprite palette attribute macro.
 
#define OBJ_PRIO(prio)   ((prio) << 4)
 Metasprite priority attribute macro.
 
#define OBJ_QUEUELIST_SIZE   128
 Maximum sprites in VRAM upload queue.
 
#define OBJ_SHOW   1
 Sprite visibility.
 
#define OBJ_SIZE16_L32   3
 
#define OBJ_SIZE16_L64   4
 
#define OBJ_SIZE32_L64   5
 
#define OBJ_SIZE8_L16   0
 Sprite size indices (for oamInit, oamInitGfxSet)
 
#define OBJ_SIZE8_L32   1
 
#define OBJ_SIZE8_L64   2
 
#define OBJ_SIZE_TO_REG(size)   ((size) << 5)
 Macro to convert size index to OBJSEL register value.
 
#define OBJ_SMALL   0
 Sprite size selection.
 
#define OBJ_SPRITE16   2
 
#define OBJ_SPRITE32   1
 Sprite type identifiers for dynamic engine.
 
#define OBJ_SPRITE8   4
 
#define OBJSEL(size, vram_addr)   ((u8)(OBJ_SIZE_TO_REG(size) | OBJ_BASE(vram_addr)))
 Build OBJSEL register value from size constant + VRAM base address.
 
#define PALETTE_16_SIZE   32
 Size of one 16-color palette in bytes (16 colors x 2 bytes per BGR555)
 

Typedefs

typedef MetaspriteItem t_metasprite
 PVSnesLib compatibility typedef.
 

Functions

void oamClear (void)
 Clear all sprites.
 
u8 oamDrawMeta (u8 startId, s16 x, s16 y, const MetaspriteItem *meta, u16 baseTile, u8 basePalette, u8 size)
 Draw a metasprite (PVSnesLib compatible)
 
u8 oamDrawMetaFlip (u8 startId, s16 x, s16 y, const MetaspriteItem *meta, u16 baseTile, u8 basePalette, u8 size, u8 flipX, u8 flipY, u8 width, u8 height)
 Draw a metasprite with flip support.
 
u8 oamDrawMetasprite (u8 startId, u16 x, u8 y, const u8 *data, u8 palette)
 Draw a metasprite (legacy simple interface)
 
void oamDynamicDrainQueue (void)
 Block until the dynamic-sprite VRAM tile queue is empty.
 
void oamDynamicDraw (u16 id)
 Draw a dynamic sprite — engine picks the size routine.
 
void oamDynamicInit (const OamDynamicConfig *cfg)
 Initialize the dynamic sprite engine from a config struct.
 
void oamDynamicSetSize (u16 id, u8 size)
 Override the dispatched pixel size for a dynamic sprite slot.
 
void oamHide (u8 id)
 Hide sprite.
 
void oamInit (u16 size, u16 tile_base)
 Initialize the sprite (OAM) system.
 
void oamInitGfxSet (u8 *tileSource, u16 tileSize, u8 *tilePalette, u16 paletteSize, u8 paletteEntry, u16 vramAddr, u8 oamSize)
 Initialize sprite graphics and palette (PVSnesLib compatible)
 
void oamMetaDrawDyn (u16 id, s16 x, s16 y, const MetaspriteItem *meta, u8 *gfxptr, u8 size_class)
 Draw a dynamic metasprite — engine picks the size routine.
 
void oamSet (u16 id, u16 x, u16 y, u16 tile, u16 palette, u16 priority, u16 flags)
 Set sprite properties.
 
void oamSetSize (u16 id, u16 large)
 Set sprite size (large/small)
 
void oamSetTile (u8 id, u16 tile)
 Set sprite tile.
 
void oamSetVisible (u8 id, u8 visible)
 Set sprite visibility.
 
void oamSetX (u8 id, u16 x)
 Set sprite X position.
 
void oamSetXY (u8 id, u16 x, u8 y)
 Set sprite position.
 
void oamSetY (u8 id, u8 y)
 Set sprite Y position.
 
void oamUpdate (void)
 Copy OAM buffer to hardware.
 

Variables

u16 lkup16idB []
 VRAM destination addresses for 16x16 sprites (64 entries)
 
u16 lkup16idT []
 OAM tile IDs for 16x16 sprites - small size mode (64 entries)
 
u16 lkup16idT0 []
 OAM tile IDs for 16x16 sprites - large size mode (64 entries)
 
u16 lkup16oamS []
 VRAM source offsets for 16x16 sprites (64 entries)
 
u16 lkup32idB []
 VRAM destination addresses for 32x32 sprites (16 entries)
 
u16 lkup32idT []
 OAM tile IDs for 32x32 sprites (16 entries)
 
u16 lkup32oamS []
 VRAM source offsets for 32x32 sprites (16 entries)
 
u16 lkup8idB []
 VRAM destination addresses for 8x8 sprites (128 entries)
 
u16 lkup8idT []
 OAM tile IDs for 8x8 sprites (128 entries)
 
u16 lkup8oamS []
 VRAM source offsets for 8x8 sprites (128 entries)
 
t_sprites oambuffer [128]
 Dynamic sprite buffer (128 entries, 2048 bytes)
 

Detailed Description

SNES Sprite (Object) Management.

Functions for managing hardware sprites (OBJ).

SNES Sprite Limits

  • 128 sprites total
  • 32 sprites per scanline
  • Sizes: 8x8, 16x16, 32x32, 64x64
  • 8 palettes (16 colors each, sharing color 0)

Usage

// Initialize sprite system (defaults: 8x8/16x16 sprites, tile base 0)
// Set up a sprite
oamSet(0, 100, 80, 0, 0, 0, 0); // Sprite 0 at (100, 80)
// In main loop
oamUpdate(); // Copy OAM buffer to hardware
void WaitForVBlank(void)
Wait for next VBlank period.
#define OAM_DEFAULT_SIZE
Default sprite size mode — small=8×8 / large=16×16.
Definition sprite.h:265
#define OAM_DEFAULT_TILE_BASE
Default sprite tile base — 0 = tiles at VRAM word $0000.
Definition sprite.h:267
void oamSet(u16 id, u16 x, u16 y, u16 tile, u16 palette, u16 priority, u16 flags)
Set sprite properties.
void oamUpdate(void)
Copy OAM buffer to hardware.
void oamInit(u16 size, u16 tile_base)
Initialize the sprite (OAM) system.
Author
OpenSNES Team

Attribution

Based on: PVSnesLib sprite system by Alekmaul

Macro Definition Documentation

◆ MAX_SPRITES

#define MAX_SPRITES   128

Maximum number of hardware sprites.

◆ MAXSPRTRF

#define MAXSPRTRF   (7 * 6)

Maximum sprite transfers per frame (7 sprites * 6 bytes each)

◆ METASPR_ITEM

#define METASPR_ITEM (   dx,
  dy,
  tile,
  attr 
)    { (dx), (dy), (tile), (attr), 0 }

Metasprite item macro (PVSnesLib compatible)

◆ METASPR_TERM

#define METASPR_TERM   { -128, 0, 0, 0, 0 }

End marker for metasprite data (dx = -128)

◆ metasprite_end

#define metasprite_end   (-128)

Legacy end marker value.

◆ OAM_ATTR

#define OAM_ATTR (   _tile,
  _pal,
  _prio,
  _fl 
)
Value:
((u8)(((_fl) & 0xC0) | \
(((_prio) & 0x03) << 4) | \
(((_pal) & 0x07) << 1) | \
(((_tile) >> 8) & 0x01)))
unsigned char u8
8-bit unsigned integer (0 to 255)
Definition types.h:46

Pre-compute OAM attribute byte (vhoopppc)

Parameters
_tileTile number (0-511, only bit 8 used)
_palPalette (0-7)
_prioPriority (0-3)
_flFlip flags (bit 6 = H flip, bit 7 = V flip)
Returns
Packed attribute byte

◆ OAM_BUFFER_SIZE

#define OAM_BUFFER_SIZE   544

Total OAM buffer size in bytes (512 main + 32 extension)

◆ OAM_DEFAULT_SIZE

#define OAM_DEFAULT_SIZE   OBJ_SIZE8_L16

Default sprite size mode — small=8×8 / large=16×16.

Same value as OBJ_SIZE8_L16 (the most common configuration: 8×8 tiles for HUD elements and 16×16 for characters/projectiles).

◆ OAM_DEFAULT_TILE_BASE

#define OAM_DEFAULT_TILE_BASE   0

Default sprite tile base — 0 = tiles at VRAM word $0000.

◆ OAM_EXT_OFFSET

#define OAM_EXT_OFFSET   512

OAM extension table offset in bytes (starts after 128*4 main entries)

◆ OAM_EXT_SIZE

#define OAM_EXT_SIZE   32

OAM extension table size in bytes (2 bits per sprite, 128 sprites)

◆ OAM_SET_GFX

#define OAM_SET_GFX (   id,
  gfx 
)
Value:
do { \
oambuffer[id].oamgfxaddr = (u16)(gfx); \
oambuffer[id].oamgfxbank = 0; \
} while(0)
unsigned short u16
16-bit unsigned integer (0 to 65535)
Definition types.h:52
t_sprites oambuffer[128]
Dynamic sprite buffer (128 entries, 2048 bytes)
u16 oamgfxaddr
Definition sprite.h:194
u8 oamgfxbank
Definition sprite.h:195

Set sprite graphics address (bank $00 only)

Sets the 16-bit graphics address with bank byte = 0. cc65816 passes 16-bit pointers, so the bank byte is always lost before this macro runs. Use OAM_SET_GFX_BANK() for data in other banks.

Parameters
idSprite index (0-127)
gfxPointer to graphics data in bank $00

◆ OAM_SET_GFX_BANK

#define OAM_SET_GFX_BANK (   id,
  gfx,
  bank 
)
Value:
do { \
oambuffer[id].oamgfxaddr = (u16)(gfx); \
oambuffer[id].oamgfxbank = (u8)(bank); \
} while(0)

Set sprite graphics address with explicit bank byte.

Use this when sprite data is in a bank other than $00.

Parameters
idSprite index (0-127)
gfxPointer to graphics data
bankROM bank where graphics data is located (0-255)

◆ OAM_XHI_MASK

#define OAM_XHI_MASK (   _slot)
Value:
((u8)((_slot) == 0 ? 0x01 : (_slot) == 1 ? 0x04 : \
(_slot) == 2 ? 0x10 : 0x40))

X-high-bit mask for a sprite slot (0-3 within a high-table byte)

Each high-table byte covers 4 sprites. Bit 0 of each 2-bit pair is the X high bit. This macro returns the mask for the X-high bit of the given slot.

◆ OAM_Y_OFFSCREEN

#define OAM_Y_OFFSCREEN   0xE0

Y coordinate that hides a sprite below the NTSC visible area.

◆ oamSetFast

#define oamSetFast (   _id,
  _x,
  _y,
  _tile,
  _pal,
  _prio,
  _fl 
)
Value:
do { \
u16 _off = (u16)(_id) << 2; \
oamMemory[_off + 0] = (u8)((_x) & 0xFF); \
oamMemory[_off + 1] = (u8)(((_y) - 1) & 0xFF); /* compensate +1 PPU scanline quirk */ \
oamMemory[_off + 2] = (u8)((_tile) & 0xFF); \
oamMemory[_off + 3] = OAM_ATTR(_tile, _pal, _prio, _fl); \
u16 _ext = 512 + ((u16)(_id) >> 2); \
u16 _sl = (u16)(_id) & 0x03; \
u8 _xhi = OAM_XHI_MASK(_sl); \
if ((_x) & 0x100) \
oamMemory[_ext] |= _xhi; \
else \
oamMemory[_ext] &= ~_xhi; \
} while(0)
#define OAM_ATTR(_tile, _pal, _prio, _fl)
Pre-compute OAM attribute byte (vhoopppc)
Definition sprite.h:749
#define OAM_XHI_MASK(_slot)
X-high-bit mask for a sprite slot (0-3 within a high-table byte)
Definition sprite.h:761
u8 oamMemory[]
Hardware OAM buffer (544 bytes at $7E:0300)
volatile u8 oam_update_flag
OAM DMA trigger flag.

Set sprite properties with zero function-call overhead.

Drop-in replacement for oamSet() that writes directly to oamMemory[]. Same parameters, same behavior, but compiles to direct memory writes instead of a function call with framesize=158.

Parameters
_idSprite ID (0-127)
_xX position (0-511)
_yY position (0-255)
_tileTile number (0-511)
_palPalette (0-7)
_prioPriority (0-3)
_flFlip flags (bit 6 = H flip, bit 7 = V flip)

◆ oamSetXYFast

#define oamSetXYFast (   _id,
  _x,
  _y 
)
Value:
do { \
u16 _off = (u16)(_id) << 2; \
oamMemory[_off + 0] = (u8)((_x) & 0xFF); \
oamMemory[_off + 1] = (u8)(((_y) - 1) & 0xFF); /* compensate +1 PPU scanline quirk */ \
u16 _ext = 512 + ((u16)(_id) >> 2); \
u16 _sl = (u16)(_id) & 0x03; \
u8 _xhi = OAM_XHI_MASK(_sl); \
if ((_x) & 0x100) \
oamMemory[_ext] |= _xhi; \
else \
oamMemory[_ext] &= ~_xhi; \
} while(0)

Update sprite position only (most common per-frame operation)

Fastest possible sprite update — only writes X, Y, and X high bit. Use when tile/palette/priority/flags don't change between frames.

Parameters
_idSprite ID (0-127)
_xX position (0-511)
_yY position (0-255)

◆ OBJ_BASE

#define OBJ_BASE (   vram_addr)    (((vram_addr) >> 13) & 0x07)

Convert VRAM word address to OBJSEL name base bits (0-2)

◆ OBJ_CGRAM_BASE

#define OBJ_CGRAM_BASE   128

CGRAM base offset for sprite palettes (sprites use colors 128-255)

◆ OBJ_CGRAM_PAL

#define OBJ_CGRAM_PAL (   n)    (OBJ_CGRAM_BASE + (n) * 16)

CGRAM color index for sprite palette n (0-7)

◆ OBJ_FLIPX

#define OBJ_FLIPX   0x40

Metasprite horizontal flip flag.

◆ OBJ_FLIPY

#define OBJ_FLIPY   0x80

Metasprite vertical flip flag.

◆ OBJ_HIDE

#define OBJ_HIDE   0

Sprite hidden

◆ OBJ_HIDE_Y

#define OBJ_HIDE_Y   240

Y position to hide sprite.

◆ OBJ_LARGE

#define OBJ_LARGE   1

Use large sprite size

◆ OBJ_NAMETABLE_HIGH

#define OBJ_NAMETABLE_HIGH   0x01

OAM attribute bit 0: second name table select (tile numbers 256+)

◆ OBJ_PAL

#define OBJ_PAL (   pal)    ((pal) << 1)

Metasprite palette attribute macro.

◆ OBJ_PRIO

#define OBJ_PRIO (   prio)    ((prio) << 4)

Metasprite priority attribute macro.

◆ OBJ_QUEUELIST_SIZE

#define OBJ_QUEUELIST_SIZE   128

Maximum sprites in VRAM upload queue.

◆ OBJ_SHOW

#define OBJ_SHOW   1

Sprite visibility.

Sprite visible

◆ OBJ_SIZE16_L32

#define OBJ_SIZE16_L32   3

Small=16x16, Large=32x32

◆ OBJ_SIZE16_L64

#define OBJ_SIZE16_L64   4

Small=16x16, Large=64x64

◆ OBJ_SIZE32_L64

#define OBJ_SIZE32_L64   5

Small=32x32, Large=64x64

◆ OBJ_SIZE8_L16

#define OBJ_SIZE8_L16   0

Sprite size indices (for oamInit, oamInitGfxSet)

Small=8x8, Large=16x16

◆ OBJ_SIZE8_L32

#define OBJ_SIZE8_L32   1

Small=8x8, Large=32x32

◆ OBJ_SIZE8_L64

#define OBJ_SIZE8_L64   2

Small=8x8, Large=64x64

◆ OBJ_SIZE_TO_REG

#define OBJ_SIZE_TO_REG (   size)    ((size) << 5)

Macro to convert size index to OBJSEL register value.

◆ OBJ_SMALL

#define OBJ_SMALL   0

Sprite size selection.

Use small sprite size

◆ OBJ_SPRITE16

#define OBJ_SPRITE16   2

16x16 sprite identifier

◆ OBJ_SPRITE32

#define OBJ_SPRITE32   1

Sprite type identifiers for dynamic engine.

32x32 sprite identifier

◆ OBJ_SPRITE8

#define OBJ_SPRITE8   4

8x8 sprite identifier

◆ OBJSEL

#define OBJSEL (   size,
  vram_addr 
)    ((u8)(OBJ_SIZE_TO_REG(size) | OBJ_BASE(vram_addr)))

Build OBJSEL register value from size constant + VRAM base address.

Parameters
sizeOne of OBJ_SIZE8_L16 .. OBJ_SIZE32_L64
vram_addrVRAM word address for sprite tiles (must be 8KB-aligned)
REG_OBJSEL = OBJSEL(OBJ_SIZE16_L32, 0x4000); // = 0x62
REG_OBJSEL = OBJSEL(OBJ_SIZE8_L16, 0x4000); // = 0x02
#define REG_OBJSEL
Object (sprite) size and base (W)
Definition registers.h:52
#define OBJ_SIZE16_L32
Definition sprite.h:52
#define OBJSEL(size, vram_addr)
Build OBJSEL register value from size constant + VRAM base address.
Definition sprite.h:72
#define OBJ_SIZE8_L16
Sprite size indices (for oamInit, oamInitGfxSet)
Definition sprite.h:49

◆ PALETTE_16_SIZE

#define PALETTE_16_SIZE   32

Size of one 16-color palette in bytes (16 colors x 2 bytes per BGR555)

Typedef Documentation

◆ t_metasprite

PVSnesLib compatibility typedef.

Function Documentation

◆ oamClear()

void oamClear ( void  )

Clear all sprites.

Hides all sprites by moving them off-screen.

◆ oamDrawMeta()

u8 oamDrawMeta ( u8  startId,
s16  x,
s16  y,
const MetaspriteItem meta,
u16  baseTile,
u8  basePalette,
u8  size 
)

Draw a metasprite (PVSnesLib compatible)

Draws a multi-tile sprite composed of multiple hardware sprites. The metasprite data is an array of MetaspriteItem structures terminated by METASPR_TERM.

Parameters
startIdFirst sprite ID to use (0-127)
xX position of metasprite origin
yY position of metasprite origin
metaPointer to metasprite data array (MetaspriteItem[])
baseTileBase tile number to add to each item's tile offset
basePaletteBase palette (0-7) when item doesn't specify one
sizeSize selection for all sprites (OBJ_SMALL or OBJ_LARGE)
Returns
Number of hardware sprites used
// Define a 32x32 metasprite using 4 16x16 sprites
const MetaspriteItem hero_frame0[] = {
METASPR_ITEM(0, 0, 0, OBJ_PRIO(2)), // Top-left
METASPR_ITEM(16, 0, 1, OBJ_PRIO(2)), // Top-right
METASPR_ITEM(0, 16, 2, OBJ_PRIO(2)), // Bottom-left
METASPR_ITEM(16, 16, 3, OBJ_PRIO(2)), // Bottom-right
};
// Draw at position (100, 80)
oamDrawMeta(0, 100, 80, hero_frame0, 0, 0, OBJ_LARGE);
u8 oamDrawMeta(u8 startId, s16 x, s16 y, const MetaspriteItem *meta, u16 baseTile, u8 basePalette, u8 size)
Draw a metasprite (PVSnesLib compatible)
#define OBJ_LARGE
Definition sprite.h:104
#define OBJ_PRIO(prio)
Metasprite priority attribute macro.
Definition sprite.h:479
#define METASPR_ITEM(dx, dy, tile, attr)
Metasprite item macro (PVSnesLib compatible)
Definition sprite.h:467
#define METASPR_TERM
End marker for metasprite data (dx = -128)
Definition sprite.h:470
Metasprite item structure (PVSnesLib compatible)
Definition sprite.h:455

◆ oamDrawMetaFlip()

u8 oamDrawMetaFlip ( u8  startId,
s16  x,
s16  y,
const MetaspriteItem meta,
u16  baseTile,
u8  basePalette,
u8  size,
u8  flipX,
u8  flipY,
u8  width,
u8  height 
)

Draw a metasprite with flip support.

Like oamDrawMeta but supports horizontal and vertical flipping of the entire metasprite.

Parameters
startIdFirst sprite ID to use
xX position
yY position
metaMetasprite data
baseTileBase tile number
basePaletteBase palette
sizeSize selection (OBJ_SMALL or OBJ_LARGE)
flipXFlip horizontally if non-zero
flipYFlip vertically if non-zero
widthMetasprite width for flip calculations
heightMetasprite height for flip calculations
Returns
Number of hardware sprites used

◆ oamDrawMetasprite()

u8 oamDrawMetasprite ( u8  startId,
u16  x,
u8  y,
const u8 data,
u8  palette 
)

Draw a metasprite (legacy simple interface)

Simplified interface for basic metasprite drawing.

Parameters
startIdFirst sprite ID to use
xX position
yY position
dataMetasprite data (cast to const u8*)
palettePalette to use
Returns
Number of hardware sprites used

◆ oamDynamicDrainQueue()

void oamDynamicDrainQueue ( void  )

Block until the dynamic-sprite VRAM tile queue is empty.

Called once during init, after queueing the starting frame via oamDynamicDraw / oamMetaDrawDyn, and before setScreenOn. The NMI auto-flush hook drains up to 7 queue entries per VBlank, so init sequences that enqueue more than that (typical for metasprites with many sub-sprites) need several VBlanks to complete. This helper loops WaitForVBlank() until the queue is empty and tells the NMI hook to skip the end-of-frame "hide stale sprites" step during the drain so the just-drawn sprites are not pushed off-screen between waits.

Safe to call only while the screen is in force blank — VRAM writes during active display are silently dropped by the PPU.

setScreenOff(); // force blank
drawAllSprites(); // queues many tile uploads
oamDynamicDrainQueue(); // wait until VRAM matches OAM
setScreenOn(); // first frame renders correctly
void setScreenOff(void)
Disable screen display (blank)
void setScreenOn(void)
Enable screen display.
void oamDynamicInit(const OamDynamicConfig *cfg)
Initialize the dynamic sprite engine from a config struct.
void oamDynamicDrainQueue(void)
Block until the dynamic-sprite VRAM tile queue is empty.

◆ oamDynamicDraw()

void oamDynamicDraw ( u16  id)

Draw a dynamic sprite — engine picks the size routine.

Preferred entry point — replaces the manual choice between oamDynamic8Draw / oamDynamic16Draw / oamDynamic32Draw. The engine uses the per-sprite size set via oamDynamicSetSize if any; otherwise it falls back to the "large" pixel size of the size pair selected at init by oamInitDynamicSprite (or oamDynamicInit).

64x64 dynamic streaming is not currently supported; calls that would resolve to 64x64 are silently skipped.

Parameters
idIndex into oambuffer array (0-127)

◆ oamDynamicInit()

void oamDynamicInit ( const OamDynamicConfig cfg)

Initialize the dynamic sprite engine from a config struct.

Preferred over oamInitDynamicSprite — the struct-based form makes the intent of each parameter visible at the call site and survives future additions without a signature break.

Parameters
cfgConfiguration (caller-owned; the engine reads it once).
static const OamDynamicConfig dyn = {
.vramLarge = 0x0000,
.vramSmall = 0x1000,
.slotLargeInit = 0,
.slotSmallInit = 0,
.sizeMode = OBJ_SIZE16_L32,
};
Configuration for the dynamic sprite engine.
Definition sprite.h:574
u16 vramLarge
Definition sprite.h:575

◆ oamDynamicSetSize()

void oamDynamicSetSize ( u16  id,
u8  size 
)

Override the dispatched pixel size for a dynamic sprite slot.

Optional companion to oamDynamicDraw. By default each slot dispatches to the "large" half of the size pair set at init. Call this to make a specific slot use a different pixel size (8, 16, or 32) — typical when mixing small and large dynamic sprites under the same mode pair.

Pass 0 to clear the override and revert to the mode default.

Parameters
idSprite slot id (0-127)
sizePixel size: 8, 16, or 32 (or 0 to clear)

◆ oamHide()

void oamHide ( u8  id)

Hide sprite.

Parameters
idSprite ID (0-127)

◆ oamInit()

void oamInit ( u16  size,
u16  tile_base 
)

Initialize the sprite (OAM) system.

Sets the OBJSEL register (sprite size mode + tile base) and clears the OAM shadow buffer so all sprites start hidden. Must be called before any other oam* function. Replaces the v1 oamInit/oamInitEx pair — pass OAM_DEFAULT_* constants for the previous oamInit(void) defaults.

Parameters
sizeSprite size mode (OBJ_SIZE_*; use OAM_DEFAULT_SIZE for the standard 8×8/16×16 layout)
tile_baseVRAM tile-base index 0-7 (each step = $1000 word addresses; use OAM_DEFAULT_TILE_BASE for tiles at VRAM $0000)

◆ oamInitGfxSet()

void oamInitGfxSet ( u8 tileSource,
u16  tileSize,
u8 tilePalette,
u16  paletteSize,
u8  paletteEntry,
u16  vramAddr,
u8  oamSize 
)

Initialize sprite graphics and palette (PVSnesLib compatible)

Loads sprite tiles to VRAM and palette to CGRAM, and configures the sprite tile base address and sizes.

Parameters
tileSourceAddress of sprite tile graphics
tileSizeSize of tile data in bytes
tilePaletteAddress of sprite palette data
paletteSizeSize of palette data in bytes
paletteEntryPalette number (0-7, placed at color 128+entry*16)
vramAddrVRAM address for tiles (must be 8KB aligned)
oamSizeSprite size configuration (OBJ_SIZE_*)
extern char sprite_tiles[], sprite_tiles_end[];
extern char sprite_pal[];
sprite_pal, 32, 0, 0x6000, OBJ_SIZE16_L32);
u8 sprite_pal[]
Palette for the character sprite (16 colors, 4bpp)
u8 sprite_tiles[]
Sprite sheet tile data containing all animation frames (defined in data.asm)
u8 sprite_tiles_end[]
Definition main.c:44
void oamInitGfxSet(u8 *tileSource, u16 tileSize, u8 *tilePalette, u16 paletteSize, u8 paletteEntry, u16 vramAddr, u8 oamSize)
Initialize sprite graphics and palette (PVSnesLib compatible)

◆ oamMetaDrawDyn()

void oamMetaDrawDyn ( u16  id,
s16  x,
s16  y,
const MetaspriteItem meta,
u8 gfxptr,
u8  size_class 
)

Draw a dynamic metasprite — engine picks the size routine.

Iterates meta (a MetaspriteItem array terminated by METASPR_TERM), sets up oambuffer[id..] for each sub-sprite, and dispatches to the matching oamDynamic{8,16,32}Draw based on the engine's current size pair (set at init via oamDynamicInit) and the caller-supplied size_class:

  • OBJ_SMALL → small half of the size pair, with OBJ_NAMETABLE_HIGH ORed into the attribute byte so the tile id reaches the second name table (where small dynamic tiles live in modes 0/1/3).
  • OBJ_LARGE → large half of the size pair.

Replaces the legacy trio oamMetaDrawDyn{8,16,32}. The pixel size is resolved from the engine state, so callers no longer pick a function by sprite size — they just say which half of the pair to use.

Parameters
idStarting oambuffer index (each sub-sprite uses id, id+1, ...).
x,yMetasprite origin in screen coordinates.
metaMetaspriteItem array, terminated by METASPR_TERM.
gfxptrROM source for the dynamic tile data (bank $00 — cc65816 passes 16-bit pointers only).
size_classOBJ_SMALL (0) or OBJ_LARGE (1).
static const OamDynamicConfig dyn = {
.vramLarge = 0x0000, .vramSmall = 0x1000,
.slotLargeInit = 0, .slotSmallInit = 0,
.sizeMode = OBJ_SIZE16_L32,
};
const MetaspriteItem hero[] = {
METASPR_ITEM(0, 0, 0, OBJ_PRIO(2)),
METASPR_ITEM(16, 0, 1, OBJ_PRIO(2)),
METASPR_ITEM(0, 16, 2, OBJ_PRIO(2)),
METASPR_ITEM(16, 16, 3, OBJ_PRIO(2)),
};
oamMetaDrawDyn(0, 100, 80, hero, hero_tiles, OBJ_LARGE);
void oamMetaDrawDyn(u16 id, s16 x, s16 y, const MetaspriteItem *meta, u8 *gfxptr, u8 size_class)
Draw a dynamic metasprite — engine picks the size routine.
u8 oamrefresh
Definition sprite.h:193

◆ oamSet()

void oamSet ( u16  id,
u16  x,
u16  y,
u16  tile,
u16  palette,
u16  priority,
u16  flags 
)

Set sprite properties.

Parameters
idSprite ID (0-127)
xX position (0-511, negative wraps)
yY position (0-255, use OBJ_HIDE_Y to hide)
tileTile number (0-511)
palettePalette (0-7)
priorityPriority (0-3, 3=highest)
flagsFlip flags (bit 6 = H flip, bit 7 = V flip)
Warning
Performance: oamSet() has framesize=158 per call (158 bytes of stack manipulation due to SSA temporaries). Calling it more than 2-3 times per frame in the main loop causes visible jitter on real hardware. Use oamSetFast() or oamSetXYFast() macros for performance-critical code (see "Fast Macro Sprite API" section below).
Coordinate Variable Pattern: Due to a compiler quirk, sprite coordinates MUST be stored in a struct with s16 members for correct behavior. Using separate u16 variables causes jerky horizontal movement.

CORRECT (use struct with s16):

typedef struct { s16 x, y; } Position;
Position player = {100, 100};
oamSet(0, player.x, player.y, 0, 0, 3, 0);
player.x += 1; // Smooth movement
signed short s16
16-bit signed integer (-32768 to 32767)
Definition types.h:49

WRONG (separate u16 variables - causes bugs):

u16 player_x = 100; // DON'T do this!
u16 player_y = 100;
oamSet(0, player_x, player_y, 0, 0, 3, 0);
player_x += 1; // Jerky movement!
static s16 player_y
Player Y position in screen coordinates.
Definition main.c:57
static s16 player_x
Player X position in screen coordinates.
Definition main.c:55

See examples/graphics/backgrounds/continuous_scroll for details on this pattern.

◆ oamSetSize()

void oamSetSize ( u16  id,
u16  large 
)

Set sprite size (large/small)

Parameters
idSprite ID (0-127)
largeTRUE for large size, FALSE for small

◆ oamSetTile()

void oamSetTile ( u8  id,
u16  tile 
)

Set sprite tile.

Parameters
idSprite ID (0-127)
tileTile number (0-511)

◆ oamSetVisible()

void oamSetVisible ( u8  id,
u8  visible 
)

Set sprite visibility.

Parameters
idSprite ID (0-127)
visibleOBJ_SHOW (1) or OBJ_HIDE (0)
Note
Important: SNES sprite visibility is controlled by Y position. Setting Y to 240 (OBJ_HIDE_Y) hides the sprite below the visible screen. This function only handles HIDING (sets Y=240). Passing OBJ_SHOW does nothing - to show a sprite, set a valid Y coordinate using oamSetY() or oamSet(). For explicit hiding, use oamHide() which is clearer.
oamSetVisible(0, OBJ_HIDE); // Hides sprite 0 (sets Y=240)
oamSetVisible(0, OBJ_SHOW); // Does nothing! Sprite stays hidden.
oamSetY(0, 100); // This shows the sprite at Y=100
#define OBJ_SHOW
Sprite visibility.
Definition sprite.h:99
void oamSetY(u8 id, u8 y)
Set sprite Y position.
#define OBJ_HIDE
Definition sprite.h:100
void oamSetVisible(u8 id, u8 visible)
Set sprite visibility.

◆ oamSetX()

void oamSetX ( u8  id,
u16  x 
)

Set sprite X position.

Parameters
idSprite ID (0-127)
xX position

◆ oamSetXY()

void oamSetXY ( u8  id,
u16  x,
u8  y 
)

Set sprite position.

Parameters
idSprite ID (0-127)
xX position
yY position

◆ oamSetY()

void oamSetY ( u8  id,
u8  y 
)

Set sprite Y position.

Parameters
idSprite ID (0-127)
yY position

◆ oamUpdate()

void oamUpdate ( void  )

Copy OAM buffer to hardware.

Call during VBlank to update sprite display.

Variable Documentation

◆ lkup16idB

u16 lkup16idB[]
extern

VRAM destination addresses for 16x16 sprites (64 entries)

◆ lkup16idT

u16 lkup16idT[]
extern

OAM tile IDs for 16x16 sprites - small size mode (64 entries)

◆ lkup16idT0

u16 lkup16idT0[]
extern

OAM tile IDs for 16x16 sprites - large size mode (64 entries)

◆ lkup16oamS

u16 lkup16oamS[]
extern

VRAM source offsets for 16x16 sprites (64 entries)

VRAM addressing lookup tables for dynamic sprite engines. These tables convert sprite frame indices to VRAM addresses.

Usage: u16 vramOffset = lkup16oamS[frameId]; // VRAM source offset u16 tileId = lkup16idT[spriteSlot]; // OAM tile number u16 vramDest = lkup16idB[spriteSlot]; // VRAM destination

◆ lkup32idB

u16 lkup32idB[]
extern

VRAM destination addresses for 32x32 sprites (16 entries)

◆ lkup32idT

u16 lkup32idT[]
extern

OAM tile IDs for 32x32 sprites (16 entries)

◆ lkup32oamS

u16 lkup32oamS[]
extern

VRAM source offsets for 32x32 sprites (16 entries)

◆ lkup8idB

u16 lkup8idB[]
extern

VRAM destination addresses for 8x8 sprites (128 entries)

◆ lkup8idT

u16 lkup8idT[]
extern

OAM tile IDs for 8x8 sprites (128 entries)

◆ lkup8oamS

u16 lkup8oamS[]
extern

VRAM source offsets for 8x8 sprites (128 entries)

◆ oambuffer

t_sprites oambuffer[128]
extern

Dynamic sprite buffer (128 entries, 2048 bytes)

Game-level sprite state for the dynamic sprite engine. Each entry tracks a sprite's position, animation frame, and graphics pointer. Separate from oamMemory (hardware OAM buffer at $0300-$051F).