//fileio.h //Utilities for reading and writing to files in the game's subdirectories //fileio works by creating a table of all files within the applications directory //at startup. this way all files we need can be addressed simply using reference numbers. //sometimes also refered to as "ID numbers". #include #include #include #include #include "fileio.h" #include #include "gamemem.h" #include "error.h" #include "parser.h" int gFileTableSize; //size of the file reference table int gFileTableExtendedSize; int gFileTampered=false; tFileTableEntry *gFileTable; //the file reference table char gNoName[]=""; void FileInitFileTable(tFileTableEntry *fileTable,int maxSize,int *fileTableSize,int reInit); #define kNumValidateFiles 42 char gValidateNames[][256]={ "500gt.car", "500gthotrod.car", "959.car", "maserati.car", "bmw2002.car", "charger.car", "chargerdragdrag.car", "corvette.car", "diablo.car", "dmc12.car", "dmc12flying.car", "gt40.car", "gti.car", "mini.car", "55ford.car", "tt.car", "ttpimp.car", "viper.car", "viperracer.car", "accelbrake.mapinfo", "accelbrake2.mapinfo", "canyon.mapinfo", "canyoncorner.mapinfo", "city2.mapinfo", "citycorner.mapinfo", "downhill.mapinfo", "highspeed.mapinfo", "highspeedtrial.mapinfo", "mountainside.mapinfo", "offroad.mapinfo", "quarter.mapinfo", "ralley2.mapinfo", "scorner.mapinfo", "slalom.mapinfo", "slalom2.mapinfo", "snow.mapinfo", "snowtrial.mapinfo", "tight.mapinfo", "canyon.road", "city2.road", "mountainside.road", "ralley2.road", "snow.road", }; int gValidateChecksums[]={ 0xc98d7f36, 0x833e4a7d, 0xdcd7e89, 0x3e6a08b7, 0x251efab, 0xed2a6577, 0x6d654b5, 0x1c468570, 0x1380a984, 0x7c69956, 0xcc2746e4, 0x22349629, 0x8d0d50b4, 0x51994161, 0x90a4cc85, 0x931cbd6c, 0xe42301b9, 0xcc9bd572, 0x1b7951e7, 0x72d87975, 0x1eb05d11, 0xa2182ab9, 0xde1122e6, 0xc44b1aab, 0x815cb099, 0x8eb6b530, 0x6c93ce2, 0x77263bb7, 0x18ebbbad, 0xc57f8785, 0x117ba80c, 0xb513b806, 0x75938236, 0x2437d140, 0xb249c233, 0x6e92dc33, 0x9e5c31de, 0x8766b155, 0x1bbdc55d, 0x28f6a9b8, 0x66e5492e, 0x8b5a55d8, }; //Initialize file reference table void FileInitIO() { gFileTableExtendedSize=0; gFileTableSize=0; gFileTable=(tFileTableEntry*)calloc(kMaxFiles,sizeof(tFileTableEntry)); FileInitFileTable(gFileTable,kMaxFiles,&gFileTableSize,false); for(int i=0;iname,((tFileTableEntry*)b)->name); } int gFileErrorReporting=true; //Search file reference table for a file matching a name and return its reference number tFileRef FileGetReference(char *name) { if(*name=='\0') return -1; //the key to search for tFileTableEntry key; #ifndef __TARGET_TEXTURECOMPRESSOR #ifndef __TARGET_TOOLAPP snprintf(key.name,32,"%s.txr",name); //search for an entry matching our search key tFileTableEntry *result=(tFileTableEntry*)bsearch(&key,gFileTable,gFileTableSize,sizeof(tFileTableEntry),&FileTableCompare); //return results if(result) return result-gFileTable; else { snprintf(key.name,32,"%s.ima",name); //search for an entry matching our search key tFileTableEntry *result=(tFileTableEntry*)bsearch(&key,gFileTable,gFileTableSize,sizeof(tFileTableEntry),&FileTableCompare); //return results if(result) return result-gFileTable; else { #endif #endif strcpy(key.name,name); tFileTableEntry *result=(tFileTableEntry*)bsearch(&key,gFileTable,gFileTableSize,sizeof(tFileTableEntry),&FileTableCompare); if(result) return result-gFileTable; else { for(int i=gFileTableSize;i0) { char nameCopy[kMaxFileNameLength]; strcpy(nameCopy,FileGetName(base)); char *found=strchr(nameCopy,'.'); char indexedName[kMaxFileNameLength]; if(found) { *found='\0'; sprintf(indexedName,"%s#%x.%s",nameCopy,i,found+1); } else sprintf(indexedName,"%s#%x",nameCopy,i); int seek=base-1; while(_stricmp(gFileTable[seek].name,indexedName)>0&&seek>0) seek--; if(_stricmp(gFileTable[seek].name,indexedName)) return base; else return seek; } else return base; } tFileRef FileGetBaseReference(tFileRef ref) { if(ref<0||ref>=gFileTableExtendedSize+gFileTableSize) return kFileErr; char *found=strchr(FileGetName(ref),'.'); if(!found) return ref; char *cross=found; while(*cross!='#'&&cross>FileGetName(ref)) cross--; if(*cross!='#') return ref; int l=cross-FileGetName(ref); char nameCopy[kMaxFileNameLength]; memcpy(nameCopy,FileGetName(ref),l); strcpy(nameCopy+l,found); tFileRef base=FileGetReference(nameCopy); return base!=kFileErr?base:ref; } //platform specific, can be found in macfileio.cpp int FileLoadData(tFileRef fileRef); void FileStoreData(tFileRef fileRef); //return the extension of a file given it's reference number char *FileGetExtension(tFileRef reference) { if(reference<0||reference>=gFileTableExtendedSize+gFileTableSize) return NULL; char *found=NULL; char *dot=gFileTable[reference].name; do{ dot=strchr(dot,'.'); if(dot){ found=dot; dot++; } }while(dot); if(found) return found; else return gFileTable[reference].name+strlen(gFileTable[reference].name);//'\0'; } //return the name of a file given it's reference number char *FileGetName(tFileRef reference) { if(reference<0||reference>=gFileTableExtendedSize+gFileTableSize) return gNoName; return gFileTable[reference].name; } //return the size of a file given it's reference number int FileGetSize(tFileRef reference) { if(reference<0||reference>=gFileTableExtendedSize+gFileTableSize) return 0; if(!gFileTable[reference].loaded) gFileTable[reference].loaded=FileLoadData(reference); return gFileTable[reference].size; } //return a pointer to the file's data (and load the file if necessary) void *FileGetDataPtr(tFileRef reference) { if(reference<0||reference>=gFileTableExtendedSize+gFileTableSize) return NULL; if(!gFileTable[reference].loaded) gFileTable[reference].loaded=FileLoadData(reference); return gFileTable[reference].loaded?gFileTable[reference].data:(void*)0; } unsigned int FileGetChecksum(tFileRef reference) { if(reference<0||reference>=gFileTableExtendedSize+gFileTableSize) return 0; return MemoryChecksum(FileGetDataPtr(reference),FileGetSize(reference)); } //Changes a file's contents to data, and writes the file to disk. void FileSetData(tFileRef reference,void *data) { if(reference<0||reference>=gFileTableExtendedSize+gFileTableSize) return; if(gFileTable[reference].loaded&&data!=gFileTable[reference].data) MemoryFreeBlock(gFileTable[reference].data); gFileTable[reference].data=data; gFileTable[reference].loaded=true; gFileTable[reference].size=MemoryBlockSize(data); FileStoreData(reference); } //parses a file's data using a file format parser //and return a pointer to parsed data structure void* FileGetParsedDataPtr(tFileRef reference, int parserType, int dataSize) { if(reference<0||reference>=gFileTableExtendedSize+gFileTableSize) return NULL; if(!gFileTable[reference].parsed) { gFileTable[reference].parsedData=MemoryAllocateZeroedBlock(dataSize); ParseFile(reference,gFileTable[reference].parsedData,parserType); gFileTable[reference].parsed=true; } return gFileTable[reference].parsedData; }