Renames and more usage of xbaddr

This commit is contained in:
PatrickvL 2017-02-07 13:39:55 +01:00
parent 8601a4e874
commit 1960e1afee
4 changed files with 76 additions and 79 deletions

View File

@ -39,6 +39,8 @@
#undef FIELD_OFFSET // prevent macro redefinition warnings
#include <windows.h>
#include "CxbxKrnl.h" // For xbaddr
extern "C" const char *szHLELastCompileTime = __TIMESTAMP__;
const char *Lib_D3D8 = "D3D8";
@ -184,4 +186,4 @@ extern const uint32 HLEDataBaseCount = sizeof(HLEDataBase) / sizeof(HLEData);
// ******************************************************************
// * XRefDataBase
// ******************************************************************
extern uint32 XRefDataBase[XREF_COUNT] = { 0 }; // Reset and populated by EmuHLEIntercept
extern xbaddr XRefDataBase[XREF_COUNT] = { 0 }; // Reset and populated by EmuHLEIntercept

View File

@ -343,6 +343,6 @@ enum XRefDataBaseOffset
// ******************************************************************
// * XRefDataBase
// ******************************************************************
extern uint32 XRefDataBase[XREF_COUNT];
extern xbaddr XRefDataBase[XREF_COUNT];
#endif /*HLEDATABASE_H*/

View File

