130 lines
5 KiB
C
130 lines
5 KiB
C
// iigs/sprite.h - 16x16 fixed-shape 4bpp packed sprite primitives for
|
|
// SHR 320 mode.
|
|
//
|
|
// Phase 4.2 / Phase 0.6 standalone path: sprite.c brings up SHR 320
|
|
// mode itself (NEWVIDEO bit 7 via $C029, SCBs at $E1:9D00, palette 0
|
|
// at $E1:9E00) so callers don't have to drag startdesk()'s full 16-
|
|
// tool chain in. 640 mode deferred per Phase 0.6.
|
|
//
|
|
// Pixel format (4bpp packed, SHR 320 mode native):
|
|
// - 128 bytes per sprite image: 16 lines x 8 bytes per line.
|
|
// - Byte layout: high nibble = LEFT pixel, low nibble = RIGHT pixel.
|
|
// - Pixel value 0 is TRANSPARENT (no plot, background shows through).
|
|
// Pixel values 1..15 plot the corresponding palette-0 color.
|
|
//
|
|
// ----- $C035 SHADOW GOTCHA (CRITICAL) -----
|
|
// Bank 0 $2000..$9FFF mirrors to $E1:2000..$E1:9FFF via the IIgs SHR
|
|
// shadow register at $C035. This means a background save buffer
|
|
// allocated in bank-0 $2000..$9FFF would alias the very SHR pixels it
|
|
// is trying to preserve. The built-in save area lives in bank 0
|
|
// $A000..$AFFF (16 sprites x 128 bytes = 2 KB), which is OUTSIDE the
|
|
// shadowed range and safe. If you need more than 16 sprites or want
|
|
// to relocate the save area, call iigsSpriteAttachBuffer() with a
|
|
// caller-supplied buffer that lives EITHER above $A000 in bank 0 OR in
|
|
// a non-zero bank. Buffers inside bank-0 $2000..$9FFF will silently
|
|
// scribble on the screen.
|
|
//
|
|
// Coordinate system: (x, y) is the top-left corner of the sprite.
|
|
// - x in pixels (0..303 for full sprite visibility at right edge).
|
|
// Currently MUST be even (no sub-byte horizontal alignment in this
|
|
// first cut). Odd x is clamped down 1 pixel.
|
|
// - y in scan lines (0..183 for full sprite visibility at bottom).
|
|
//
|
|
// Off-screen clipping is NOT implemented in this first cut. Callers
|
|
// must place sprites entirely on-screen (x <= 304 even, y <= 184).
|
|
|
|
#ifndef IIGS_SPRITE_H
|
|
#define IIGS_SPRITE_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
|
|
// Maximum sprites tracked by the built-in list. Bumped past this only
|
|
// by calling iigsSpriteAttachBuffer() with a larger caller buffer.
|
|
#define IIGS_SPRITE_MAX_DEFAULT 16
|
|
|
|
|
|
// Each sprite is (position, pointer-to-128-bytes). pixels points to
|
|
// the 4bpp packed image (16 lines x 8 bytes). Pixel value 0 in the
|
|
// source is transparent.
|
|
typedef struct IigsSpriteT {
|
|
uint16_t x; // top-left x, even pixel
|
|
uint16_t y; // top-left scan line
|
|
const uint8_t * pixels; // 128 bytes, 4bpp packed
|
|
} IigsSpriteT;
|
|
|
|
|
|
// Bring up SHR 320 mode (NEWVIDEO bit 7 = 1, all SCBs = 0x00 for
|
|
// palette 0 in 320 mode, palette 0 loaded with a default 16-color
|
|
// ramp). Idempotent: subsequent calls reset the screen state.
|
|
//
|
|
// After this returns, callers can write SHR pixel bytes directly to
|
|
// $E1:2000..$E1:9CFF, or use the sprite list API below.
|
|
void iigsSpriteInit(void);
|
|
|
|
|
|
// Set palette 0 to a caller-supplied 16-entry table. Each entry is a
|
|
// 12-bit RGB value (0x0RGB). Pass NULL to reset to the default ramp
|
|
// iigsSpriteInit() installed.
|
|
void iigsSpriteSetPalette(const uint16_t *palette16);
|
|
|
|
|
|
// Replace the built-in save buffer with caller-supplied storage. buf
|
|
// MUST live OUTSIDE bank-0 $2000..$9FFF (see $C035 shadow gotcha at
|
|
// top of this header). size must be at least sprites * 128 bytes.
|
|
// Returns the maximum number of sprites the new buffer supports
|
|
// (size / 128, capped). Pass buf=NULL,size=0 to revert to the built-in
|
|
// 16-sprite buffer.
|
|
uint16_t iigsSpriteAttachBuffer(void *buf, size_t size);
|
|
|
|
|
|
// ----- sprite list API -----------------------------------------------
|
|
// Typical frame:
|
|
// iigsSpriteBegin();
|
|
// for (each sprite) iigsSpriteAdd(&s);
|
|
// iigsSpriteRenderAll(); // save background + blit each sprite
|
|
// // ... game logic, animation update ...
|
|
// iigsSpriteEraseAll(); // restore saved background in reverse
|
|
//
|
|
// Render/erase pair preserves the framebuffer outside the sprite
|
|
// rectangles. EraseAll MUST be called before the next Begin if the
|
|
// background should not accumulate prior frames.
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Clear the sprite list. Call once at the start of each frame.
|
|
void iigsSpriteBegin(void);
|
|
|
|
|
|
// Append one sprite to the current frame's list. Copies the sprite
|
|
// descriptor by value (caller may modify or free *s after return).
|
|
// Silently no-ops if the list is full. Returns the slot index, or
|
|
// 0xFFFF if full.
|
|
uint16_t iigsSpriteAdd(const IigsSpriteT *s);
|
|
|
|
|
|
// Save the 16x16 background under each sprite into the save buffer,
|
|
// then blit each sprite (with pixel 0 = transparent). Walk order:
|
|
// list order (sprite 0 first, last drawn on top).
|
|
void iigsSpriteRenderAll(void);
|
|
|
|
|
|
// Restore each saved background in REVERSE order (last sprite first)
|
|
// so overlapping sprites de-occlude correctly. Pair with the most
|
|
// recent iigsSpriteRenderAll().
|
|
void iigsSpriteEraseAll(void);
|
|
|
|
|
|
// Count of sprites currently in the list. Useful for tests + debug.
|
|
uint16_t iigsSpriteCount(void);
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif // IIGS_SPRITE_H
|