647 lines
21 KiB
C
647 lines
21 KiB
C
/*=========================================================================
|
||
* Snammg.c : Save & Read the memory blocks
|
||
*
|
||
* Version 1.0
|
||
* Creation date 03/09/97
|
||
* Revision date
|
||
*
|
||
* (c) Ubi R&D 1997
|
||
*=======================================================================*/
|
||
|
||
#include "MMG.h"
|
||
#include "ToolsCPA.h"
|
||
#include "SNA.h"
|
||
#include "snafile.h"
|
||
#include "windows.h"
|
||
#include "acp_opfi.h"
|
||
|
||
|
||
// This define allows the encryption of the .sna files.
|
||
// Comment it for no encryption.
|
||
#define SNA_ENCRYPTION
|
||
|
||
ACP_tdxBool g_a_bIsBlocRelocated[C_ucNbOfMaxModule][10];
|
||
long g_a_ulOffset[C_ucNbOfMaxModule][10];
|
||
|
||
extern unsigned char g_ucGameModuleId;
|
||
extern unsigned char g_ucAIModuleId;
|
||
extern unsigned char g_ucGEOModuleId;
|
||
extern unsigned char g_ucIPTModuleId;
|
||
extern unsigned char g_ucFONModuleId;
|
||
extern unsigned char g_ucTMPModuleId;
|
||
extern unsigned char g_ucSndModuleId;
|
||
|
||
// Memory blocks that are saved for each level.
|
||
// Ex: (Game,0) => Block 0 of module Game.
|
||
struct tdstModuleBloc_ g_a_stModuleBlocToSaveInLevel[] =
|
||
{
|
||
SNA_M_SetBlocForSaving( Game, 1 ),
|
||
SNA_M_SetBlocForSaving( GEO, 2 ),
|
||
SNA_M_SetBlocForSaving( AI, 1 )
|
||
};
|
||
|
||
// Memory blocks that are saved in the fix.
|
||
struct tdstModuleBloc_ g_a_stModuleBlocToSaveInFix[] =
|
||
{
|
||
SNA_M_SetBlocForSaving( Game, 0 ),
|
||
SNA_M_SetBlocForSaving( GEO, 0 ),
|
||
SNA_M_SetBlocForSaving( GEO, 1 ),
|
||
SNA_M_SetBlocForSaving( IPT, 0 ),
|
||
SNA_M_SetBlocForSaving( AI, 0 ),
|
||
SNA_M_SetBlocForSaving( FON, 0 )
|
||
};
|
||
|
||
// Memory blocks that are NOT saved, but some infos will be included for relocation purpose.
|
||
// Actually, pointers from other blocks to these blocks will be correctly relocated.
|
||
// (except for TMP block: pointers to TMP will be set to NULL at load time)
|
||
struct tdstModuleBloc_ g_a_stModuleBlocToSaveInfos[] =
|
||
{
|
||
SNA_M_SetBlocForSaving( TMP, 0 ),
|
||
SNA_M_SetBlocForSaving( Snd, 0 )
|
||
};
|
||
|
||
unsigned long SNA_g_ulNbBlocksInFix = SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInFix);
|
||
unsigned long SNA_g_ulNbBlocksInLevel = SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInLevel);
|
||
|
||
char g_bSaveLoadFix;
|
||
|
||
|
||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
// Sort an array of blocks so that blocks are sorted by module and block number.
|
||
// An old good bubble sort :-)
|
||
void SNA_fn_vSortAnArray( struct tdstModuleBloc_ *_p_stArray, unsigned long _ulArraySize )
|
||
{
|
||
struct tdstModuleBloc_ *p_stArray2;
|
||
struct tdstModuleBloc_ *p_stLastElement = _p_stArray + _ulArraySize-1;
|
||
struct tdstModuleBloc_ *p_stEndOfArray = p_stLastElement + 1;
|
||
struct tdstModuleBloc_ stTmp;
|
||
|
||
for( ; _p_stArray < p_stLastElement; _p_stArray++ )
|
||
for( p_stArray2 = _p_stArray+1; p_stArray2 < p_stEndOfArray; p_stArray2++ )
|
||
if( (*(_p_stArray->p_ucModuleId) > *(p_stArray2->p_ucModuleId))
|
||
|| ( (*(_p_stArray->p_ucModuleId) == *(p_stArray2->p_ucModuleId))
|
||
&& (_p_stArray->ucBlockId > p_stArray2->ucBlockId) ) )
|
||
{
|
||
memcpy( &stTmp, _p_stArray, sizeof(struct tdstModuleBloc_) );
|
||
memcpy( _p_stArray, p_stArray2, sizeof(struct tdstModuleBloc_) );
|
||
memcpy( p_stArray2, &stTmp, sizeof(struct tdstModuleBloc_) );
|
||
}
|
||
}
|
||
|
||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
void SNA_fn_vSetSaveLoadFix()
|
||
{
|
||
g_bSaveLoadFix=TRUE;
|
||
}
|
||
|
||
void SNA_fn_vSetSaveLoadLevel()
|
||
{
|
||
g_bSaveLoadFix=FALSE;
|
||
}
|
||
|
||
|
||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
// Tells if the bloc is to be loaded.
|
||
// Assumes that arrays of block are SORTED by module and block.
|
||
BOOL SNA_fn_bLoadThisModuleBloc( unsigned char _ucModule, unsigned char _ucBlock )
|
||
{
|
||
struct tdstModuleBloc_ *p_stArray, *p_stEndArray;
|
||
// Test Fix array when we load the fix or level array when we load the level
|
||
if( g_bSaveLoadFix )
|
||
{
|
||
p_stArray = g_a_stModuleBlocToSaveInFix;
|
||
p_stEndArray = p_stArray+SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInFix);
|
||
}
|
||
else
|
||
{
|
||
p_stArray = g_a_stModuleBlocToSaveInLevel;
|
||
p_stEndArray = p_stArray+SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInLevel);
|
||
}
|
||
|
||
// Go to the first block that have the module number "_ucModule"
|
||
while( p_stArray < p_stEndArray
|
||
&& _ucModule > *(p_stArray->p_ucModuleId) )
|
||
p_stArray ++;
|
||
|
||
// If we find one block with the good module ID, find the one with the good block ID.
|
||
if( p_stArray<p_stEndArray )
|
||
while( p_stArray < p_stEndArray
|
||
&& _ucModule == *(p_stArray->p_ucModuleId) )
|
||
{
|
||
if( _ucBlock == p_stArray->ucBlockId )
|
||
// Found one, return TRUE
|
||
return TRUE;
|
||
p_stArray ++;
|
||
}
|
||
|
||
// Block was not found in array, return FALSE
|
||
return FALSE;
|
||
}
|
||
|
||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
// Initialise the global arrays that hold the block to save and load.
|
||
// Basically, that means sorting them by module ID and block ID.
|
||
// The sorting needs to be done only once.
|
||
void SNA_fn_vInitArrays()
|
||
{
|
||
static ucArrayAreSorted = 0;
|
||
if( ! ucArrayAreSorted )
|
||
{
|
||
SNA_fn_vSortAnArray(g_a_stModuleBlocToSaveInFix, SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInFix) );
|
||
SNA_fn_vSortAnArray(g_a_stModuleBlocToSaveInLevel, SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInLevel) );
|
||
SNA_fn_vSortAnArray(g_a_stModuleBlocToSaveInfos, SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInfos) );
|
||
ucArrayAreSorted = 1;
|
||
}
|
||
}
|
||
|
||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
// Write the MMG header of each block in the given array to file.
|
||
//
|
||
// Input:
|
||
// _p_stArrayToSaveInfos : an array of block (ie: g_a_stModuleBlocToSaveInFix, etc)
|
||
// _ulNbElem : Number of elements in the array
|
||
// _ucBlockType : Type of block in the array (SNA_C_ucBlockOfFix, SNA_C_ucBlockOfLevel or SNA_C_ucEmptyBlock)
|
||
// _p_stFile : An opened file to write the infos.
|
||
void SNA_fn_vWriteMemoryInfosOfArray(
|
||
struct tdstModuleBloc_ *_p_stArrayToSaveInfos, unsigned long _ulNbElem,
|
||
unsigned char _ucBlocType, struct SNA_tdstFile_ *_p_stFile )
|
||
{
|
||
unsigned char ucModule, ucBlock;
|
||
unsigned long ulBlockSize,ulBeginBlock,ulEndBlock,ulMaxMem;
|
||
tdstBlockInfo stBloc;
|
||
|
||
while( _ulNbElem-- )
|
||
{
|
||
ucModule = *(_p_stArrayToSaveInfos->p_ucModuleId);
|
||
ucBlock = _p_stArrayToSaveInfos->ucBlockId;
|
||
|
||
// Write block header : ModuleID, BlockID and type(fix, level or empty)
|
||
SNA_fn_ulFWrite( &ucModule, sizeof(unsigned char), 1, _p_stFile );
|
||
SNA_fn_ulFWrite( &ucBlock, sizeof(unsigned char), 1, _p_stFile );
|
||
SNA_fn_ulFWrite( &_ucBlocType, sizeof(unsigned char), 1, _p_stFile );
|
||
|
||
// Get current infos from MMG
|
||
Mmg_fn_vGiveInformationBlock( ucModule, ucBlock, &stBloc );
|
||
|
||
ulBeginBlock=(unsigned long)stBloc.p_cBeginBlock;
|
||
ulEndBlock=(unsigned long)stBloc.p_cEndBlock;
|
||
ulMaxMem=(unsigned long)stBloc.p_cMaxMem;
|
||
|
||
SNA_fn_ulFWrite( &ulBeginBlock, 4, 1, _p_stFile );
|
||
|
||
if( ulBeginBlock != (unsigned long)C_p_cBlockNotValidKey )
|
||
{
|
||
SNA_fn_ulFWrite( &ulEndBlock, 4, 1, _p_stFile );
|
||
SNA_fn_ulFWrite( &(stBloc.p_cFirstFree), 4, 1, _p_stFile );
|
||
SNA_fn_ulFWrite( &(stBloc.p_cMaxMem), 4, 1, _p_stFile );
|
||
|
||
// Write block size
|
||
ulBlockSize=0;
|
||
SNA_fn_ulFWrite( &ulBlockSize, 4, 1, _p_stFile );
|
||
}
|
||
|
||
// Go to next element of the array
|
||
_p_stArrayToSaveInfos++;
|
||
}
|
||
}
|
||
|
||
|
||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
// Write the MMG header AND CONTENT of each block in the given array to file.
|
||
//
|
||
// Input:
|
||
// _p_stArrayToSaveInfos : an array of block (ie: g_a_stModuleBlocToSaveInFix, etc)
|
||
// _ulNbElem : Number of elements in the array
|
||
// _ucBlockType : Type of block in the array (SNA_C_ucBlockOfFix, SNA_C_ucBlockOfLevel or SNA_C_ucEmptyBlock)
|
||
// _p_stFile : An opened file to write the infos.
|
||
void SNA_fn_vWriteMemoryBlocksOfArray(
|
||
struct tdstModuleBloc_ *_p_stArrayToSaveInfos, unsigned long _ulNbElem,
|
||
unsigned char _ucBlocType, struct SNA_tdstFile_ *_p_stFile )
|
||
{
|
||
unsigned char ucModule, ucBlock;
|
||
unsigned long ulBlockSize,ulBeginBlock,ulEndBlock,ulMaxMem;
|
||
tdstBlockInfo stBloc;
|
||
|
||
while( _ulNbElem-- )
|
||
{
|
||
ucModule = *(_p_stArrayToSaveInfos->p_ucModuleId);
|
||
ucBlock = _p_stArrayToSaveInfos->ucBlockId;
|
||
|
||
// Write block header : ModuleID, BlockID and type(fix, level or empty)
|
||
SNA_fn_ulFWrite( &ucModule, sizeof(unsigned char), 1, _p_stFile );
|
||
SNA_fn_ulFWrite( &ucBlock, sizeof(unsigned char), 1, _p_stFile );
|
||
SNA_fn_ulFWrite( &_ucBlocType, sizeof(unsigned char), 1, _p_stFile );
|
||
|
||
|
||
Mmg_fn_vGiveInformationBlock( ucModule, ucBlock, &stBloc );
|
||
|
||
ulBeginBlock=(unsigned long)stBloc.p_cBeginBlock;
|
||
ulEndBlock=(unsigned long)stBloc.p_cEndBlock;
|
||
ulMaxMem=(unsigned long)stBloc.p_cMaxMem;
|
||
|
||
SNA_fn_ulFWrite( &ulBeginBlock, 4, 1, _p_stFile );
|
||
|
||
if( ulBeginBlock != (unsigned long)C_p_cBlockNotValidKey )
|
||
{
|
||
SNA_fn_ulFWrite( &ulEndBlock, 4, 1, _p_stFile );
|
||
SNA_fn_ulFWrite( &(stBloc.p_cFirstFree), 4, 1, _p_stFile );
|
||
SNA_fn_ulFWrite( &(stBloc.p_cMaxMem), 4, 1, _p_stFile );
|
||
|
||
// Write block size
|
||
ulBlockSize=ulMaxMem-ulBeginBlock+1+8; // 8 : Remain place bloc info
|
||
SNA_fn_ulFWrite( &ulBlockSize, 4, 1, _p_stFile );
|
||
// Write the block
|
||
SNA_fn_ulFWrite(stBloc.p_cBeginBlock,1,ulBlockSize,_p_stFile);
|
||
}
|
||
|
||
_p_stArrayToSaveInfos++;
|
||
}
|
||
}
|
||
|
||
/*-----------------------------------------------------------------------------
|
||
* Description : Write all memory blocks to file
|
||
*-----------------------------------------------------------------------------
|
||
* Input : None
|
||
* Output : None
|
||
*-----------------------------------------------------------------------------
|
||
* Creation date : 03/09/97 Author : Micha<68>l
|
||
*-----------------------------------------------------------------------------
|
||
* Modification date : 29/09/97 Modification Author : CGHT
|
||
* Modifications :
|
||
*---------------------------------------------------------------------------*/
|
||
void SNA_fn_vWriteAllMemoryBlocks(char *szFilename)
|
||
{
|
||
struct SNA_tdstFile_ stSnaFile;
|
||
DWORD dwBytesWritten;
|
||
|
||
SNA_fn_vInitArrays();
|
||
|
||
#if defined(SNA_ENCRYPTION)
|
||
SNA_fn_bFOpen(szFilename,SNA_C_ucWrite,SNA_C_ucUseEncryption,&stSnaFile);
|
||
#else
|
||
SNA_fn_bFOpen(szFilename,SNA_C_ucWrite,0,&stSnaFile);
|
||
#endif
|
||
|
||
// Write crypt key in file
|
||
SNA_M_WRITEFILE(stSnaFile.hFile , &stSnaFile.ulCryptKey , sizeof(stSnaFile.ulCryptKey) , &dwBytesWritten, NULL);
|
||
|
||
// First, write some infos on some block witch content will not be saved (for pointer destination detection only)
|
||
SNA_fn_vWriteMemoryInfosOfArray(
|
||
g_a_stModuleBlocToSaveInfos, SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInfos),
|
||
SNA_C_ucEmptyBlock, &stSnaFile);
|
||
|
||
// Then write the infos about the blocks that will be saved
|
||
SNA_fn_vWriteMemoryInfosOfArray(
|
||
g_a_stModuleBlocToSaveInFix, SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInFix),
|
||
SNA_C_ucBlockOfFix, &stSnaFile );
|
||
|
||
if( g_bSaveLoadFix )
|
||
{
|
||
// In the fix sna file, write the content of all fix memory blocks
|
||
SNA_fn_vWriteMemoryBlocksOfArray(
|
||
g_a_stModuleBlocToSaveInFix, SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInFix),
|
||
SNA_C_ucBlockOfFix, &stSnaFile );
|
||
}
|
||
else
|
||
{
|
||
// In the level sna file, write the infos of the level mem blocks
|
||
SNA_fn_vWriteMemoryInfosOfArray(
|
||
g_a_stModuleBlocToSaveInLevel, SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInLevel),
|
||
SNA_C_ucBlockOfLevel, &stSnaFile );
|
||
// Then write the content of all level memory blocks
|
||
SNA_fn_vWriteMemoryBlocksOfArray(
|
||
g_a_stModuleBlocToSaveInLevel, SNA_M_NbElementOfBlocArray(g_a_stModuleBlocToSaveInLevel),
|
||
SNA_C_ucBlockOfLevel, &stSnaFile );
|
||
}
|
||
|
||
SNA_fn_bFClose(&stSnaFile);
|
||
}
|
||
|
||
/*-----------------------------------------------------------------------------
|
||
* Description : Read all memory blocks from file
|
||
*-----------------------------------------------------------------------------
|
||
* Input : Name of the file
|
||
* Output : None
|
||
*-----------------------------------------------------------------------------
|
||
* Creation date : 03/09/97 Author : Micha<68>l
|
||
*-----------------------------------------------------------------------------
|
||
* Modification date : Modification Author :
|
||
* Modifications :
|
||
*---------------------------------------------------------------------------*/
|
||
BOOL SNA_fn_bReadAllMemoryBlocks(char *szFilename)
|
||
{
|
||
struct SNA_tdstFile_ stFile;
|
||
ACP_tdxBool bOpenFileOK;
|
||
unsigned char ucModule,ucBlock;
|
||
unsigned long ulBlockSize,ulBeginBlock,ulEndBlock,ulFirstFree,ulMaxMem;
|
||
unsigned long p_vPtr,*p_ulPtr;
|
||
unsigned long i,j,k;
|
||
unsigned char ucTargetModule, ucTargetBloc;
|
||
tdstBlockInfo stBloc;
|
||
unsigned long ulNbReloc = 0;
|
||
DWORD dwBytesRead;
|
||
#ifndef RETAIL
|
||
char szText[150];
|
||
unsigned long ulNbPointerToUnknown = 0;
|
||
unsigned long ulNbPointerToTmp = 0;
|
||
#endif
|
||
|
||
// MR2711
|
||
SNA_fn_vInitArrays();
|
||
|
||
#if defined(SNA_ENCRYPTION)
|
||
ACP_M_OPENFILE(SNA_fn_bFOpen,bOpenFileOK,FALSE,szFilename,(szFilename,SNA_C_ucRead,SNA_C_ucUseEncryption,&stFile));
|
||
#else
|
||
ACP_M_OPENFILE(SNA_fn_bFOpen,bOpenFileOK,FALSE,szFilename,(szFilename,SNA_C_ucRead,0,&stFile));
|
||
#endif
|
||
|
||
if (! bOpenFileOK)
|
||
return FALSE;
|
||
|
||
stFile.bReadSuccess = SNA_M_READFILE(stFile.hFile , &stFile.ulCryptKey , sizeof(stFile.ulCryptKey) , &dwBytesRead , NULL);
|
||
|
||
#ifdef _DEBUG
|
||
// Set relocation infos to invalid values.
|
||
memset( g_a_bIsBlocRelocated, 55, C_ucNbOfMaxModule*10 );
|
||
#endif
|
||
|
||
/// Load Reloc Table
|
||
SNA_M_LoadUsedRelocationTable();
|
||
|
||
// Take care of the progress bar
|
||
VIG_fn_vAddToProgressBar(1);
|
||
|
||
// Begin read from SNA file.
|
||
while(stFile.bReadSuccess)
|
||
{
|
||
|
||
// Read Module ID and Block ID
|
||
i=SNA_fn_ulFRead(&ucModule,1,1,&stFile);
|
||
if(i==0)
|
||
{
|
||
break;
|
||
}
|
||
|
||
SNA_fn_ulFRead(&ucBlock,1,1,&stFile);
|
||
|
||
// Read block location (fix or level)
|
||
SNA_fn_ulFRead(&i,1,1,&stFile);
|
||
|
||
// Get current info on this block
|
||
Mmg_fn_vGiveInformationBlock(ucModule,ucBlock,&stBloc);
|
||
|
||
g_a_bIsBlocRelocated[ucModule][ucBlock]=FALSE;
|
||
|
||
// Read beginning of block
|
||
SNA_fn_ulFRead(&ulBeginBlock,4,1,&stFile);
|
||
|
||
// Test if block's emplacement has changed (=if it is relocated).
|
||
if(stBloc.p_cBeginBlock!=(char *)ulBeginBlock)
|
||
{
|
||
|
||
// If so, compute the offset between the old block and the new one.
|
||
g_a_bIsBlocRelocated[ucModule][ucBlock]=TRUE;
|
||
g_a_ulOffset[ucModule][ucBlock]=(long)stBloc.p_cBeginBlock-(long)ulBeginBlock;
|
||
|
||
#ifndef RETAIL
|
||
sprintf( szText, "Module %d Bloc %d is relocated from %lx to %lx\n", ucModule, ucBlock, ulBeginBlock, stBloc.p_cBeginBlock );
|
||
OutputDebugString(szText);
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
// If it's not relocated, offset=0
|
||
g_a_ulOffset[ucModule][ucBlock]=0;
|
||
}
|
||
|
||
// MR0310
|
||
if ((char *)ulBeginBlock==C_p_cBlockNotValidKey)
|
||
continue;
|
||
|
||
SNA_fn_ulFRead(&ulEndBlock,4,1,&stFile);
|
||
|
||
// If this block is to be loaded by sna, update some infos in MMG structures.
|
||
// (FirstFree and MaxMem)
|
||
SNA_fn_ulFRead(&ulFirstFree,4,1,&stFile);
|
||
SNA_fn_ulFRead(&ulMaxMem,4,1,&stFile);
|
||
|
||
SNA_fn_ulFRead(&ulBlockSize,4,1,&stFile);
|
||
if( SNA_fn_bLoadThisModuleBloc(ucModule,ucBlock) && ulBlockSize>0 )
|
||
{
|
||
stBloc.p_cMaxMem=(char *)ulMaxMem+g_a_ulOffset[ucModule][ucBlock];
|
||
if( ulFirstFree!= (unsigned long)C_p_cBlockNotValidKey )
|
||
stBloc.p_cFirstFree=(char *)ulFirstFree+g_a_ulOffset[ucModule][ucBlock];
|
||
|
||
// Read the block
|
||
SNA_fn_ulFRead(stBloc.p_cBeginBlock,1,ulBlockSize,&stFile);
|
||
|
||
// Save the updated memory block info for MMG.
|
||
Mmg_fn_vSaveInformationBlock(ucModule,ucBlock,&stBloc);
|
||
|
||
// Take care of the progress bar
|
||
VIG_fn_vAddToProgressBar(1);
|
||
|
||
// Now we are going to relocate each pointer in the current block.
|
||
// Search reloc info for current block.
|
||
for (k=0;k<SNA_g_PTCRelocationTable->ucBlocNumber;k++)
|
||
if ((SNA_g_PTCRelocationTable->p_stBloc[k].ucModuleNumber==ucModule) &&
|
||
(SNA_g_PTCRelocationTable->p_stBloc[k].ucBlocNumber==ucBlock))
|
||
{
|
||
break;
|
||
}
|
||
|
||
// If there are reloc infos,
|
||
if (k<SNA_g_PTCRelocationTable->ucBlocNumber)
|
||
{
|
||
// go throught the pointer table.
|
||
for (j=0;j<SNA_g_PTCRelocationTable->p_stBloc[k].ulSize;j++)
|
||
{
|
||
// For each pointer to be relocated,
|
||
// get his target module and block.
|
||
ucTargetModule=SNA_g_PTCRelocationTable->p_stBloc[k].p_stPtr[j].ucTargetModule;
|
||
ucTargetBloc=SNA_g_PTCRelocationTable->p_stBloc[k].p_stPtr[j].ucTargetBlock;
|
||
|
||
#ifdef _DEBUG
|
||
// Make sure the source and dest block infos have been read.
|
||
assert( g_a_bIsBlocRelocated[ucModule][ucBlock] != 55 );
|
||
if( ucTargetModule < 0xf0 )
|
||
assert( g_a_bIsBlocRelocated[ucTargetModule][ucTargetBloc] != 55 );
|
||
#endif
|
||
|
||
p_vPtr=g_a_bIsBlocRelocated[ucModule][ucBlock]?
|
||
SNA_g_PTCRelocationTable->p_stBloc[k].p_stPtr[j].p_vPtr+g_a_ulOffset[ucModule][ucBlock]:
|
||
SNA_g_PTCRelocationTable->p_stBloc[k].p_stPtr[j].p_vPtr;
|
||
p_ulPtr=(unsigned long *)p_vPtr;
|
||
|
||
if (ucTargetModule == g_ucTMPModuleId)
|
||
{
|
||
// If pointer points to TMP, set it to NULL.
|
||
(*p_ulPtr) = (unsigned long)NULL; // GuS (28/09/98)
|
||
#ifndef RETAIL
|
||
ulNbPointerToTmp ++;
|
||
#endif
|
||
}
|
||
else if (ucTargetModule==0xff)
|
||
{
|
||
// If that pointer point to an unknown place ... well... we let it do that !
|
||
#ifndef RETAIL
|
||
ulNbPointerToUnknown ++;
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
(*p_ulPtr) += g_a_ulOffset[ucTargetModule][ucTargetBloc];
|
||
}
|
||
}
|
||
|
||
// Take care of the progress bar
|
||
VIG_fn_vAddToProgressBar(1);
|
||
}
|
||
}
|
||
else if( ulBlockSize > 0 )
|
||
{
|
||
SNA_fn_bFseek( &stFile, ulBlockSize, SEEK_CUR );
|
||
}
|
||
|
||
}
|
||
|
||
SNA_M_FreeRelocationTable();
|
||
SNA_fn_bFClose(&stFile);
|
||
|
||
#ifndef RETAIL
|
||
sprintf
|
||
( szText,
|
||
"Found %li pointers in %s that point to a TMP block.\n(Those pointers have been set to NULL)\n",
|
||
ulNbPointerToTmp, szFilename );
|
||
OutputDebugString( szText );
|
||
sprintf
|
||
( szText,
|
||
"Found %li pointers in %s that point to an unknown place.\n(Those pointers have not been relocated)\n",
|
||
ulNbPointerToUnknown, szFilename );
|
||
OutputDebugString( szText );
|
||
#endif
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
#ifndef RETAIL
|
||
// For debug ONLY !
|
||
|
||
/*
|
||
fn_vChangeWindowTitle("Checking MMG blocks...");
|
||
//SNA_fn_vCheckAllMMGBlocks();
|
||
fn_vChangeWindowTitle("Rayman II");
|
||
|
||
static unsigned char ucDelay = 0;
|
||
if( ucDelay++ >= 30 )
|
||
{
|
||
fn_vChangeWindowTitle("Checking MMG blocks...");
|
||
//SNA_fn_vCheckAllMMGBlocks();
|
||
fn_vChangeWindowTitle("Rayman II");
|
||
ucDelay = 0;
|
||
}
|
||
|
||
|
||
*/
|
||
|
||
// Function for checking integrity of a mem block.
|
||
// Block must be static and with free.
|
||
// This function can detect errors caused by memory overwrites.
|
||
void SNA_fn_vCheckMMGBlock( unsigned char _ucModule, unsigned char _ucBlock, unsigned char _ucLog )
|
||
{
|
||
static unsigned long ulCallCount = 0;
|
||
struct tdstBlockInfo_ stInfoMMG;
|
||
long *p_lFree;
|
||
long *p_lAlloc;
|
||
long lSize, lNext;
|
||
long lNbFree, lNbAlloc, lTotalFree, lTotalAlloc;
|
||
char szFileName[255];
|
||
FILE *p_xFile;
|
||
|
||
lNbFree = lNbAlloc = lTotalFree = lTotalAlloc = 0;
|
||
|
||
Mmg_fn_vGiveInformationBlock( _ucModule, _ucBlock, &stInfoMMG );
|
||
|
||
// Can't check uninitialised block
|
||
if( stInfoMMG.p_cBeginBlock == (char *)0xffffffff )
|
||
return;
|
||
|
||
// Can't check block without free
|
||
if( stInfoMMG.p_cFirstFree == (char *)0xffffffff )
|
||
return;
|
||
|
||
p_lFree = (long *)stInfoMMG.p_cFirstFree;
|
||
p_lAlloc = (long *)stInfoMMG.p_cBeginBlock;
|
||
|
||
// FirstFree is out of block ?
|
||
if( p_lFree )
|
||
assert( (p_lFree >= (long *)(stInfoMMG.p_cBeginBlock)) && (p_lFree < (long *)(stInfoMMG.p_cEndBlock)) );
|
||
|
||
// BeginBlock is greater than EndOfBlock ?
|
||
assert( p_lAlloc < (long *)(stInfoMMG.p_cEndBlock) );
|
||
|
||
while( p_lAlloc < (long *)(stInfoMMG.p_cEndBlock) )
|
||
{
|
||
lSize = *p_lAlloc << C_uwShiftAllocSize >> 2;
|
||
|
||
// Size of allocated block is null or too big ?
|
||
assert( lSize > 0 );
|
||
|
||
// This is a free memory block.
|
||
if( p_lAlloc == p_lFree )
|
||
{
|
||
lNext = *(p_lFree+1);
|
||
// Size of free block is too big ?
|
||
assert( (p_lFree+lSize >= (long *)(stInfoMMG.p_cBeginBlock)) && (p_lFree+lSize < (long *)(stInfoMMG.p_cEndBlock+4)) );
|
||
if( lNext != 0 )
|
||
// Next free is out of Block bounds ?
|
||
assert( (lNext >= (long)(stInfoMMG.p_cBeginBlock)) && (lNext < (long)(stInfoMMG.p_cEndBlock)) );
|
||
p_lFree = (long *)lNext;
|
||
lNbFree++;
|
||
lTotalFree += lSize;
|
||
}
|
||
else
|
||
{
|
||
// Allocated mem block goes beyong it's bounds ?
|
||
if( p_lFree )
|
||
assert( p_lAlloc+lSize <= p_lFree );
|
||
// Allocated mem block size is too big ?
|
||
assert( (p_lAlloc+lSize >= (long *)(stInfoMMG.p_cBeginBlock)) && (p_lAlloc+lSize < (long *)(stInfoMMG.p_cEndBlock+4)) );
|
||
lNbAlloc++;
|
||
lTotalAlloc += lSize;
|
||
}
|
||
|
||
p_lAlloc += lSize;
|
||
}
|
||
|
||
if( _ucLog )
|
||
{
|
||
sprintf( szFileName, "Block%02x%02x.log", _ucModule, _ucBlock );
|
||
p_xFile = fopen( szFileName, "at" );
|
||
if( p_xFile )
|
||
{
|
||
ulCallCount++;
|
||
fprintf( p_xFile, "Block=#%02x%02x (Number=#%03d)\n", _ucModule, _ucBlock, ulCallCount );
|
||
fprintf( p_xFile, " Nb Alloc=%05d Total Allocated=%d\n", lNbAlloc, lTotalAlloc );
|
||
fprintf( p_xFile, " Nb Free=%05d Total Free=%d\n", lNbFree, lTotalFree );
|
||
fclose( p_xFile );
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
// Call CheckMMGBlock for each block.
|
||
void SNA_fn_vCheckAllMMGBlocks()
|
||
{
|
||
unsigned char i, j;
|
||
for( i=0; i<C_ucNbOfMaxModule; i++ )
|
||
for( j=0; j<g_a_ucBlocksNbInModule[i]; j++ )
|
||
SNA_fn_vCheckMMGBlock( i, j, 0 );
|
||
}
|
||
|
||
|
||
#endif // ! RETAIL
|
||
|