Remove HLE v1 Method From Cxbx

- Removed v1 database method
- Migrate v2 into v1 functions
- Format some coding standard
- Fix compile issue
- Say goodbye to HLE v1 method.
This commit is contained in:
RadWolfie 2017-10-24 03:23:32 -05:00
parent 71aabebe27
commit d33ffe0c15
6 changed files with 105 additions and 309 deletions

View File

@ -231,6 +231,7 @@ $(SOLUTIONDIR)Export.bat</Command>
<ClInclude Include="..\..\src\CxbxKrnl\EmuXOnline.h" /> <ClInclude Include="..\..\src\CxbxKrnl\EmuXOnline.h" />
<ClInclude Include="..\..\src\CxbxKrnl\EmuXTL.h" /> <ClInclude Include="..\..\src\CxbxKrnl\EmuXTL.h" />
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase.h" /> <ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase.h" />
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\D3D8.OOVPA.h" />
<ClInclude Include="..\..\src\CxbxKrnl\HLEIntercept.h" /> <ClInclude Include="..\..\src\CxbxKrnl\HLEIntercept.h" />
<ClInclude Include="..\..\src\CxbxKrnl\LibRc4.h" /> <ClInclude Include="..\..\src\CxbxKrnl\LibRc4.h" />
<ClInclude Include="..\..\src\CxbxKrnl\MemoryManager.h" /> <ClInclude Include="..\..\src\CxbxKrnl\MemoryManager.h" />

View File

@ -399,6 +399,9 @@
<ClInclude Include="..\..\src\Common\Win32\XBAudio.h"> <ClInclude Include="..\..\src\Common\Win32\XBAudio.h">
<Filter>Shared</Filter> <Filter>Shared</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\D3D8.OOVPA.h">
<Filter>HLEDatabase\D3D8</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\..\resource\Splash.jpg"> <None Include="..\..\resource\Splash.jpg">

View File

