spriteforge/docs/format-v1.md

45 lines
2.3 KiB
Markdown

# 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.