#include "SaiCPA.h" #include "MmgSai.h" #include "ErmSai.h" #include "Sai_Enum.h" #include "Sai_Pub.h" #include "Sai_str.h" #include "Sai_Priv.h" #include "Sai_Save.h" #include "cmp.h" /* To avoid using compressed file in debug mode */ /* (uncompressed files are easier to view :-)*/ #ifdef _DEBUG #undef SAVEGAME_COMPRESSION #else #define SAVEGAME_COMPRESSION #endif /**************************************************************************/ unsigned char SAI_fn_ucSaveAllGameTableValues(struct SAI_tdstInternalStructure_ *p_stInternalStructure,char *_szFileName,SAI_tdeFlags _eFlags) { unsigned char bReturn = SAI_TRUE; SAI_tdxHandleToListEntry hListEntry = p_stInternalStructure -> p_stFirstEntry; FILE *p_stTempFile; #ifdef SAVEGAME_COMPRESSION char szTempFile[_MAX_PATH]; sprintf(szTempFile,"%s/TT.tmp",fn_szGetTempDataPath()); DeleteFile(szTempFile); FIL_fn_bValidatePath(".",_szFileName); p_stTempFile = fopen(szTempFile,"wb"); #else /* SAVEGAME_COMPRESSION */ FIL_fn_bValidatePath(".",_szFileName); p_stTempFile = fopen(_szFileName,"wb"); #endif /* SAVEGAME_COMPRESSION */ if (p_stTempFile!=NULL) { SAI_fn_vClearBooleanBuffer(); while (hListEntry) { if ((hListEntry->eFlags&(_eFlags))) SAI_fn_ucSaveGameTableValue(hListEntry,p_stTempFile); hListEntry = hListEntry -> p_stNextEntry; } SAI_fn_vFlushBooleanBuffer( p_stTempFile ); fclose(p_stTempFile); #ifndef _DEBUG CMP_fn_vCompressFileIn(szTempFile,_szFileName,D_CMP_DIFF); #endif } else bReturn = SAI_FALSE; #ifdef SAVEGAME_COMPRESSION DeleteFile(szTempFile); #endif /* SAVEGAME_COMPRESSION */ return(bReturn); } /**************************************************************************/ unsigned char SAI_fn_ucSaveGameTableValue(SAI_tdxHandleToListEntry hListEntry,FILE *_p_stFile) { unsigned char bReturn = SAI_TRUE; switch( hListEntry->eFlags & C_TypesFlags ) { /* GuS : Save a boolean */ /* (WARNING: all boolean entries must be at the end of the list, no other data should be saved AFTER booleans,*/ /* More over, the list must be saved from the first element to the last one.)*/ case SAI_eType1: if (hListEntry->eFlags&SAI_ePlayerSaveTableValue||hListEntry->eFlags&SAI_eLevelSaveTableValue) SAI_fn_vSaveBoolean( hListEntry->uData.stBooleanData.ucCharData, hListEntry->uData.stBooleanData.ucBitPosition, _p_stFile ); else if(hListEntry->eFlags&SAI_ePlayerSaveCurrentValue||hListEntry->eFlags&SAI_eLevelSaveCurrentValue) SAI_fn_vSaveBoolean( *(unsigned char *)hListEntry->p_vDataPointer, hListEntry->uData.stBooleanData.ucBitPosition, _p_stFile ); else M_SAIFatalError(E_uwSAI_InvalidSaveMode); break; case SAI_eType8: if (hListEntry->eFlags&SAI_ePlayerSaveTableValue||hListEntry->eFlags&SAI_eLevelSaveTableValue) fwrite(&hListEntry->uData.ucCharData,1,sizeof(unsigned char),_p_stFile); else if(hListEntry->eFlags&SAI_ePlayerSaveCurrentValue||hListEntry->eFlags&SAI_eLevelSaveCurrentValue) fwrite(hListEntry->p_vDataPointer,1,sizeof(unsigned char),_p_stFile); else M_SAIFatalError(E_uwSAI_InvalidSaveMode); break; case SAI_eType16: if (hListEntry->eFlags&SAI_ePlayerSaveTableValue||hListEntry->eFlags&SAI_eLevelSaveTableValue) fwrite(&hListEntry->uData.uwShortData,1,sizeof(unsigned short),_p_stFile); else if(hListEntry->eFlags&SAI_ePlayerSaveCurrentValue||hListEntry->eFlags&SAI_eLevelSaveCurrentValue) fwrite(hListEntry->p_vDataPointer,1,sizeof(unsigned short),_p_stFile); else M_SAIFatalError(E_uwSAI_InvalidSaveMode); break; case SAI_eType32: if (hListEntry->eFlags&SAI_ePlayerSaveTableValue||hListEntry->eFlags&SAI_eLevelSaveTableValue) fwrite(&hListEntry->uData.ulLongData,1,sizeof(unsigned long),_p_stFile); else if(hListEntry->eFlags&SAI_ePlayerSaveCurrentValue||hListEntry->eFlags&SAI_eLevelSaveCurrentValue) fwrite(hListEntry->p_vDataPointer,1,sizeof(unsigned long),_p_stFile); else M_SAIFatalError(E_uwSAI_InvalidSaveMode); break; case SAI_eType64: if (hListEntry->eFlags&SAI_ePlayerSaveTableValue||hListEntry->eFlags&SAI_eLevelSaveTableValue) fwrite(&hListEntry->uData.i64Long64Data,1,sizeof(tdLong64),_p_stFile); else if(hListEntry->eFlags&SAI_ePlayerSaveCurrentValue||hListEntry->eFlags&SAI_eLevelSaveCurrentValue) fwrite(hListEntry->p_vDataPointer,1,sizeof(tdLong64),_p_stFile); else M_SAIFatalError(E_uwSAI_InvalidSaveMode); break; case SAI_eTypePointer: if (hListEntry->eFlags&SAI_ePlayerSaveTableValue||hListEntry->eFlags&SAI_eLevelSaveTableValue) { fwrite(&hListEntry->uData.stPointerData.uwBlocAndModuleID,1,sizeof(unsigned short),_p_stFile); fwrite(&hListEntry->uData.stPointerData.p_vPointer,1,sizeof(void *),_p_stFile); } else if(hListEntry->eFlags&SAI_ePlayerSaveCurrentValue||hListEntry->eFlags&SAI_eLevelSaveCurrentValue) { void *p_vBeginBloc; unsigned short uwBlocId; void *p_vPointer = (void*)(*((void**)hListEntry->p_vDataPointer)); if (p_vPointer!=NULL) { Mmg_fn_vWhereIs((void*)p_vPointer,&uwBlocId,&p_vBeginBloc); if (uwBlocId==0xffff) p_vPointer = (void*)p_vPointer; else p_vPointer = (void*)(((long)p_vPointer)-(long)p_vBeginBloc); } else uwBlocId = 0xffff; fwrite(&uwBlocId,1,sizeof(unsigned short),_p_stFile); fwrite(&p_vPointer,1,sizeof(void *),_p_stFile); } else M_SAIFatalError(E_uwSAI_InvalidSaveMode); break; case SAI_eTypeXX: if (hListEntry->eFlags&SAI_ePlayerSaveTableValue||hListEntry->eFlags&SAI_eLevelSaveTableValue) fwrite(hListEntry->uData.stArrayData.p_ucPointer,hListEntry->uData.stArrayData.ulArraySize,sizeof(unsigned char),_p_stFile); else if(hListEntry->eFlags&SAI_ePlayerSaveCurrentValue||hListEntry->eFlags&SAI_eLevelSaveCurrentValue) fwrite(hListEntry->p_vDataPointer,hListEntry->uData.stArrayData.ulArraySize,sizeof(unsigned char),_p_stFile); else M_SAIFatalError(E_uwSAI_InvalidSaveMode); break; default: bReturn = SAI_FALSE; break; } return(bReturn); } /**************************************************************************/ unsigned char SAI_fn_ucLoadGameTableValue( SAI_tdxHandleToListEntry hListEntry, FILE *_p_stFile ) { unsigned char bReturn = SAI_TRUE; if (!feof(_p_stFile)) { switch( hListEntry->eFlags & C_TypesFlags ) { case SAI_eType1: hListEntry->uData.stBooleanData.ucCharData = (unsigned char)(SAI_fn_cLoadBoolean( _p_stFile ) << hListEntry->uData.stBooleanData.ucBitPosition); break; case SAI_eType8: fread(&hListEntry->uData.ucCharData,1,sizeof(hListEntry->uData.ucCharData),_p_stFile); break; case SAI_eType16: fread(&hListEntry->uData.uwShortData,1,sizeof(hListEntry->uData.uwShortData),_p_stFile); break; case SAI_eType32: fread(&hListEntry->uData.ulLongData,1,sizeof(hListEntry->uData.ulLongData),_p_stFile); break; case SAI_eType64: fread(&hListEntry->uData.i64Long64Data,1,sizeof(hListEntry->uData.i64Long64Data),_p_stFile); break; case SAI_eTypePointer: fread(&hListEntry->uData.stPointerData.uwBlocAndModuleID,1,sizeof(hListEntry->uData.stPointerData.uwBlocAndModuleID),_p_stFile); fread(&hListEntry->uData.stPointerData.p_vPointer,1,sizeof(hListEntry->uData.stPointerData.p_vPointer),_p_stFile); break; case SAI_eTypeXX: fread(hListEntry->uData.stArrayData.p_ucPointer,hListEntry->uData.stArrayData.ulArraySize,sizeof(*hListEntry->uData.stArrayData.p_ucPointer),_p_stFile); break; default: bReturn = SAI_FALSE; break; } } return(bReturn); } /**************************************************************************/ unsigned char SAI_fn_ucLoadAllGameTableValues( struct SAI_tdstInternalStructure_ *p_stInternalStructure, char *_szFileName, SAI_tdeFlags _eFlags ) { unsigned char bReturn = SAI_FALSE; SAI_tdxHandleToListEntry hListEntry = p_stInternalStructure -> p_stFirstEntry; FILE *p_stTempFile; #ifdef SAVEGAME_COMPRESSION char szTempFile[_MAX_PATH]; sprintf(szTempFile,"%s/TT.tmp",fn_szGetTempDataPath()); DeleteFile(szTempFile); if (CMP_fn_bExpandFileIn(_szFileName,szTempFile,D_CMP_DIFF)) { p_stTempFile = fopen(szTempFile,"rb"); #else /* SAVEGAME_COMPRESSION */ p_stTempFile = fopen(_szFileName,"rb"); #endif /* SAVEGAME_COMPRESSION */ if (p_stTempFile!=NULL) { SAI_fn_vClearBooleanBuffer(); while (hListEntry) { if( hListEntry->eFlags & _eFlags ) SAI_fn_ucLoadGameTableValue( hListEntry, p_stTempFile ); hListEntry = hListEntry -> p_stNextEntry; } fclose(p_stTempFile); bReturn = SAI_TRUE; } #ifdef SAVEGAME_COMPRESSION } DeleteFile(szTempFile); #endif return(bReturn); } /**************************************************************************/ /* GuS*/ /* To optimize saving of boolean data, all booleans are grouped by 8 in a char.*/ /* To achieve this, saving is bufferised into one char witch is written to file*/ /* only when it is full.*/ static unsigned char g_ucBooleanBuffer = 0; static unsigned char g_ucCurrentPosition = 0; /* Next bit to be read or set (0..7)*/ void SAI_fn_vSaveBoolean( unsigned char _ucData, unsigned char _ucBitPosition, FILE *_p_stFile ) { g_ucBooleanBuffer |= ((_ucData >> _ucBitPosition) & (unsigned char)1 ) << g_ucCurrentPosition; g_ucCurrentPosition++; if( g_ucCurrentPosition > 7 ) SAI_fn_vFlushBooleanBuffer( _p_stFile ); } /**************************************************************************/ /* GuS*/ /* Function for reading boolean previously saved with SAI_fn_vSaveBoolean.*/ /* Return one boolean in the first (lowest) bit of a char.*/ /* Return -1 if end of file is reached.*/ char SAI_fn_cLoadBoolean( FILE *_p_stFile ) { if( g_ucCurrentPosition == 0 || g_ucCurrentPosition > 7 ) { if( fread( &g_ucBooleanBuffer, 1, sizeof(unsigned char), _p_stFile ) == 0 ) return -1; g_ucCurrentPosition = 0; } return (unsigned char)((g_ucBooleanBuffer >> (g_ucCurrentPosition++)) & 1); } /**************************************************************************/ void SAI_fn_vClearBooleanBuffer() { g_ucBooleanBuffer = 0; g_ucCurrentPosition = 0; } /**************************************************************************/ void SAI_fn_vFlushBooleanBuffer( FILE *_p_stFile ) { if( g_ucCurrentPosition ) { fwrite( &g_ucBooleanBuffer, 1, sizeof(unsigned char), _p_stFile ); g_ucBooleanBuffer = 0; g_ucCurrentPosition = 0; } } /**************************************************************************/