// .spc "sprite pre-compiled" format -- shared spec for the offline baker
// (tools/spritebake) and the runtime loader (src/core/assetLoad.c).
//
// A .spc is a superset of a .spr: the same 44-byte header, then per cel the
// raw chunky tile blob (as .spr) PLUS the pre-emitted native blit-routine
// image + its slot-relative routineOffsets table, so the runtime skips the
// jlSpriteCompile JIT entirely -- it just codegenArenaAlloc + memcpy + stamp
// routineOffsets. Because the emitted routines are position-independent
// (dest passed as arg; routineOffsets are slot-relative), NO load-time
// relocation is needed on IIgs/DOS/Amiga; the Atari ST alone bakes an
// absolute jmp to stSpriteDrawShiftWalker, whose sites are recorded as a
// per-cel reloc list and re-stamped at load.
//
// Header-clean (only fixed-width types + the shared header layout), so it is
// included by both the host bake tool and the target loader.

#ifndef JOEYLIB_SPRITE_PRECOMPILED_H
#define JOEYLIB_SPRITE_PRECOMPILED_H

// 4-byte magic. Trailing digit is the format version; bump it if the emitted
// machine-code ABI or this container layout changes (the loader validates it,
// so a stale .spc is rejected rather than mis-executed).
#define SPC_MAGIC              "JSC1"

// Upper bound on one cel's routine-image size (== the JIT staging cap): the
// uint16 slot-relative offset budget keeps every image under 64 KB. The
// loader sizes its staging read buffer to this and rejects any larger
// (corrupt) imageSize.
#define SPC_MAX_IMAGE_BYTES    (0x10000ul)

// Shared 44-byte header (identical prefix to .spr/.tbk so openReadValidate
// works unchanged). Per-machine target byte (1=amiga 2=atarist 3=dos 4=iigs)
// -- NOT 0: pre-compiled code is machine-specific, so a .spc is validated
// against the build platform exactly like a .tbk.
#define SPC_HEADER_BYTES       44
#define SPC_OFF_TARGET         4    // 1B  per-machine target (see TARGET_* in assetLoad.c/assetbake.py)
#define SPC_OFF_HAS_PALETTE    5    // 1B
#define SPC_OFF_WIDTH_TILES    6    // 1B
#define SPC_OFF_HEIGHT_TILES   7    // 1B
#define SPC_OFF_CELL_COUNT     8    // LE16
#define SPC_OFF_SHIFT_COUNT    10   // 1B  JOEY_SPRITE_SHIFT_COUNT baked for this target (validated at load)
#define SPC_OFF_RESERVED       11   // 1B  (0)
#define SPC_OFF_PALETTE        12   // 16 * LE16 $0RGB

// Per-cel layout (all multi-byte fields little-endian, hand-encoded so the
// container is host-endian-independent; the image bytes themselves are native
// target machine code and are inherently per-target):
//
//   tileData[widthTiles*heightTiles*32]   raw chunky 4bpp cel (as .spr) --
//                                          feeds spriteInitFields + the
//                                          interpreter/clip fallback path.
//   celMeta (fixed size = 4 + shiftCount*3*2 + 2):
//       imageSize            LE32   compiled routine-image byte count
//       routineOffsets[shiftCount][3]  LE16 each, slot-relative
//                                      (0xFFFF == SPRITE_NOT_COMPILED)
//       relocCount           LE16   walker-address patch sites (ST only; 0 else)
//   image[imageSize]                 the pre-emitted routines
//   relocOffsets[relocCount]  LE16 each  image offsets to patch with the
//                                        4-byte big-endian &stSpriteDrawShiftWalker

// Atari ST shifted-phase DRAW thunk: `jmp abs.l stSpriteDrawShiftWalker`
// bakes the walker address (2 words, big-endian high-word-first) at
// thunk-relative offset +18. The bake tool records (routineOffsets[shift][DRAW]
// + this) for every shift with (shift & 7) != 0 that compiled.
#define SPC_ST_WALKER_JMP_OFFSET   18

#endif
