# SpriteForge binary formats v1 All integers and IEEE-754 floats are little-endian. Every offset is an unsigned 32-bit byte offset from the beginning of its file. Files over 4 GiB, big-endian hosts, and per-entry alpha are not supported by v1. Readers must bounds-check all arithmetic before dereferencing data. ## SFA (sprite frames) The 64-byte header contains `SFA\0`, major/minor version, flags, file size, counts and offsets for strings, animation records, direction records, frame records, layer-order values and payload data. Flag bit 0 means normals exist, bit 1 means depth exists, and bit 31 is reserved for future palette alpha. Animation names have both FNV-1a 32-bit IDs and NUL-terminated UTF-8 strings. Multiple animation records share the direction-angle table and each stores its own first frame and frames-per-direction range. Directions use signed centidegrees. A frame record stores uint16 dimensions, int16 pivot, uint16 duration in milliseconds, local `depth_min/depth_max` in world units, and offsets/sizes for three independent streams. Each present stream starts with `height + 1` uint32 row offsets relative to the stream start. Thus a clipped row is found in O(1). A row consists of a uint16 span count followed by spans. Each span starts with uint16 x and length, then: - color: `length` palette-index bytes (index 0 is forbidden in spans); - normals: `length * 2` signed-normalized bytes, X right and Y up; positive Z is reconstructed as `sqrt(max(0, 1-x*x-y*y))`; - depth: `length` bytes, where 0 is locally nearest and 255 locally farthest. Layer order is a frame-major array of uint16 layer indices. V1 expresses one permutation per frame; self-intersecting components must be split into passes. ## SFP (palette pack) One SFP can hold named palettes and colormaps; multiple SFP views may coexist. A palette is exactly 256 RGB triples. Index 0 is transparent by convention and its RGB is ignored. Entries 1..255 are opaque. A colormap is a 256-byte index mapping. Blending is selected once per blit call (`opaque`, `alpha25`, `alpha50`, `alpha75`, `additive`, `subtractive`), never stored per entry. Readers accept the same major version and a minor version no newer than theirs. Unknown flag bits are rejected except the reserved future-alpha bit, which v1 readers must reject when set because they cannot interpret it.