210 lines
7.2 KiB
C++
210 lines
7.2 KiB
C++
/*
|
|
** Command & Conquer Renegade(tm)
|
|
** Copyright 2025 Electronic Arts Inc.
|
|
**
|
|
** This program is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/***********************************************************************************************
|
|
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
|
***********************************************************************************************
|
|
* *
|
|
* Project Name : WWSaveLoad *
|
|
* *
|
|
* $Archive:: /Commando/Code/wwsaveload/pointerremap.cpp $*
|
|
* *
|
|
* Author:: Greg Hjelstrom *
|
|
* *
|
|
* $Modtime:: 5/09/01 11:36a $*
|
|
* *
|
|
* $Revision:: 9 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
|
|
#include "pointerremap.h"
|
|
#include "refcount.h"
|
|
#include "wwdebug.h"
|
|
|
|
|
|
const int POINTER_TABLES_GROWTH_STEP = 4096;
|
|
|
|
|
|
PointerRemapClass::PointerRemapClass(void)
|
|
{
|
|
PointerPairTable.Set_Growth_Step(POINTER_TABLES_GROWTH_STEP);
|
|
PointerRequestTable.Set_Growth_Step(POINTER_TABLES_GROWTH_STEP);
|
|
RefCountRequestTable.Set_Growth_Step(POINTER_TABLES_GROWTH_STEP);
|
|
}
|
|
|
|
PointerRemapClass::~PointerRemapClass(void)
|
|
{
|
|
}
|
|
|
|
void PointerRemapClass::Reset(void)
|
|
{
|
|
PointerPairTable.Delete_All();
|
|
PointerRequestTable.Delete_All();
|
|
RefCountRequestTable.Delete_All();
|
|
}
|
|
|
|
void PointerRemapClass::Process(void)
|
|
{
|
|
if ( PointerPairTable.Count() > 0 ) {
|
|
qsort(&PointerPairTable[0], PointerPairTable.Count(), sizeof(PointerPairTable[0]), ptr_pair_compare_function);
|
|
}
|
|
|
|
if ( PointerRequestTable.Count() > 0 ) {
|
|
WWASSERT( PointerPairTable.Count() > 0 );
|
|
qsort(&PointerRequestTable[0],PointerRequestTable.Count(), sizeof(PointerRequestTable[0]), ptr_request_compare_function);
|
|
Process_Request_Table(PointerRequestTable,false);
|
|
}
|
|
|
|
// remap the ref-counted pointers
|
|
if ( RefCountRequestTable.Count() > 0 ) {
|
|
WWASSERT( PointerPairTable.Count() > 0 );
|
|
qsort(&RefCountRequestTable[0],RefCountRequestTable.Count(), sizeof(RefCountRequestTable[0]), ptr_request_compare_function);
|
|
Process_Request_Table(RefCountRequestTable,true);
|
|
}
|
|
}
|
|
|
|
void PointerRemapClass::Process_Request_Table(DynamicVectorClass<PtrRemapStruct> & request_table,bool refcount)
|
|
{
|
|
// Remap the pointers
|
|
int pointer_index = 0;
|
|
int pair_index = 0;
|
|
|
|
for (pointer_index = 0; pointer_index < request_table.Count(); pointer_index++) {
|
|
|
|
void * pointer_to_remap = *(request_table[pointer_index].PointerToRemap);
|
|
int pre_search_index = pair_index;
|
|
|
|
// Find the pair which contains the pointer we are looking for as its "old" pointer
|
|
while ( (pair_index < PointerPairTable.Count()) &&
|
|
(PointerPairTable[pair_index].OldPointer < pointer_to_remap) )
|
|
{
|
|
pair_index++;
|
|
}
|
|
|
|
if ((pair_index < PointerPairTable.Count()) && (PointerPairTable[pair_index].OldPointer == pointer_to_remap)) {
|
|
|
|
// we found the match, plug in the new pointer and add a ref if needed.
|
|
*request_table[pointer_index].PointerToRemap = PointerPairTable[pair_index].NewPointer;
|
|
|
|
if (refcount) {
|
|
RefCountClass * refptr = (RefCountClass *)(*request_table[pointer_index].PointerToRemap);
|
|
refptr->Add_Ref();
|
|
}
|
|
|
|
} else {
|
|
|
|
// Failed to re-map the pointer.
|
|
// warn the user, set pointer to NULL, reset index to the pre_search_index.
|
|
// If this happens, things could be going very wrong. (find out why its happening!)
|
|
pair_index = pre_search_index;
|
|
*request_table[pointer_index].PointerToRemap = NULL;
|
|
#ifdef WWDEBUG
|
|
const char * file = request_table[pointer_index].File;
|
|
int line = request_table[pointer_index].Line;
|
|
WWDEBUG_SAY(("Warning! Failed to re-map pointer! old_ptr = 0x%X file = %s line = %d\r\n",(unsigned int)pointer_to_remap,file,line));
|
|
WWASSERT( 0 );
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
void PointerRemapClass::Register_Pointer (void *old_pointer, void *new_pointer)
|
|
{
|
|
PointerPairTable.Add(PtrPairStruct(old_pointer,new_pointer));
|
|
}
|
|
|
|
#ifdef WWDEBUG
|
|
void PointerRemapClass::Request_Pointer_Remap(void **pointer_to_convert,const char * file,int line)
|
|
{
|
|
PtrRemapStruct remap;
|
|
remap.PointerToRemap = pointer_to_convert;
|
|
remap.File = file;
|
|
remap.Line = line;
|
|
PointerRequestTable.Add(remap);
|
|
}
|
|
|
|
void PointerRemapClass::Request_Ref_Counted_Pointer_Remap (RefCountClass **pointer_to_convert,const char * file, int line)
|
|
{
|
|
PtrRemapStruct remap;
|
|
remap.PointerToRemap = (void**)pointer_to_convert;
|
|
remap.File = file;
|
|
remap.Line = line;
|
|
RefCountRequestTable.Add(remap);
|
|
}
|
|
|
|
#else
|
|
|
|
void PointerRemapClass::Request_Pointer_Remap (void **pointer_to_convert)
|
|
{
|
|
PtrRemapStruct remap;
|
|
remap.PointerToRemap = pointer_to_convert;
|
|
PointerRequestTable.Add(remap);
|
|
}
|
|
|
|
void PointerRemapClass::Request_Ref_Counted_Pointer_Remap (RefCountClass **pointer_to_convert)
|
|
{
|
|
PtrRemapStruct remap;
|
|
remap.PointerToRemap = (void**)pointer_to_convert;
|
|
RefCountRequestTable.Add(remap);
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
** sort compare function for pointer pair structures
|
|
** sorts by the old pointer value
|
|
*/
|
|
int __cdecl PointerRemapClass::ptr_pair_compare_function(void const * ptr1, void const * ptr2)
|
|
{
|
|
void * old1 = ((PointerRemapClass::PtrPairStruct const *)ptr1)->OldPointer;
|
|
void * old2 = ((PointerRemapClass::PtrPairStruct const *)ptr2)->OldPointer;
|
|
|
|
if (old1 == old2) {
|
|
return(0);
|
|
}
|
|
if (old1 < old2) {
|
|
return(-1);
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
/*
|
|
** sort compare function for pointer remap structures
|
|
** sorts by the old pointer value
|
|
*/
|
|
int __cdecl PointerRemapClass::ptr_request_compare_function(void const * ptr1, void const * ptr2)
|
|
{
|
|
PtrRemapStruct * remap1 = (PtrRemapStruct *)ptr1;
|
|
PtrRemapStruct * remap2 = (PtrRemapStruct *)ptr2;
|
|
|
|
void * old1 = *(remap1->PointerToRemap);
|
|
void * old2 = *(remap2->PointerToRemap);
|
|
|
|
if (old1 == old2) {
|
|
return(0);
|
|
}
|
|
if (old1 < old2) {
|
|
return(-1);
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
|