// Amiga per-surface planar storage, shared between the HAL
// (src/amiga/hal.c) and the cross-platform sprite dispatchers
// (src/codegen/spriteCompile.c) so plane-pointer access inlines
// instead of paying a cross-TU function call per plane (NATIVE-PERF
// Phase 2). Plane pointers are lifetime-immutable: portData is written
// only at surface create/destroy, so reading them needs no cache and
// no invalidation.
#ifndef JOEY_AMIGA_PLANAR_H
#define JOEY_AMIGA_PLANAR_H

#include <stdint.h>
#include <stdbool.h>

#include "surfaceInternal.h"

#define AMIGA_BITPLANES      4
#define AMIGA_BYTES_PER_ROW  (SURFACE_WIDTH / 8)
#define AMIGA_PLANE_SIZE     (AMIGA_BYTES_PER_ROW * SURFACE_HEIGHT)

// jlSurfaceT.portData points to this on Amiga: the 4 plane base
// pointers + stride. Every surface (including the stage, which gets
// its OWN shadow planes, NOT aliased to the displayed gPlanes) owns
// AllocMem(MEMF_CHIP) planes so the blitter can reach them; present
// copies shadow -> display planes atomically.
//
// Direct fields rather than a union because the consumer is asm /
// inline C that wants minimal indirection in the inner loop.
typedef struct {
    uint8_t *planes[AMIGA_BITPLANES];
    uint16_t bytesPerRow;       // = AMIGA_BYTES_PER_ROW (40)
    uint16_t bytesPerPlane;     // = AMIGA_PLANE_SIZE (8000)
    bool     ownsPlanes;        // true = AllocMem'd (free at destroy);
                                // false = aliased (don't free)
} AmigaPlanarT;


// NULL means "surface has no planar storage" -- callers use that as
// their route-to-generic / no-op gate, exactly the contract the old
// jlpSurfacePlanePtr cross-TU function provided.
static inline AmigaPlanarT *amigaSurfacePlanar(const jlSurfaceT *s) {
    return (AmigaPlanarT *)s->portData;
}

#endif
