36#ifndef OPENSNES_SPRITE_H
37#define OPENSNES_SPRITE_H
49#define MAX_SPRITES 128
52#define OBJ_SIZE8_L16 0
53#define OBJ_SIZE8_L32 1
54#define OBJ_SIZE8_L64 2
55#define OBJ_SIZE16_L32 3
56#define OBJ_SIZE16_L64 4
57#define OBJ_SIZE32_L64 5
60#define OBJ_SIZE_TO_REG(size) ((size) << 5)
63#define OBJ_BASE(vram_addr) (((vram_addr) >> 13) & 0x07)
75#define OBJSEL(size, vram_addr) ((u8)(OBJ_SIZE_TO_REG(size) | OBJ_BASE(vram_addr)))
78#define OBJ_CGRAM_BASE 128
81#define OBJ_CGRAM_PAL(n) (OBJ_CGRAM_BASE + (n) * 16)
84#define PALETTE_16_SIZE 32
87#define OAM_Y_OFFSCREEN 0xE0
90#define OAM_EXT_OFFSET 512
93#define OAM_EXT_SIZE 32
96#define OAM_BUFFER_SIZE 544
110#define OBJ_SPRITE32 1
111#define OBJ_SPRITE16 2
115#define OBJ_QUEUELIST_SIZE 128
118#define MAXSPRTRF (7 * 6)
161_Static_assert(
sizeof(
t_sprites) == 16,
"t_sprites must be 16 bytes");
162_Static_assert(__builtin_offsetof(
t_sprites, oamx) == 0,
"oamx offset mismatch");
163_Static_assert(__builtin_offsetof(
t_sprites, oamy) == 2,
"oamy offset mismatch");
164_Static_assert(__builtin_offsetof(
t_sprites, oamframeid) == 4,
"oamframeid offset mismatch");
165_Static_assert(__builtin_offsetof(
t_sprites, oamattribute) == 6,
"oamattribute offset mismatch");
166_Static_assert(__builtin_offsetof(
t_sprites, oamrefresh) == 7,
"oamrefresh offset mismatch");
167_Static_assert(__builtin_offsetof(
t_sprites, oamgfxaddr) == 8,
"oamgfxaddr offset mismatch");
168_Static_assert(__builtin_offsetof(
t_sprites, oamgfxbank) == 10,
"oamgfxbank offset mismatch");
182#define OAM_SET_GFX(id, gfx) do { \
183 oambuffer[id].oamgfxaddr = (u16)(u32)(const void *)(gfx); \
184 oambuffer[id].oamgfxbank = (u8)((u32)(const void *)(gfx) >> 16); \
211#define OAM_DEFAULT_SIZE OBJ_SIZE8_L16
213#define OAM_DEFAULT_TILE_BASE 0
257#define OBJ_NAME_BASE(vram_word_addr) (((vram_word_addr) >> 13) & 0x07)
281 u16 paletteSize,
u8 paletteEntry,
u16 vramAddr,
u8 oamSize);
396_Static_assert(__builtin_offsetof(
OamWorldBatch, y) == 4,
"OamWorldBatch.y offset (sprite_world.asm)");
397_Static_assert(__builtin_offsetof(
OamWorldBatch, tile) == 8,
"OamWorldBatch.tile offset (sprite_world.asm)");
398_Static_assert(__builtin_offsetof(
OamWorldBatch, attr) == 12,
"OamWorldBatch.attr offset (sprite_world.asm)");
399_Static_assert(__builtin_offsetof(
OamWorldBatch, visible) == 16,
"OamWorldBatch.visible offset (sprite_world.asm)");
400_Static_assert(__builtin_offsetof(
OamWorldBatch, first_id) == 20,
"OamWorldBatch.first_id offset (sprite_world.asm)");
401_Static_assert(__builtin_offsetof(
OamWorldBatch, count) == 21,
"OamWorldBatch.count offset (sprite_world.asm)");
402_Static_assert(__builtin_offsetof(
OamWorldBatch, size) == 22,
"OamWorldBatch.size offset (sprite_world.asm)");
403_Static_assert(__builtin_offsetof(
OamWorldBatch, order) == 24,
"OamWorldBatch.order offset (sprite_world.asm)");
569#define METASPR_ITEM(dx, dy, tile, attr) { (dx), (dy), (tile), (attr), 0 }
572#define METASPR_TERM { -128, 0, 0, 0, 0 }
575#define metasprite_end (-128)
578#define OBJ_PAL(pal) ((pal) << 1)
581#define OBJ_PRIO(prio) ((prio) << 4)
584#define OBJ_FLIPX 0x40
587#define OBJ_FLIPY 0x80
590#define OBJ_NAMETABLE_HIGH 0x01
848#define OAM_ATTR(_tile, _pal, _prio, _fl) \
849 ((u8)(((_fl) & 0xC0) | \
850 (((_prio) & 0x03) << 4) | \
851 (((_pal) & 0x07) << 1) | \
852 (((_tile) >> 8) & 0x01)))
860#define OAM_XHI_MASK(_slot) \
861 ((u8)((_slot) == 0 ? 0x01 : (_slot) == 1 ? 0x04 : \
862 (_slot) == 2 ? 0x10 : 0x40))
879#define oamSetFast(_id, _x, _y, _tile, _pal, _prio, _fl) do { \
880 u16 _off = (u16)(_id) << 2; \
881 oamMemory[_off + 0] = (u8)((_x) & 0xFF); \
882 oamMemory[_off + 1] = (u8)((_y) & 0xFF); \
883 oamMemory[_off + 2] = (u8)((_tile) & 0xFF); \
884 oamMemory[_off + 3] = OAM_ATTR(_tile, _pal, _prio, _fl); \
885 u16 _ext = 512 + ((u16)(_id) >> 2); \
886 u16 _sl = (u16)(_id) & 0x03; \
887 u8 _xhi = OAM_XHI_MASK(_sl); \
889 oamMemory[_ext] |= _xhi; \
891 oamMemory[_ext] &= ~_xhi; \
892 oam_update_flag = 1; \
905#define oamSetXYFast(_id, _x, _y) do { \
906 u16 _off = (u16)(_id) << 2; \
907 oamMemory[_off + 0] = (u8)((_x) & 0xFF); \
908 oamMemory[_off + 1] = (u8)((_y) & 0xFF); \
909 u16 _ext = 512 + ((u16)(_id) >> 2); \
910 u16 _sl = (u16)(_id) & 0x03; \
911 u8 _xhi = OAM_XHI_MASK(_sl); \
913 oamMemory[_ext] |= _xhi; \
915 oamMemory[_ext] &= ~_xhi; \
916 oam_update_flag = 1; \
u16 flip
Frame counter for scroll speed throttle (scrolls every 3 frames).
Definition main.c:65
u8 palette[]
Full 256-color palette for BG and sprite layers (512 bytes).
signed short s16
16-bit signed integer (-32768 to 32767)
Definition types.h:50
unsigned short u16
16-bit unsigned integer (0 to 65535)
Definition types.h:53
unsigned char u8
8-bit unsigned integer (0 to 255)
Definition types.h:47
u16 frame
Current sprite tile number.
Definition main.c:77
void oamDynamicSetSize(u16 id, u8 size)
Override the dispatched pixel size for a dynamic sprite slot.
void oamInit(u16 size, u16 name_base)
Initialize the sprite (OAM) system.
void oamSetY(u16 id, u16 y)
Set sprite Y position.
t_sprites oambuffer[128]
Dynamic sprite buffer (128 entries, 2048 bytes).
void oamSetSize(u16 id, u16 large)
Set sprite size (large/small).
void oamDynamicInit(const OamDynamicConfig *cfg)
Initialize the dynamic sprite engine from a config struct.
void oamDynamicDraw(u16 id)
Draw a dynamic sprite — engine picks the size routine.
u16 oamGetX(u16 id)
Read back a sprite's X position.
void oamSet(u16 id, u16 x, u16 y, u16 tile, u16 palette, u16 priority, u16 flags)
Set sprite properties.
void oamSetXY(u16 id, u16 x, u16 y)
Set sprite position.
void oamClear(void)
Clear all sprites.
void oamUpdate(void)
Copy OAM buffer to hardware.
void oamInitGfxSet(const u8 *tileSource, u16 tileSize, const u8 *tilePalette, u16 paletteSize, u8 paletteEntry, u16 vramAddr, u8 oamSize)
Initialize sprite graphics and palette (PVSnesLib compatible).
void oamHide(u16 id)
Park a sprite off screen.
u8 oamGetY(u16 id)
Read back a sprite's Y position.
void oamPlaceWorld(const OamWorldBatch *batch, u16 cam_x, u16 cam_y)
Place a batch of world-space sprites: camera, culling, OAM, in one call.
void oamDynamicDrainQueue(void)
Block until the dynamic-sprite VRAM tile queue is empty.
u16 oamDrawMetasprite(u16 startId, s16 x, s16 y, const MetaspriteItem *frame, const MetaspriteStyle *style, u8 flip)
Draw one frame of a metasprite.
void oamSetTile(u16 id, u16 tile)
Set sprite tile.
MetaspriteItem t_metasprite
PVSnesLib compatibility typedef.
Definition sprite.h:566
void oamMetaDrawDyn(u16 id, s16 x, s16 y, const MetaspriteItem *meta, const u8 *gfxptr, u8 size_class)
Draw a dynamic metasprite — engine picks the size routine.
void oamSetX(u16 id, u16 x)
Set sprite X position.
u16 cam_y
Definition main.c:80
u16 cam_x
Probe oracles: the camera, the coins placed this frame, the walker in the front slot.
Definition main.c:79
Configuration for the dynamic sprite engine.
Definition sprite.h:666
u16 vramLarge
Definition sprite.h:667
u16 vramSmall
Definition sprite.h:671
u16 slotSmallInit
Definition sprite.h:674
u8 sizeMode
Definition sprite.h:675
u16 slotLargeInit
Definition sprite.h:673
A batch of sprites in world coordinates, for oamPlaceWorld().
Definition sprite.h:381
const s16 * x
Definition sprite.h:382
u8 count
Definition sprite.h:388
u8 * visible
Definition sprite.h:386
const u8 * order
Definition sprite.h:390
const u8 * attr
Definition sprite.h:385
u8 size
Definition sprite.h:389
u8 first_id
Definition sprite.h:387
const u8 * tile
Definition sprite.h:384
const s16 * y
Definition sprite.h:383
Dynamic sprite state structure (16 bytes, PVSnesLib compatible).
Definition sprite.h:143
u16 oamframeid
Definition sprite.h:146
u8 _pad
Definition sprite.h:151
s16 oamx
Definition sprite.h:144
u16 _reserved2
Definition sprite.h:153
s16 oamy
Definition sprite.h:145
u16 oamgfxaddr
Definition sprite.h:149
u16 _reserved1
Definition sprite.h:152
u8 oamgfxbank
Definition sprite.h:150
u8 oamattribute
Definition sprite.h:147
u8 oamrefresh
Definition sprite.h:148