/* MACLIB: A companion library to SDL for working with Macintosh (tm) data Copyright (C) 1997 Sam Lantinga This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Sam Lantinga 5635-34 Springhouse Dr. Pleasanton, CA 94588 (USA) slouken@devolution.com */ /* These are routines to parse a Macintosh Resource Fork file -Sam Lantinga (slouken@devolution.com) Note: Most of the info in this file came from "Inside Macintosh" */ #include #include #include "SDL_types.h" #include "bitesex.h" #include "Mac_Resource.h" #ifndef SEEK_SET #define SEEK_SET 0 #endif /* The format for AppleDouble files -- in a header file */ #define APPLEDOUBLE_MAGIC 0x00051607 #include "applefile.h" /* The format for MacBinary files -- in a header file */ #define MACBINARY_MASK 0xFCFF #define MACBINARY_MAGIC 0x8081 #include "macbinary.h" /* These are the data structures that make up the Macintosh Resource Fork */ struct Resource_Header { Uint32 res_offset; /* Offset of resources in file */ Uint32 map_offset; /* Offset of resource map in file */ Uint32 res_length; /* Length of the resource data */ Uint32 map_length; /* Length of the resource map */ }; struct Resource_Data { Uint32 Data_length; /* Length of the resources data */ #ifdef SHOW_VARLENGTH_FIELDS Uint8 Data[0]; /* The Resource Data */ #endif }; struct Type_entry { char Res_type[4]; /* Resource type */ Uint16 Num_rez; /* # this type resources in map - 1 */ Uint16 Ref_offset; /* Offset from type list, of reference list for this type */ }; struct Ref_entry { Uint16 Res_id; /* The ID for this resource */ Uint16 Name_offset; /* Offset in name list of resource name, or -1 if no name */ Uint8 Res_attrs; /* Resource attributes */ Uint8 Res_offset[3]; /* 3-byte offset from Resource data */ Uint32 Reserved; /* Reserved for use in-core */ }; struct Name_entry { Uint8 Name_len; /* Length of the following name */ #ifdef SHOW_VARLENGTH_FIELDS Uint8 name[0]; /* Variable length resource name */ #endif }; struct Resource_Map { Uint8 Reserved[22]; /* Reserved for use in-core */ Uint16 Map_attrs; /* Map attributes */ Uint16 types_offset; /* Offset of resource type list */ Uint16 names_offset; /* Offset of resource name list */ Uint16 num_types; /* # of types in map - 1 */ #ifdef SHOW_VARLENGTH_FIELDS struct Type_entry types[0]; /* Variable length types list */ struct Ref_entry refs[0]; /* Variable length reference list */ struct Name_entry names[0]; /* Variable length name list */ #endif }; int Res_cmp(const void *A, const void *B) { struct Mac_Resource::resource *a, *b; a=(struct Mac_Resource::resource *)A; b=(struct Mac_Resource::resource *)B; if ( a->id > b->id ) return(1); else if ( a->id < b->id ) return(-1); else /* They are equal?? */ return(0); } /* Here's an iterator to find heuristically (I've always wanted to use that word :-) a macintosh resource fork from a general mac name. This function may be overkill, but I want to be able to find any Macintosh resource fork, darn it! :) */ static void CheckAppleFile(FILE *resfile, Uint32 *resbase) { ASHeader header; if (fread(&header.magicNum,sizeof(header.magicNum),1,resfile)&& (bytesex32(header.magicNum) == APPLEDOUBLE_MAGIC) ) { fread(&header.versionNum, sizeof(header.versionNum), 1, resfile); bytesex32(header.versionNum); fread(&header.filler, sizeof(header.filler), 1, resfile); fread(&header.numEntries, sizeof(header.numEntries), 1, resfile); bytesex16(header.numEntries); #ifdef APPLEDOUBLE_DEBUG mesg("Header magic: 0x%.8x, version 0x%.8x\n", header.magicNum, header.versionNum); #endif ASEntry entry; #ifdef APPLEDOUBLE_DEBUG mesg("Number of entries: %d, sizeof(entry) = %d\n", header.numEntries, sizeof(entry)); #endif for ( int i = 0; idata; delete Resources[i].list[n].data; } } delete[] Resources[i].list; } delete[] Resources; } char ** Mac_Resource:: Types(void) { int i; char **types; types = new char *[num_types+1]; for ( i=0; ilength, 4, 1, filep); bytesex32(d->length); d->data = new Uint8[d->length]; if (!fread(d->data,d->length,1,filep)) { delete[] d->data; error("Couldn't read %d bytes", d->length); delete d; return(NULL); } Resources[i].list[n].data = d; return(d); } } } } error("Couldn't find resource of type '%s', id %hu", res_type, id); return(NULL); } Mac_ResData * Mac_Resource:: Resource(const char *res_type, const char *name) { int i, n; Mac_ResData *d; for ( i=0; ilength, 4, 1, filep); bytesex32(d->length); d->data = new Uint8[d->length]; if (!fread(d->data,d->length,1,filep)) { delete[] d->data; error("Couldn't read %d bytes", d->length); delete d; return(NULL); } Resources[i].list[n].data = d; return(d); } } } } error("Couldn't find resource of type '%s', name %s", res_type, name); return(NULL); }