// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. // See LICENSE.md for license information. // SPDX-License-Identifier: MIT // // 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 #include #include "surfaceInternal.h" #define AMIGA_BITPLANES 4 #define AMIGA_BYTES_PER_ROW (JL_SURFACE_WIDTH / 8) #define AMIGA_PLANE_SIZE (AMIGA_BYTES_PER_ROW * JL_SURFACE_HEIGHT) // What a surface actually allocates per plane: one byte of slack past the end, // which src/m68k/planarFill.s relies on. See the note at the AllocMem in // jlpSurfaceAllocPortData. #define AMIGA_PLANE_ALLOC (AMIGA_PLANE_SIZE + 1u) // 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'd planes, in chip RAM where the blitter can reach them; a // surface other than the stage made when chip RAM has run out gets them // anywhere (chip false), and its fills and copies run on the CPU. 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) bool chip; // the planes are chip RAM: the blitter reaches them } 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