@ -44,8 +44,8 @@
#include "HLEDataBase.h"
#include "HLEIntercept.h"
static void *EmuLocateFunction(OOVPA *Oovpa, uint32 lower, uint32 upper);
static void EmuInstallWrappers(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::Header *pXbeHeader);
static xbaddr EmuLocateFunction(OOVPA *Oovpa, xbaddr lower, xbaddr upper);
static void EmuInstallPatches(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::Header *pXbeHeader);
static void EmuXRefFailure();
#include <shlobj.h>
@ -57,11 +57,11 @@ void * funcExclude[2048] = { nullptr };
uint32 g_BuildVersion;
uint32 g_OrigBuildVersion;
static std::vector<void *> vCacheOut;
static std::vector<xbaddr> vCacheOut;
static bool bCacheInp = false;
static std::vector<void *> vCacheInp;
static std::vector<void*>::const_iterator vCacheInpIter;
static std::vector<xbaddr> vCacheInp;
static std::vector<xbaddr>::const_iterator vCacheInpIter;
bool bLLE_APU = false; // Set this to true for experimental APU (sound) LLE
@ -140,7 +140,7 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
{
while(true)
{
void *cur;
xbaddr cur;
if(fread(&cur, 4, 1, pCacheFile) != 1)
break;
@ -167,7 +167,7 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
{
DbgPrintf("HLE: Detected Microsoft XDK application...\n");
UnResolvedXRefs = XREF_COUNT; // = sizeof(XRefDataBase) / sizeof(uint32)
UnResolvedXRefs = XREF_COUNT; // = sizeof(XRefDataBase) / sizeof(xbaddr)
uint32 dwLibraryVersions = pXbeHeader->dwLibraryVersions;
uint32 LastUnResolvedXRefs = UnResolvedXRefs+1;
@ -324,8 +324,8 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
|| BuildVersion == 4432 || BuildVersion == 4627 || BuildVersion == 5233 || BuildVersion == 5558
|| BuildVersion == 5788 || BuildVersion == 5849))
{
uint32 lower = pXbeHeader->dwBaseAddr;
uint32 upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
xbaddr lower = pXbeHeader->dwBaseAddr;
xbaddr upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
}
else if(strcmp(Lib_D3D8, szLibraryName) == 0 /*&& strcmp(Lib_D3D8LTCG, szOrigLibraryName)*/ &&
(BuildVersion == 3925 || BuildVersion == 4134 || BuildVersion == 4361 || BuildVersion == 4432
@ -336,10 +336,9 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
g_BuildVersion = BuildVersion;
g_OrigBuildVersion = OrigBuildVersion;
uint32 lower = pXbeHeader->dwBaseAddr;
uint32 upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
void *pFunc = nullptr;
xbaddr lower = pXbeHeader->dwBaseAddr;
xbaddr upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
xbaddr pFunc = (xbaddr)nullptr;
if(BuildVersion == 3925)
pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetRenderState_CullMode_3925, lower, upper);
@ -349,49 +348,49 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetRenderState_CullMode_5233, lower, upper);
// locate D3DDeferredRenderState
if(pFunc != nullptr)
if(pFunc != (xbaddr)nullptr)
{
// offset for stencil cull enable render state in the deferred render state buffer
int patchOffset = 0;
if(BuildVersion == 3925)
{
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x25) - 0x1FC + 82*4); // TODO: Clean up (?)
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)(pFunc + 0x25) - 0x1FC + 82*4); // TODO: Clean up (?)
patchOffset = 142*4 - 82*4; // TODO: Verify
//XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x25) - 0x19F + 72*4); // TODO: Clean up (?)
//XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)(pFunc + 0x25) - 0x19F + 72*4); // TODO: Clean up (?)
//patchOffset = 142*4 - 72*4; // TODO: Verify
}
else if(BuildVersion == 4034 || BuildVersion == 4134)
{
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x2B) - 0x248 + 82*4); // TODO: Verify
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)(pFunc + 0x2B) - 0x248 + 82*4); // TODO: Verify
patchOffset = 142*4 - 82*4;
}
else if(BuildVersion == 4361)
{
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x2B) - 0x200 + 82*4);
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)(pFunc + 0x2B) - 0x200 + 82*4);
patchOffset = 142*4 - 82*4;
}
else if(BuildVersion == 4432)
{
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x2B) - 0x204 + 83*4);
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)(pFunc + 0x2B) - 0x204 + 83*4);
patchOffset = 143*4 - 83*4;
}
else if(BuildVersion == 4627 || BuildVersion == 5233 || BuildVersion == 5558 || BuildVersion == 5788
|| BuildVersion == 5849)
{
// WARNING: Not thoroughly tested (just seemed very correct right away)
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x2B) - 0x24C + 92*4);
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)(pFunc + 0x2B) - 0x24C + 92*4);
patchOffset = 162*4 - 92*4;
}
XRefDataBase[XREF_D3DDEVICE] = *(DWORD*)((DWORD)pFunc + 0x03);
XRefDataBase[XREF_D3DRS_MULTISAMPLEMODE] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset - 8*4;
XRefDataBase[XREF_D3DRS_MULTISAMPLERENDERTARGETMODE] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset - 7*4;
XRefDataBase[XREF_D3DRS_STENCILCULLENABLE] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset + 0*4;
XRefDataBase[XREF_D3DRS_ROPZCMPALWAYSREAD] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset + 1*4;
XRefDataBase[XREF_D3DRS_ROPZREAD] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset + 2*4;
XRefDataBase[XREF_D3DRS_DONOTCULLUNCOMPRESSED] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset + 3*4;
XRefDataBase[XREF_D3DRS_MULTISAMPLEMODE] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset - 8*4;
XRefDataBase[XREF_D3DRS_MULTISAMPLERENDERTARGETMODE] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset - 7*4;
XRefDataBase[XREF_D3DRS_STENCILCULLENABLE] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset + 0*4;
XRefDataBase[XREF_D3DRS_ROPZCMPALWAYSREAD] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset + 1*4;
XRefDataBase[XREF_D3DRS_ROPZREAD] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset + 2*4;
XRefDataBase[XREF_D3DRS_DONOTCULLUNCOMPRESSED] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset + 3*4;
for(int v=0;v<44;v++)
{
@ -409,7 +408,7 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
// locate D3DDeferredTextureState
{
pFunc = nullptr;
pFunc = (xbaddr)nullptr;
if(BuildVersion == 3925)
pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetTextureState_TexCoordIndex_3925, lower, upper);
@ -421,14 +420,14 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
|| BuildVersion == 5849)
pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetTextureState_TexCoordIndex_4627, lower, upper);
if(pFunc != nullptr)
if(pFunc != (xbaddr)nullptr)
{
if(BuildVersion == 3925) // 0x18F180
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x11) - 0x70); // TODO: Verify
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)(pFunc + 0x11) - 0x70); // TODO: Verify
else if(BuildVersion == 4134)
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x18) - 0x70); // TODO: Verify
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)(pFunc + 0x18) - 0x70); // TODO: Verify
else
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x19) - 0x70);
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)(pFunc + 0x19) - 0x70);
for(int s=0;s<4;s++)
{
@ -452,10 +451,9 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
// g_BuildVersion = BuildVersion;
// g_OrigBuildVersion = OrigBuildVersion;
// uint32 lower = pXbeHeader->dwBaseAddr;
// uint32 upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
// void *pFunc = nullptr;
// xbaddr lower = pXbeHeader->dwBaseAddr;
// xbaddr upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
// xbaddr pFunc = (xbaddr)nullptr;
// if(BuildVersion == 5849)
// pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetRenderState_CullMode_LTCG_5849, lower, upper);
@ -469,17 +467,17 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
// if(BuildVersion == 5849)
// {
// // WARNING: Not thoroughly tested (just seemed very correct right away)
// XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x2B) - 0x24C + 92*4);
// XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)(pFunc + 0x2B) - 0x24C + 92*4);
// patchOffset = 162*4 - 92*4;
// }
// XRefDataBase[XREF_D3DDEVICE] = *(DWORD*)((DWORD)pFunc + 0x03);
// XRefDataBase[XREF_D3DRS_MULTISAMPLEMODE] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset - 8*4;
// XRefDataBase[XREF_D3DRS_MULTISAMPLERENDERTARGETMODE] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset - 7*4;
// XRefDataBase[XREF_D3DRS_STENCILCULLENABLE] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset + 0*4;
// XRefDataBase[XREF_D3DRS_ROPZCMPALWAYSREAD] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset + 1*4;
// XRefDataBase[XREF_D3DRS_ROPZREAD] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset + 2*4;
// XRefDataBase[XREF_D3DRS_DONOTCULLUNCOMPRESSED] = (uint32)XTL::EmuD3DDeferredRenderState + patchOffset + 3*4;
// XRefDataBase[XREF_D3DRS_MULTISAMPLEMODE] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset - 8*4;
// XRefDataBase[XREF_D3DRS_MULTISAMPLERENDERTARGETMODE] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset - 7*4;
// XRefDataBase[XREF_D3DRS_STENCILCULLENABLE] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset + 0*4;
// XRefDataBase[XREF_D3DRS_ROPZCMPALWAYSREAD] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset + 1*4;
// XRefDataBase[XREF_D3DRS_ROPZREAD] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset + 2*4;
// XRefDataBase[XREF_D3DRS_DONOTCULLUNCOMPRESSED] = (xbaddr)XTL::EmuD3DDeferredRenderState + patchOffset + 3*4;
// for(int v=0;v<44;v++)
// {
@ -496,19 +494,19 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
// // locate D3DDeferredTextureState
// {
// pFunc = nullptr;
// pFunc = (xbaddr)nullptr;
// if(BuildVersion == 3925)
// pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetTextureState_TexCoordIndex_LTCG_5849, lower, upper);
// if(pFunc != nullptr)
// if(pFunc != (xbaddr)nullptr)
// {
// if(BuildVersion == 3925) // 0x18F180
// XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x11) - 0x70); // TODO: Verify
// XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)(pFunc + 0x11) - 0x70); // TODO: Verify
// else if(BuildVersion == 4134)
// XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x18) - 0x70); // TODO: Verify
// XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)(pFunc + 0x18) - 0x70); // TODO: Verify
// else
// XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x19) - 0x70);
// XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)(pFunc + 0x19) - 0x70);
// for(int s=0;s<4;s++)
// {
@ -539,7 +537,7 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
if (FoundHLEData) {
if (g_bPrintfOn) printf("Found\n");
EmuInstallWrappers(FoundHLEData->OovpaTable, FoundHLEData->OovpaTableSize, pXbeHeader);
EmuInstallPatches(FoundHLEData->OovpaTable, FoundHLEData->OovpaTableSize, pXbeHeader);
} else {
if (g_bPrintfOn) printf("Skipped\n");
}
@ -600,13 +598,12 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
return;
}
// install function interception wrapper
static inline void EmuInstallWrapper(void *FunctionAddr, void *WrapperAddr)
static inline void EmuInstallPatch(xbaddr FunctionAddr, void *Patch)
{
uint08 *FuncBytes = (uint08*)FunctionAddr;
*(uint08*)&FuncBytes[0] = 0xE9; // = opcode for JMP rel32 (Jump near, relative, displacement relative to next instruction)
*(uint32*)&FuncBytes[1] = (uint32)WrapperAddr - (uint32)FunctionAddr - 5;
*(uint32*)&FuncBytes[1] = (uint32)Patch - FunctionAddr - 5;
}
static inline void GetOovpaEntry(OOVPA *oovpa, int index, OUT uint32 &offset, OUT uint08 &value)
@ -622,12 +619,12 @@ static inline void GetOovpaEntry(OOVPA *oovpa, int index, OUT uint32 &offset, OU
}
// locate the given function, searching within lower and upper bounds
static void *EmuLocateFunction(OOVPA *Oovpa, uint32 lower, uint32 upper)
static xbaddr EmuLocateFunction(OOVPA *Oovpa, xbaddr lower, xbaddr upper)
{
uint32 xref_count = Oovpa->XRefCount;
// skip out if this is an unnecessary search
if(!bXRefFirstPass && xref_count == XRefZero && Oovpa->XRefSaveIndex == XRefNoSaveIndex)
return nullptr;
return (xbaddr)nullptr;
// correct upper bound with highest Oovpa offset
uint32 count = Oovpa->Count;
@ -640,7 +637,7 @@ static void *EmuLocateFunction(OOVPA *Oovpa, uint32 lower, uint32 upper)
}
// search all of the image memory
for (uint32 cur = lower; cur < upper; cur++)
for (xbaddr cur = lower; cur < upper; cur++)
{
uint32 v; // verification counter
@ -652,13 +649,13 @@ static void *EmuLocateFunction(OOVPA *Oovpa, uint32 lower, uint32 upper)
// get XRef offset + value pair and currently registered (un)known address
GetOovpaEntry(Oovpa, v, Offset, Value);
uint32 XRefValue = XRefDataBase[Value];
xbaddr XRefValue = XRefDataBase[Value];
// unknown XRef cannot be checked yet
if (XRefValue == XREF_UNKNOWN)
break;
uint32 RealValue = *(uint32*)(cur + Offset);
xbaddr RealValue = *(xbaddr*)(cur + Offset);
// check if PC-relative or direct reference matches XRef
if ((RealValue + cur + Offset + 4 != XRefValue) && (RealValue != XRefValue))
break;
@ -696,37 +693,35 @@ static void *EmuLocateFunction(OOVPA *Oovpa, uint32 lower, uint32 upper)
{
// TODO : Check identical result?
// already found, no bother patching again
return (void*)XRefDataBase[Oovpa->XRefSaveIndex];
return XRefDataBase[Oovpa->XRefSaveIndex];
}
}
// return found address
return (void*)cur;
return cur;
}
}
}
// found nothing
return nullptr;
return (xbaddr)nullptr;
}
// install function interception wrappers
static void EmuInstallWrappers(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::Header *pXbeHeader)
static void EmuInstallPatches(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::Header *pXbeHeader)
{
uint32 lower = pXbeHeader->dwBaseAddr;
uint32 upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
xbaddr lower = pXbeHeader->dwBaseAddr;
xbaddr upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
// traverse the full OOVPA table
for(uint32 a=0;a<OovpaTableSize/sizeof(OOVPATable);a++)
for(size_t a=0;a<OovpaTableSize/sizeof(OOVPATable);a++)
{
OOVPA *Oovpa = OovpaTable[a].Oovpa;
void *pFunc = nullptr;
xbaddr pFunc = (xbaddr)nullptr;
if(bCacheInp && (vCacheInpIter != vCacheInp.end()))
{
pFunc = (*vCacheInpIter);
pFunc = *vCacheInpIter;
++vCacheInpIter;
}
else
@ -735,22 +730,22 @@ static void EmuInstallWrappers(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xb
vCacheOut.push_back(pFunc);
}
if(pFunc != nullptr)
if(pFunc != (xbaddr)nullptr)
{
#ifdef _DEBUG_TRACE
DbgPrintf("HLE: 0x%.08X -> %s\n", pFunc, OovpaTable[a].szFuncName);
#endif
if(OovpaTable[a].lpRedirect == nullptr)
if(OovpaTable[a].emuPatch == nullptr)
{
// Insert breakpoint
*(uint8_t*)pFunc = 0xCC;
EmuInstallWrapper((void*)(((uint32_t)pFunc)+1), EmuXRefFailure);
EmuInstallPatch(pFunc + 1, EmuXRefFailure);
}
else
{
EmuInstallWrapper(pFunc, OovpaTable[a].lpRedirect);
funcExclude[fcount++] = pFunc;
EmuInstallPatch(pFunc, OovpaTable[a].emuPatch);
funcExclude[fcount++] = (void *)pFunc;
}
}
}
@ -913,7 +908,7 @@ void VerifyHLEDataEntry(HLEVerifyContext *context, const OOVPATable *table, uint
if (context->against == nullptr) {
context->main_index = index;
// does this entry specify a redirection (patch)?
void * entry_redirect = table[index].lpRedirect;
void * entry_redirect = table[index].emuPatch;
if (entry_redirect != nullptr) {
if (table[index].Oovpa == nullptr) {
HLEError(context, "Patch without an OOVPA at index %d",
@ -921,7 +916,7 @@ void VerifyHLEDataEntry(HLEVerifyContext *context, const OOVPATable *table, uint
} else
// check no patch occurs twice in this table
for (uint32 t = index + 1; t < count; t++) {
if (entry_redirect == table[t].lpRedirect) {
if (entry_redirect == table[t].emuPatch) {
if (table[index].Oovpa == table[t].Oovpa) {
HLEError(context, "Patch registered again (with same OOVPA) at index %d",
t);

View File

@ -117,11 +117,11 @@ struct OOVPA
// defined for the OOVPA.
const uint08 XRefNoSaveIndex = (uint08)-1;
// This XRefZero constant, when set in the OOVPA.XRefSaveIndex field,
// This XRefZero constant, when set in the OOVPA.XRefCount field,
// indicates there are no {offset, XREF_*-enum} present in the OOVPA.
const uint08 XRefZero = (uint08)0;
// This XRefOne constant, when set in the OOVPA.XRefSaveIndex field,
// This XRefOne constant, when set in the OOVPA.XRefCount field,
// indicates the OOVPA contains one (1) {offset, XREF_* enum} pair.
const uint08 XRefOne = (uint08)1;
@ -173,7 +173,7 @@ OOVPA_XREF(Name, Version, Count, XRefNoSaveIndex, XRefZero)
struct OOVPATable
{
OOVPA *Oovpa;
void *lpRedirect;
void *emuPatch;
#ifdef _DEBUG_TRACE
char *szFuncName;
#endif