176 lines
6 KiB
C
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
|