joeylib2/include/joey/surface.h
2026-05-04 11:23:28 -05:00

75 lines
3.1 KiB
C

// Surface type and allocation.
//
// All surfaces are 320x200 16-color images. In-memory storage is
// target-native: chunky 4bpp packed (two pixels per byte, high nibble
// is the left pixel) on IIgs and DOS; native planar (4 separate
// bitplanes on Amiga, word-interleaved planes on Atari ST) on the
// 68k ports. Public API entry points speak in color indices (0..15)
// regardless, so game code does not see the storage format.
//
// Each surface carries its own 200-entry SCB (scanline control byte)
// table and a 16-by-16 $0RGB palette set. See docs/DESIGN.md section 6.
#ifndef JOEYLIB_SURFACE_H
#define JOEYLIB_SURFACE_H
#include "platform.h"
#include "types.h"
// ----- Fixed surface dimensions (library contract) -----
#define SURFACE_WIDTH 320
#define SURFACE_HEIGHT 200
#define SURFACE_BYTES_PER_ROW 160
#define SURFACE_PIXELS_SIZE (SURFACE_BYTES_PER_ROW * SURFACE_HEIGHT)
#define SURFACE_PALETTE_COUNT 16
#define SURFACE_COLORS_PER_PALETTE 16
#define SURFACE_PALETTE_ENTRIES (SURFACE_PALETTE_COUNT * SURFACE_COLORS_PER_PALETTE)
// ----- Opaque public type -----
typedef struct SurfaceT SurfaceT;
// Allocate a new offscreen surface. Returns NULL on failure (joeyLastError
// describes the reason).
SurfaceT *surfaceCreate(void);
// Release an offscreen surface previously returned by surfaceCreate.
// Passing NULL is a no-op. Passing the stage is a no-op.
void surfaceDestroy(SurfaceT *s);
// The library-owned stage: the back-buffer surface that stagePresent
// flips to the display. Always valid between joeyInit and joeyShutdown.
// On IIgs the stage's pixel buffer is pinned to bank $01 SHR space with
// shadow inhibited so writes are full-speed (2.8 MHz) and isolated from
// the displayed framebuffer until the next stagePresent.
SurfaceT *stageGet(void);
// Copy pixels, SCBs, and palettes from src into dst. Both must be valid
// surfaces.
void surfaceCopy(SurfaceT *dst, const SurfaceT *src);
// Persist a surface to disk in target-native form: 32000 bytes of
// pixels followed by 200 bytes of SCB followed by 512 bytes of $0RGB
// palette table (16 palettes x 16 colors, native uint16_t). Returns
// false if the file can't be opened or the write fails. The same
// platform that wrote the file must read it -- no endianness
// conversion is performed.
bool surfaceSaveFile(const SurfaceT *src, const char *path);
// Read a surface from disk, overwriting dst. Returns false if the
// file is missing, the wrong size, or the read fails. dst keeps its
// identity (no reallocation).
bool surfaceLoadFile(SurfaceT *dst, const char *path);
// FNV-1a 32-bit hash of the surface's logical pixel content (color
// indices in row-major order, 0..15 per pixel). Same logical pixels
// produce the same hash on every port regardless of internal storage
// format -- so a hash captured on IIgs (chunky) compares directly
// against the same op's output on Amiga (planar) once the planar
// rewrite is done. Used by the UBER validation harness to
// pixel-compare ports against an IIgs golden reference.
uint32_t surfaceHash(const SurfaceT *s);
#endif