diff --git a/macosx/ReClassicfication/EndianStuff.h b/macosx/ReClassicfication/EndianStuff.h new file mode 100755 index 00000000..1e6d3d4d --- /dev/null +++ b/macosx/ReClassicfication/EndianStuff.h @@ -0,0 +1,28 @@ +/* + * EndianStuff.h + * stackimport + * + * Created by Mr. Z. on 10/06/06. + * Copyright 2006 Mr Z. All rights reserved. + * + */ + +#pragma once + +#include + + +#if RECLASSIFICATION_BUILD_BIG_ENDIAN +#define BIG_ENDIAN_16(value) (value) +#define BIG_ENDIAN_32(value) (value) +#else +#define BIG_ENDIAN_16(value) \ + (((((uint16_t)(value))<<8) & 0xFF00) | \ + ((((uint16_t)(value))>>8) & 0x00FF)) + +#define BIG_ENDIAN_32(value) \ + (((((uint32_t)(value))<<24) & 0xFF000000) | \ + ((((uint32_t)(value))<< 8) & 0x00FF0000) | \ + ((((uint32_t)(value))>> 8) & 0x0000FF00) | \ + ((((uint32_t)(value))>>24) & 0x000000FF)) +#endif diff --git a/macosx/ReClassicfication/FakeHandles.c b/macosx/ReClassicfication/FakeHandles.c new file mode 100755 index 00000000..e2315cc4 --- /dev/null +++ b/macosx/ReClassicfication/FakeHandles.c @@ -0,0 +1,269 @@ +/* =========================================================================== + + PROJECT: FakeHandles + + FILE: FakeHandles.c + + PURPOSE: Simulate Handles on machines which only have ANSI-C to easily + port some of the more simple Macintosh code fragments to other + platforms. + + (C) Copyright 1998 by Uli Kusterer, all rights reserved. + + ======================================================================== */ + +#pragma mark [Headers] + + +// ----------------------------------------------------------------------------- +// Headers: +// ----------------------------------------------------------------------------- + +#include "FakeHandles.h" + + +// ----------------------------------------------------------------------------- +// Globals: +// ----------------------------------------------------------------------------- + +/* The last entry in the master pointer array is mis-used to hold a pointer + to another master pointer array. Thus, we have a linked list of master + pointer arrays in RAM, and we don't run out of master pointers as easily. */ +MasterPointer gMasterPointers[MASTERPOINTER_CHUNK_SIZE]; +long gFakeHandleError = noErr; + + +/* ----------------------------------------------------------------------------- + FakeInitHandles: + Call this to initialize the fake memory Manager at the start of your + program. Only call this once or you'll lose all your Handles and will have + stale memory lying around. Pass the global gMasterPointers in + masterPtrArray. + + REVISIONS: + 98-08-30 UK Created. + ----------------------------------------------------------------------------- */ + +void FakeInitHandles( MasterPointer* masterPtrArray ) +{ + long x; + + for( x = 0; x < MASTERPOINTER_CHUNK_SIZE; x++ ) + { + masterPtrArray[x].actualPointer = NULL; + masterPtrArray[x].used = false; + masterPtrArray[x].memoryFlags = 0; + masterPtrArray[x].size = 0; + } + + gFakeHandleError = noErr; +} + + +/* ----------------------------------------------------------------------------- + FakeMoreMasters: + Call this if you need more master pointers Called internally by + FakeNewHandle() when it runs out of master pointers. + + REVISIONS: + 98-08-30 UK Created. + ----------------------------------------------------------------------------- */ + +void FakeMoreMasters() +{ + long x; + MasterPointer* vMPtrBlock; + MasterPointer* vCurrBlock; + + // Make a new master pointer block: + vMPtrBlock = malloc( MASTERPOINTER_CHUNK_SIZE *sizeof(MasterPointer) ); + if( vMPtrBlock == NULL ) + { + gFakeHandleError = memFulErr; + return; + } + + // Clear it: + for( x = 0; x < MASTERPOINTER_CHUNK_SIZE; x++ ) + { + vMPtrBlock[x].actualPointer = NULL; + vMPtrBlock[x].used = false; + vMPtrBlock[x].memoryFlags = 0; + vMPtrBlock[x].size = 0; + } + + // Find last master pointer in last master pointer block: + vCurrBlock = gMasterPointers; + while( vCurrBlock[MASTERPOINTER_CHUNK_SIZE -1].used == true ) + vCurrBlock = (MasterPointer*) vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].actualPointer; + + // Make this last master pointer point to our new block: + vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].actualPointer = (char*) vMPtrBlock; + vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].used = true; + vMPtrBlock[MASTERPOINTER_CHUNK_SIZE-1].size = MASTERPOINTER_CHUNK_SIZE *sizeof(MasterPointer); + + gFakeHandleError = noErr; +} + + +Handle FakeNewEmptyHandle() +{ + Handle theHandle = NULL; + long x; + MasterPointer* vCurrBlock = gMasterPointers; + bool notFound = true; + + gFakeHandleError = noErr; + + while( notFound ) + { + for( x = 0; x < (MASTERPOINTER_CHUNK_SIZE-1); x++ ) + { + if( !(vCurrBlock[x].used) ) + { + vCurrBlock[x].used = true; + vCurrBlock[x].memoryFlags = 0; + vCurrBlock[x].size = 0; + + theHandle = (Handle) &(vCurrBlock[x]); + notFound = false; + break; + } + } + + if( !vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].used ) // Last is unused? We need a new master pointer block! + { + FakeMoreMasters(); + if( !vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].used ) // No new block added?! + notFound = false; // Terminate, it's very likely an error occurred. + } + vCurrBlock = (MasterPointer*) vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].actualPointer; // Go next master pointer block. + } + + return theHandle; +} + + +/* ----------------------------------------------------------------------------- + NewHandle: + Create a new Handle. This creates a new entry in the Master Ptr array and + allocates memory of the specified size for it. Then it returns a Ptr to + this entry. + + Returns NULL if not successful. If MemError() is noErr upon a NULL return + value, we are out of master pointers. + + REVISIONS: + 2001-02-16 UK Added support for error codes. + 1998-08-30 UK Created. + ----------------------------------------------------------------------------- */ + +Handle FakeNewHandle( long theSize ) +{ + MasterPointer * theHandle = (MasterPointer*) FakeNewEmptyHandle(); + + theHandle->actualPointer = malloc( theSize ); + if( theHandle->actualPointer == NULL ) + { + FakeDisposeHandle( (Handle) theHandle ); + gFakeHandleError = memFulErr; + } + else + theHandle->size = theSize; + + return (Handle)theHandle; +} + + +/* ----------------------------------------------------------------------------- + DisposeHandle: + Dispose an existing Handle. Only call this once or you might kill valid + memory or worse. + + This frees the memory we use and marks the entry for the specified Handle + as unused. + + REVISIONS: + 1998-08-30 UK Created. + ----------------------------------------------------------------------------- */ + +void FakeDisposeHandle( Handle theHand ) +{ + MasterPointer* theEntry = (MasterPointer*) theHand; + + if( theEntry->actualPointer ) + free( theEntry->actualPointer ); + theEntry->used = false; + theEntry->actualPointer = NULL; + theEntry->memoryFlags = 0; + theEntry->size = 0; +} + + +void FakeEmptyHandle( Handle theHand ) +{ + MasterPointer* theEntry = (MasterPointer*) theHand; + + if( theEntry->actualPointer ) + free( theEntry->actualPointer ); + theEntry->actualPointer = NULL; +} + + +/* ----------------------------------------------------------------------------- + GetHandleSize: + Return the size of an existing Handle. This simply examines the "size" + field of the Handle's entry. + + REVISIONS: + 1998-08-30 UK Created. + ----------------------------------------------------------------------------- */ + +long FakeGetHandleSize( Handle theHand ) +{ + MasterPointer* theEntry = (MasterPointer*) theHand; + + gFakeHandleError = noErr; + + return( theEntry->size ); +} + + +/* ----------------------------------------------------------------------------- + SetHandleSize: + Change the size of an existing Handle. This reallocates the Handle (keeping + its data) and updates the size field of the Handle's entry accordingly. + + REVISIONS: + 1998-08-30 UK Created. + ----------------------------------------------------------------------------- */ + +void FakeSetHandleSize( Handle theHand, long theSize ) +{ + MasterPointer* theEntry = (MasterPointer*) theHand; + char* thePtr; + + thePtr = theEntry->actualPointer; + thePtr = realloc( thePtr, theSize ); + + if( thePtr ) + { + theEntry->actualPointer = thePtr; + theEntry->size = theSize; + gFakeHandleError = noErr; + } + else + gFakeHandleError = memFulErr; +} + + + + + + + + + + + + diff --git a/macosx/ReClassicfication/FakeHandles.h b/macosx/ReClassicfication/FakeHandles.h new file mode 100755 index 00000000..35c0014f --- /dev/null +++ b/macosx/ReClassicfication/FakeHandles.h @@ -0,0 +1,114 @@ +/* =========================================================================== + + PROJECT: FakeHandles + + FILE: FakeHandles.h + + PURPOSE: Simulate Handles on machines which only have ANSI-C to easily + port some of the more simple Macintosh code fragments to other + platforms. + + (C) Copyright 1998 by Uli Kusterer, all rights reserved. + + DIRECTIONS: + A Handle is a memory block that remembers its size automatically. + To the user, a Handle is simply a pointer to a pointer to the actual + data. Dereference it twice to get at the actual data. Before you + pass a once-dereferenced Handle to any other functions, you need to + call HLock() on it to avoid that it moves. Call HUnlock() when you + are finished with that. + To create a Handle, use NewHandle(). To free a Handle, call + DisposeHandle(). To resize use SetHandleSize() (the Handle itself + will not change, but the pointer to the actual data may change), + GetHandleSize() returns the actual size of the Handle. + Before making any of these calls, you *must have* called + InitHandles(). + + ======================================================================== */ + +#ifndef FAKEHANDLES_H +#define FAKEHANDLES_H + +#pragma mark [Headers] + + +// ----------------------------------------------------------------------------- +// Headers: +// ----------------------------------------------------------------------------- + +#include +#include +#include + + +// ----------------------------------------------------------------------------- +// Constants: +// ----------------------------------------------------------------------------- + +#ifndef NULL + #define NULL 0L +#endif + +#define MASTERPOINTER_CHUNK_SIZE 1024 // Size of blocks of master pointers we allocate in one go. + + +// Error codes MemError() may return after Handle calls: +enum +{ +#ifndef __MACTYPES__ + noErr = 0, // No error, success. +#endif /* __MACTYPES__ */ + memFulErr = -108 // Out of memory error. +}; + + +// ----------------------------------------------------------------------------- +// Data Types: +// ----------------------------------------------------------------------------- + +// Data types special to Mac: + +typedef char** Handle; +#ifndef __MACTYPES__ +typedef unsigned char Boolean; +#endif /* __MACTYPES__ */ + + +// Private data structure used internally to keep track of Handles: +typedef struct MasterPointer +{ + char* actualPointer; // The actual Pointer we're pointing to. + Boolean used; // Is this master Ptr being used? + long memoryFlags; // Some flags for this Handle. + long size; // The size of this Handle. +} MasterPointer; + +// ----------------------------------------------------------------------------- +// Globals: +// ----------------------------------------------------------------------------- + +extern MasterPointer gMasterPointers[MASTERPOINTER_CHUNK_SIZE]; +extern long gFakeHandleError; + + +// ----------------------------------------------------------------------------- +// Prototypes: +// ----------------------------------------------------------------------------- + +extern void FakeInitHandles( MasterPointer* masterPtrArray ); +extern Handle FakeNewHandle( long theSize ); +extern void FakeDisposeHandle( Handle theHand ); +extern long FakeGetHandleSize( Handle theHand ); +extern void FakeSetHandleSize( Handle theHand, long theSize ); +extern void FakeMoreMasters( void ); +extern Handle FakeNewEmptyHandle(); +extern void FakeEmptyHandle( Handle theHand ); + + + + + + + + +#endif /*FAKEHANDLES_H*/ diff --git a/macosx/ReClassicfication/FakeResources.c b/macosx/ReClassicfication/FakeResources.c new file mode 100755 index 00000000..0006fb91 --- /dev/null +++ b/macosx/ReClassicfication/FakeResources.c @@ -0,0 +1,1127 @@ +// +// FakeResources.c +// ReClassicfication +// +// Created by Uli Kusterer on 20.02.13. +// Copyright (c) 2013 Uli Kusterer. All rights reserved. +// + +#include +#include // for memmove(). +#include +#include "FakeResources.h" +#include "EndianStuff.h" + + +// Turn this on if you want to read actual Mac resource forks on a Mac or Darwin +// but using the ANSI file APIs (uses Apple's "/..namedfork/rsrc" trick). +#define READ_REAL_RESOURCE_FORKS 1 + + +/* + resource data offset 4 bytes + resource map offset 4 bytes + resource data length 4 bytes + resource map length 4 bytes + Reserved for system use 112 bytes + Application data 128 bytes + resource data ... + resource map ... + + + Resource data is 4-byte-long-counted, followed by actual data. + + + Resource map: + + copy of resource header in RAM 16 bytes + next resource map in RAM 4 bytes + file reference number in RAM 2 bytes + Resource file attributes 2 bytes + type list offset (resource map-relative) 2 bytes + name list offset (resource map-relative) 2 bytes +*/ + +struct FakeResourceMap +{ + struct FakeResourceMap* nextResourceMap; + bool dirty; // per-file tracking of whether FakeUpdateResFile() needs to write + FILE* fileDescriptor; + int16_t fileRefNum; + uint16_t resFileAttributes; + uint16_t numTypes; + struct FakeTypeListEntry* typeList; +}; + +/* + Type list: + + number of types (-1) 2 bytes + resource type 4 bytes + number of resources (-1) 2 bytes + offset to reference list (type list relative) 2 bytes +*/ + +struct FakeTypeListEntry +{ + uint32_t resourceType; + uint16_t numberOfResourcesOfType; // -1 + struct FakeReferenceListEntry* resourceList; +}; + +/* + Reference list: + + resource ID 2 bytes + resource name offset (relative to resource name list) 2 bytes + resource attributes 1 byte + resource data offset (resource data relative) 3 bytes + handle to resource in RAM 4 bytes +*/ + +struct FakeReferenceListEntry +{ + int16_t resourceID; + uint8_t resourceAttributes; + Handle resourceHandle; + char resourceName[257]; // 257 = 1 Pascal length byte, 255 characters for actual string, 1 byte for C terminator \0. +}; + +/* + Resource names are stored as byte-counted strings. (I.e. packed P-Strings) + Look-up by name is case-insensitive but case-preserving and diacritic-sensitive. +*/ + + +struct FakeResourceMap * gResourceMap = NULL; // Linked list. +struct FakeResourceMap * gCurrResourceMap = NULL; // Start search of map here. +int16_t gFileRefNumSeed = 0; +int16_t gFakeResError = noErr; +struct FakeTypeCountEntry* gLoadedTypes = NULL; +int16_t gNumLoadedTypes = 0; + + +struct FakeTypeCountEntry +{ + uint32_t type; + int16_t retainCount; +}; + + +size_t FakeFWriteUInt32BE( uint32_t inInt, FILE* theFile ) +{ + inInt = BIG_ENDIAN_32(inInt); + return fwrite( &inInt, sizeof(inInt), 1, theFile ); +} + + +size_t FakeFWriteInt16BE( int16_t inInt, FILE* theFile ) +{ + inInt = BIG_ENDIAN_16(inInt); + return fwrite( &inInt, sizeof(inInt), 1, theFile ); +} + + +size_t FakeFWriteUInt16BE( uint16_t inInt, FILE* theFile ) +{ + inInt = BIG_ENDIAN_16(inInt); + return fwrite( &inInt, sizeof(inInt), 1, theFile ); +} + + +void FakeFSeek( FILE* inFile, long inOffset, int inMode ) +{ + int theResult = fseek( inFile, inOffset, inMode ); + if( theResult != 0 ) + printf( "Seek to %ld result %d\n", inOffset, theResult ); +} + + +int16_t FakeResError() +{ + return gFakeResError; +} + + +// To be able to iterate types across files without duplicates, we build a list +// of all types in open files and keep track of how many files contain each type +// by "retaining" each type and "releasing" it when a file closes. +void FakeRetainType( uint32_t resType ) +{ + if( gLoadedTypes == NULL ) + { + gLoadedTypes = malloc( sizeof(struct FakeTypeCountEntry) ); + gLoadedTypes[0].type = resType; + gLoadedTypes[0].retainCount = 1; + } + + for( int x = 0; x < gNumLoadedTypes; x++ ) + { + if( gLoadedTypes[x].type == resType ) + { + gLoadedTypes[x].retainCount++; + return; + } + } + + gNumLoadedTypes++; + gLoadedTypes = realloc( gLoadedTypes, gNumLoadedTypes * sizeof(struct FakeTypeCountEntry) ); + gLoadedTypes[gNumLoadedTypes -1].type = resType; + gLoadedTypes[gNumLoadedTypes -1].retainCount = 1; +} + + +// The converse of FakeRetainType (see for more info): +void FakeReleaseType( uint32_t resType ) +{ + for( int x = 0; x < gNumLoadedTypes; x++ ) + { + if( gLoadedTypes[x].type == resType ) + { + gLoadedTypes[x].retainCount--; + if( gLoadedTypes[x].retainCount == 0 ) + { + gNumLoadedTypes--; + if( gNumLoadedTypes > 0 ) + gLoadedTypes[x] = gLoadedTypes[gNumLoadedTypes]; + } + break; + } + } +} + + +struct FakeResourceMap* FakeFindResourceMap( int16_t inFileRefNum, struct FakeResourceMap*** outPrevMapPtr ) +{ + struct FakeResourceMap* currMap = gResourceMap; + if( outPrevMapPtr ) + *outPrevMapPtr = &gResourceMap; + + while( currMap != NULL && currMap->fileRefNum != inFileRefNum ) + { + if( outPrevMapPtr ) + *outPrevMapPtr = &currMap->nextResourceMap; + currMap = currMap->nextResourceMap; + } + return currMap; +} + + +struct FakeResourceMap* FakeResFileOpen( const char* inPath, const char* inMode ) +{ + FILE * theFile = fopen( inPath, inMode ); + if( !theFile ) + { + gFakeResError = fnfErr; + return NULL; + } + + uint32_t resourceDataOffset = 0; + uint32_t resourceMapOffset = 0; + uint32_t lengthOfResourceData = 0; + uint32_t lengthOfResourceMap = 0; + + struct FakeResourceMap * newMap = calloc( 1, sizeof(struct FakeResourceMap) ); + newMap->fileDescriptor = theFile; + newMap->fileRefNum = gFileRefNumSeed++; + + if( fread( &resourceDataOffset, 1, sizeof(resourceDataOffset), theFile ) != sizeof(resourceDataOffset) ) + { + gFakeResError = eofErr; + free( newMap ); + newMap = NULL; + return NULL; + } + resourceDataOffset = BIG_ENDIAN_32(resourceDataOffset); + printf("resourceDataOffset %d\n", resourceDataOffset); + + if( fread( &resourceMapOffset, 1, sizeof(resourceMapOffset), theFile ) != sizeof(resourceMapOffset) ) + { + gFakeResError = eofErr; + free( newMap ); + newMap = NULL; + return NULL; + } + resourceMapOffset = BIG_ENDIAN_32(resourceMapOffset); + printf("resourceMapOffset %d\n", resourceMapOffset); + + if( fread( &lengthOfResourceData, 1, sizeof(lengthOfResourceData), theFile ) != sizeof(lengthOfResourceData) ) + { + gFakeResError = eofErr; + free( newMap ); + newMap = NULL; + return NULL; + } + lengthOfResourceData = BIG_ENDIAN_32(lengthOfResourceData); + + if( fread( &lengthOfResourceMap, 1, sizeof(lengthOfResourceMap), theFile ) != sizeof(lengthOfResourceMap) ) + { + gFakeResError = eofErr; + free( newMap ); + newMap = NULL; + return NULL; + } + lengthOfResourceMap = BIG_ENDIAN_32(lengthOfResourceMap); + + FakeFSeek( theFile, 112, SEEK_CUR ); // Skip system data. + FakeFSeek( theFile, 128, SEEK_CUR ); // Skip application data. + + FakeFSeek( theFile, resourceMapOffset, SEEK_SET ); + FakeFSeek( theFile, 16, SEEK_CUR ); // Skip resource file header copy. + FakeFSeek( theFile, 4, SEEK_CUR ); // Skip next resource map placeholder. + FakeFSeek( theFile, 2, SEEK_CUR ); // Skip file ref num placeholder. + fread( &newMap->resFileAttributes, 1, sizeof(uint16_t), theFile ); // Read file attributes. + newMap->resFileAttributes = BIG_ENDIAN_16(newMap->resFileAttributes); + printf("resFileAttributes %d\n", newMap->resFileAttributes); + + uint16_t typeListOffset = 0; + uint16_t nameListOffset = 0; + + fread( &typeListOffset, 1, sizeof(typeListOffset), theFile ); + typeListOffset = BIG_ENDIAN_16(typeListOffset); + fread( &nameListOffset, 1, sizeof(nameListOffset), theFile ); + nameListOffset = BIG_ENDIAN_16(nameListOffset); + + long typeListSeekPos = resourceMapOffset +(long)typeListOffset; + printf("typeListSeekPos %ld\n", typeListSeekPos); + FakeFSeek( theFile, typeListSeekPos, SEEK_SET ); + + uint16_t numTypes = 0; + fread( &numTypes, 1, sizeof(numTypes), theFile ); + numTypes = BIG_ENDIAN_16(numTypes) +1; + printf("numTypes %d\n", numTypes); + + newMap->typeList = calloc( ((int)numTypes), sizeof(struct FakeTypeListEntry) ); + newMap->numTypes = numTypes; + for( int x = 0; x < ((int)numTypes); x++ ) + { + uint32_t currType = 0; + fread( &currType, 1, sizeof(uint32_t), theFile ); // Read type code (4CC). + char typeStr[5] = {0}; + memmove( typeStr, &currType, 4 ); + printf( "currType '%s'\n", typeStr ); + currType = BIG_ENDIAN_32( currType ); + newMap->typeList[x].resourceType = currType; + + FakeRetainType( currType ); + + uint16_t numResources = 0; + fread( &numResources, 1, sizeof(numResources), theFile ); + numResources = BIG_ENDIAN_16(numResources); + printf("\tnumResources %d\n", numResources +1); + + uint16_t refListOffset = 0; + fread( &refListOffset, 1, sizeof(refListOffset), theFile ); + refListOffset = BIG_ENDIAN_16(refListOffset); + + long oldOffset = ftell(theFile); + + long refListSeekPos = typeListSeekPos +(long)refListOffset; + printf("\trefListSeekPos %ld\n", refListSeekPos); + FakeFSeek( theFile, refListSeekPos, SEEK_SET ); + + newMap->typeList[x].resourceList = calloc( ((int)numResources) +1, sizeof(struct FakeReferenceListEntry) ); + newMap->typeList[x].numberOfResourcesOfType = ((int)numResources) +1; + for( int y = 0; y < ((int)numResources) +1; y++ ) + { + fread( &newMap->typeList[x].resourceList[y].resourceID, 1, sizeof(uint16_t), theFile ); + newMap->typeList[x].resourceList[y].resourceID = BIG_ENDIAN_16(newMap->typeList[x].resourceList[y].resourceID); + + uint16_t nameOffset = 0; + fread( &nameOffset, 1, sizeof(nameOffset), theFile ); + nameOffset = BIG_ENDIAN_16(nameOffset); + + unsigned char attributesAndDataOffset[4]; + uint32_t dataOffset = 0; + fread( &attributesAndDataOffset, 1, sizeof(attributesAndDataOffset), theFile ); + newMap->typeList[x].resourceList[y].resourceAttributes = attributesAndDataOffset[0]; + memmove( ((char*)&dataOffset) +1, attributesAndDataOffset +1, 3 ); + dataOffset = BIG_ENDIAN_32(dataOffset); + FakeFSeek( theFile, 4, SEEK_CUR ); // Skip resource Handle placeholder. + + long innerOldOffset = ftell(theFile); + long dataSeekPos = resourceDataOffset +(long)dataOffset; + FakeFSeek( theFile, dataSeekPos, SEEK_SET ); + uint32_t dataLength = 0; + fread( &dataLength, 1, sizeof(dataLength), theFile ); + dataLength = BIG_ENDIAN_32(dataLength); + newMap->typeList[x].resourceList[y].resourceHandle = FakeNewHandle(dataLength); + fread( (*newMap->typeList[x].resourceList[y].resourceHandle), 1, dataLength, theFile ); + + if( -1 != (long)nameOffset ) + { + long nameSeekPos = resourceMapOffset +(long)nameListOffset +(long)nameOffset; + FakeFSeek( theFile, nameSeekPos, SEEK_SET ); + uint8_t nameLength = 0; + fread( &nameLength, 1, sizeof(nameLength), theFile ); + newMap->typeList[x].resourceList[y].resourceName[0] = nameLength; + if( nameLength > 0 ) + fread( newMap->typeList[x].resourceList[y].resourceName +1, 1, nameLength, theFile ); + } + + printf( "\t%d: \"%s\"\n", newMap->typeList[x].resourceList[y].resourceID, newMap->typeList[x].resourceList[y].resourceName +1 ); + + FakeFSeek( theFile, innerOldOffset, SEEK_SET ); + } + + FakeFSeek( theFile, oldOffset, SEEK_SET ); + } + + newMap->nextResourceMap = gResourceMap; + gResourceMap = newMap; + gFakeResError = noErr; + + gCurrResourceMap = gResourceMap; + + return newMap; +} + + +int16_t FakeOpenResFile( const unsigned char* inPath ) +{ +#if READ_REAL_RESOURCE_FORKS + const char* resForkSuffix = "/..namedfork/rsrc"; +#endif // READ_REAL_RESOURCE_FORKS + char thePath[256 +17] = {0}; + memmove(thePath,inPath +1,inPath[0]); +#if READ_REAL_RESOURCE_FORKS + memmove(thePath +inPath[0],resForkSuffix,17); +#endif // READ_REAL_RESOURCE_FORKS + struct FakeResourceMap* theMap = FakeResFileOpen( thePath, "r+" ); + if( !theMap ) + theMap = FakeResFileOpen( thePath, "r" ); + if( theMap ) + return theMap->fileRefNum; + else + return gFakeResError; +} + + +static bool FakeFindResourceHandleInMap( Handle theResource, struct FakeTypeListEntry** outTypeEntry, struct FakeReferenceListEntry** outRefEntry, struct FakeResourceMap* inMap ) +{ + if( (theResource != NULL) && (inMap != NULL) ) + { + for( int x = 0; x < inMap->numTypes; x++ ) + { + for( int y = 0; y < inMap->typeList[x].numberOfResourcesOfType; y++ ) + { + if( inMap->typeList[x].resourceList[y].resourceHandle == theResource ) + { + if (outTypeEntry) + { + *outTypeEntry = &inMap->typeList[x]; + } + + if (outRefEntry) + { + *outRefEntry = &inMap->typeList[x].resourceList[y]; + } + + return true; + } + } + } + } + + if (outTypeEntry) + { + *outTypeEntry = NULL; + } + + if (outRefEntry) + { + *outRefEntry = NULL; + } + + return false; +} + + +static bool FakeFindResourceHandle( Handle theResource, struct FakeResourceMap** outMap, struct FakeTypeListEntry** outTypeEntry, struct FakeReferenceListEntry** outRefEntry ) +{ + struct FakeResourceMap* currMap = gResourceMap; + while( currMap != NULL ) + { + if( FakeFindResourceHandleInMap(theResource, outTypeEntry, outRefEntry, currMap) ) + { + if( outMap ) + { + *outMap = currMap; + } + return true; + } + + currMap = currMap->nextResourceMap; + } + + if ( outMap ) + { + *outMap = NULL; + } + + if (outTypeEntry) + { + *outTypeEntry = NULL; + } + + if (outRefEntry) + { + *outRefEntry = NULL; + } + + return false; +} + + +static struct FakeTypeListEntry* FakeFindTypeListEntry(struct FakeResourceMap* inMap, uint32_t theType) +{ + if( inMap != NULL ) + { + for( int x = 0; x < inMap->numTypes; x++ ) + { + if( inMap->typeList[x].resourceType == theType ) + { + return &inMap->typeList[x]; + } + } + } + + return NULL; +} + +int16_t FakeHomeResFile( Handle theResource ) +{ + struct FakeResourceMap* currMap = NULL; + + if( FakeFindResourceHandle( theResource, &currMap, NULL, NULL) ) + { + gFakeResError = noErr; + return currMap->fileRefNum; + } + + gFakeResError = resNotFound; + return -1; +} + + +void FakeUpdateResFile( int16_t inFileRefNum ) +{ + const long kResourceHeaderLength = 16; + const long kResourceHeaderMapOffsetPos = 4; + const long kResourceHeaderMapLengthPos = 4 + 4 + 4; + const long kResourceHeaderReservedLength = 112; + const long kResourceHeaderAppReservedLength = 128; + const long kReservedHeaderLength = kResourceHeaderReservedLength + kResourceHeaderAppReservedLength; + const long kResourceDataSizeLength = 4; + const long kResourceMapNextHandleLength = 4; + const long kResourceMapFileRefLength = 2; + const long kResourceMapTypeListOffsetLength = 2; + const long kResourceMapNameListOffsetLength = 2; + const long kResourceMapNumTypesLength = 2; + const long kResourceRefLength = 2 + 2 + 1 + 3 + 4; + const long kResourceTypeLength = 4 + 2 + 2; + + struct FakeResourceMap* currMap = FakeFindResourceMap( inFileRefNum, NULL ); + long headerLength = kResourceHeaderLength + kReservedHeaderLength; + uint32_t resMapOffset = 0; + long refListSize = 0; + + if (!currMap->dirty) + return; + + // Write header: + FakeFSeek( currMap->fileDescriptor, 0, SEEK_SET ); + uint32_t resDataOffset = (uint32_t)headerLength; + FakeFWriteUInt32BE( resDataOffset, currMap->fileDescriptor ); + FakeFWriteUInt32BE( 0, currMap->fileDescriptor ); // placeholder offset to resource map + FakeFWriteUInt32BE( 0, currMap->fileDescriptor ); // placeholder resource data length + FakeFWriteUInt32BE( 0, currMap->fileDescriptor ); // placeholder resource map length + + // reserved + for( int x = 0; x < (kResourceHeaderReservedLength / sizeof(uint32_t)); x++ ) + FakeFWriteUInt32BE( 0, currMap->fileDescriptor ); + for( int x = 0; x < (kResourceHeaderAppReservedLength / sizeof(uint32_t)); x++ ) + FakeFWriteUInt32BE( 0, currMap->fileDescriptor ); + + resMapOffset = (uint32_t)headerLength; + + // Write out data for each resource and calculate space needed: + for( int x = 0; x < currMap->numTypes; x++ ) + { + for( int y = 0; y < currMap->typeList[x].numberOfResourcesOfType; y++ ) + { + uint32_t theSize = (uint32_t)FakeGetHandleSize( currMap->typeList[x].resourceList[y].resourceHandle ); + FakeFWriteUInt32BE( theSize, currMap->fileDescriptor ); + resMapOffset += sizeof(theSize); + fwrite( *currMap->typeList[x].resourceList[y].resourceHandle, 1, theSize, currMap->fileDescriptor ); + resMapOffset += theSize; + } + + refListSize += currMap->typeList[x].numberOfResourcesOfType * kResourceRefLength; + } + + // Write out what we know into the header now: + FakeFSeek( currMap->fileDescriptor, kResourceHeaderMapOffsetPos, SEEK_SET ); + FakeFWriteUInt32BE( resMapOffset, currMap->fileDescriptor ); + uint32_t resDataLength = resMapOffset -(uint32_t)headerLength; + FakeFWriteUInt32BE( resDataLength, currMap->fileDescriptor ); + + // Start writing resource map after data: + uint32_t resMapLength = 0; + FakeFSeek( currMap->fileDescriptor, resMapOffset, SEEK_SET ); + + // Copy what we know from the resource header + FakeFWriteUInt32BE( resDataOffset, currMap->fileDescriptor ); + FakeFWriteUInt32BE( resMapOffset, currMap->fileDescriptor ); + FakeFWriteUInt32BE( resDataLength, currMap->fileDescriptor ); + FakeFWriteUInt32BE( 0, currMap->fileDescriptor ); // Placeholder + + // Fake a next handle + FakeFWriteUInt32BE( 0, currMap->fileDescriptor ); + + resMapLength += kResourceHeaderLength + kResourceMapNextHandleLength + kResourceMapFileRefLength; // reserved: copy of resource header, next resource handle, file ref + FakeFWriteInt16BE( inFileRefNum, currMap->fileDescriptor ); + FakeFWriteUInt16BE( currMap->resFileAttributes, currMap->fileDescriptor ); + resMapLength += sizeof(uint16_t); + + uint16_t typeListOffset = ftell(currMap->fileDescriptor) + +kResourceMapTypeListOffsetLength +kResourceMapNameListOffsetLength -resMapOffset; + FakeFWriteUInt16BE( typeListOffset, currMap->fileDescriptor ); // Res map relative, points to the type count + long refListStartPosition = typeListOffset + kResourceMapNumTypesLength + currMap->numTypes * kResourceTypeLength; // Calc where we'll start to put resource lists (right after types). + + uint16_t nameListOffset = refListStartPosition +refListSize; // Calc where we'll start to put name lists (right after resource lists). + FakeFWriteUInt16BE( nameListOffset, currMap->fileDescriptor ); // Res map relative. + + // Now write type list and ref lists: + uint32_t nameListStartOffset = 0; + FakeFWriteUInt16BE( currMap->numTypes -1, currMap->fileDescriptor ); + uint32_t resDataCurrOffset = 0; // Keep track of where we wrote the associated data for each resource, relative to the start of resource data + + refListStartPosition = kResourceMapNumTypesLength + currMap->numTypes * kResourceTypeLength; // relative to beginning of resource type list + + for( int x = 0; x < currMap->numTypes; x++ ) + { + // Write entry for this type: + uint32_t currType = currMap->typeList[x].resourceType; + FakeFWriteUInt32BE( currType, currMap->fileDescriptor ); + + uint16_t numResources = currMap->typeList[x].numberOfResourcesOfType -1; + FakeFWriteUInt16BE( numResources, currMap->fileDescriptor ); + + uint16_t refListOffset = refListStartPosition; + FakeFWriteUInt16BE( refListOffset, currMap->fileDescriptor ); + + // Jump to ref list location and write ref list out: + long oldOffsetAfterPrevType = ftell(currMap->fileDescriptor); + + FakeFSeek( currMap->fileDescriptor, resMapOffset + typeListOffset + refListStartPosition, SEEK_SET ); + + for( int y = 0; y < currMap->typeList[x].numberOfResourcesOfType; y++ ) + { + FakeFWriteInt16BE( currMap->typeList[x].resourceList[y].resourceID, currMap->fileDescriptor ); + + // Write name to name table: + if( currMap->typeList[x].resourceList[y].resourceName[0] == 0 ) + FakeFWriteInt16BE( -1, currMap->fileDescriptor ); // Don't have a name, mark as -1. + else + { + FakeFWriteUInt16BE( nameListStartOffset, currMap->fileDescriptor ); // Associate name in name table with this. + + long oldOffsetAfterNameOffset = ftell( currMap->fileDescriptor ); + FakeFSeek( currMap->fileDescriptor, resMapOffset +nameListOffset +nameListStartOffset, SEEK_SET ); + fwrite( currMap->typeList[x].resourceList[y].resourceName, currMap->typeList[x].resourceList[y].resourceName[0] +1, sizeof(uint8_t), currMap->fileDescriptor ); + + long currMapLen = (ftell(currMap->fileDescriptor) -resMapOffset); + if( currMapLen > resMapLength ) + resMapLength = (uint32_t)currMapLen; + + FakeFSeek( currMap->fileDescriptor, oldOffsetAfterNameOffset, SEEK_SET ); + nameListStartOffset += currMap->typeList[x].resourceList[y].resourceName[0] +1; // Make sure we write next name *after* this one. + } + + fwrite( &currMap->typeList[x].resourceList[y].resourceAttributes, 1, sizeof(uint8_t), currMap->fileDescriptor ); + uint32_t resDataCurrOffsetBE = BIG_ENDIAN_32(resDataCurrOffset); + fwrite( ((uint8_t*)&resDataCurrOffsetBE) +1, 1, 3, currMap->fileDescriptor ); + resDataCurrOffset += kResourceDataSizeLength + FakeGetHandleSize(currMap->typeList[x].resourceList[y].resourceHandle); + FakeFWriteUInt32BE( 0, currMap->fileDescriptor ); // Handle placeholder. + + long currMapLen = (ftell(currMap->fileDescriptor) -resMapOffset); + if( currMapLen > resMapLength ) + resMapLength = (uint32_t)currMapLen; + } + + refListStartPosition += currMap->typeList[x].numberOfResourcesOfType * kResourceRefLength; + + // Jump back to after our type entry so we can write the next one: + FakeFSeek( currMap->fileDescriptor, oldOffsetAfterPrevType, SEEK_SET ); + } + + // Write res map length: + FakeFSeek( currMap->fileDescriptor, kResourceHeaderMapLengthPos, SEEK_SET ); + FakeFWriteUInt32BE( resMapLength, currMap->fileDescriptor ); + FakeFSeek( currMap->fileDescriptor, resMapOffset + kResourceHeaderMapLengthPos, SEEK_SET ); + FakeFWriteUInt32BE( resMapLength, currMap->fileDescriptor ); + + ftruncate(fileno(currMap->fileDescriptor), resMapOffset + resMapLength); + + currMap->dirty = false; +} + + +void FakeRedirectResFileToPath( int16_t inFileRefNum, const char* cPath ) +{ + struct FakeResourceMap** prevMapPtr = NULL; + struct FakeResourceMap* currMap = FakeFindResourceMap( inFileRefNum, &prevMapPtr ); + if( currMap ) + { + fclose( currMap->fileDescriptor ); + currMap->fileDescriptor = fopen( cPath, "w" ); + currMap->dirty = true; + } +} + + +void FakeCloseResFile( int16_t inFileRefNum ) +{ + struct FakeResourceMap** prevMapPtr = NULL; + struct FakeResourceMap* currMap = FakeFindResourceMap( inFileRefNum, &prevMapPtr ); + if( currMap ) + { + FakeUpdateResFile(inFileRefNum); + + *prevMapPtr = currMap->nextResourceMap; // Remove this from the linked list. + if( gCurrResourceMap == currMap ) + gCurrResourceMap = currMap->nextResourceMap; + + for( int x = 0; x < currMap->numTypes; x++ ) + { + FakeReleaseType( currMap->typeList[x].resourceType ); + + for( int y = 0; y < currMap->typeList[x].numberOfResourcesOfType; y++ ) + { + FakeDisposeHandle( currMap->typeList[x].resourceList[y].resourceHandle ); + } + free( currMap->typeList[x].resourceList ); + } + free( currMap->typeList ); + + fclose( currMap->fileDescriptor ); + free( currMap ); + } +} + + +Handle FakeGet1ResourceFromMap( uint32_t resType, int16_t resID, struct FakeResourceMap* inMap ) +{ + gFakeResError = noErr; + + if( inMap != NULL ) + { + for( int x = 0; x < inMap->numTypes; x++ ) + { + uint32_t currType = inMap->typeList[x].resourceType; + if( currType == resType ) + { + for( int y = 0; y < inMap->typeList[x].numberOfResourcesOfType; y++ ) + { + if( inMap->typeList[x].resourceList[y].resourceID == resID ) + { + return inMap->typeList[x].resourceList[y].resourceHandle; + } + } + break; + } + } + } + + gFakeResError = resNotFound; + + return NULL; +} + + +Handle FakeGet1Resource( uint32_t resType, int16_t resID ) +{ + return FakeGet1ResourceFromMap( resType, resID, gCurrResourceMap ); +} + + +Handle FakeGetResource( uint32_t resType, int16_t resID ) +{ + struct FakeResourceMap * currMap = gCurrResourceMap; + Handle theRes = NULL; + + while( theRes == NULL && currMap != NULL ) + { + theRes = FakeGet1ResourceFromMap( resType, resID, currMap ); + if( theRes != NULL ) + { + gFakeResError = noErr; + return theRes; + } + + currMap = currMap->nextResourceMap; + } + + gFakeResError = resNotFound; + + return NULL; +} + + +int16_t FakeCount1ResourcesInMap( uint32_t resType, struct FakeResourceMap* inMap ) +{ + gFakeResError = noErr; + + if( inMap != NULL ) + { + for( int x = 0; x < inMap->numTypes; x++ ) + { + uint32_t currType = inMap->typeList[x].resourceType; + if( currType == resType ) + return inMap->typeList[x].numberOfResourcesOfType; + } + } + + return 0; +} + + +int16_t FakeCount1TypesInMap( struct FakeResourceMap* inMap ) +{ + if( inMap == NULL ) + return 0; + + return inMap->numTypes; +} + + +int16_t FakeCount1Types() +{ + return FakeCount1TypesInMap( gCurrResourceMap ); +} + + +int16_t FakeCount1Resources( uint32_t resType ) +{ + return FakeCount1ResourcesInMap( resType, gCurrResourceMap ); +} + + +int16_t FakeCountResources( uint32_t resType ) +{ + int16_t numRes = 0; + struct FakeResourceMap* theMap = gCurrResourceMap; + + while( theMap ) + { + numRes += FakeCount1ResourcesInMap( resType, theMap ); + + theMap = theMap->nextResourceMap; + } + + return numRes; +} + + +int16_t FakeCountTypes() +{ + return gNumLoadedTypes; +} + + +int16_t FakeCurResFile() +{ + struct FakeResourceMap* currMap = gCurrResourceMap; + + if( !currMap ) + return 0; + + return currMap->fileRefNum; +} + +void FakeUseResFile( int16_t resRefNum ) +{ + struct FakeResourceMap* currMap = FakeFindResourceMap( resRefNum, NULL ); + if( !currMap ) + currMap = gResourceMap; + + gCurrResourceMap = currMap; +} + + +void FakeGet1IndType( uint32_t * resType, int16_t index ) +{ + if( resType == NULL ) + return; + + *resType = 0; + + struct FakeResourceMap* currMap = gCurrResourceMap; + if( (index <= 0) || (index > FakeCount1Types()) || !currMap ) + { + gFakeResError = resNotFound; + return; + } + + *resType = currMap->typeList[index-1].resourceType; + + gFakeResError = noErr; +} + +Handle FakeGet1IndResource( uint32_t resType, int16_t index ) +{ + struct FakeResourceMap* currMap = gCurrResourceMap; + + if( !currMap || (index <= 0) || (index > FakeCount1Resources(resType))) + { + gFakeResError = resNotFound; + } + + for( int x = 0; x < currMap->numTypes; x++ ) + { + uint32_t currType = currMap->typeList[x].resourceType; + if( currType == resType ) + { + gFakeResError = noErr; + return currMap->typeList[x].resourceList[index-1].resourceHandle; + } + } + + gFakeResError = resNotFound; + + return NULL; +} + +void FakeGetResInfo( Handle theResource, int16_t * theID, uint32_t * theType, FakeStr255 * name ) +{ + struct FakeTypeListEntry* typeEntry = NULL; + struct FakeReferenceListEntry* refEntry = NULL; + + + if( FakeFindResourceHandle(theResource, NULL, &typeEntry, &refEntry) ) + { + gFakeResError = noErr; + if( theID ) + { + *theID = refEntry->resourceID; + } + + if( theType ) + { + *theType = typeEntry->resourceType; + } + + if( name ) + { + memcpy(name, refEntry->resourceName, sizeof(FakeStr255)); + } + return; + } + + gFakeResError = resNotFound; +} + + +void FakeSetResInfo( Handle theResource, int16_t theID, FakeStr255 name ) +{ + struct FakeReferenceListEntry* refEntry = NULL; + + if( !theResource || !FakeFindResourceHandle( theResource, NULL, NULL, &refEntry) ) + { + gFakeResError = resNotFound; + return; + } + + if( (refEntry->resourceAttributes & resProtected) != 0 ) + { + gFakeResError = resAttrErr; + return; + } + + refEntry->resourceID = theID; + memcpy(refEntry->resourceName, name, sizeof(FakeStr255)); + + gFakeResError = noErr; +} + + +void FakeAddResource( Handle theData, uint32_t theType, int16_t theID, FakeStr255 name ) +{ + struct FakeResourceMap* currMap = gCurrResourceMap; + struct FakeTypeListEntry* typeEntry = NULL; + struct FakeReferenceListEntry* resourceEntry = NULL; + + // AddResource() only ensures that the handle is not a resource, but doesn't check whether the type/ID are already in use + if( !theData || FakeFindResourceHandleInMap( theData, &typeEntry, &resourceEntry, currMap ) ) + { + gFakeResError = addResFailed; + return; + } + + typeEntry = FakeFindTypeListEntry( currMap, theType ); + if( !typeEntry ) + { + currMap->numTypes++; + currMap->typeList = realloc(currMap->typeList, currMap->numTypes * sizeof(struct FakeTypeListEntry)); + + typeEntry = currMap->typeList + (currMap->numTypes - 1); + typeEntry->resourceType = theType; + typeEntry->numberOfResourcesOfType = 0; + typeEntry->resourceList = NULL; + + FakeRetainType(theType); + } + + typeEntry->numberOfResourcesOfType++; + + if( typeEntry->resourceList ) + { + typeEntry->resourceList = realloc( typeEntry->resourceList, typeEntry->numberOfResourcesOfType * sizeof(struct FakeReferenceListEntry) ); + } + else + { + typeEntry->resourceList = calloc(typeEntry->numberOfResourcesOfType, sizeof(struct FakeReferenceListEntry)); + } + + resourceEntry = typeEntry->resourceList + ( typeEntry->numberOfResourcesOfType - 1 ); + resourceEntry->resourceAttributes = 0; + resourceEntry->resourceID = theID; + memcpy(resourceEntry->resourceName, name, sizeof(FakeStr255)); + resourceEntry->resourceHandle = theData; + + currMap->dirty = true; + + gFakeResError = noErr; +} + +void FakeChangedResource( Handle theResource ) +{ + struct FakeResourceMap* theMap = NULL; + struct FakeReferenceListEntry* theEntry = NULL; + if( !FakeFindResourceHandle( theResource, &theMap, NULL, &theEntry ) ) + { + gFakeResError = resNotFound; + return; + } + + if( (theEntry->resourceAttributes & resProtected) == 0 ) + { + theMap->dirty = true; + gFakeResError = noErr; + } + else + { + gFakeResError = resAttrErr; + } +} + +// NOTE: you must call DisposeHandle(theResource) manually to release the memory. Normally, +// the Resource Manager will dispose the handle on update or file close, but this implementation +// does not track removed resource handles for later disposal. +void FakeRemoveResource( Handle theResource ) +{ + struct FakeResourceMap* currMap = gCurrResourceMap; + struct FakeTypeListEntry* typeEntry = NULL; + struct FakeReferenceListEntry* resEntry = NULL; + if( !currMap || !FakeFindResourceHandleInMap( theResource, &typeEntry, &resEntry, currMap ) || ((resEntry->resourceAttributes & resProtected) != 0) ) + { + gFakeResError = rmvResFailed; + return; + } + + struct FakeReferenceListEntry* nextResEntry = resEntry + 1; + int resourcesListSize = typeEntry->numberOfResourcesOfType * sizeof(struct FakeReferenceListEntry); + long nextResEntryOffset = (void*)nextResEntry - (void*)typeEntry->resourceList; + + typeEntry->numberOfResourcesOfType--; + + if( typeEntry->numberOfResourcesOfType > 0 ) + { + memcpy( resEntry, nextResEntry, resourcesListSize - nextResEntryOffset ); + typeEntry->resourceList = realloc( typeEntry->resourceList, resourcesListSize - sizeof(struct FakeReferenceListEntry) ); + } + else + { + // got rid of the last resource reference, release the memory + free(typeEntry->resourceList); + typeEntry->resourceList = NULL; + + // now remove the type entry + struct FakeTypeListEntry* nextTypeEntry = typeEntry + 1; + int typeListSize = currMap->numTypes * sizeof(struct FakeTypeListEntry); + long nextTypeEntryOffset = (void*)nextTypeEntry - (void*)currMap->typeList; + + currMap->numTypes--; + FakeReleaseType(typeEntry->resourceType); + + if( currMap->numTypes > 0 ) + { + memcpy( typeEntry, nextTypeEntry, typeListSize - nextTypeEntryOffset ); + currMap->typeList = realloc( currMap->typeList, typeListSize - sizeof(struct FakeTypeListEntry) ); + } + else + { + // got rid of the last type entry + free(currMap->typeList); + currMap->typeList = NULL; + } + } + + + currMap->dirty = true; + gFakeResError = noErr; +} + + +// NOTE: effectively a no-op since we don't have a way to write a resource without writing the whole map +void FakeWriteResource( Handle theResource ) +{ + struct FakeReferenceListEntry* resEntry = NULL; + if( !theResource || !FakeFindResourceHandle( theResource, NULL, NULL, &resEntry )) + { + gFakeResError = resNotFound; + } + else + { + gFakeResError = noErr; + } +} + +// NOTE: effectively a no-op since we don't have a way to load an individual resource from disk right now. +// All resources are already loaded at file open time. +void FakeLoadResource( Handle theResource ) +{ + struct FakeReferenceListEntry* resEntry = NULL; + if( !theResource || !FakeFindResourceHandle( theResource, NULL, NULL, &resEntry )) + { + gFakeResError = resNotFound; + } + else + { + gFakeResError = noErr; + } +} + +// NOTE: effectively a no-op since we don't have a way to reload a released resource from disk right now +void FakeReleaseResource( Handle theResource ) +{ + struct FakeReferenceListEntry* resEntry = NULL; + if( !theResource || !FakeFindResourceHandle( theResource, NULL, NULL, &resEntry )) + { + gFakeResError = resNotFound; + } + else + { + gFakeResError = noErr; + } +} + + +void FakeSetResLoad(bool load) +{ + // NOTE: a no-op since resources are always loaded at file open time +} + + + diff --git a/macosx/ReClassicfication/FakeResources.h b/macosx/ReClassicfication/FakeResources.h new file mode 100755 index 00000000..0792d503 --- /dev/null +++ b/macosx/ReClassicfication/FakeResources.h @@ -0,0 +1,84 @@ +// +// FakeResources.h +// ReClassicfication +// +// Created by Uli Kusterer on 21.02.13. +// Copyright (c) 2013 Uli Kusterer. All rights reserved. +// + +#ifndef ReClassicfication_FakeResources_h +#define ReClassicfication_FakeResources_h + + +#include "FakeHandles.h" + + +// Possible return values of FakeResError(): +#ifndef __MACERRORS__ +enum +{ + resNotFound = -192, + resFNotFound = -193, + addResFailed = -194, + rmvResFailed = -196, + resAttrErr = -198, + eofErr = -39, + fnfErr = -43 +}; +#endif /* __MACERRORS__ */ + + +#ifndef __RESOURCES__ +// Resource attribute bit flags: +enum +{ + resReserved = (1 << 0), // Apparently not yet used. + resChanged = (1 << 1), + resPreload = (1 << 2), + resProtected = (1 << 3), + resLocked = (1 << 4), + resPurgeable = (1 << 5), + resSysHeap = (1 << 6), + resReserved2 = (1 << 7) // Apparently not yet used. +}; +#endif + +typedef unsigned char FakeStr255[256]; + + +int16_t FakeOpenResFile( const unsigned char* inPath ); +void FakeCloseResFile( int16_t resRefNum ); +Handle FakeGet1Resource( uint32_t resType, int16_t resID ); +Handle FakeGetResource( uint32_t resType, int16_t resID ); +int16_t FakeCurResFile(); +void FakeUseResFile( int16_t resRefNum ); +void FakeUpdateResFile( int16_t inFileRefNum ); +int16_t FakeHomeResFile( Handle theResource ); +int16_t FakeCount1Types(); +int16_t FakeCount1Resources( uint32_t resType ); +int16_t FakeCountTypes(); +int16_t FakeCountResources( uint32_t resType ); + +void FakeGet1IndType( uint32_t * resType, int16_t index ); +Handle FakeGet1IndResource( uint32_t resType, int16_t index ); +void FakeGetResInfo( Handle theResource, int16_t * theID, uint32_t * theType, FakeStr255 * name ); +void FakeSetResInfo( Handle theResource, int16_t theID, FakeStr255 name ); +void FakeAddResource( Handle theData, uint32_t theType, int16_t theID, FakeStr255 name ); +void FakeChangedResource( Handle theResource ); +void FakeRemoveResource( Handle theResource ); +void FakeWriteResource( Handle theResource ); +void FakeLoadResource( Handle theResource ); +void FakeReleaseResource( Handle theResource ); +void FakeSetResLoad(bool load); + +int16_t FakeResError(); + + +// Private calls for internal use/tests: +void FakeRedirectResFileToPath( int16_t inFileRefNum, const char* cPath ); +struct FakeResourceMap* FakeResFileOpen( const char* inPath, const char* inMode ); +struct FakeResourceMap* FakeFindResourceMap( int16_t inFileRefNum, struct FakeResourceMap*** outPrevMapPtr ); +int16_t FakeCount1ResourcesInMap( uint32_t resType, struct FakeResourceMap* inMap ); +int16_t FakeCount1TypesInMap( struct FakeResourceMap* inMap ); + +#endif diff --git a/macosx/logo_defrost.png b/macosx/logo_defrost.png index 208704dd..7bb36dfd 100644 Binary files a/macosx/logo_defrost.png and b/macosx/logo_defrost.png differ diff --git a/macosx/logo_freeze.png b/macosx/logo_freeze.png index 8d6eaa0b..7e341123 100644 Binary files a/macosx/logo_freeze.png and b/macosx/logo_freeze.png differ diff --git a/macosx/mac-file.mm b/macosx/mac-file.mm index ded631db..5c68b5ec 100644 --- a/macosx/mac-file.mm +++ b/macosx/mac-file.mm @@ -117,7 +117,7 @@ static NSURL *FindApplicationSupportFolder (const char *folderName) NSURL *oldURL = nil; NSString *fstr = [NSString stringWithUTF8String:folderName]; - baseURL = [[NSFileManager.defaultManager URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask].firstObject URLByAppendingPathComponent:fstr]; + baseURL = [NSFileManager.defaultManager URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask].firstObject; if (!baseURL) { @@ -129,20 +129,20 @@ static NSURL *FindApplicationSupportFolder (const char *folderName) if ([NSFileManager.defaultManager fileExistsAtPath:s9xURL.path]) { - purl = s9xURL; + purl = [s9xURL URLByAppendingPathComponent:fstr]; } else { if ([NSFileManager.defaultManager fileExistsAtPath:oldURL.path]) { - purl = oldURL; + purl = [oldURL URLByAppendingPathComponent:fstr]; } else { NSError *error = nil; if ([NSFileManager.defaultManager createDirectoryAtURL:s9xURL withIntermediateDirectories:YES attributes:nil error:&error]) { - purl = s9xURL; + purl = [s9xURL URLByAppendingPathComponent:fstr]; AddFolderIcon(purl, folderName); } } diff --git a/macosx/mac-os.mm b/macosx/mac-os.mm index 2f761c76..f71bdf17 100644 --- a/macosx/mac-os.mm +++ b/macosx/mac-os.mm @@ -138,7 +138,7 @@ int macCurvatureWarp = 15, macAspectRatio = 0; bool8 startopendlog = false, - showtimeinfrz = true, + showtimeinfrz = false, enabletoggle = true, savewindowpos = false, onscreeninfo = true; @@ -229,6 +229,7 @@ uint8 functionButtons[kNumFunctionButtons] = { bool8 pressedKeys[MAC_MAX_PLAYERS][kNumButtons] = { 0 }; bool8 pressedGamepadButtons[MAC_MAX_PLAYERS][kNumButtons] = { 0 }; bool8 pressedFunctionButtons[kNumFunctionButtons] = { 0 }; +bool8 pressedRawKeyboardButtons[MAC_NUM_KEYCODES] = { 0 }; bool8 heldFunctionButtons[kNumFunctionButtons] = { 0 }; os_unfair_lock keyLock; os_unfair_lock renderLock; @@ -1722,6 +1723,22 @@ void ApplyNSRTHeaderControllers (void) ChangeInputDevice(); } +void DrawString(CGContextRef ctx, NSString *string, CGFloat size, CGFloat x, CGFloat y) +{ + NSAttributedString *astr = [[NSAttributedString alloc] initWithString:string attributes:@{NSFontAttributeName: [NSFont fontWithName:@"Helvetica" size:size], NSForegroundColorAttributeName: NSColor.whiteColor}]; + + CTLineRef line = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)astr); + CGFloat ascent = 0.0; + CGFloat descent = 0.0; + CGFloat leading = 0.0; + CTLineGetTypographicBounds(line, &ascent, &descent, &leading); + + // Draw the text in the new CoreGraphics Context + CGContextSetTextPosition(ctx, x, y + descent); + CTLineDraw(line, ctx); + CFRelease(line); +} + int PromptFreezeDefrost (Boolean freezing) { OSStatus err; @@ -1741,7 +1758,7 @@ int PromptFreezeDefrost (Boolean freezing) char dateC[256]; uint8 *back, *draw; - const UInt32 repeatDelay = 10; + const UInt32 repeatDelay = 200000; const int w = SNES_WIDTH << 1, h = SNES_HEIGHT << 1; const char letters[] = "123456789ABC", *filename; @@ -1795,7 +1812,7 @@ int PromptFreezeDefrost (Boolean freezing) if (image) { - rct = CGRectMake(0.0f, (float) h - 118.0f, w, 118.0f); + rct = CGRectMake(0.0f, (float) h - 88.0f, w, 88.0f); CGContextDrawImage(ctx, rct, image); CGImageRelease(image); } @@ -1805,7 +1822,7 @@ int PromptFreezeDefrost (Boolean freezing) CGContextSetLineJoin(ctx, kCGLineJoinRound); - rct = CGRectMake(0.0f, (float) h - 238.0f, 128.0f, 120.0f); + rct = CGRectMake(0.0f, (float) h - 208.0f, 128.0f, 120.0f); for (int count = 0; count < 12; count++) { @@ -1855,10 +1872,10 @@ int PromptFreezeDefrost (Boolean freezing) CGContextSetShouldAntialias(ctx, true); CGContextSetLineWidth(ctx, 3.0f); - [[NSColor colorWithDeviceRed:1.0 green:0.7 blue:0.7 alpha:1.0] setFill]; + CGContextSetRGBFillColor(ctx, 1.0, 0.7, 0.7, 1.0); x = rct.origin.x + 5.0f; - y = rct.origin.y + 107.0f; - [[NSString stringWithFormat:@"%c", letters[count]] drawAtPoint:NSMakePoint(x, y) withAttributes:@{NSFontNameAttribute: [NSFont fontWithName:@"Helvetica" size:12.0]}]; + y = rct.origin.y + 102.0f; + DrawString(ctx, [NSString stringWithFormat:@"%c", letters[count]], 12.0, x, y); if (showtimeinfrz) { @@ -1878,17 +1895,15 @@ int PromptFreezeDefrost (Boolean freezing) CFRelease(locale); x = rct.origin.x + 20.0f; - y = rct.origin.y + 107.0f; - [NSColor.whiteColor setFill]; - [[NSString stringWithUTF8String:dateC] drawAtPoint:NSMakePoint(x, y) withAttributes:@{NSFontNameAttribute: [NSFont fontWithName:@"Helvetica" size:10.0]}]; + y = rct.origin.y + 102.0f; + DrawString(ctx, [NSString stringWithUTF8String:dateC], 10.0, x, y); } } else { - [[NSColor colorWithDeviceRed:1.0 green:0.7 blue:0.7 alpha:1.0] setFill]; x = rct.origin.x + 5.0f; - y = rct.origin.y + 107.0f; - [[NSString stringWithFormat:@"%c", letters[count]] drawAtPoint:NSMakePoint(x, y) withAttributes:@{NSFontNameAttribute: [NSFont fontWithName:@"Helvetica" size:12.0]}]; + y = rct.origin.y + 102.0f; + DrawString(ctx, [NSString stringWithFormat:@"%c", letters[count]], 12.0, x, y); } if ((count % 4) == 3) @@ -1933,13 +1948,82 @@ int PromptFreezeDefrost (Boolean freezing) { CopyPressedKeys(keys, gamepadButtons); - for (int count = 0; count <= 12; count++) + while (pressedRawKeyboardButtons[kVK_ANSI_1]) { - while (KeyIsPressed(keys, gamepadButtons, 0, count)) - { - result = count - 1; - CopyPressedKeys(keys, gamepadButtons); - } + result = 0; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_ANSI_2]) + { + result = 1; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_ANSI_3]) + { + result = 2; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_ANSI_4]) + { + result = 3; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_ANSI_5]) + { + result = 4; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_ANSI_6]) + { + result = 5; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_ANSI_7]) + { + result = 6; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_ANSI_8]) + { + result = 7; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_ANSI_9]) + { + result = 8; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_ANSI_A]) + { + result = 9; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_ANSI_B]) + { + result = 10; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_ANSI_C]) + { + result = 11; + usleep(repeatDelay); + } + + while (pressedRawKeyboardButtons[kVK_Return] || pressedRawKeyboardButtons[kVK_ANSI_KeypadEnter]) + { + result = current_selection; + usleep(repeatDelay); } while (KeyIsPressed(keys, gamepadButtons, 0, kRight)) @@ -1949,8 +2033,8 @@ int PromptFreezeDefrost (Boolean freezing) if (current_selection > 11) current_selection -= 12; UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); - while (KeyIsPressed(keys, gamepadButtons, 0, kRight) && (mach_absolute_time() < (startTime + repeatDelay))) - CopyPressedKeys(keys, gamepadButtons); + usleep(repeatDelay); + CopyPressedKeys(keys, gamepadButtons); } while (KeyIsPressed(keys, gamepadButtons, 0, kLeft)) @@ -1960,8 +2044,8 @@ int PromptFreezeDefrost (Boolean freezing) if (current_selection < 0) current_selection += 12; UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); - while (KeyIsPressed(keys, gamepadButtons, 0, kLeft) && (mach_absolute_time() < (startTime + repeatDelay))) - CopyPressedKeys(keys, gamepadButtons); + usleep(repeatDelay); + CopyPressedKeys(keys, gamepadButtons); } while (KeyIsPressed(keys, gamepadButtons, 0, kDown)) @@ -1971,8 +2055,8 @@ int PromptFreezeDefrost (Boolean freezing) if (current_selection > 11) current_selection -= 12; UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); - while (KeyIsPressed(keys, gamepadButtons, 0, kDown) && (mach_absolute_time() < (startTime + repeatDelay))) - CopyPressedKeys(keys, gamepadButtons); + usleep(repeatDelay); + CopyPressedKeys(keys, gamepadButtons); } while (KeyIsPressed(keys, gamepadButtons, 0, kUp)) @@ -1982,33 +2066,15 @@ int PromptFreezeDefrost (Boolean freezing) if (current_selection < 0) current_selection += 12; UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); - while (KeyIsPressed(keys, gamepadButtons, 0, kUp) && (mach_absolute_time() < (startTime + repeatDelay))) - CopyPressedKeys(keys, gamepadButtons); + usleep(repeatDelay); + CopyPressedKeys(keys, gamepadButtons); } - while (KeyIsPressed(keys, gamepadButtons, 1, kA ) || - KeyIsPressed(keys, gamepadButtons, 2, kA ) || - KeyIsPressed(keys, gamepadButtons, 1, kB ) || - KeyIsPressed(keys, gamepadButtons, 2, kB ) || - KeyIsPressed(keys, gamepadButtons, 1, kX ) || - KeyIsPressed(keys, gamepadButtons, 2, kX ) || - KeyIsPressed(keys, gamepadButtons, 1, kY ) || - KeyIsPressed(keys, gamepadButtons, 2, kY ) || - KeyIsPressed(keys, gamepadButtons, 1, kStart ) || - KeyIsPressed(keys, gamepadButtons, 2, kStart ) || - KeyIsPressed(keys, gamepadButtons, 1, kSelect) || - KeyIsPressed(keys, gamepadButtons, 2, kSelect)) + while (ISpKeyIsPressed(keys, gamepadButtons, kISpEsc)) { - CopyPressedKeys(keys, gamepadButtons); - result = current_selection; - } - - while (ISpKeyIsPressed(keys, gamepadButtons, kISpEsc) || - KeyIsPressed(keys, gamepadButtons, 0, kStart) || - KeyIsPressed(keys, gamepadButtons, 1, kStart)) - { - CopyPressedKeys(keys, gamepadButtons); result = -1; + usleep(repeatDelay); + CopyPressedKeys(keys, gamepadButtons); } while (KeyIsPressed(keys, gamepadButtons, 0, kA) || @@ -2019,7 +2085,11 @@ int PromptFreezeDefrost (Boolean freezing) KeyIsPressed(keys, gamepadButtons, 1, kX) || KeyIsPressed(keys, gamepadButtons, 0, kY) || KeyIsPressed(keys, gamepadButtons, 1, kY)) + { result = current_selection; + usleep(repeatDelay); + CopyPressedKeys(keys, gamepadButtons); + } } usleep(30000); @@ -2051,14 +2121,14 @@ static void UpdateFreezeDefrostScreen (int newIndex, CGImageRef image, uint8 *dr if (newIndex >= 0 && newIndex < 12) { CGRect rct; - const int w = SNES_WIDTH << 1, h = kMacWindowHeight; + const int w = SNES_WIDTH << 1, h = SNES_HEIGHT << 1; CGContextSetLineWidth(ctx, 1.0f); rct = CGRectMake(0.0f, 0.0f, (float) w, (float) h); CGContextDrawImage(ctx, rct, image); - rct = CGRectMake(0.0f, (float) h - 238.0f, 128.0f, 120.0f); + rct = CGRectMake(0.0f, (float) h - 208.0f, 128.0f, 120.0f); rct = CGRectOffset(rct, (float) (128 * (newIndex % 4)), (float) (-120 * (newIndex / 4))); rct.size.width -= 1.0f; rct.size.height -= 1.0f; @@ -2545,7 +2615,7 @@ static void Initialize (void) Settings.Stereo = true; Settings.SoundPlaybackRate = 32000; Settings.SoundInputRate = 31950; - Settings.SupportHiRes = true; + Settings.SupportHiRes = false; Settings.Transparency = true; Settings.AutoDisplayMessages = true; Settings.InitialInfoStringTimeout = 120; @@ -2882,6 +2952,8 @@ void QuitWithFatalError ( NSString *message) } } + pressedRawKeyboardButtons[event.keyCode] = true; + os_unfair_lock_unlock(&keyLock); } @@ -2904,6 +2976,8 @@ void QuitWithFatalError ( NSString *message) } } + pressedRawKeyboardButtons[event.keyCode] = false; + os_unfair_lock_unlock(&keyLock); } diff --git a/macosx/mac-screenshot.mm b/macosx/mac-screenshot.mm index 02a6eea6..ae349979 100644 --- a/macosx/mac-screenshot.mm +++ b/macosx/mac-screenshot.mm @@ -31,6 +31,10 @@ #include "mac-render.h" #include "mac-screenshot.h" +extern "C" { +#include "FakeResources.h" +} + const char *extendedAttributeName = "com.snes9x.preview"; unsigned char *CGImageToPNGData (CGImageRef image, CFIndex *outLength); @@ -199,26 +203,79 @@ void DrawThumbnailFromExtendedAttribute (const char *path, CGContextRef ctx, CGR unsigned char *buffer = (unsigned char *)malloc(size); if (buffer != NULL) { - CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, buffer, size, NULL); + getxattr(path, extendedAttributeName, buffer, size, 0, 0); + NSData *data = [NSData dataWithBytes:buffer length:size]; if (data) { - CGImageSourceRef source = CGImageSourceCreateWithData(data, NULL); - if (source) - { - CGImageRef image = CGImageSourceCreateImageAtIndex(source, 0, NULL); - if (image) - { - CGContextDrawImage(ctx, bounds, image); - CGImageRelease(image); - } - } + NSImage *image = [[NSImage alloc] initWithData:data]; - CFRelease(data); + if (image) + { + CGContextDrawImage(ctx, bounds, [image CGImageForProposedRect:NULL context:[NSGraphicsContext currentContext] hints:nil]); + } } free(buffer); } } + else + { + struct FakeResourceMap *resourceMap = FakeResFileOpen(std::string(std::string(path) + "/..namedfork/rsrc").c_str(), "r"); + if (resourceMap != NULL) + { + int16 fileNum = FakeCurResFile(); + Handle pict = FakeGet1Resource('PICT', 128); + if (pict) + { + Size size = FakeGetHandleSize(pict); + NSData *imageData = [NSData dataWithBytes:*pict length:size]; + + if (imageData) + { + NSImage *image = [[NSImage alloc] initWithData:imageData]; + + if (image) + { + CGContextDrawImage(ctx, bounds, [image CGImageForProposedRect:NULL context:[NSGraphicsContext currentContext] hints:nil]); + } + } + } + else + { + pict = FakeGet1Resource('Thum', 128); + Size size = FakeGetHandleSize(pict); + NSData *imageData = [NSData dataWithBytes:*pict length:size]; + + if (imageData) + { + CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, (__bridge CFDataRef)imageData, size, NULL); + + if (provider) + { + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + + if (colorSpace) + { + CGImageRef image = CGImageCreate(128, 120, 5, 16, 256, colorSpace, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder16Big, provider, NULL, 0, kCGRenderingIntentDefault); + + if (image) + { + CGContextDrawImage(ctx, bounds, image); + CGImageRelease(image); + } + + CGColorSpaceRelease(colorSpace); + } + + CFRelease(provider); + } + } + } + + FakeCloseResFile(fileNum); + } + + } CGContextRestoreGState(ctx); } diff --git a/macosx/snes9x.xcodeproj/project.pbxproj b/macosx/snes9x.xcodeproj/project.pbxproj index e098095f..3fa6d545 100755 --- a/macosx/snes9x.xcodeproj/project.pbxproj +++ b/macosx/snes9x.xcodeproj/project.pbxproj @@ -54,6 +54,11 @@ 307C863322D29E29001B879E /* mac-stringtools.mm in Sources */ = {isa = PBXBuildFile; fileRef = EAECB68804AC7FCE00A80003 /* mac-stringtools.mm */; }; 308092F72320B041006A2860 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 308092F62320B041006A2860 /* CoreGraphics.framework */; }; 308092F92320B06F006A2860 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 308092F82320B06F006A2860 /* Quartz.framework */; }; + 3082C4232378BCE80081CA7C /* FakeHandles.h in Headers */ = {isa = PBXBuildFile; fileRef = 3082C41E2378BCE80081CA7C /* FakeHandles.h */; }; + 3082C4242378BCE80081CA7C /* EndianStuff.h in Headers */ = {isa = PBXBuildFile; fileRef = 3082C41F2378BCE80081CA7C /* EndianStuff.h */; }; + 3082C4252378BCE80081CA7C /* FakeHandles.c in Sources */ = {isa = PBXBuildFile; fileRef = 3082C4202378BCE80081CA7C /* FakeHandles.c */; }; + 3082C4262378BCE80081CA7C /* FakeResources.c in Sources */ = {isa = PBXBuildFile; fileRef = 3082C4212378BCE80081CA7C /* FakeResources.c */; }; + 3082C4272378BCE80081CA7C /* FakeResources.h in Headers */ = {isa = PBXBuildFile; fileRef = 3082C4222378BCE80081CA7C /* FakeResources.h */; }; 30D15CF322CE6B5A005BC352 /* snes9x_framework.h in Headers */ = {isa = PBXBuildFile; fileRef = 30D15CF122CE6B5A005BC352 /* snes9x_framework.h */; settings = {ATTRIBUTES = (Public, ); }; }; 30D15CFC22CE6B74005BC352 /* sha256.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 85FEF90A20DDB18D00C038E9 /* sha256.cpp */; }; 30D15CFE22CE6B74005BC352 /* bml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 85FEF90620DDB15B00C038E9 /* bml.cpp */; }; @@ -257,6 +262,11 @@ 307C861C22D29DD2001B879E /* GLUT.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLUT.framework; path = System/Library/Frameworks/GLUT.framework; sourceTree = SDKROOT; }; 308092F62320B041006A2860 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 308092F82320B06F006A2860 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; }; + 3082C41E2378BCE80081CA7C /* FakeHandles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FakeHandles.h; sourceTree = ""; }; + 3082C41F2378BCE80081CA7C /* EndianStuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EndianStuff.h; sourceTree = ""; }; + 3082C4202378BCE80081CA7C /* FakeHandles.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = FakeHandles.c; sourceTree = ""; }; + 3082C4212378BCE80081CA7C /* FakeResources.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = FakeResources.c; sourceTree = ""; }; + 3082C4222378BCE80081CA7C /* FakeResources.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FakeResources.h; sourceTree = ""; }; 30AD1D1E22FBB2EA000EE989 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 30AD1D1F22FBB2EA000EE989 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 30AD1D2022FBB2EA000EE989 /* en */ = {isa = PBXFileReference; lastKnownFileType = folder; name = en; path = "en.lproj/Snes9x Help"; sourceTree = ""; }; @@ -549,6 +559,7 @@ 20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */, 30D15CF022CE6B5A005BC352 /* snes9x framework */, 30714716230E379500917F82 /* Snes9x */, + 3082C41D2378BC280081CA7C /* ReClassicfication */, 195DF8C9FE9D4F0611CA2CBB /* Products */, 3045A1EB22D03C420092B97D /* Frameworks */, ); @@ -624,6 +635,18 @@ path = Snes9x; sourceTree = ""; }; + 3082C41D2378BC280081CA7C /* ReClassicfication */ = { + isa = PBXGroup; + children = ( + 3082C41F2378BCE80081CA7C /* EndianStuff.h */, + 3082C4202378BCE80081CA7C /* FakeHandles.c */, + 3082C41E2378BCE80081CA7C /* FakeHandles.h */, + 3082C4212378BCE80081CA7C /* FakeResources.c */, + 3082C4222378BCE80081CA7C /* FakeResources.h */, + ); + path = ReClassicfication; + sourceTree = ""; + }; 30D15CF022CE6B5A005BC352 /* snes9x framework */ = { isa = PBXGroup; children = ( @@ -966,6 +989,7 @@ 30D15DA122CE6BC9005BC352 /* debug.h in Headers */, 30D15DA222CE6BC9005BC352 /* display.h in Headers */, 30D15DA322CE6BC9005BC352 /* dma.h in Headers */, + 3082C4242378BCE80081CA7C /* EndianStuff.h in Headers */, 30D15DA422CE6BC9005BC352 /* dsp.h in Headers */, 30D15DA522CE6BC9005BC352 /* font.h in Headers */, 30D15DA622CE6BC9005BC352 /* fxemu.h in Headers */, @@ -977,6 +1001,7 @@ 30D15DAC22CE6BC9005BC352 /* memmap.h in Headers */, 30D15DAD22CE6BC9005BC352 /* messages.h in Headers */, 30D15DAE22CE6BC9005BC352 /* missing.h in Headers */, + 3082C4272378BCE80081CA7C /* FakeResources.h in Headers */, 30D15DAF22CE6BC9005BC352 /* movie.h in Headers */, 30D15DB022CE6BC9005BC352 /* msu1.h in Headers */, 30D15DB122CE6BC9005BC352 /* obc1.h in Headers */, @@ -996,6 +1021,7 @@ 30D15DC322CE6BC9005BC352 /* tile.h in Headers */, 30D15DC422CE6BC9005BC352 /* apu.h in Headers */, 30D15DC522CE6BC9005BC352 /* blargg_common.h in Headers */, + 3082C4232378BCE80081CA7C /* FakeHandles.h in Headers */, 30D15DC622CE6BC9005BC352 /* blargg_config.h in Headers */, 30D15DC722CE6BC9005BC352 /* blargg_endian.h in Headers */, 30D15DC822CE6BC9005BC352 /* blargg_source.h in Headers */, @@ -1197,6 +1223,7 @@ 30D15D3122CE6B74005BC352 /* cheats2.cpp in Sources */, 30D15D3222CE6B74005BC352 /* clip.cpp in Sources */, 30D15D3322CE6B74005BC352 /* controls.cpp in Sources */, + 3082C4262378BCE80081CA7C /* FakeResources.c in Sources */, 30D15D3422CE6B74005BC352 /* cpu.cpp in Sources */, 30D15D3522CE6B74005BC352 /* cpuexec.cpp in Sources */, 30D15D3622CE6B74005BC352 /* cpuops.cpp in Sources */, @@ -1205,6 +1232,7 @@ 30D15D3922CE6B74005BC352 /* dma.cpp in Sources */, 307C861222D27C53001B879E /* tileimpl-n1x1.cpp in Sources */, 30D15D3A22CE6B74005BC352 /* dsp.cpp in Sources */, + 3082C4252378BCE80081CA7C /* FakeHandles.c in Sources */, 30D15D3B22CE6B74005BC352 /* dsp1.cpp in Sources */, 307C861622D27C53001B879E /* tileimpl-n2x1.cpp in Sources */, 30D15D3C22CE6B74005BC352 /* dsp2.cpp in Sources */,