MWCC/command_line/CmdLine/Src/MacEmul/Resources.c

1672 lines
41 KiB
C

#include "mwcc_decomp.h"
#define OPTION_ASSERT(cond) do { if (!(cond)) { printf("%s:%u: failed assertion\n", __FILE__, __LINE__); abort(); } } while(0)
// Fork Attributes
enum {
mapReadOnly = 0x80,
mapCompact = 0x40,
mapChanged = 0x20
};
// Resources
enum {
resSysHeap = 0x40,
resPurgeable = 0x20,
resLocked = 0x10,
resProtected = 8,
resPreload = 4,
resChanged = 2
};
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct {
char sysdata[66];
char type[4];
char creator[4];
char sysdata2[38];
char appdata[128];
} MemRsrcSysData; // assumed name
typedef struct { // Resource Header
UInt32 data_offs;
UInt32 map_offs;
UInt32 data_len;
UInt32 map_len;
} Ty70;
typedef struct { // Resource Map
Ty70 mem_hdr;
Handle mem_next_map_handle; // fixme for 64-bit probably
SInt16 mem_refnum;
UInt16 fork_attr;
UInt16 typelist_offs;
UInt16 namelist_offs;
UInt16 types_idx;
} Ty73;
typedef struct { // Resource Type List Item
OSType type;
UInt16 rsrc_idx;
UInt16 ref_list_offs;
} Ty75;
typedef struct { // Reference List Item
UInt16 id;
UInt16 name_offs;
unsigned char attr;
unsigned char data_offs[3];
Handle mem_rsrc_handle;
} Ty77;
typedef struct { // Name List Item
unsigned char len;
} Ty80;
typedef struct { // Resource
UInt32 len;
} Ty82;
#ifdef __MWERKS__
#pragma options align=reset
#endif
typedef struct MemRefList {
UInt16 id;
OSType type;
StringPtr name;
unsigned char attr;
Handle hand;
struct MemRefList *next;
} MemRefList;
typedef struct MemRsrcTypeList {
OSType type;
MemRefList *ref_list;
struct MemRsrcTypeList *next;
} MemRsrcTypeList;
typedef struct MemRsrcMap {
SInt16 refnum;
UInt16 fork_attr;
MemRsrcTypeList *type_list;
MemRsrcSysData sys_data;
struct MemRsrcMap *prev;
} MemRsrcMap;
typedef struct ResRef {
OSSpec spec;
int ref;
struct ResRef *next;
} ResRef;
static OSErr resError;
static SInt16 cur_res_file;
Boolean ResLoad;
static MemRsrcMap *maplist;
static ResRef *resForkList;
static ResRef *resForkLast;
static Boolean UseResourceForkInfo;
// Forward declarations
static void ReadResourceFork(SInt16 ref, SInt8 permission, void *file_data, SInt32 file_size);
Boolean OS_UsingMacResourceForkInfo() {
return UseResourceForkInfo;
}
void OS_UseMacResourceForkInfo(Boolean which) {
UseResourceForkInfo = which;
}
OSErr SystemInitResources(OSSpec *spec) {
FSSpec prog;
void *file_data;
SInt32 file_len;
maplist = 0;
cur_res_file = 0;
if (!OS_LoadMacResourceFork(spec, &file_data, &file_len)) {
ReadResourceFork(-1, 1, file_data, file_len);
cur_res_file = -1;
resError = noErr;
return noErr;
} else {
if (!OS_OSSpec_To_FSSpec(spec, &prog) && !FSpOpenResFile(&prog, 1)) {
resError = noErr;
return noErr;
} else {
resError = fnfErr;
return fnfErr;
}
}
}
static MemRsrcMap *NewResourceMap(SInt16 ref, UInt16 attr, MemRsrcTypeList *list, void *unk) {
MemRsrcMap **scan;
MemRsrcMap *nw;
scan = &maplist;
nw = malloc(sizeof(MemRsrcMap));
if (!nw) {
resError = memFullErr;
return 0;
}
nw->refnum = ref;
nw->fork_attr = attr;
nw->type_list = list;
nw->prev = *scan;
*scan = nw;
return nw;
}
static MemRsrcTypeList *NewTypeListEntry(MemRsrcTypeList **scan, OSType type, MemRefList *list, MemRsrcTypeList *next) {
MemRsrcTypeList *nw;
while (*scan)
scan = &(*scan)->next;
nw = malloc(sizeof(MemRsrcTypeList));
if (!nw) {
resError = memFullErr;
return 0;
}
nw->type = type;
nw->ref_list = list;
nw->next = next;
*scan = nw;
return nw;
}
static MemRefList *NewRefListEntry(MemRefList **scan, UInt16 id, OSType type, StringPtr name, unsigned char attr, Handle hand) {
MemRefList *prev;
MemRefList *nw;
char mname[256];
prev = 0;
if (name)
p2cstrcpy(mname, name);
else
strcpy(mname, "(none)");
while (*scan && (*scan)->id != id) {
prev = *scan;
scan = &(*scan)->next;
}
nw = malloc(sizeof(MemRefList));
if (!nw) {
resError = memFullErr;
return 0;
}
nw->id = id;
nw->type = type;
nw->name = name;
nw->attr = attr;
nw->hand = hand;
if (prev) {
nw->next = prev->next;
prev->next = nw;
} else {
nw->next = 0;
}
*scan = nw;
return nw;
}
static MemRsrcMap *FindResourceMap(SInt16 ref) {
MemRsrcMap *list = maplist;
while (list) {
if (list->refnum == ref)
return list;
list = list->prev;
}
return 0;
}
static MemRsrcMap *FindResourceMap2(SInt16 ref, MemRsrcMap **next) {
MemRsrcMap *list = maplist;
*next = 0;
while (list) {
if (list->refnum == ref)
return list;
*next = list;
list = list->prev;
}
return 0;
}
static void DeleteResources(SInt16 refNum) {
MemRsrcMap *rm, *rmnext;
MemRsrcTypeList *mtyptmp, *mtyp;
MemRefList *mrletmp, *mrle;
rm = FindResourceMap2(refNum, &rmnext);
if (rm) {
mtyp = rm->type_list;
while (mtyp) {
mrle = mtyp->ref_list;
while (mrle) {
if (mrle->hand)
DisposeHandle(mrle->hand);
if (mrle->name)
free(mrle->name);
mrletmp = mrle;
mrle = mrle->next;
free(mrletmp);
}
mtyptmp = mtyp;
mtyp = mtyp->next;
free(mtyptmp);
}
if (rmnext)
rmnext->prev = rm->prev;
else
maplist = rm->prev;
free(rm);
}
}
#define RF_READ(buf, offset, count, failBranch) \
do { \
SInt32 __offs = (offset); \
if (!file_data) { \
if ((resError = SetFPos(ref, fsFromStart, __offs)) != noErr) goto failBranch; \
if ((resError = FSRead(ref, (SInt32 *) &(count), buf)) != noErr) goto failBranch; \
} else { \
if ((__offs + (count)) > file_size) goto failBranch; \
memcpy(buf, ((unsigned char *) file_data) + __offs, (count)); \
} \
} while(0)
static void ReadResourceFork(SInt16 ref, SInt8 permission, void *file_data, SInt32 file_size) {
MemRsrcMap *rm;
Ty70 thdr;
Ty70 *dhdr;
MemRsrcSysData tsys;
MemRsrcSysData *dsys;
Ty73 *dmap;
Ty75 *dtyp;
Ty77 *drle;
Ty80 *dnam;
void *buffer;
SInt32 msize;
SInt32 cnt;
SInt32 ref_offs;
int rcnt;
MemRsrcTypeList *mtyp;
Ty82 tent;
SInt32 esize;
SInt32 offs;
Handle hand;
unsigned char *name;
unsigned char *nameptr;
if (!file_data) {
if ((resError = GetEOF(ref, &file_size)) != noErr)
goto mapFail;
}
if (file_size < 90)
goto mapFail;
cnt = sizeof(Ty70);
RF_READ(&thdr, 0, cnt, mapFail);
ref_offs = cnt;
cnt = ((thdr.map_offs < thdr.data_offs) ? thdr.map_offs : thdr.data_offs) - sizeof(Ty70);
if (cnt > sizeof(MemRsrcSysData))
cnt = sizeof(MemRsrcSysData);
RF_READ(&tsys, ref_offs, cnt, mapFail);
msize = thdr.map_len;
buffer = malloc(msize);
if (!buffer)
goto memFail;
ref_offs = thdr.map_offs;
RF_READ(buffer, ref_offs, msize, mapFail);
if (
(thdr.map_offs > file_size)
|| ((thdr.map_offs + thdr.map_len) > file_size)
|| (thdr.data_offs > file_size)
|| ((thdr.data_offs + thdr.data_len) > file_size)
|| ((thdr.map_offs < thdr.data_offs) ? ((thdr.map_offs + thdr.map_len) != thdr.data_offs) : ((thdr.data_offs + thdr.data_len) != thdr.map_offs))
)
goto mapFail;
rm = NewResourceMap(ref, ((permission == 1) ? mapReadOnly : 0) | mapCompact, 0, 0);
if (!rm)
goto memFail;
rm->sys_data = tsys;
dmap = (Ty73 *) buffer;
if ((dmap->typelist_offs + thdr.map_offs) > file_size)
goto freeAndMapFail;
dtyp = (Ty75 *) (((unsigned char *) buffer) + dmap->typelist_offs + 2);
if ((dmap->namelist_offs + thdr.map_offs) > file_size)
goto freeAndMapFail;
dnam = (Ty80 *) (((unsigned char *) buffer) + dmap->namelist_offs);
if (dmap->types_idx != 0xFFFF) {
for (cnt = 0; cnt <= dmap->types_idx; cnt++) {
mtyp = NewTypeListEntry(&rm->type_list, dtyp[cnt].type, 0, 0);
if (!mtyp)
goto freeAndReturn;
if ((thdr.map_offs + dmap->typelist_offs + dtyp[cnt].ref_list_offs) > file_size)
goto freeAndMapFail;
drle = (Ty77 *) (((unsigned char *) dtyp) + dtyp[cnt].ref_list_offs - 2);
if (dtyp[cnt].rsrc_idx != 0xFFFF) {
for (rcnt = 0; rcnt <= dtyp[cnt].rsrc_idx; rcnt++) {
ref_offs = (drle[rcnt].data_offs[0] << 16) | (drle[rcnt].data_offs[1] << 8) | drle[rcnt].data_offs[2];
offs = thdr.data_offs + ref_offs;
if (offs > file_size)
goto freeAndMapFail;
esize = 4;
RF_READ(&tent, offs, esize, freeAndMapFail);
offs += esize;
if ((thdr.data_offs + ref_offs + tent.len) > file_size)
goto freeAndMapFail;
hand = NewHandle(tent.len);
if (!hand)
goto freeAndMapFail;
HLock(hand);
RF_READ(*hand, offs, tent.len, freeAndMapFail);
HUnlock(hand);
if (drle[rcnt].name_offs != 0xFFFF) {
nameptr = (StringPtr) (dnam + drle[rcnt].name_offs);
name = malloc(nameptr[0] + 1);
memcpy(name, nameptr, nameptr[0] + 1);
} else {
name = 0;
}
if (!NewRefListEntry(&mtyp->ref_list, drle[rcnt].id, dtyp[cnt].type, name, drle[rcnt].attr, hand))
goto freeAndReturn;
}
}
}
}
free(buffer);
resError = noErr;
return;
freeAndMapFail:
resError = mapReadErr;
freeAndReturn:
DeleteResources(ref);
if (buffer)
free(buffer);
return;
memFail:
resError = memFullErr;
return;
mapFail:
resError = mapReadErr;
}
static void GetResourceSizes(MemRsrcMap *rm, SInt32 *data_size, SInt32 *name_size, SInt32 *reflist_size, SInt32 *typelist_size) {
MemRsrcTypeList *mtyp;
MemRefList *mrle;
*data_size = *name_size = *reflist_size = *typelist_size = 0;
mtyp = rm->type_list;
while (mtyp) {
mrle = mtyp->ref_list;
while (mrle) {
*name_size += !mrle->name ? 0 : (mrle->name[0] + 1);
*data_size += (!mrle->hand ? 0 : GetHandleSize(mrle->hand)) + 4;
*reflist_size += 12;
mrle = mrle->next;
}
*typelist_size += 8;
mtyp = mtyp->next;
}
}
static SInt32 GetResourceTypesCount(MemRsrcMap *dm) {
SInt32 tmp;
MemRsrcTypeList *mtyp;
tmp = 0;
mtyp = dm->type_list;
while (mtyp) {
mtyp = mtyp->next;
++tmp;
}
return tmp;
}
static SInt32 GetResourceEntriesCount(MemRsrcTypeList *mtyp) {
SInt32 tmp;
MemRefList *mrle;
tmp = 0;
mrle = mtyp->ref_list;
while (mrle) {
mrle = mrle->next;
++tmp;
}
return tmp;
}
#define RF_HANDLE_INSERT(hand, what, offset, size) \
do { \
SInt32 __offs = (offset); \
SInt32 __len = (size); \
if ((SInt32) (__offs + __len) > GetHandleSize(hand)) { \
resError = mapReadErr; \
return; \
} else { \
memcpy(*hand + __offs, (what), __len); \
} \
} \
while (0)
static void WriteResourceFork(SInt16 ref) {
MemRsrcMap *rm;
Ty70 dhdr;
Ty70 thdr;
MemRsrcSysData tsys;
Ty73 dmap;
Ty73 tmap;
Handle hand_ref;
SInt32 reflist_size, typelist_size;
SInt32 name_size, data_size;
SInt32 reflist_offs, typelist_offs;
SInt32 name_offs, data_offs;
MemRsrcTypeList *mtyp;
Ty75 dtyp;
Ty75 ttyp;
MemRefList *mrle;
Ty77 drle;
Ty77 trle;
Ty82 dent;
Ty82 tent;
SInt32 sz;
rm = FindResourceMap(ref);
if (!rm) {
resError = resFNotFound;
return;
}
if (rm->refnum == -1) {
resError = resFNotFound;
return;
}
if (rm->fork_attr & mapReadOnly) {
resError = resAttrErr;
return;
}
if (!(rm->fork_attr & mapChanged)) {
return;
}
GetResourceSizes(rm, &data_size, &name_size, &reflist_size, &typelist_size);
dhdr.data_offs = sizeof(dhdr) + sizeof(tsys);
dhdr.data_len = data_size;
dhdr.map_offs = sizeof(dhdr) + sizeof(tsys) + data_size;
dhdr.map_len = name_size + reflist_size + typelist_size + sizeof(dmap);
hand_ref = NewHandle(dhdr.map_offs + dhdr.map_len);
if (!hand_ref) {
resError = MemError();
return;
}
HLock(hand_ref);
memset(*hand_ref, 0, dhdr.map_offs + dhdr.map_len);
thdr = dhdr;
// This is where it would be endian-swapped i guess
RF_HANDLE_INSERT(hand_ref, &thdr, 0, sizeof(thdr));
tsys = rm->sys_data;
RF_HANDLE_INSERT(hand_ref, &tsys, sizeof(thdr), sizeof(tsys));
dmap.mem_hdr = thdr;
dmap.mem_next_map_handle = 0;
dmap.mem_refnum = 0;
dmap.fork_attr = rm->fork_attr & ~resChanged; // bug! should be mapChanged
dmap.typelist_offs = sizeof(dmap) - 2;
dmap.namelist_offs = typelist_size + reflist_size + sizeof(dmap);
dmap.types_idx = GetResourceTypesCount(rm) - 1;
tmap = dmap;
RF_HANDLE_INSERT(hand_ref, &tmap, dhdr.map_offs, sizeof(tmap));
// Now write the actual shit
name_offs = 0;
data_offs = 0;
reflist_offs = 0;
typelist_offs = 0;
mtyp = rm->type_list;
while (mtyp) {
dtyp.type = mtyp->type;
dtyp.rsrc_idx = GetResourceEntriesCount(mtyp) - 1;
dtyp.ref_list_offs = typelist_size + reflist_offs + 2;
ttyp = dtyp;
RF_HANDLE_INSERT(hand_ref, &ttyp, (dhdr.map_offs + dmap.typelist_offs + 2) + typelist_offs, sizeof(ttyp));
mrle = mtyp->ref_list;
while (mrle) {
#line 943
OPTION_ASSERT(reflist_offs < dmap.namelist_offs);
drle.id = mrle->id;
drle.name_offs = (mrle->name) ? name_offs : -1;
drle.attr = mrle->attr & ~resChanged;
drle.data_offs[0] = (data_offs & 0xFF0000) >> 16;
drle.data_offs[1] = (data_offs & 0x00FF00) >> 8;
drle.data_offs[2] = (data_offs & 0x0000FF);
drle.mem_rsrc_handle = 0;
trle = drle;
RF_HANDLE_INSERT(hand_ref, &trle, (dhdr.map_offs + dmap.typelist_offs + 2) + typelist_size + reflist_offs, sizeof(trle));
reflist_offs += sizeof(trle);
if (mrle->name) {
#line 962
if (dhdr.map_offs < dhdr.data_offs)
OPTION_ASSERT(name_offs + dmap.namelist_offs + dhdr.map_offs < dhdr.data_offs);
RF_HANDLE_INSERT(hand_ref, mrle->name, dhdr.map_offs + dmap.namelist_offs + drle.name_offs, mrle->name[0] + 1);
name_offs += mrle->name[0] + 1;
}
#line 970
OPTION_ASSERT(data_offs < dhdr.data_len);
OPTION_ASSERT(mrle->hand!=NULL);
if (dhdr.map_offs > dhdr.data_offs)
OPTION_ASSERT(data_offs + dhdr.data_offs < dhdr.map_offs);
HLock(mrle->hand);
dent.len = GetHandleSize(mrle->hand);
tent = dent;
RF_HANDLE_INSERT(hand_ref, &tent, dhdr.data_offs + data_offs, sizeof(tent));
data_offs += sizeof(tent);
RF_HANDLE_INSERT(hand_ref, *mrle->hand, dhdr.data_offs + data_offs, dent.len);
data_offs += dent.len;
HUnlock(mrle->hand);
mrle = mrle->next;
}
mtyp = mtyp->next;
typelist_offs += sizeof(ttyp);
}
sz = GetHandleSize(hand_ref);
if ((resError = SetFPos(ref, fsFromStart, 0)) != noErr)
return;
if ((resError = SetEOF(ref, sz)) != noErr)
return;
if ((resError = FSWrite(ref, &sz, *hand_ref)) != noErr)
return;
HUnlock(hand_ref);
DisposeHandle(hand_ref);
}
static void WriteEmptyResourceFork(SInt16 ref) {
Ty70 dhdr;
MemRsrcSysData dsys;
Ty73 dmap;
Handle hand_ref;
SInt32 sz;
dhdr.map_offs = sizeof(dhdr) + sizeof(dsys);
dhdr.map_len = sizeof(dmap);
dhdr.data_offs = sizeof(dhdr) + sizeof(dsys) + sizeof(dmap);
dhdr.data_len = 0;
memset(&dsys, 0, sizeof(dsys));
memset(&dsys.creator, 0, sizeof(dsys.creator));
memset(&dsys.type, 0, sizeof(dsys.type));
dmap.mem_hdr = dhdr;
dmap.mem_next_map_handle = 0;
dmap.mem_refnum = 0;
dmap.fork_attr = 0;
dmap.typelist_offs = sizeof(dmap) - 2;
dmap.namelist_offs = sizeof(dmap) - 2;
dmap.types_idx = 0xFFFF;
hand_ref = NewHandle(sizeof(dhdr) + sizeof(dsys) + sizeof(dmap));
if (!hand_ref) {
resError = MemError();
return;
}
HLock(hand_ref);
memset(*hand_ref, 0, sizeof(dhdr) + sizeof(dsys) + sizeof(dmap));
RF_HANDLE_INSERT(hand_ref, &dhdr, 0, sizeof(dhdr));
RF_HANDLE_INSERT(hand_ref, &dsys, sizeof(dhdr), sizeof(dsys));
RF_HANDLE_INSERT(hand_ref, &dmap, sizeof(dhdr) + sizeof(dsys), sizeof(dmap));
sz = GetHandleSize(hand_ref);
if ((resError = SetFPos(ref, fsFromStart, 0)) != noErr)
return;
if ((resError = SetEOF(ref, sz)) != noErr)
return;
if ((resError = FSWrite(ref, &sz, *hand_ref)) != noErr)
return;
HUnlock(hand_ref);
DisposeHandle(hand_ref);
}
static MemRsrcTypeList *FindResourceType1(MemRsrcMap *rm, OSType theType) {
MemRsrcTypeList *mtyp;
mtyp = rm->type_list;
while (mtyp) {
if (mtyp->type == theType)
return mtyp;
mtyp = mtyp->next;
}
return 0;
}
static SInt32 CountResourceType1(MemRsrcMap *rm, OSType theType) {
MemRsrcTypeList *mtyp;
mtyp = rm->type_list;
while (mtyp) {
if (mtyp->type == theType)
return GetResourceEntriesCount(mtyp);
mtyp = mtyp->next;
}
return 0;
}
static SInt32 CountResourceType(OSType theType) {
MemRsrcMap *rm;
SInt32 total;
total = 0;
rm = FindResourceMap(cur_res_file);
while (rm) {
total += CountResourceType1(rm, theType);
rm = rm->prev;
}
return total;
}
static MemRefList *FindIndResource1(MemRsrcMap *rm, OSType theType, SInt16 index) {
MemRsrcTypeList *mtyp;
MemRefList *mrle;
mtyp = rm->type_list;
while (mtyp) {
if (mtyp->type == theType) {
mrle = mtyp->ref_list;
while (mrle && --index > 0) {
mrle = mrle->next;
}
return mrle;
}
mtyp = mtyp->next;
}
return 0;
}
static MemRefList *FindIndResource(OSType theType, SInt16 index) {
MemRsrcMap *rm = FindResourceMap(cur_res_file);
MemRefList *mrle;
while (rm) {
mrle = FindIndResource1(rm, theType, index);
if (mrle)
return mrle;
rm = rm->prev;
}
return 0;
}
static MemRefList *FindResourceTypeAndID1(MemRsrcMap *rm, OSType theType, SInt16 theID) {
MemRsrcTypeList *mtyp = FindResourceType1(rm, theType);
MemRefList *mref;
if (mtyp) {
mref = mtyp->ref_list;
while (mref) {
if (mref->id == theID)
return mref;
mref = mref->next;
}
}
return 0;
}
static MemRefList *FindResourceTypeAndID(OSType theType, SInt16 theID) {
MemRsrcMap *rm = FindResourceMap(cur_res_file);
MemRefList *mref;
while (rm) {
mref = FindResourceTypeAndID1(rm, theType, theID);
if (mref)
return mref;
rm = rm->prev;
}
return 0;
}
static MemRefList *FindResourceTypeAndName1(MemRsrcMap *rm, OSType theType, ConstStringPtr theName) {
MemRsrcTypeList *mtyp;
MemRefList *mref;
mtyp = FindResourceType1(rm, theType);
if (mtyp) {
mref = mtyp->ref_list;
while (mref) {
if (mref->name && EqualString(mref->name, theName, 0, 0))
return mref;
mref = mref->next;
}
}
return 0;
}
static MemRefList *FindResourceTypeAndName(OSType theType, ConstStringPtr theName) {
MemRsrcMap *rm = FindResourceMap(cur_res_file);
MemRefList *mref;
while (rm) {
mref = FindResourceTypeAndName1(rm, theType, theName);
if (mref)
return mref;
rm = rm->prev;
}
return 0;
}
static MemRefList *FindResourceHandle1(MemRsrcMap *rm, Handle theResource) {
MemRsrcTypeList *mtyp;
MemRefList *mrle;
for (mtyp = rm->type_list; mtyp; mtyp = mtyp->next) {
for (mrle = mtyp->ref_list; mrle; mrle = mrle->next) {
if (mrle->hand == theResource)
return mrle;
}
}
return 0;
}
static MemRefList *FindResourceHandle(Handle theResource) {
MemRsrcMap *rm;
MemRefList *mrle;
for (rm = FindResourceMap(cur_res_file); rm; rm = rm->prev) {
mrle = FindResourceHandle1(rm, theResource);
if (mrle)
return mrle;
}
return 0;
}
static int RemoveResourceHandle1(MemRsrcMap *rm, Handle theResource) {
MemRsrcTypeList *mtyp, *pmtyp;
MemRefList *mrle, *pmrle;
mtyp = rm->type_list;
pmtyp = 0;
while (mtyp) {
mrle = mtyp->ref_list;
pmrle = 0;
while (mrle) {
if (mrle->hand == theResource) {
if (pmrle)
pmrle->next = mrle->next;
else
mtyp->ref_list = mrle->next;
free(mrle);
if (!mtyp->ref_list) {
if (pmtyp)
pmtyp->next = mtyp->next;
else
rm->type_list = mtyp->next;
free(mtyp);
}
return 1;
}
pmrle = mrle;
mrle = mrle->next;
}
pmtyp = mtyp;
mtyp = mtyp->next;
}
return 0;
}
static int RemoveResourceHandle(Handle theResource) {
MemRsrcMap *rm;
for (rm = FindResourceMap(cur_res_file); rm; rm = rm->prev) {
if (RemoveResourceHandle1(rm, theResource))
return 1;
}
return 0;
}
static SInt16 FindResourceHandleFile1(MemRsrcMap *rm, Handle theResource) {
MemRsrcTypeList *mtyp;
MemRefList *mrle;
for (mtyp = rm->type_list; mtyp; mtyp = mtyp->next) {
for (mrle = mtyp->ref_list; mrle; mrle = mrle->next) {
if (mrle->hand == theResource)
return rm->refnum;
}
}
return -1;
}
static SInt16 FindResourceHandleFile(Handle theResource) {
MemRsrcMap *rm;
MemRefList *mrle;
for (rm = FindResourceMap(cur_res_file); rm; rm = rm->prev) {
mrle = FindResourceHandle1(rm, theResource);
if (mrle)
return rm->refnum;
}
return -1;
}
void OS_AddMacResourceForkRef(int ref, const OSSpec *spec) {
ResRef *nw;
nw = malloc(sizeof(ResRef));
if (nw) {
nw->spec = *spec;
nw->ref = ref;
nw->next = 0;
if (resForkLast)
resForkLast->next = nw;
else
resForkList = nw;
resForkLast = nw;
}
}
void OS_RemoveMacResourceForkRef(int ref) {
ResRef *lst;
ResRef *prev;
lst = resForkList;
prev = 0;
while (lst && lst->ref != ref) {
prev = lst;
lst = lst->next;
}
if (lst) {
if (prev) {
prev->next = lst->next;
if (!prev->next)
resForkLast = prev;
} else {
resForkList = lst->next;
if (!resForkList)
resForkLast = 0;
}
free(lst);
}
}
OSSpec *OS_GetMacResourceForkFromRef(int ref) {
ResRef *lst;
for (lst = resForkList; lst; lst = lst->next) {
if (lst->ref == ref)
return &lst->spec;
}
return 0;
}
Boolean OS_SearchMacResourceForkList(const OSSpec *rspec, int *ref) {
ResRef *lst;
for (lst = resForkList; lst; lst = lst->next) {
if (OS_EqualSpec(&lst->spec, rspec)) {
*ref = lst->ref;
return 1;
}
}
return 0;
}
int OS_SetMacResourceForkCreatorAndType(int ref, OSType creator, OSType type) {
int err;
UInt32 buf[2];
UInt32 sz;
MemRsrcMap *rm;
if (!OS_GetMacResourceForkFromRef(ref)) {
sz = 8;
buf[0] = type;
buf[1] = creator;
err = OS_Seek(ref, OSSeekAbs, 0x52);
if (!err) {
err = OS_Write(ref, buf, &sz);
if (!err && sz == 8) {
err = 0;
}
}
} else {
rm = FindResourceMap(OS_RefToMac(ref));
if (!rm) {
err = 2;
} else if (rm->fork_attr & mapReadOnly) {
err = 13;
} else {
rm->sys_data.creator[0] = (creator & 0xFF000000) >> 24;
rm->sys_data.creator[1] = (creator & 0x00FF0000) >> 16;
rm->sys_data.creator[2] = (creator & 0x0000FF00) >> 8;
rm->sys_data.creator[3] = (creator & 0x000000FF);
rm->sys_data.type[0] = (type & 0xFF000000) >> 24;
rm->sys_data.type[1] = (type & 0x00FF0000) >> 16;
rm->sys_data.type[2] = (type & 0x0000FF00) >> 8;
rm->sys_data.type[3] = (type & 0x000000FF);
rm->fork_attr |= mapChanged;
err = 0;
}
}
return err;
}
int OS_GetMacResourceForkCreatorAndType(int ref, OSType *creator, OSType *type) {
int err;
UInt32 buf[2];
UInt32 sz;
MemRsrcMap *rm;
if (!OS_GetMacResourceForkFromRef(ref)) {
sz = 8;
err = OS_Seek(ref, OSSeekAbs, 0x52);
if (!err) {
err = OS_Read(ref, buf, &sz);
if (!err && sz == 8) {
err = 0;
*type = buf[0];
*creator = buf[1];
}
}
} else {
rm = FindResourceMap(OS_RefToMac(ref));
if (!rm) {
err = 2;
} else {
*creator = (rm->sys_data.creator[0] << 24) | (rm->sys_data.creator[1] << 16) | (rm->sys_data.creator[2] << 8) | rm->sys_data.creator[3];
*type = (rm->sys_data.type[0] << 24) | (rm->sys_data.type[1] << 16) | (rm->sys_data.type[2] << 8) | rm->sys_data.type[3];
err = 0;
}
}
return err;
}
void OS_CleanupMacResourceForkDir(const OSPathSpec *dir) {
OS_Rmdir(dir);
}
OSErr OS_MacDumpResourceFork(SInt16 ref, Boolean dumpContents) {
MemRsrcMap *rm;
MemRsrcTypeList *tl;
MemRefList *rl;
char name[256];
unsigned char *ptr;
SInt32 idx;
SInt32 size;
char safe[16];
int spaces;
rm = FindResourceMap(ref);
if (!rm) {
fprintf(stderr, "Could not find resource fork for ref = %d\n", ref);
return fnfErr;
}
printf("Fork attributes = %04X\n", rm->fork_attr);
printf("Creator = '%4.4s'; Type = '%4.4s'\n", rm->sys_data.creator, rm->sys_data.type);
printf("Types:\n");
for (tl = rm->type_list; tl; tl = tl->next) {
printf("'%c%c%c%c':\n",
(tl->type & 0xFF000000) >> 24,
(tl->type & 0x00FF0000) >> 16,
(tl->type & 0x0000FF00) >> 8,
(tl->type & 0x000000FF)
);
for (rl = tl->ref_list; rl; rl = rl->next) {
if (rl->type != tl->type)
printf("!!! RefList type '%c%c%c%c' does not match TypeList type !!!\n",
(rl->type & 0xFF000000) >> 24,
(rl->type & 0x00FF0000) >> 16,
(rl->type & 0x0000FF00) >> 8,
(rl->type & 0x000000FF)
);
if (rl->name)
p2cstrcpy(name, rl->name);
else
strcpy(name, "<none>");
printf("\tID = %d '%s'\n", rl->id, name);
printf("\tAttributes: ");
if (rl->attr & resSysHeap)
printf("SysHeap ");
if (rl->attr & resPurgeable)
printf("Purgeable ");
if (rl->attr & resLocked)
printf("Locked ");
if (rl->attr & resProtected)
printf("Protected ");
if (rl->attr & resPreload)
printf("Preload ");
if (rl->attr & resChanged)
printf("Changed ");
printf("\n");
if (dumpContents) {
size = GetHandleSize(rl->hand);
HLock(rl->hand);
ptr = (unsigned char *) *rl->hand;
idx = 0;
printf("Contents:");
while (idx < size) {
if ((idx % 16) == 0) {
printf("\n%08X: ", idx);
memset(safe, ' ', 16);
}
printf("%02X ", ptr[idx]);
if (isprint(ptr[idx]))
safe[idx & 15] = ptr[idx];
else
safe[idx & 15] = '.';
if (((idx % 16) == 15) || (idx + 1) == size) {
spaces = (((idx & 15) + 15) & ~15) - (idx & 15);
while (spaces--)
printf(" ");
printf(" %16.16s", safe);
}
++idx;
}
printf("\n");
}
}
}
printf("\n");
CloseResFile(ref);
return noErr;
}
OSErr FSpOpenRF(const FSSpec *fss, SInt8 permission, SInt16 *refNum) {
OSErr err;
int oserr;
FSSpec rfss;
OSSpec spec, rspec;
Boolean create;
create = (permission != fsRdPerm);
oserr = OS_FSSpec_To_OSSpec(fss, &spec);
if (oserr)
return OS_MacError(oserr);
oserr = OS_GetRsrcOSSpec(&spec, &rspec, create);
if (oserr)
return OS_MacError(oserr);
oserr = OS_OSSpec_To_FSSpec(&rspec, &rfss);
if (oserr)
return OS_MacError(oserr);
if (OS_Status(&rspec) && create)
HCreate(rfss.vRefNum, rfss.parID, rfss.name, 'CWIE', 'rsrc');
err = HOpen(rfss.vRefNum, rfss.parID, rfss.name, permission, refNum);
if (!err)
OS_AddMacResourceForkRef(OS_MacToRef(*refNum), &rspec);
return err;
}
OSErr HOpenRF(SInt16 vRefNum, SInt32 dirID, ConstStringPtr fileName, SInt8 permission, SInt16 *refNum) {
FSSpec fss;
OSErr __err;
__err = FSMakeFSSpec(vRefNum, dirID, fileName, &fss);
if (__err != noErr && __err != fnfErr) {
return __err;
} else {
return FSpOpenRF(&fss, permission, refNum);
}
}
OSErr InitResources() {
MemRsrcMap *map;
map = maplist;
cur_res_file = 0;
while (map) {
cur_res_file = map->refnum;
map = map->prev;
}
ResLoad = 1;
resError = noErr;
return 0;
}
OSErr ResError() {
return resError;
}
void FSpCreateResFile(const FSSpec *fss, OSType creator, OSType fileType, ScriptCode scriptTag) {
int oserr;
OSSpec spec, rspec;
SInt16 ref;
FSpCreate(fss, creator, fileType, scriptTag);
oserr = OS_FSSpec_To_OSSpec(fss, &spec);
if (oserr) {
resError = OS_MacError(oserr);
return;
}
oserr = OS_GetRsrcOSSpec(&spec, &rspec, 1);
if (oserr) {
resError = OS_MacError(oserr);
return;
}
if (OS_Status(&rspec)) {
oserr = OS_Create(&rspec, &OS_TEXTTYPE);
if (oserr) {
resError = OS_MacError(oserr);
return;
}
resError = FSpOpenRF(fss, 3, &ref);
if (!resError) {
WriteEmptyResourceFork(ref);
FSClose(ref);
}
} else {
resError = dupFNErr;
}
}
void HCreateResFile(SInt16 vRefNum, SInt32 dirID, ConstStringPtr fileName) {
FSSpec fss;
OSErr __err;
__err = FSMakeFSSpec(vRefNum, dirID, fileName, &fss);
if (__err != noErr && __err != fnfErr) {
resError = __err;
} else {
FSpCreateResFile(&fss, 'CWIE', kUnknownType, -1);
}
}
OSErr FSpOpenResFile(const FSSpec *fss, SInt8 permission) {
SInt16 ref;
SInt32 size;
if (permission != fsRdPerm)
FSpCreate(fss, 'CWIE', 'TEXT', -1);
resError = FSpOpenRF(fss, (permission == fsWrPerm) ? fsRdWrPerm : permission, &ref);
if (!resError) {
GetEOF(ref, &size);
if (size == 0 && permission != fsRdPerm)
WriteEmptyResourceFork(ref);
ReadResourceFork(ref, permission, 0, 0);
if (resError) {
FSClose(ref);
CloseResFile(ref);
ref = -1;
}
cur_res_file = ref;
} else {
ref = -1;
}
return ref;
}
OSErr HOpenResFile(SInt16 vRefNum, SInt32 dirID, ConstStringPtr fileName, SInt8 permission) {
FSSpec fss;
OSErr __err;
__err = FSMakeFSSpec(vRefNum, dirID, fileName, &fss);
if (__err != noErr && __err != fnfErr)
return __err;
return FSpOpenResFile(&fss, permission);
}
SInt16 CurResFile() {
return cur_res_file;
}
void UseResFile(SInt16 refNum) {
MemRsrcMap *map;
for (map = maplist; map; map = map->prev) {
if (map->refnum == refNum) {
cur_res_file = refNum;
resError = noErr;
return;
}
}
resError = resFNotFound;
}
SInt16 HomeResFile(Handle theResource) {
SInt16 refnum = FindResourceHandleFile(theResource);
resError = (refnum == -1) ? resNotFound : 0;
return refnum;
}
Handle GetResource(OSType theType, SInt16 theID) {
MemRefList *mref;
mref = FindResourceTypeAndID(theType, theID);
if (mref) {
resError = noErr;
return mref->hand;
} else {
resError = ResLoad ? resNotFound : noErr;
return 0;
}
}
Handle Get1Resource(OSType theType, SInt16 theID) {
MemRsrcMap *rm;
MemRefList *mref;
rm = FindResourceMap(cur_res_file);
if (!rm) {
resError = resFNotFound;
return 0;
}
mref = FindResourceTypeAndID1(rm, theType, theID);
if (mref) {
resError = noErr;
return mref->hand;
} else {
resError = ResLoad ? resNotFound : noErr;
return 0;
}
}
Handle GetNamedResource(OSType theType, ConstStringPtr theName) {
MemRefList *mref;
mref = FindResourceTypeAndName(theType, theName);
if (mref) {
resError = noErr;
return mref->hand;
} else {
resError = ResLoad ? resNotFound : noErr;
return 0;
}
}
Handle Get1NamedResource(OSType theType, ConstStringPtr theName) {
MemRsrcMap *rm;
MemRefList *mref;
rm = FindResourceMap(cur_res_file);
if (!rm) {
resError = resFNotFound;
return 0;
}
mref = FindResourceTypeAndName1(rm, theType, theName);
if (mref) {
resError = noErr;
return mref->hand;
} else {
resError = (ResLoad != 0) ? resNotFound : noErr;
return 0;
}
}
void SetResLoad(Boolean load) {
ResLoad = load;
}
void MacEmul_LoadResource(Handle theResource) {
resError = (theResource == 0) ? nilHandleErr : 0;
}
void GetResInfo(Handle theResource, SInt16 *theID, OSType *theType, StringPtr name) {
MemRefList *mrle;
mrle = FindResourceHandle(theResource);
if (mrle) {
resError = noErr;
*theID = mrle->id;
*theType = mrle->type;
if (mrle->name)
_pstrcpy(name, mrle->name);
else
name[0] = 0;
} else {
resError = resNotFound;
}
}
void SetResInfo(Handle theResource, SInt16 theID, ConstStringPtr name) {
MemRefList *mrle;
mrle = FindResourceHandle(theResource);
if (mrle) {
resError = noErr;
if (mrle->name)
free(mrle->name);
mrle->name = malloc(name[0] + 1);
mrle->attr |= resChanged;
if (mrle->name)
_pstrcpy(mrle->name, name);
else
resError = memFullErr;
} else {
resError = resNotFound;
}
}
SInt16 GetResAttrs(Handle theResource) {
MemRefList *mrle;
mrle = FindResourceHandle(theResource);
if (mrle) {
resError = noErr;
return mrle->attr;
} else {
resError = resNotFound;
return 0;
}
}
void SetResAttrs(Handle theResource, SInt16 attrs) {
MemRefList *mrle;
mrle = FindResourceHandle(theResource);
if (mrle) {
resError = noErr;
mrle->attr = attrs;
} else {
resError = resNotFound;
}
}
void ChangedResource(Handle theResource) {
MemRsrcMap *rm;
MemRefList *mrle;
rm = FindResourceMap(cur_res_file);
mrle = FindResourceHandle(theResource);
if (mrle) {
if (rm && (rm->fork_attr & mapReadOnly)) {
resError = resAttrErr;
} else {
resError = noErr;
mrle->attr |= resChanged;
rm->fork_attr |= mapChanged;
}
} else {
resError = resNotFound;
}
}
void AddResource(Handle theData, OSType theType, SInt16 theID, ConstStringPtr name) {
MemRsrcMap *rm;
MemRsrcTypeList *mtyp;
MemRefList *mrle;
StringPtr namecpy;
rm = FindResourceMap(cur_res_file);
if (rm) {
if (rm->fork_attr & mapReadOnly) {
resError = resAttrErr;
return;
}
resError = noErr;
mtyp = FindResourceType1(rm, theType);
if (!mtyp) {
mtyp = NewTypeListEntry(&rm->type_list, theType, 0, 0);
if (!mtyp) {
resError = memFullErr;
return;
}
rm->fork_attr |= mapChanged;
}
if (!theData || FindResourceHandle(theData)) {
resError = addResFailed;
return;
}
if (name && name[0]) {
namecpy = malloc(name[0] + 1);
_pstrcpy(namecpy, name);
} else {
namecpy = 0;
}
mrle = NewRefListEntry(&mtyp->ref_list, theID, theType, namecpy, 2, theData);
if (!mrle) {
resError = memFullErr;
return;
}
rm->fork_attr |= mapChanged;
} else {
resError = resFNotFound;
}
}
void UpdateResFile(SInt16 refnum) {
WriteResourceFork(refnum);
}
void WriteResource(Handle theResource) {
resError = noErr;
}
void SetResPurge(Boolean install) {
}
SInt16 CountResources(OSType theType) {
return CountResourceType(theType);
}
SInt16 Count1Resources(OSType theType) {
MemRsrcMap *rm;
rm = FindResourceMap(cur_res_file);
if (rm) {
resError = noErr;
return CountResourceType1(rm, theType);
} else {
resError = resFNotFound;
return 0;
}
}
Handle GetIndResource(OSType theType, SInt16 index) {
MemRefList *mrle;
mrle = FindIndResource(theType, index);
resError = mrle ? 0 : resNotFound;
return mrle->hand;
}
Handle Get1IndResource(OSType theType, SInt16 index) {
MemRsrcMap *rm;
MemRefList *mrle;
rm = FindResourceMap(cur_res_file);
if (rm) {
mrle = FindIndResource1(rm, theType, index);
if (mrle) {
resError = noErr;
return mrle->hand;
} else {
resError = resNotFound;
return 0;
}
} else {
resError = resFNotFound;
return 0;
}
}
SInt16 Count1Types() {
MemRsrcMap *rm;
MemRsrcTypeList *rtl;
SInt16 count;
count = 0;
rm = FindResourceMap(cur_res_file);
if (rm) {
rtl = rm->type_list;
while (rtl) {
rtl = rtl->next;
++count;
}
} else {
resError = resFNotFound;
}
return count;
}
void Get1IndType(OSType *theType, SInt16 index) {
MemRsrcMap *rm;
MemRsrcTypeList *rtl;
SInt16 count;
count = 1;
rm = FindResourceMap(cur_res_file);
if (rm) {
rtl = rm->type_list;
while (rtl && count < index) {
rtl = rtl->next;
++count;
}
if (rtl)
*theType = rtl->type;
else
resError = inputOutOfBounds;
} else {
resError = resFNotFound;
}
}
void ReleaseResource(Handle theResource) {
resError = noErr;
}
void DetachResource(Handle theResource) {
MemRefList *mrle;
SInt32 ns;
mrle = FindResourceHandle(theResource);
if (mrle) {
ns = GetHandleSize(theResource);
mrle->hand = NewHandle(ns);
if (!mrle->hand) {
resError = memFullErr;
} else {
HLock(mrle->hand);
HLock(theResource);
memcpy(*mrle->hand, *theResource, ns);
HUnlock(theResource);
HUnlock(mrle->hand);
resError = noErr;
}
} else {
resError = resNotFound;
}
}
void RemoveResource(Handle theResource) {
resError = RemoveResourceHandle(theResource) ? 0 : rmvResFailed;
}
void CloseResFile(SInt16 refNum) {
MemRsrcMap *rm = FindResourceMap(refNum);
if (rm && refNum != -1) {
WriteResourceFork(refNum);
DeleteResources(refNum);
FSClose(refNum);
}
cur_res_file = maplist ? maplist->refnum : 0;
}
SInt16 GetResFileAttrs(SInt16) {
MemRsrcMap *rm = FindResourceMap(cur_res_file);
if (rm) {
resError = 0;
return rm->fork_attr;
} else {
resError = resFNotFound;
return 0;
}
}
Boolean LMGetResLoad() {
return 1;
}