Loading...
Searching...
No Matches
sprite.h
Go to the documentation of this file.
1
36#ifndef OPENSNES_SPRITE_H
37#define OPENSNES_SPRITE_H
38
39#include <snes/types.h>
40
41/*============================================================================
42 * Constants
43 *============================================================================*/
44
46#define MAX_SPRITES 128
47
49#define OBJ_SIZE8_L16 0
50#define OBJ_SIZE8_L32 1
51#define OBJ_SIZE8_L64 2
52#define OBJ_SIZE16_L32 3
53#define OBJ_SIZE16_L64 4
54#define OBJ_SIZE32_L64 5
57#define OBJ_SIZE_TO_REG(size) ((size) << 5)
58
60#define OBJ_BASE(vram_addr) (((vram_addr) >> 13) & 0x07)
61
72#define OBJSEL(size, vram_addr) ((u8)(OBJ_SIZE_TO_REG(size) | OBJ_BASE(vram_addr)))
73
75#define OBJ_CGRAM_BASE 128
76
78#define OBJ_CGRAM_PAL(n) (OBJ_CGRAM_BASE + (n) * 16)
79
81#define PALETTE_16_SIZE 32
82
84#define OAM_Y_OFFSCREEN 0xE0
85
87#define OAM_EXT_OFFSET 512
88
90#define OAM_EXT_SIZE 32
91
93#define OAM_BUFFER_SIZE 544
94
96#define OBJ_HIDE_Y 240
97
99#define OBJ_SHOW 1
100#define OBJ_HIDE 0
103#define OBJ_SMALL 0
104#define OBJ_LARGE 1
106/*============================================================================
107 * Dynamic Sprite Engine Constants
108 *============================================================================*/
109
111#define OBJ_SPRITE32 1
112#define OBJ_SPRITE16 2
113#define OBJ_SPRITE8 4
116#define OBJ_QUEUELIST_SIZE 128
117
119#define MAXSPRTRF (7 * 6)
120
121/*============================================================================
122 * Sprite Lookup Tables (for dynamic sprite management)
123 *============================================================================*/
124
136extern u16 lkup16oamS[];
137
139extern u16 lkup16idT[];
140
142extern u16 lkup16idT0[];
143
145extern u16 lkup16idB[];
146
148extern u16 lkup32oamS[];
149
151extern u16 lkup32idT[];
152
154extern u16 lkup32idB[];
155
157extern u16 lkup8oamS[];
158
160extern u16 lkup8idT[];
161
163extern u16 lkup8idB[];
164
165/*============================================================================
166 * Dynamic Sprite Structure
167 *============================================================================*/
168
200
201/*============================================================================
202 * Compile-time struct layout assertions
203 * Must match the oambuffer layout in sprite_dynamic.asm exactly.
204 *============================================================================*/
205
206_Static_assert(sizeof(t_sprites) == 16, "t_sprites must be 16 bytes");
207_Static_assert(__builtin_offsetof(t_sprites, oamx) == 0, "oamx offset mismatch");
208_Static_assert(__builtin_offsetof(t_sprites, oamy) == 2, "oamy offset mismatch");
209_Static_assert(__builtin_offsetof(t_sprites, oamframeid) == 4, "oamframeid offset mismatch");
210_Static_assert(__builtin_offsetof(t_sprites, oamattribute) == 6, "oamattribute offset mismatch");
211_Static_assert(__builtin_offsetof(t_sprites, oamrefresh) == 7, "oamrefresh offset mismatch");
212_Static_assert(__builtin_offsetof(t_sprites, oamgfxaddr) == 8, "oamgfxaddr offset mismatch");
213_Static_assert(__builtin_offsetof(t_sprites, oamgfxbank) == 10, "oamgfxbank offset mismatch");
214
225#define OAM_SET_GFX(id, gfx) do { \
226 oambuffer[id].oamgfxaddr = (u16)(gfx); \
227 oambuffer[id].oamgfxbank = 0; \
228} while(0)
229
239#define OAM_SET_GFX_BANK(id, gfx, bank) do { \
240 oambuffer[id].oamgfxaddr = (u16)(gfx); \
241 oambuffer[id].oamgfxbank = (u8)(bank); \
242} while(0)
243
244/* --- Bank $00 SLOT 1 (C-accessible, < $2000) --- */
245
253extern t_sprites oambuffer[128];
254
255/*============================================================================
256 * Initialization
257 *============================================================================*/
258
265#define OAM_DEFAULT_SIZE OBJ_SIZE8_L16
267#define OAM_DEFAULT_TILE_BASE 0
268
283void oamInit(u16 size, u16 tile_base);
284
306void oamInitGfxSet(u8 *tileSource, u16 tileSize, u8 *tilePalette,
307 u16 paletteSize, u8 paletteEntry, u16 vramAddr, u8 oamSize);
308
309/*============================================================================
310 * Sprite Properties
311 *============================================================================*/
312
352void oamSet(u16 id, u16 x, u16 y, u16 tile, u16 palette, u16 priority, u16 flags);
353
360void oamSetX(u8 id, u16 x);
361
368void oamSetY(u8 id, u8 y);
369
377void oamSetXY(u8 id, u16 x, u8 y);
378
385void oamSetTile(u8 id, u16 tile);
386
405void oamSetVisible(u8 id, u8 visible);
406
412void oamHide(u8 id);
413
420void oamSetSize(u16 id, u16 large);
421
422/*============================================================================
423 * OAM Update
424 *============================================================================*/
425
436void oamUpdate(void);
437
443void oamClear(void);
444
445/*============================================================================
446 * Metasprites
447 *============================================================================*/
448
462
465
467#define METASPR_ITEM(dx, dy, tile, attr) { (dx), (dy), (tile), (attr), 0 }
468
470#define METASPR_TERM { -128, 0, 0, 0, 0 }
471
473#define metasprite_end (-128)
474
476#define OBJ_PAL(pal) ((pal) << 1)
477
479#define OBJ_PRIO(prio) ((prio) << 4)
480
482#define OBJ_FLIPX 0x40
483
485#define OBJ_FLIPY 0x80
486
488#define OBJ_NAMETABLE_HIGH 0x01
489
521u8 oamDrawMeta(u8 startId, s16 x, s16 y, const MetaspriteItem *meta,
522 u16 baseTile, u8 basePalette, u8 size);
523
544u8 oamDrawMetaFlip(u8 startId, s16 x, s16 y, const MetaspriteItem *meta,
545 u16 baseTile, u8 basePalette, u8 size,
546 u8 flipX, u8 flipY, u8 width, u8 height);
547
561u8 oamDrawMetasprite(u8 startId, u16 x, u8 y, const u8 *data, u8 palette);
562
563/*============================================================================
564 * Dynamic Sprite Engine
565 *============================================================================*/
566
581
603
617void oamDynamicSetSize(u16 id, u8 size);
618
634
659
660/*============================================================================
661 * Dynamic Metasprite Engine
662 *============================================================================*/
663
709void oamMetaDrawDyn(u16 id, s16 x, s16 y,
710 const MetaspriteItem *meta, u8 *gfxptr, u8 size_class);
711
712/*============================================================================
713 * Fast Macro Sprite API
714 *
715 * Zero-overhead alternatives to oamSet/oamSetXY for performance-critical code.
716 * These write directly to oamMemory[] without function call overhead.
717 *
718 * oamSet() has framesize=158 per call due to SSA temporaries. With >2-3
719 * sprites/frame in the main loop, the stack manipulation causes visible
720 * jitter. These macros eliminate that overhead entirely.
721 *
722 * Note: cc65816 does not truly inline 'static inline' functions — they
723 * become separate SUPERFREE sections with global labels that conflict
724 * across translation units. Macros are the only zero-overhead option.
725 *
726 * oamMemory[] and oam_update_flag are declared in <snes/system.h>
727 * (included automatically via <snes.h>).
728 *
729 * Usage:
730 * // Pre-compute attribute byte once at init
731 * u8 attr = OAM_ATTR(tile, palette, priority, flags);
732 *
733 * // Per-frame: fast full update
734 * oamSetFast(id, x, y, tile, palette, priority, flags);
735 *
736 * // Per-frame: position-only update (most common)
737 * oamSetXYFast(id, x, y);
738 *============================================================================*/
739
749#define OAM_ATTR(_tile, _pal, _prio, _fl) \
750 ((u8)(((_fl) & 0xC0) | \
751 (((_prio) & 0x03) << 4) | \
752 (((_pal) & 0x07) << 1) | \
753 (((_tile) >> 8) & 0x01)))
754
761#define OAM_XHI_MASK(_slot) \
762 ((u8)((_slot) == 0 ? 0x01 : (_slot) == 1 ? 0x04 : \
763 (_slot) == 2 ? 0x10 : 0x40))
764
780#define oamSetFast(_id, _x, _y, _tile, _pal, _prio, _fl) do { \
781 u16 _off = (u16)(_id) << 2; \
782 oamMemory[_off + 0] = (u8)((_x) & 0xFF); \
783 oamMemory[_off + 1] = (u8)(((_y) - 1) & 0xFF); /* compensate +1 PPU scanline quirk */ \
784 oamMemory[_off + 2] = (u8)((_tile) & 0xFF); \
785 oamMemory[_off + 3] = OAM_ATTR(_tile, _pal, _prio, _fl); \
786 u16 _ext = 512 + ((u16)(_id) >> 2); \
787 u16 _sl = (u16)(_id) & 0x03; \
788 u8 _xhi = OAM_XHI_MASK(_sl); \
789 if ((_x) & 0x100) \
790 oamMemory[_ext] |= _xhi; \
791 else \
792 oamMemory[_ext] &= ~_xhi; \
793 oam_update_flag = 1; \
794} while(0)
795
806#define oamSetXYFast(_id, _x, _y) do { \
807 u16 _off = (u16)(_id) << 2; \
808 oamMemory[_off + 0] = (u8)((_x) & 0xFF); \
809 oamMemory[_off + 1] = (u8)(((_y) - 1) & 0xFF); /* compensate +1 PPU scanline quirk */ \
810 u16 _ext = 512 + ((u16)(_id) >> 2); \
811 u16 _sl = (u16)(_id) & 0x03; \
812 u8 _xhi = OAM_XHI_MASK(_sl); \
813 if ((_x) & 0x100) \
814 oamMemory[_ext] |= _xhi; \
815 else \
816 oamMemory[_ext] &= ~_xhi; \
817 oam_update_flag = 1; \
818} while(0)
819
820#endif /* OPENSNES_SPRITE_H */
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:49
unsigned short u16
16-bit unsigned integer (0 to 65535)
Definition types.h:52
unsigned char u8
8-bit unsigned integer (0 to 255)
Definition types.h:46
void oamDynamicSetSize(u16 id, u8 size)
Override the dispatched pixel size for a dynamic sprite slot.
void oamSetTile(u8 id, u16 tile)
Set sprite tile.
u16 lkup16idT[]
OAM tile IDs for 16x16 sprites - small size mode (64 entries)
void oamSetX(u8 id, u16 x)
Set sprite X position.
u8 oamDrawMeta(u8 startId, s16 x, s16 y, const MetaspriteItem *meta, u16 baseTile, u8 basePalette, u8 size)
Draw a metasprite (PVSnesLib compatible)
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.
u16 lkup32oamS[]
VRAM source offsets for 32x32 sprites (16 entries)
u16 lkup16oamS[]
VRAM source offsets for 16x16 sprites (64 entries)
u8 oamDrawMetasprite(u8 startId, u16 x, u8 y, const u8 *data, u8 palette)
Draw a metasprite (legacy simple interface)
void oamInitGfxSet(u8 *tileSource, u16 tileSize, u8 *tilePalette, u16 paletteSize, u8 paletteEntry, u16 vramAddr, u8 oamSize)
Initialize sprite graphics and palette (PVSnesLib compatible)
u16 lkup8oamS[]
VRAM source offsets for 8x8 sprites (128 entries)
void oamHide(u8 id)
Hide sprite.
void oamSetXY(u8 id, u16 x, u8 y)
Set sprite position.
void oamDynamicDraw(u16 id)
Draw a dynamic sprite — engine picks the size routine.
u16 lkup16idT0[]
OAM tile IDs for 16x16 sprites - large size mode (64 entries)
void oamSet(u16 id, u16 x, u16 y, u16 tile, u16 palette, u16 priority, u16 flags)
Set sprite properties.
u16 lkup16idB[]
VRAM destination addresses for 16x16 sprites (64 entries)
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 oamClear(void)
Clear all sprites.
void oamUpdate(void)
Copy OAM buffer to hardware.
void oamInit(u16 size, u16 tile_base)
Initialize the sprite (OAM) system.
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.
void oamDynamicDrainQueue(void)
Block until the dynamic-sprite VRAM tile queue is empty.
void oamSetY(u8 id, u8 y)
Set sprite Y position.
u16 lkup8idB[]
VRAM destination addresses for 8x8 sprites (128 entries)
u16 lkup32idT[]
OAM tile IDs for 32x32 sprites (16 entries)
MetaspriteItem t_metasprite
PVSnesLib compatibility typedef.
Definition sprite.h:464
u16 lkup8idT[]
OAM tile IDs for 8x8 sprites (128 entries)
u16 lkup32idB[]
VRAM destination addresses for 32x32 sprites (16 entries)
void oamSetVisible(u8 id, u8 visible)
Set sprite visibility.
Metasprite item structure (PVSnesLib compatible)
Definition sprite.h:455
u16 tile
Definition sprite.h:458
u8 reserved
Definition sprite.h:460
s16 dx
Definition sprite.h:456
s16 dy
Definition sprite.h:457
u8 attr
Definition sprite.h:459
Configuration for the dynamic sprite engine.
Definition sprite.h:574
u16 vramLarge
Definition sprite.h:575
u16 vramSmall
Definition sprite.h:576
u16 slotSmallInit
Definition sprite.h:578
u8 sizeMode
Definition sprite.h:579
u16 slotLargeInit
Definition sprite.h:577
Dynamic sprite state structure (16 bytes, PVSnesLib compatible)
Definition sprite.h:188
u16 oamframeid
Definition sprite.h:191
u8 _pad
Definition sprite.h:196
s16 oamx
Definition sprite.h:189
u16 _reserved2
Definition sprite.h:198
s16 oamy
Definition sprite.h:190
u16 oamgfxaddr
Definition sprite.h:194
u16 _reserved1
Definition sprite.h:197
u8 oamgfxbank
Definition sprite.h:195
u8 oamattribute
Definition sprite.h:192
u8 oamrefresh
Definition sprite.h:193
OpenSNES Standard Types.