#include "cmdline.h" // 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(void) { 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) { // this function has various awkwardly swapped registers 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); dhdr = &thdr; 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); dsys = &tsys; msize = dhdr->map_len; buffer = malloc(msize); if (!buffer) goto memFail; ref_offs = dhdr->map_offs; RF_READ(buffer, ref_offs, msize, mapFail); if ( (dhdr->map_offs > file_size) || ((dhdr->map_offs + dhdr->map_len) > file_size) || (dhdr->data_offs > file_size) || ((dhdr->data_offs + dhdr->data_len) > file_size) || ((dhdr->map_offs < dhdr->data_offs) ? ((dhdr->map_offs + dhdr->map_len) > dhdr->data_offs) : ((dhdr->data_offs + dhdr->data_len) > dhdr->map_offs)) ) goto mapFail; rm = NewResourceMap(ref, ((permission == 1) ? mapReadOnly : 0) | mapCompact, 0, 0); if (!rm) goto memFail; rm->sys_data = *dsys; dmap = (Ty73 *) buffer; if ((dmap->typelist_offs + dhdr->map_offs) > file_size) goto freeAndMapFail; dtyp = (Ty75 *) (((unsigned char *) buffer) + dmap->typelist_offs + 2); if ((dmap->namelist_offs + dhdr->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 ((dmap->typelist_offs + dtyp[cnt].ref_list_offs + dhdr->map_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 = ref_offs + dhdr->data_offs; if (offs > file_size) goto freeAndMapFail; esize = 4; RF_READ(&tent, offs, esize, freeAndMapFail); offs += esize; if ((tent.len + ref_offs + dhdr->data_offs) > 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, ""); 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(void) { 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(void) { 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 *spec, SInt8 permission) { SInt16 ref; SInt32 size; if (permission != fsRdPerm) FSpCreate(spec, 'CWIE', 'TEXT', -1); resError = FSpOpenRF(spec, (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(void) { 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(void) { 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(void) { return 1; }