reman3/Rayman_X/cpa/tempgrp/SNA/snammg.c

647 lines
21 KiB
C
Raw Blame History

/*=========================================================================
* 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