65816-llvm-mos/runtime/include/iigs/resource.h
Scott Duensing 09f7405362 Updates
2026-06-03 16:08:42 -05:00

176 lines
6 KiB
C

// iigs/resource.h - typed-C facade over the IIgs Resource Manager.
//
// Phase 3.4 REAL implementation: parses .rsrc resource forks via the
// stdio surface (fopen/fread/fseek/fclose) and serves resources from a
// per-file cache. Read-only. No AddResource, no DetachResource, no
// partial-load, no encryption - those are features we do not yet need.
//
// What you GET today:
// - openResourceFile(path, accessByte, fileType) -> refNum (>0) or
// 0 on failure (errno-style code lands in *err if provided).
// - loadResource(type, id) -> Handle (void **) on success; cached so
// repeated calls return the same handle. *handle points at the
// resource bytes (already read from the file).
// - releaseResource(verb, handle) -> 0 on success. verb 0 just
// releases the current load; verb 1 also evicts the cache entry
// and frees the data.
// - closeResourceFile(refNum) -> 0 on success. Frees all cached
// handles owned by that file.
//
// On-disk format (Apple IIgs Toolbox Reference Vol 3, ch.42):
// File offset 0: rResourceMap header (24 bytes, little-endian fields
// because the 65816 is LE). Field rmToIndex is the file offset of
// the rIndex table; rmIndexUsed is the number of valid entries; the
// remaining header fields are bookkeeping/zero at build time.
// Body bytes: resource payloads at the offsets recorded in rIndex.
// At rmToIndex: array of 20-byte rIndex entries, each:
// uint16 rType, uint32 rID, uint32 rOffset, uint16 rAttr,
// uint32 rSize, uint32 rHandle (zero on disk).
//
// HLock semantics:
// The handles we return are NOT relocatable - they point straight at
// a malloc'd payload buffer. That means HLock/HUnlock are no-ops
// here. The void ** indirection is preserved so that real Memory
// Manager handles can swap in later without changing callers.
#ifndef IIGS_RESOURCE_H
#define IIGS_RESOURCE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
// Status codes returned by the typed wrappers. Mirror the runtime's
// existing errno-style convention (negative = error).
enum {
RES_OK = 0,
RES_ERR_BLOCKED = -1, // legacy stub marker - kept for
// backwards compat with old probes
RES_ERR_NOT_STARTED = -2, // openResourceFile not called yet
RES_ERR_NOT_FOUND = -3, // file open / resource lookup failed
RES_ERR_TOOLBOX = -4, // map header corrupt / IO failure
RES_ERR_NO_MEM = -5, // malloc failed
RES_ERR_BAD_HANDLE = -6 // release/close given an unknown ref
};
// Resource type codes we expect to bundle. See Apple IIgs Toolbox
// Reference Vol 3 chapter 42 for the canonical list.
#define RES_TYPE_RICON 0x8005
#define RES_TYPE_RTEXT 0x8014
#define RES_TYPE_RPSTRING 0x8015
#define RES_TYPE_RCSTRING 0x8016
// Build-time tunables. These cap the per-process resource footprint.
#ifndef IIGS_RES_MAX_FILES
#define IIGS_RES_MAX_FILES 2
#endif
#ifndef IIGS_RES_MAX_HANDLES
#define IIGS_RES_MAX_HANDLES 16
#endif
// Resource ID (32-bit on disk and in the rIndex).
typedef uint32_t IigsResIdT;
// Resource type code (16-bit; high bit reserved for system/extended
// types, low 15 bits for the actual code).
typedef uint16_t IigsResTypeT;
// 24-byte resource map header at the start of every .rsrc file.
typedef struct {
uint16_t rmVersion;
uint32_t rmToIndex;
uint16_t rmFileNum;
uint16_t rmID;
uint32_t rmIndexSize;
uint32_t rmIndexUsed;
uint16_t rmFreeListSize;
uint16_t rmFreeListUsed;
uint16_t rmPad;
} ResourceMapHeaderT;
// 20-byte rIndex entry.
typedef struct {
uint16_t rType;
uint32_t rID;
uint32_t rOffset;
uint16_t rAttr;
uint32_t rSize;
uint32_t rHandle;
} ResourceIndexEntryT;
// Refnum returned by openResourceFile. Zero means "no file"; valid
// refnums start at 1.
typedef uint16_t ResourceRefNumT;
// One-shot init. Returns RES_OK; safe to call more than once.
int resourceProbeInit(void);
// Reports whether the Resource Manager is alive. Always 1 after
// resourceProbeInit() has run.
int resourceRuntimeEnabled(void);
// Opens a resource fork at `path`. `accessByte` and `fileType` are
// accepted for API parity with the toolbox but ignored on read-only
// in-memory backends. Returns refnum (>0) on success, 0 on failure.
// If `err` is non-NULL it receives RES_OK or one of RES_ERR_*.
ResourceRefNumT openResourceFile(const char *path, uint8_t accessByte,
uint16_t fileType, int *err);
// Closes a resource fork and frees any handles cached for that file.
// Returns RES_OK or RES_ERR_BAD_HANDLE.
int closeResourceFile(ResourceRefNumT refNum);
// Loads a resource by (type, id). Searches all open resource files
// in open order and returns a cached handle if the same (type, id)
// was previously loaded from any open file. Returns NULL on failure.
//
// The returned handle is `void **`; `*handle` is the resource bytes.
void **loadResource(IigsResTypeT type, IigsResIdT id, int *err);
// Releases a previously-loaded resource.
// verb 0: keep the cached payload (cheap; the handle may be reused).
// verb 1: evict the cache entry and free the payload.
// Returns RES_OK on success.
int releaseResource(int verb, void **handle);
// Convenience: byte size of the resource pointed to by `handle`.
// Returns 0 if `handle` is not in the cache.
uint32_t getResourceSize(void **handle);
// ---- Legacy stub API kept for backwards compatibility ----
// The pre-Phase-3.4 stub exposed iigsLoadResource / iigsGetResourceSize
// for the rsrcProbe markers. Those now dispatch to the real
// implementation when at least one resource file is open. They report
// RES_ERR_NOT_STARTED when no file is open (instead of the old
// RES_ERR_BLOCKED), preserving the "did Phase 3.4 land?" signal.
void **iigsLoadResource(IigsResTypeT resType, IigsResIdT resId, int *err);
uint32_t iigsGetResourceSize(IigsResTypeT resType, IigsResIdT resId,
int *err);
#ifdef __cplusplus
}
#endif
#endif // IIGS_RESOURCE_H