@ -81,18 +81,8 @@ const char *Sec_XNET = "XNET";
// ****************************************************************** // ******************************************************************
// * HLEDataBase // * HLEDataBase
// ****************************************************************** // ******************************************************************
#define HLE_ENTRY(Lib, DB, Version) \
{Lib, Version, DB##_##Version, DB##_##Version##_SIZE }
// For example, HLE_ENTRY(Lib_XAPILIB, XAPI, 3911) results in:
// {Lib_XAPILIB, 3911, XAPI_3911, XAPI_3911_SIZE }
const HLEData HLEDataBase[] = const HLEData HLEDataBase[] = {
{
HLE_ENTRY(Lib_XONLINE, XOnline, 4361), // TODO : Typo for XONLINES?
};
const HLEDataV2 HLEDataBaseV2[] = {
// Support inline functions in .text section // Support inline functions in .text section
{ Lib_D3D8,{ Sec_text, Sec_D3D }, D3D8_OOVPAV2, D3D8_OOVPA_SIZEV2 }, { Lib_D3D8,{ Sec_text, Sec_D3D }, D3D8_OOVPAV2, D3D8_OOVPA_SIZEV2 },
@ -146,8 +136,6 @@ const HLEDataV2 HLEDataBaseV2[] = {
// ****************************************************************** // ******************************************************************
const uint32 HLEDataBaseCount = sizeof(HLEDataBase) / sizeof(HLEData); const uint32 HLEDataBaseCount = sizeof(HLEDataBase) / sizeof(HLEData);
const uint32 HLEDataBaseCountV2 = sizeof(HLEDataBaseV2) / sizeof(HLEDataV2);
// ****************************************************************** // ******************************************************************
// * XRefDataBase // * XRefDataBase
// ****************************************************************** // ******************************************************************

View File

@ -34,6 +34,8 @@
#ifndef HLEDATABASE_H #ifndef HLEDATABASE_H
#define HLEDATABASE_H #define HLEDATABASE_H
#include "HLEDataBase\D3D8.OOVPA.h"
// ****************************************************************** // ******************************************************************
// * szHLELastCompileTime // * szHLELastCompileTime
// ****************************************************************** // ******************************************************************
@ -54,15 +56,6 @@ extern const char *Lib_XONLINES;
// ****************************************************************** // ******************************************************************
// * HLEDataBase // * HLEDataBase
// ****************************************************************** // ******************************************************************
extern const struct HLEData
{
const char *Library;
uint16 BuildVersion;
OOVPATable *OovpaTable;
uint32 OovpaTableSize;
}
HLEDataBase[];
#define PAIRSCANSEC_MAX 3 #define PAIRSCANSEC_MAX 3
@ -71,22 +64,20 @@ const struct PairScanLibSec {
const char *section[PAIRSCANSEC_MAX]; const char *section[PAIRSCANSEC_MAX];
}; };
extern const struct HLEDataV2 extern const struct HLEData
{ {
const PairScanLibSec LibSec; const PairScanLibSec LibSec;
OOVPATable *OovpaTable; OOVPATable *OovpaTable;
uint32 OovpaTableSize; uint32 OovpaTableSize;
} }
HLEDataBaseV2[]; HLEDataBase[];
// ****************************************************************** // ******************************************************************
// * HLEDataBaseCount // * HLEDataBaseCount
// ****************************************************************** // ******************************************************************
extern const uint32 HLEDataBaseCount; extern const uint32 HLEDataBaseCount;
extern const uint32 HLEDataBaseCountV2;
// ****************************************************************** // ******************************************************************
// * XRefDataBaseOffset // * XRefDataBaseOffset
// ****************************************************************** // ******************************************************************

View File

@ -0,0 +1,51 @@
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->Win32->CxbxKrnl->HLEDataBase->D3D8.OOVPA.h
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 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 recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2002-2003 Aaron Robinson <caustik@caustik.com>
// * (c) 2017 jarupxx
// * (c) 2017 RadWolfie
// *
// * All rights reserved
// *
// ******************************************************************
#ifndef D3D8_OOVPA_H
#define D3D8_OOVPA_H
#include "../OOVPA.h"
extern LOOVPA<1 + 11> D3DDevice_SetTextureState_TexCoordIndex_3911;
extern LOOVPA<2 + 15> D3DDevice_SetRenderState_CullMode_3911;
extern LOOVPA<1 + 10> D3DDevice_SetTextureState_TexCoordIndex_4034;
extern LOOVPA<2 + 14> D3DDevice_SetRenderState_CullMode_4034;
extern LOOVPA<1 + 10> D3DDevice_SetTextureState_TexCoordIndex_4242;
extern LOOVPA<1 + 10> D3DDevice_SetTextureState_TexCoordIndex_4627;
#endif

View File

@ -48,10 +48,9 @@
#include <Shlwapi.h> #include <Shlwapi.h>
#include <subhook.h> #include <subhook.h>
static xbaddr EmuLocateFunction(OOVPA *Oovpa, xbaddr lower, xbaddr upper); xbaddr EmuLocateFunction(OOVPA *Oovpa, xbaddr lower, xbaddr upper);
static void EmuInstallPatches(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::Header *pXbeHeader); void EmuInstallPatches(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::SectionHeader *pSectionHeader, uint16_t buildVersion);
static inline void EmuInstallPatch(std::string FunctionName, xbaddr FunctionAddr, void *Patch); inline void EmuInstallPatch(std::string FunctionName, xbaddr FunctionAddr, void *Patch);
void EmuInstallPatchesV2(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::SectionHeader *pSectionHeader, uint16_t buildVersion);
#include <shlobj.h> #include <shlobj.h>
#include <unordered_map> #include <unordered_map>
@ -294,7 +293,6 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
for(uint32 v=0;v<dwLibraryVersions;v++) for(uint32 v=0;v<dwLibraryVersions;v++)
{ {
uint16 BuildVersion = pLibraryVersion[v].wBuildVersion; uint16 BuildVersion = pLibraryVersion[v].wBuildVersion;
uint16 OrigBuildVersion = BuildVersion;
if (preserveVersion < BuildVersion) { if (preserveVersion < BuildVersion) {
preserveVersion = BuildVersion; preserveVersion = BuildVersion;
@ -304,21 +302,6 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
reProcessScan: reProcessScan:
// Aliases - for testing purposes only
// TODO: Remove these and come up with a better way to handle XDKs we don't hve databases for
if(BuildVersion == 4039) { BuildVersion = 4034; }
if(BuildVersion == 4238) { BuildVersion = 4361; } // I don't think this XDK was released.
if(BuildVersion == 4242) { BuildVersion = 4361; }
if(BuildVersion == 4400) { BuildVersion = 4361; }
if(BuildVersion == 4531) { BuildVersion = 4432; }
if(BuildVersion == 4721) { BuildVersion = 4627; }
if(BuildVersion == 4831) { BuildVersion = 4627; }
if(BuildVersion == 4928) { BuildVersion = 4627; }
if(BuildVersion == 5455) { BuildVersion = 5558; }
if(BuildVersion == 5659) { BuildVersion = 5558; }
if(BuildVersion == 5120) { BuildVersion = 5233; }
if(BuildVersion == 5933) { BuildVersion = 5849; } // These XDK versions are pretty much the same
Xbe::SectionHeader* pSectionHeaders = reinterpret_cast<Xbe::SectionHeader*>(pXbeHeader->dwSectionHeadersAddr); Xbe::SectionHeader* pSectionHeaders = reinterpret_cast<Xbe::SectionHeader*>(pXbeHeader->dwSectionHeadersAddr);
Xbe::SectionHeader* pSectionScan = nullptr; Xbe::SectionHeader* pSectionScan = nullptr;
std::string SectionName; std::string SectionName;
@ -362,23 +345,15 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
if(bXRefFirstPass) if(bXRefFirstPass)
{ {
if (strcmp(LibraryName.c_str(), Lib_XAPILIB) == 0 && if (strcmp(LibraryName.c_str(), Lib_D3D8) == 0) {
(BuildVersion == 3911 || BuildVersion == 4034 || BuildVersion == 4134 || BuildVersion == 4361
|| BuildVersion == 4432 || BuildVersion == 4627 || BuildVersion == 5028 || BuildVersion == 5233
|| BuildVersion == 5344 || BuildVersion == 5558 || BuildVersion == 5788 || BuildVersion == 5849))
{
xbaddr lower = pXbeHeader->dwBaseAddr;
xbaddr upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
}
else if (strcmp(LibraryName.c_str(), Lib_D3D8) == 0) {
// Save D3D8 build version // Save D3D8 build version
g_BuildVersion = OrigBuildVersion; g_BuildVersion = BuildVersion;
xbaddr lower = pXbeHeader->dwBaseAddr; xbaddr lower = pXbeHeader->dwBaseAddr;
xbaddr upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage; xbaddr upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
xbaddr pFunc = (xbaddr)nullptr; xbaddr pFunc = (xbaddr)nullptr;
if (OrigBuildVersion >= 3911 && OrigBuildVersion < 4034) { if (BuildVersion >= 3911 && BuildVersion < 4034) {
pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetRenderState_CullMode_3911, lower, upper); pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetRenderState_CullMode_3911, lower, upper);
} else { } else {
pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetRenderState_CullMode_4034, lower, upper); pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetRenderState_CullMode_4034, lower, upper);
@ -395,7 +370,7 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
// Read address of D3DRS_CULLMODE from D3DDevice_SetRenderState_CullMode // Read address of D3DRS_CULLMODE from D3DDevice_SetRenderState_CullMode
// TODO : Simplify this when XREF_D3DRS_CULLMODE derivation is deemed stable // TODO : Simplify this when XREF_D3DRS_CULLMODE derivation is deemed stable
{ {
if (OrigBuildVersion >= 3911 && OrigBuildVersion < 4034) { if (BuildVersion >= 3911 && BuildVersion < 4034) {
DerivedAddr_D3DRS_CULLMODE = *(xbaddr*)(pFunc + 0x25); DerivedAddr_D3DRS_CULLMODE = *(xbaddr*)(pFunc + 0x25);
Decrement = 0x1FC; // TODO: Clean up (?) Decrement = 0x1FC; // TODO: Clean up (?)
Increment = 82 * 4; Increment = 82 * 4;
@ -404,17 +379,17 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
//Decrement = 0x19F; // TODO: Clean up (?) //Decrement = 0x19F; // TODO: Clean up (?)
//Increment = 72 * 4; //Increment = 72 * 4;
//patchOffset = 142*4; // TODO: Verify //patchOffset = 142*4; // TODO: Verify
} else if (OrigBuildVersion >= 4034 && OrigBuildVersion <= 4361) { } else if (BuildVersion >= 4034 && BuildVersion <= 4361) {
DerivedAddr_D3DRS_CULLMODE = *(xbaddr*)(pFunc + 0x2B); DerivedAddr_D3DRS_CULLMODE = *(xbaddr*)(pFunc + 0x2B);
Decrement = 0x200; Decrement = 0x200;
Increment = 82 * 4; Increment = 82 * 4;
patchOffset = 142 * 4; patchOffset = 142 * 4;
} else if (OrigBuildVersion >= 4432 && OrigBuildVersion < 4627) { } else if (BuildVersion >= 4432 && BuildVersion < 4627) {
DerivedAddr_D3DRS_CULLMODE = *(xbaddr*)(pFunc + 0x2B); DerivedAddr_D3DRS_CULLMODE = *(xbaddr*)(pFunc + 0x2B);
Decrement = 0x204; Decrement = 0x204;
Increment = 83 * 4; Increment = 83 * 4;
patchOffset = 143 * 4; patchOffset = 143 * 4;
} else if (OrigBuildVersion >= 4627 && OrigBuildVersion <= 5933) { } else if (BuildVersion >= 4627 && BuildVersion <= 5933) {
DerivedAddr_D3DRS_CULLMODE = *(xbaddr*)(pFunc + 0x2B); DerivedAddr_D3DRS_CULLMODE = *(xbaddr*)(pFunc + 0x2B);
Decrement = 0x24C; Decrement = 0x24C;
Increment = 92 * 4; Increment = 92 * 4;
@ -469,13 +444,13 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
{ {
pFunc = (xbaddr)nullptr; pFunc = (xbaddr)nullptr;
if(OrigBuildVersion >= 3911 && OrigBuildVersion < 4034) if(BuildVersion >= 3911 && BuildVersion < 4034)
pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetTextureState_TexCoordIndex_3911, lower, upper); pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetTextureState_TexCoordIndex_3911, lower, upper);
else if(OrigBuildVersion >= 4034 && OrigBuildVersion < 4242) else if(BuildVersion >= 4034 && BuildVersion < 4242)
pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetTextureState_TexCoordIndex_4034, lower, upper); pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetTextureState_TexCoordIndex_4034, lower, upper);
else if(OrigBuildVersion >= 4242 && OrigBuildVersion < 4627) else if(BuildVersion >= 4242 && BuildVersion < 4627)
pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetTextureState_TexCoordIndex_4242, lower, upper); pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetTextureState_TexCoordIndex_4242, lower, upper);
else if(OrigBuildVersion >= 4627) else if(BuildVersion >= 4627)
pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetTextureState_TexCoordIndex_4627, lower, upper); pFunc = EmuLocateFunction((OOVPA*)&D3DDevice_SetTextureState_TexCoordIndex_4627, lower, upper);
if (pFunc != (xbaddr)nullptr) { if (pFunc != (xbaddr)nullptr) {
@ -484,9 +459,9 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
// TODO : Remove this when XREF_D3DTSS_TEXCOORDINDEX derivation is deemed stable // TODO : Remove this when XREF_D3DTSS_TEXCOORDINDEX derivation is deemed stable
{ {
if (OrigBuildVersion >= 3911 && OrigBuildVersion < 4034) // 0x18F180 if (BuildVersion >= 3911 && BuildVersion < 4034) // 0x18F180
DerivedAddr_D3DTSS_TEXCOORDINDEX = *(xbaddr*)(pFunc + 0x11); DerivedAddr_D3DTSS_TEXCOORDINDEX = *(xbaddr*)(pFunc + 0x11);
else if (OrigBuildVersion >= 4034 && OrigBuildVersion < 4242) else if (BuildVersion >= 4034 && BuildVersion < 4242)
DerivedAddr_D3DTSS_TEXCOORDINDEX = *(xbaddr*)(pFunc + 0x18); DerivedAddr_D3DTSS_TEXCOORDINDEX = *(xbaddr*)(pFunc + 0x18);
else else
DerivedAddr_D3DTSS_TEXCOORDINDEX = *(xbaddr*)(pFunc + 0x19); DerivedAddr_D3DTSS_TEXCOORDINDEX = *(xbaddr*)(pFunc + 0x19);
@ -521,22 +496,9 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
printf("HLE: * Searching HLE database for %s version 1.0.%d... ", LibraryName.c_str(), BuildVersion); printf("HLE: * Searching HLE database for %s version 1.0.%d... ", LibraryName.c_str(), BuildVersion);
bool notFoundHLEDB = true;
//HLE Database v1
for(uint32 d = 0; d < HLEDataBaseCount; d++) {
if (BuildVersion == HLEDataBase[d].BuildVersion && strcmp(LibraryName.c_str(), HLEDataBase[d].Library) == 0) {
if (g_bPrintfOn) printf("Found\n");
EmuInstallPatches(HLEDataBase[d].OovpaTable, HLEDataBase[d].OovpaTableSize, pXbeHeader);
notFoundHLEDB = false;
break;
}
}
//HLE Database v2
if (notFoundHLEDB) {
//Initialize library scan against HLE database we want to search for address of patches and xreferences. //Initialize library scan against HLE database we want to search for address of patches and xreferences.
for (uint32 d2 = 0; d2 < HLEDataBaseCountV2; d2++) { for (uint32 d2 = 0; d2 < HLEDataBaseCount; d2++) {
if (strcmp(LibraryName.c_str(), HLEDataBaseV2[d2].LibSec.library) == 0) { if (strcmp(LibraryName.c_str(), HLEDataBase[d2].LibSec.library) == 0) {
bool bPrintOn = g_bPrintfOn; bool bPrintOn = g_bPrintfOn;
for (uint32 v = 0; v < pXbeHeader->dwSections; v++) { for (uint32 v = 0; v < pXbeHeader->dwSections; v++) {
SectionName.assign((char*)pSectionHeaders[v].dwSectionNameAddr, (char*)pSectionHeaders[v].dwSectionNameAddr + 8); SectionName.assign((char*)pSectionHeaders[v].dwSectionNameAddr, (char*)pSectionHeaders[v].dwSectionNameAddr + 8);
@ -544,14 +506,13 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
//Initialize a matching specific section is currently pair with library in order to scan specific section only. //Initialize a matching specific section is currently pair with library in order to scan specific section only.
//By doing this method will reduce false detection dramatically. If it had happened before. //By doing this method will reduce false detection dramatically. If it had happened before.
for (uint32 d3 = 0; d3 < PAIRSCANSEC_MAX; d3++) { for (uint32 d3 = 0; d3 < PAIRSCANSEC_MAX; d3++) {
if (HLEDataBaseV2[d2].LibSec.section[d3] != NULL && strcmp(SectionName.c_str(), HLEDataBaseV2[d2].LibSec.section[d3]) == 0) { if (HLEDataBase[d2].LibSec.section[d3] != NULL && strcmp(SectionName.c_str(), HLEDataBase[d2].LibSec.section[d3]) == 0) {
pSectionScan = pSectionHeaders + v; pSectionScan = pSectionHeaders + v;
if (g_bPrintfOn) printf("Found\n"); if (g_bPrintfOn) printf("Found\n");
g_bPrintfOn = false; g_bPrintfOn = false;
EmuInstallPatchesV2(HLEDataBaseV2[d2].OovpaTable, HLEDataBaseV2[d2].OovpaTableSize, pSectionScan, OrigBuildVersion); EmuInstallPatches(HLEDataBase[d2].OovpaTable, HLEDataBase[d2].OovpaTableSize, pSectionScan, BuildVersion);
notFoundHLEDB = false;
break; break;
} }
} }
@ -560,13 +521,11 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
break; break;
} }
} }
if (g_bPrintfOn) printf("Skipped\n");
}
if (g_bPrintfOn && notFoundHLEDB) printf("Skipped\n");
if (v == dwLibraryVersions - 1 && bDSoundLibSection == false) { if (v == dwLibraryVersions - 1 && bDSoundLibSection == false) {
LibraryName = Lib_DSOUND; LibraryName = Lib_DSOUND;
OrigBuildVersion = BuildVersion = preserveVersion; BuildVersion = preserveVersion;
goto reProcessScan; goto reProcessScan;
} }
} }
@ -617,25 +576,25 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
return; return;
} }
static inline void EmuInstallPatch(std::string FunctionName, xbaddr FunctionAddr, void *Patch) inline void EmuInstallPatch(std::string FunctionName, xbaddr FunctionAddr, void *Patch)
{ {
g_FunctionHooks[FunctionName].Install((void*)(FunctionAddr), Patch); g_FunctionHooks[FunctionName].Install((void*)(FunctionAddr), Patch);
} }
static inline void GetXRefEntry(OOVPA *oovpa, int index, OUT uint32 &xref, OUT uint08 &offset) inline void GetXRefEntry(OOVPA *oovpa, int index, OUT uint32 &xref, OUT uint08 &offset)
{ {
// Note : These are stored swapped by the XREF_ENTRY macro, hence this difference from GetOovpaEntry : // Note : These are stored swapped by the XREF_ENTRY macro, hence this difference from GetOovpaEntry :
xref = (uint32)((LOOVPA<1>*)oovpa)->Lovp[index].Offset; xref = (uint32)((LOOVPA<1>*)oovpa)->Lovp[index].Offset;
offset = ((LOOVPA<1>*)oovpa)->Lovp[index].Value; offset = ((LOOVPA<1>*)oovpa)->Lovp[index].Value;
} }
static inline void GetOovpaEntry(OOVPA *oovpa, int index, OUT uint32 &offset, OUT uint08 &value) inline void GetOovpaEntry(OOVPA *oovpa, int index, OUT uint32 &offset, OUT uint08 &value)
{ {
offset = (uint32)((LOOVPA<1>*)oovpa)->Lovp[index].Offset; offset = (uint32)((LOOVPA<1>*)oovpa)->Lovp[index].Offset;
value = ((LOOVPA<1>*)oovpa)->Lovp[index].Value; value = ((LOOVPA<1>*)oovpa)->Lovp[index].Value;
} }
static boolean CompareOOVPAToAddress(OOVPA *Oovpa, xbaddr cur) boolean CompareOOVPAToAddress(OOVPA *Oovpa, xbaddr cur)
{ {
uint32 v = 0; // verification counter uint32 v = 0; // verification counter
@ -681,202 +640,6 @@ static boolean CompareOOVPAToAddress(OOVPA *Oovpa, xbaddr cur)
return true; return true;
} }
// locate the given function, searching within lower and upper bounds
static xbaddr EmuLocateFunction(OOVPA *Oovpa, xbaddr lower, xbaddr upper)
{
// skip out if this is an unnecessary search
if (!bXRefFirstPass && Oovpa->XRefCount == XRefZero && Oovpa->XRefSaveIndex == XRefNoSaveIndex)
return (xbaddr)nullptr;
uint32_t derive_indices = 0;
// Check all XRefs are known (if not, don't do a useless scan) :
for (uint32 v = 0; v < Oovpa->XRefCount; v++)
{
uint32 XRef;
uint08 Offset;
// get currently registered (un)known address
GetXRefEntry(Oovpa, v, XRef, Offset);
xbaddr XRefAddr = XRefDataBase[XRef];
// Undetermined XRef cannot be checked yet
if (XRefAddr == XREF_ADDR_UNDETERMINED)
// Skip this scan over the address range
return (xbaddr)nullptr;
// Don't verify an xref that has to be (but isn't yet) derived
if (XRefAddr == XREF_ADDR_DERIVE)
{
// Mark (up to index 32) which xref needs to be derived
derive_indices |= (1 << v);
continue;
}
}
// correct upper bound with highest Oovpa offset
uint32 count = Oovpa->Count;
{
uint32 Offset;
uint08 Value; // ignored
GetOovpaEntry(Oovpa, count - 1, Offset, Value);
upper -= Offset;
}
// search all of the image memory
for (xbaddr cur = lower; cur < upper; cur++)
if (CompareOOVPAToAddress(Oovpa, cur))
{
// do we need to save the found address?
if (Oovpa->XRefSaveIndex != XRefNoSaveIndex)
{
// is the XRef not saved yet?
switch (XRefDataBase[Oovpa->XRefSaveIndex]) {
case XREF_ADDR_NOT_FOUND:
{
EmuWarning("Found OOVPA after first finding nothing?");
// fallthrough to XREF_ADDR_UNDETERMINED
}
case XREF_ADDR_UNDETERMINED:
{
// save and count the found address
UnResolvedXRefs--;
XRefDataBase[Oovpa->XRefSaveIndex] = cur;
break;
}
case XREF_ADDR_DERIVE:
{
EmuWarning("Cannot derive a save index!");
break;
}
default:
{
if (XRefDataBase[Oovpa->XRefSaveIndex] != cur) {
EmuWarning("Found OOVPA on other address than in XRefDataBase!");
}
break;
}
}
}
while (derive_indices > 0)
{
uint32 XRef;
uint08 Offset;
DWORD derive_index;
// Extract an index from the indices mask :
_BitScanReverse(&derive_index, derive_indices); // MSVC intrinsic; GCC has __builtin_clz
derive_indices ^= (1 << derive_index);
// get currently registered (un)known address
GetXRefEntry(Oovpa, derive_index, XRef, Offset);
// Calculate the address where the XRef resides
xbaddr XRefAddr = cur + Offset;
// Read the address it points to
XRefAddr = *((xbaddr*)XRefAddr);
/* For now assume it's a direct reference;
// TODO : Check if it's PC-relative reference?
if (XRefAddr + cur + Offset + 4 < XBE_MAX_VA)
XRefAddr = XRefAddr + cur + Offset + 4;
*/
// Does the address seem valid?
if (XRefAddr < XBE_MAX_VA)
{
// save and count the derived address
UnResolvedXRefs--;
XRefDataBase[XRef] = XRefAddr;
printf("Derived OOVPA!\n");
}
}
return cur;
}
// found nothing
return (xbaddr)nullptr;
}
// install function interception wrappers
static void EmuInstallPatches(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::Header *pXbeHeader)
{
xbaddr lower = pXbeHeader->dwBaseAddr;
// Find the highest address contained within an executable segment
xbaddr upper = pXbeHeader->dwBaseAddr;
Xbe::SectionHeader* headers = reinterpret_cast<Xbe::SectionHeader*>(pXbeHeader->dwSectionHeadersAddr);
for (uint32_t i = 0; i < pXbeHeader->dwSections; i++) {
xbaddr end_addr = headers[i].dwVirtualAddr + headers[i].dwVirtualSize;
if (headers[i].dwFlags.bExecutable && end_addr > upper) {
upper = end_addr;
}
}
// traverse the full OOVPA table
for(size_t a=0;a<OovpaTableSize/sizeof(OOVPATable);a++)
{
// Never used : skip scans when so configured
bool DontScan = (OovpaTable[a].Flags & Flag_DontScan) > 0;
if (DontScan)
continue;
// Skip already found & handled symbols
xbaddr pFunc = g_SymbolAddresses[OovpaTable[a].szFuncName];
if (pFunc != (xbaddr)nullptr)
continue;
// Search for each function's location using the OOVPA
OOVPA *Oovpa = OovpaTable[a].Oovpa;
pFunc = (xbaddr)EmuLocateFunction(Oovpa, lower, upper);
if (pFunc == (xbaddr)nullptr)
continue;
// Now that we found the address, store it (regardless if we patch it or not)
g_SymbolAddresses[OovpaTable[a].szFuncName] = (uint32_t)pFunc;
// Output some details
std::stringstream output;
output << "HLE: 0x" << std::setfill('0') << std::setw(8) << std::hex << pFunc
<< " -> " << OovpaTable[a].szFuncName << " " << std::dec << OovpaTable[a].Version;
bool IsXRef = (OovpaTable[a].Flags & Flag_XRef) > 0;
if (IsXRef)
output << "\t(XREF)";
// Retrieve the associated patch, if any is available
void* addr = GetEmuPatchAddr(std::string(OovpaTable[a].szFuncName));
bool DontPatch = (OovpaTable[a].Flags & Flag_DontPatch) > 0;
if (DontPatch)
{
// Mention if there's an unused patch
if (addr != nullptr)
output << "\t*PATCH UNUSED!*";
else
output << "\t*DISABLED*";
}
else
{
if (addr != nullptr)
{
EmuInstallPatch(OovpaTable[a].szFuncName, pFunc, addr);
output << "\t*PATCHED*";
}
else
{
// Mention there's no patch available, if it was to be applied
if (!IsXRef) // TODO : Remove this restriction once we patch xrefs regularly
output << "\t*NO PATCH AVAILABLE!*";
}
}
output << "\n";
printf(output.str().c_str());
}
}
void EmuRegisterSymbol(OOVPATable *OovpaTable, xbaddr pFunc) void EmuRegisterSymbol(OOVPATable *OovpaTable, xbaddr pFunc)
{ {
// Ignore registered symbol in current database. // Ignore registered symbol in current database.
@ -957,9 +720,8 @@ void EmuRegisterSymbol(OOVPATable *OovpaTable, xbaddr pFunc)
printf(output.str().c_str()); printf(output.str().c_str());
} }
// locate the given function, searching within lower and upper bounds // locate the given function, searching within lower and upper bounds
xbaddr EmuLocateFunctionV2(OOVPA *Oovpa, xbaddr lower, xbaddr upper) xbaddr EmuLocateFunction(OOVPA *Oovpa, xbaddr lower, xbaddr upper)
{ {
// skip out if this is an unnecessary search // skip out if this is an unnecessary search
if (!bXRefFirstPass && Oovpa->XRefCount == XRefZero && Oovpa->XRefSaveIndex == XRefNoSaveIndex) if (!bXRefFirstPass && Oovpa->XRefCount == XRefZero && Oovpa->XRefSaveIndex == XRefNoSaveIndex)
@ -1041,7 +803,7 @@ xbaddr EmuLocateFunctionV2(OOVPA *Oovpa, xbaddr lower, xbaddr upper)
} }
// install function interception wrappers // install function interception wrappers
static void EmuInstallPatchesV2(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::SectionHeader *pSectionHeader, uint16_t buildVersion) void EmuInstallPatches(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::SectionHeader *pSectionHeader, uint16_t buildVersion)
{ {
xbaddr lower = pSectionHeader->dwVirtualAddr; xbaddr lower = pSectionHeader->dwVirtualAddr;
@ -1073,11 +835,11 @@ static void EmuInstallPatchesV2(OOVPATable *OovpaTable, uint32 OovpaTableSize, X
continue; continue;
// Search for each function's location using the OOVPA // Search for each function's location using the OOVPA
xbaddr pFunc = (xbaddr)EmuLocateFunctionV2(pLoop->Oovpa, lower, upper); xbaddr pFunc = (xbaddr)EmuLocateFunction(pLoop->Oovpa, lower, upper);
if (pFunc == (xbaddr)nullptr) if (pFunc == (xbaddr)nullptr)
continue; continue;
if (pFunc == pLastKnownFunc && pLastKnownSymbol == pLoop-1) { if (pFunc == pLastKnownFunc && pLastKnownSymbol == pLoop - 1) {
if (g_SymbolAddresses[pLastKnownSymbol->szFuncName] == 0) { if (g_SymbolAddresses[pLastKnownSymbol->szFuncName] == 0) {
printf("HLE: Duplicate OOVPA signature found for %s, %d vs %d!\n", pLastKnownSymbol->szFuncName, pLastKnownSymbol->Version, pLoop->Version); printf("HLE: Duplicate OOVPA signature found for %s, %d vs %d!\n", pLastKnownSymbol->szFuncName, pLastKnownSymbol->Version, pLoop->Version);
} }