HLE caching

This commit is contained in:
Aaron Robinson 2004-09-14 07:23:35 +00:00
parent a91947eb52
commit 7538c4268a
12 changed files with 833 additions and 515 deletions

View File

@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /O2 /I "Include" /I "Include/Core/" /I "Include/Standard" /I "Include/Standard/Cxbe" /I "Include/Win32/" /I "Include/Win32/CxbxKrnl/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "Include" /I "Include/Core/" /I "Include/Standard" /I "Include/Standard/Cxbe" /I "Include/Win32/" /I "Include/Win32/CxbxKrnl/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@ -67,7 +67,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /Zi /Od /I "Include" /I "Include/Core/" /I "Include/Standard" /I "Include/Standard/Cxbe" /I "Include/Win32/" /I "Include/Win32/CxbxKrnl/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "Include" /I "Include/Core/" /I "Include/Standard" /I "Include/Standard/Cxbe" /I "Include/Win32/" /I "Include/Win32/CxbxKrnl/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# SUBTRACT CPP /Fr
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"

View File

@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /Zi /O2 /I "Include" /I "Include/Core/" /I "Include/Win32/" /I "Include/Win32/Cxbxkrnl" /I "Include/Win32/Cxbx" /I "Include/Win32/Cxbx/jpegdec" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Fr /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "Include" /I "Include/Core/" /I "Include/Win32/" /I "Include/Win32/Cxbxkrnl" /I "Include/Win32/Cxbx" /I "Include/Win32/Cxbx/jpegdec" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Fr /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
@ -74,7 +74,7 @@ PostBuild_Cmds=cd PostBuild upxCxbx.bat
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /Zi /Od /I "Include" /I "Include/Core/" /I "Include/Win32/" /I "Include/Win32/Cxbxkrnl" /I "Include/Win32/Cxbx" /I "Include/Win32/Cxbx/jpegdec" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Fr /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "Include" /I "Include/Core/" /I "Include/Win32/" /I "Include/Win32/Cxbxkrnl" /I "Include/Win32/Cxbx" /I "Include/Win32/Cxbx/jpegdec" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Fr /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"

BIN
Cxbx.opt

Binary file not shown.

View File

@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CXBXKRNL_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /O2 /I "Include" /I "Include/Core/" /I "Include/Win32/" /I "Include/Win32/Cxbx" /I "Include/Win32/CxbxKrnl" /I "Include/Win32/CxbxKrnl/HLEDataBase" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CXBXKRNL_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "Include" /I "Include/Core/" /I "Include/Win32/" /I "Include/Win32/Cxbx" /I "Include/Win32/CxbxKrnl" /I "Include/Win32/CxbxKrnl/HLEDataBase" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CXBXKRNL_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
@ -347,6 +347,10 @@ SOURCE=.\Include\Win32\CxbxKrnl\HLEDataBase.h
# End Source File
# Begin Source File
SOURCE=.\Include\Win32\CxbxKrnl\HLEIntercept.h
# End Source File
# Begin Source File
SOURCE=.\Include\Win32\Mutex.h
# End Source File
# Begin Source File
@ -622,6 +626,10 @@ SOURCE=.\Source\Win32\CxbxKrnl\HLEDataBase.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\Win32\CxbxKrnl\HLEIntercept.cpp
# End Source File
# Begin Source File
SOURCE=.\Source\Win32\CxbxKrnl\KernelThunk.cpp
# End Source File
# Begin Source File

View File

@ -19,6 +19,8 @@ version: 0.8.0 (??/??/??)
- Toggle Wireframe/Dots/Normal with F11
- HLE caching (so very very nice and speedy!)
- Tons of new debug support, including integrated debug console
- DirectSound support! Turok and Stella (Atari 2600 emulator)

View File

@ -81,8 +81,8 @@ extern int EmuException(LPEXCEPTION_POINTERS e);
extern int EmuCheckAllocationSize(LPVOID pBase, bool largeBound);
// global flags specifying current emulation state
extern volatile BOOL g_bEmuException;
extern volatile BOOL g_bEmuSuspended;
extern volatile bool g_bEmuException;
extern volatile bool g_bEmuSuspended;
// global exception patching address
extern uint32 g_HaloHack[4];

View File

@ -60,6 +60,11 @@
#include "XNet.1.0.3911.h"
#include "XOnline.1.0.4361.h"
// ******************************************************************
// * szHLELastCompileTime
// ******************************************************************
extern "C" const char *szHLELastCompileTime;
// ******************************************************************
// * HLEDataBase
// ******************************************************************

View File

@ -0,0 +1,39 @@
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->Win32->CxbxKrnl->HLEIntercept.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>
// *
// * All rights reserved
// *
// ******************************************************************
#ifndef HLEINTERCEPT_H
#define HLEINTERCEPT_H
extern "C" void EmuHLEIntercept(Xbe::LibraryVersion *LibraryVersion, Xbe::Header *XbeHeader);
#endif

View File

@ -54,29 +54,28 @@ namespace NtDll
#include "EmuXTL.h"
#include "EmuShared.h"
#include "HLEDataBase.h"
#include "HLEIntercept.h"
#include <shlobj.h>
#include <locale.h>
// Global Variable(s)
Xbe::TLS *g_pTLS = NULL;
void *g_pTLSData = NULL;
Xbe::Header *g_pXbeHeader = NULL;
HANDLE g_hCurDir = NULL;
HANDLE g_hCurDir = NULL;
HANDLE g_hTDrive = NULL;
HANDLE g_hUDrive = NULL;
HANDLE g_hZDrive = NULL;
volatile BOOL g_bEmuSuspended = FALSE;
volatile BOOL g_bEmuException = FALSE;
volatile bool g_bEmuException = false;
volatile bool g_bEmuSuspended = false;
volatile bool g_bPrintfOn = true;
// global exception patching address
uint32 g_HaloHack[4] = {0};
// Static Function(s)
static void *EmuLocateFunction(OOVPA *Oovpa, uint32 lower, uint32 upper);
static void EmuInstallWrappers(OOVPATable *OovpaTable, uint32 OovpaTableSize, void (*Entry)(), Xbe::Header *pXbeHeader);
static void EmuXRefFailure();
static int ExitException(LPEXCEPTION_POINTERS e);
static int ExitException(LPEXCEPTION_POINTERS e);
// Static Variable(s)
static HANDLE g_hThreads[MAXIMUM_XBOX_THREADS] = {0};
@ -150,7 +149,7 @@ extern "C" CXBXKRNL_API void NTAPI EmuInit
g_pXbeHeader = pXbeHeader;
g_hEmuParent = IsWindow(hwndParent) ? hwndParent : NULL;
// For Unicode Conversions
// for unicode conversions
setlocale(LC_ALL, "English");
// debug console allocation (if configured)
@ -188,7 +187,10 @@ extern "C" CXBXKRNL_API void NTAPI EmuInit
freopen("nul", "w", stdout);
}
//
// debug trace
//
{
#ifdef _DEBUG_TRACE
printf("EmuMain (0x%X): Debug Trace Enabled.\n", GetCurrentThreadId());
@ -212,7 +214,10 @@ extern "C" CXBXKRNL_API void NTAPI EmuInit
#endif
}
//
// load the necessary pieces of XbeHeader
//
{
Xbe::Header *MemXbeHeader = (Xbe::Header*)0x00010000;
@ -231,7 +236,10 @@ extern "C" CXBXKRNL_API void NTAPI EmuInit
memcpy((void*)pXbeHeader->dwCertificateAddr, &((uint08*)pXbeHeader)[pXbeHeader->dwCertificateAddr - 0x00010000], sizeof(Xbe::Certificate));
}
//
// initialize current directory
//
{
char szBuffer[260];
@ -250,37 +258,49 @@ extern "C" CXBXKRNL_API void NTAPI EmuInit
DbgPrintf("EmuMain (0x%X): CurDir := %s\n", GetCurrentThreadId(), szBuffer);
}
// initialize T:\ and U:\ directories
//
// initialize EmuDisk
//
{
char szBuffer[260];
#ifdef _DEBUG
GetModuleFileName(GetModuleHandle("CxbxKrnl.dll"), szBuffer, 260);
#else
GetModuleFileName(GetModuleHandle("Cxbx.dll"), szBuffer, 260);
#endif
SHGetSpecialFolderPath(NULL, szBuffer, CSIDL_APPDATA, TRUE);
strcat(szBuffer, "\\Cxbx\\");
CreateDirectory(szBuffer, NULL);
sint32 spot = -1;
sint32 spot=-1;
for(int v=0;v<260;v++)
{
if(szBuffer[v] == '\\')
spot = v;
else if(szBuffer[v] == '\0')
break;
if(szBuffer[v] == '\\') { spot = v; }
else if(szBuffer[v] == '\0') { break; }
}
if(spot != -1)
szBuffer[spot] = '\0';
if(spot != -1) { szBuffer[spot] = '\0'; }
Xbe::Certificate *pCertificate = (Xbe::Certificate*)pXbeHeader->dwCertificateAddr;
// Create TData Directory
//
// create EmuDisk directory
//
strcpy(&szBuffer[spot], "\\EmuDisk");
CreateDirectory(szBuffer, NULL);
//
// create T:\ directory
//
{
strcpy(&szBuffer[spot], "\\TDATA");
strcpy(&szBuffer[spot], "\\EmuDisk\\T");
CreateDirectory(szBuffer, NULL);
sprintf(&szBuffer[spot+6], "\\%08x", pCertificate->dwTitleId);
sprintf(&szBuffer[spot+10], "\\%08x", pCertificate->dwTitleId);
CreateDirectory(szBuffer, NULL);
@ -292,13 +312,16 @@ extern "C" CXBXKRNL_API void NTAPI EmuInit
DbgPrintf("EmuMain (0x%X): T Data := %s\n", GetCurrentThreadId(), szBuffer);
}
// Create UData Directory
//
// create U:\ directory
//
{
strcpy(&szBuffer[spot], "\\UDATA");
strcpy(&szBuffer[spot], "\\EmuDisk\\U");
CreateDirectory(szBuffer, NULL);
sprintf(&szBuffer[spot+6], "\\%08x", pCertificate->dwTitleId);
sprintf(&szBuffer[spot+10], "\\%08x", pCertificate->dwTitleId);
CreateDirectory(szBuffer, NULL);
@ -310,9 +333,12 @@ extern "C" CXBXKRNL_API void NTAPI EmuInit
DbgPrintf("EmuMain (0x%X): U Data := %s\n", GetCurrentThreadId(), szBuffer);
}
// Create ZData Directory
//
// create Z:\ directory
//
{
strcpy(&szBuffer[spot], "\\CxbxCache");
strcpy(&szBuffer[spot], "\\EmuDisk\\Z");
CreateDirectory(szBuffer, NULL);
@ -331,14 +357,20 @@ extern "C" CXBXKRNL_API void NTAPI EmuInit
}
}
// initialize FS segment selector emulation
//
// initialize FS segment selector
//
{
EmuInitFS();
EmuGenerateFS(pTLS, pTLSData);
}
// we must duplicate this handle in order to retain Suspend/Resume thread rights from a remote thread
//
// duplicate handle in order to retain Suspend/Resume thread rights from a remote thread
//
{
HANDLE hDupHandle = NULL;
@ -351,274 +383,14 @@ extern "C" CXBXKRNL_API void NTAPI EmuInit
XTL::EmuD3DInit(pXbeHeader, dwXbeHeaderSize);
// initialize OpenXDK emulation (non-existant for now at least)
if(pLibraryVersion == 0)
DbgPrintf("EmuMain (0x%X): Detected OpenXDK application...\n", GetCurrentThreadId());
// initialize Microsoft XDK emulation
if(pLibraryVersion != 0)
{
DbgPrintf("EmuMain (0x%X): Detected Microsoft XDK application...\n", GetCurrentThreadId());
uint32 dwLibraryVersions = pXbeHeader->dwLibraryVersions;
uint32 dwHLEEntries = HLEDataBaseSize/sizeof(HLEData);
uint32 LastUnResolvedXRefs = UnResolvedXRefs+1;
uint32 OrigUnResolvedXRefs = UnResolvedXRefs;
for(int p=0;UnResolvedXRefs < LastUnResolvedXRefs;p++)
{
DbgPrintf("EmuMain (0x%X): Beginning HLE Pass %d...\n", GetCurrentThreadId(), p);
LastUnResolvedXRefs = UnResolvedXRefs;
bool bFoundD3D = false;
for(uint32 v=0;v<dwLibraryVersions;v++)
{
uint16 MajorVersion = pLibraryVersion[v].wMajorVersion;
uint16 MinorVersion = pLibraryVersion[v].wMinorVersion;
uint16 BuildVersion = pLibraryVersion[v].wBuildVersion;
uint16 OrigBuildVersion = BuildVersion;
//
// Aliases
//
{
if(BuildVersion == 4928)
BuildVersion = 4627;
if(BuildVersion == 5659)
BuildVersion = 5558;
}
char szLibraryName[9] = {0};
for(uint32 c=0;c<8;c++)
szLibraryName[c] = pLibraryVersion[v].szName[c];
// TODO: HACK: These libraries are packed into one database
if(strcmp(szLibraryName, "D3DX8") == 0)
strcpy(szLibraryName, "D3D8");
if(strcmp(szLibraryName, "D3D8") == 0)
{
if(bFoundD3D)
{
DbgPrintf("Redundant\n");
continue;
}
bFoundD3D = true;
}
if(bXRefFirstPass)
{
if(strcmp("XAPILIB", szLibraryName) == 0 && MajorVersion == 1 && MinorVersion == 0 &&
(BuildVersion == 3911 || BuildVersion == 4034 || BuildVersion == 4134 || BuildVersion == 4361
|| BuildVersion == 4432 || BuildVersion == 4627 || BuildVersion == 5558 || BuildVersion == 5849))
{
uint32 lower = pXbeHeader->dwBaseAddr;
uint32 upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
// locate XapiProcessHeap
{
void *pFunc = 0;
uint ProcessHeapOffs;
uint RtlCreateHeapOffs;
if(BuildVersion >= 5849)
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_5849, lower, upper);
ProcessHeapOffs = 0x51;
RtlCreateHeapOffs = 0x4A;
}
else if(BuildVersion >= 5558)
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_5558, lower, upper);
// 5659 has an updated function
if(pFunc == 0)
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_5659, lower, upper);
}
ProcessHeapOffs = 0x51;
RtlCreateHeapOffs = 0x4A;
}
else if(BuildVersion >= 4361)
{
if(OrigBuildVersion == 4928)
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_4928, lower, upper);
ProcessHeapOffs = 0x44;
RtlCreateHeapOffs = 0x3B;
}
else
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_4361, lower, upper);
ProcessHeapOffs = 0x3E;
RtlCreateHeapOffs = 0x37;
}
}
else // 3911, 4034, 4134
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_3911, lower, upper);
ProcessHeapOffs = 0x3E;
RtlCreateHeapOffs = 0x37;
}
if(pFunc != 0)
{
XTL::EmuXapiProcessHeap = *(PVOID**)((uint32)pFunc + ProcessHeapOffs);
XTL::g_pRtlCreateHeap = *(XTL::pfRtlCreateHeap*)((uint32)pFunc + RtlCreateHeapOffs);
XTL::g_pRtlCreateHeap = (XTL::pfRtlCreateHeap)((uint32)pFunc + (uint32)XTL::g_pRtlCreateHeap + RtlCreateHeapOffs + 0x04);
DbgPrintf("EmuMain (0x%X): 0x%.08X -> EmuXapiProcessHeap\n", GetCurrentThreadId(), XTL::EmuXapiProcessHeap);
DbgPrintf("EmuMain (0x%X): 0x%.08X -> g_pRtlCreateHeap\n", GetCurrentThreadId(), XTL::g_pRtlCreateHeap);
}
}
}
else if(strcmp("D3D8", szLibraryName) == 0 && MajorVersion == 1 && MinorVersion == 0 &&
(BuildVersion == 3925 || BuildVersion == 4134 || BuildVersion == 4361 || BuildVersion == 4432
|| BuildVersion == 4627 || BuildVersion == 5558 || BuildVersion == 5849))
{
uint32 lower = pXbeHeader->dwBaseAddr;
uint32 upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
void *pFunc = 0;
if(BuildVersion == 3925)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetRenderState_CullMode_1_0_3925, lower, upper);
else if(BuildVersion < 5558)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetRenderState_CullMode_1_0_4134, lower, upper);
else
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetRenderState_CullMode_1_0_5558, lower, upper);
// locate D3DDeferredRenderState
if(pFunc != 0)
{
// 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) - 0x19F + 72*4); // TODO: Clean up (?)
patchOffset = 142*4 - 72*4; // TODO: Verify
}
else if(BuildVersion == 4134)
{
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)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);
patchOffset = 142*4 - 82*4;
}
else if(BuildVersion == 4432)
{
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x2B) - 0x204 + 83*4);
patchOffset = 143*4 - 83*4;
}
else if(BuildVersion == 4627)
{
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x2B) - 0x24C + 92*4);
patchOffset = 162*4 - 92*4;
}
else if(BuildVersion == 5558 || BuildVersion == 5849)
{
// WARNING: Not thoroughly tested (just seemed very correct right away)
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x2B) - 0x24C + 92*4);
patchOffset = 162*4 - 92*4;
}
XRefDataBase[XREF_D3DDEVICE] = *(DWORD*)((DWORD)pFunc + 0x03);
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;
for(int v=0;v<44;v++)
XTL::EmuD3DDeferredRenderState[v] = X_D3DRS_UNK;
DbgPrintf("EmuMain (0x%X): 0x%.08X -> EmuD3DDeferredRenderState\n", GetCurrentThreadId(), XTL::EmuD3DDeferredRenderState);
}
else
{
XTL::EmuD3DDeferredRenderState = 0;
EmuWarning("EmuD3DDeferredRenderState was not found!");
}
// locate D3DDeferredTextureState
{
pFunc = 0;
if(BuildVersion == 3925)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetTextureState_TexCoordIndex_1_0_3925, lower, upper);
else if(BuildVersion == 4134)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetTextureState_TexCoordIndex_1_0_4134, lower, upper);
else if(BuildVersion == 4361 || BuildVersion == 4432)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetTextureState_TexCoordIndex_1_0_4361, lower, upper);
else if(BuildVersion == 4627 || BuildVersion == 5558 || BuildVersion == 5849)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetTextureState_TexCoordIndex_1_0_4627, lower, upper);
if(pFunc != 0)
{
if(BuildVersion == 3925) // 0x18F180
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x11) - 0x70); // TODO: Verify
else if(BuildVersion == 4134)
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x18) - 0x70); // TODO: Verify
else
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x19) - 0x70);
for(int s=0;s<4;s++)
{
for(int v=0;v<32;v++)
XTL::EmuD3DDeferredTextureState[v+s*32] = X_D3DTSS_UNK;
}
DbgPrintf("EmuMain (0x%X): 0x%.08X -> EmuD3DDeferredTextureState\n", GetCurrentThreadId(), XTL::EmuD3DDeferredTextureState);
}
else
{
XTL::EmuD3DDeferredTextureState = 0;
EmuCleanup("EmuD3DDeferredTextureState was not found!");
}
}
}
}
DbgPrintf("EmuMain (0x%X): Locating HLE Information for %s %d.%d.%d...", GetCurrentThreadId(), pLibraryVersion[v].szName, MajorVersion, MinorVersion, BuildVersion);
bool found=false;
for(uint32 d=0;d<dwHLEEntries;d++)
{
if(BuildVersion != HLEDataBase[d].BuildVersion || MinorVersion != HLEDataBase[d].MinorVersion || MajorVersion != HLEDataBase[d].MajorVersion || strcmp(szLibraryName, HLEDataBase[d].Library) != 0)
continue;
found = true;
DbgPrintf("Found\n");
EmuInstallWrappers(HLEDataBase[d].OovpaTable, HLEDataBase[d].OovpaTableSize, Entry, pXbeHeader);
}
if(!found)
DbgPrintf("Skipped\n");
}
bXRefFirstPass = false;
}
// display Xref summary
DbgPrintf("EmuMain (0x%X): Resolved %d cross reference(s)\n", GetCurrentThreadId(), OrigUnResolvedXRefs - UnResolvedXRefs);
}
EmuHLEIntercept(pLibraryVersion, pXbeHeader);
DbgPrintf("EmuMain (0x%X): Initial thread starting.\n", GetCurrentThreadId());
//
// Xbe entry point
//
__try
{
EmuSwapFS(); // XBox FS
@ -702,7 +474,7 @@ extern "C" CXBXKRNL_API void NTAPI EmuWarning(const char *szWarningMessage, ...)
// cleanup emulation
extern "C" CXBXKRNL_API void NTAPI EmuCleanup(const char *szErrorMessage, ...)
{
g_bEmuException = TRUE;
g_bEmuException = true;
EmuResume();
@ -818,7 +590,7 @@ extern "C" CXBXKRNL_API void NTAPI EmuSuspend()
SetWindowText(hWnd, szBuffer);
}
g_bEmuSuspended = TRUE;
g_bEmuSuspended = true;
}
// resume all threads that have been created with PsCreateSystemThreadEx
@ -859,7 +631,7 @@ extern "C" CXBXKRNL_API void NTAPI EmuResume()
}
}
g_bEmuSuspended = FALSE;
g_bEmuSuspended = false;
}
// exception handler
@ -868,7 +640,7 @@ extern int EmuException(LPEXCEPTION_POINTERS e)
if(EmuIsXboxFS())
EmuSwapFS();
g_bEmuException = TRUE;
g_bEmuException = true;
// check for Halo hack
{
@ -923,7 +695,7 @@ extern int EmuException(LPEXCEPTION_POINTERS e)
DbgPrintf("EmuMain (0x%X): Halo Access Adjust 1 was applied!\n", GetCurrentThreadId());
g_bEmuException = FALSE;
g_bEmuException = false;
return EXCEPTION_CONTINUE_EXECUTION;
}
@ -956,7 +728,7 @@ extern int EmuException(LPEXCEPTION_POINTERS e)
DbgPrintf("EmuMain (0x%X): Halo Access Adjust 2 was applied!\n", GetCurrentThreadId());
g_bEmuException = FALSE;
g_bEmuException = false;
return EXCEPTION_CONTINUE_EXECUTION;
}
@ -1015,7 +787,7 @@ extern int EmuException(LPEXCEPTION_POINTERS e)
{
printf("EmuMain (0x%X): Ignored Breakpoint Exception\n", GetCurrentThreadId());
g_bEmuException = FALSE;
g_bEmuException = false;
return EXCEPTION_CONTINUE_EXECUTION;
}
@ -1042,7 +814,7 @@ extern int EmuException(LPEXCEPTION_POINTERS e)
}
}
g_bEmuException = FALSE;
g_bEmuException = false;
return EXCEPTION_CONTINUE_SEARCH;
}
@ -1072,197 +844,6 @@ extern int EmuCheckAllocationSize(LPVOID pBase, bool largeBound)
return MemoryBasicInfo.RegionSize - ((DWORD)pBase - (DWORD)MemoryBasicInfo.BaseAddress);
}
// install function interception wrapper
static inline void EmuInstallWrapper(void *FunctionAddr, void *WrapperAddr)
{
uint08 *FuncBytes = (uint08*)FunctionAddr;
*(uint08*)&FuncBytes[0] = 0xE9;
*(uint32*)&FuncBytes[1] = (uint32)WrapperAddr - (uint32)FunctionAddr - 5;
}
// locate the given function, searching within lower and upper bounds
static void *EmuLocateFunction(OOVPA *Oovpa, uint32 lower, uint32 upper)
{
uint32 count = Oovpa->Count;
// Skip out if this is an unnecessary search
if(!bXRefFirstPass && Oovpa->XRefCount == 0 && Oovpa->XRefSaveIndex == (uint08)-1)
return 0;
// large
if(Oovpa->Large == 1)
{
LOOVPA<1> *Loovpa = (LOOVPA<1>*)Oovpa;
upper -= Loovpa->Lovp[count-1].Offset;
// search all of the image memory
for(uint32 cur=lower;cur<upper;cur++)
{
uint32 v;
// check all cross references
for(v=0;v<Loovpa->XRefCount;v++)
{
uint32 Offset = Loovpa->Lovp[v].Offset;
uint32 Value = Loovpa->Lovp[v].Value;
uint32 RealValue = *(uint32*)(cur + Offset);
if(XRefDataBase[Value] == -1)
goto skipout_L; // unsatisfied Xref is not acceptable
if((RealValue + cur + Offset+4 != XRefDataBase[Value]) && (RealValue != XRefDataBase[Value]))
break;
}
// check all pairs, moving on if any do not match
for(v=0;v<count;v++)
{
uint32 Offset = Loovpa->Lovp[v].Offset;
uint32 Value = Loovpa->Lovp[v].Value;
uint08 RealValue = *(uint08*)(cur + Offset);
if(RealValue != Value)
break;
}
// success if we found all pairs
if(v == count)
{
if(Loovpa->XRefSaveIndex != (uint08)-1)
{
if(XRefDataBase[Loovpa->XRefSaveIndex] == -1)
{
UnResolvedXRefs--;
XRefDataBase[Loovpa->XRefSaveIndex] = cur;
return (void*)cur;
}
else
{
return (void*)XRefDataBase[Loovpa->XRefSaveIndex]; // already Found, no bother patching again
}
}
return (void*)cur;
}
skipout_L:;
}
}
// small
else
{
SOOVPA<1> *Soovpa = (SOOVPA<1>*)Oovpa;
upper -= Soovpa->Sovp[count-1].Offset;
// search all of the image memory
for(uint32 cur=lower;cur<upper;cur++)
{
uint32 v;
// check all cross references
for(v=0;v<Soovpa->XRefCount;v++)
{
uint32 Offset = Soovpa->Sovp[v].Offset;
uint32 Value = Soovpa->Sovp[v].Value;
uint32 RealValue = *(uint32*)(cur + Offset);
if(XRefDataBase[Value] == -1)
goto skipout_S; // Unsatisfied XRef is not acceptable
if( (RealValue + cur + Offset + 4 != XRefDataBase[Value]) && (RealValue != XRefDataBase[Value]))
break;
}
// check OV pairs if all xrefs matched
if(v == Soovpa->XRefCount)
{
// check all pairs, moving on if any do not match
for(;v<count;v++)
{
uint32 Offset = Soovpa->Sovp[v].Offset;
uint32 Value = Soovpa->Sovp[v].Value;
uint08 RealValue = *(uint08*)(cur + Offset);
if(RealValue != Value)
break;
}
}
// success if we found all pairs
if(v == count)
{
if(Soovpa->XRefSaveIndex != (uint08)-1)
{
if(XRefDataBase[Soovpa->XRefSaveIndex] == -1)
{
UnResolvedXRefs--;
XRefDataBase[Soovpa->XRefSaveIndex] = cur;
return (void*)cur;
}
else
{
return (void*)XRefDataBase[Soovpa->XRefSaveIndex]; // already Found, no bother patching again
}
}
return (void*)cur;
}
skipout_S:;
}
}
return 0;
}
// install function interception wrappers
static void EmuInstallWrappers(OOVPATable *OovpaTable, uint32 OovpaTableSize, void (*Entry)(), Xbe::Header *pXbeHeader)
{
uint32 lower = pXbeHeader->dwBaseAddr;
uint32 upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
// traverse the full OOVPA table
for(uint32 a=0;a<OovpaTableSize/sizeof(OOVPATable);a++)
{
OOVPA *Oovpa = OovpaTable[a].Oovpa;
void *pFunc = EmuLocateFunction(Oovpa, lower, upper);
if(pFunc != 0)
{
#ifdef _DEBUG_TRACE
DbgPrintf("EmuMain (0x%X): 0x%.08X -> %s\n", GetCurrentThreadId(), pFunc, OovpaTable[a].szFuncName);
#endif
if(OovpaTable[a].lpRedirect == 0)
{
EmuInstallWrapper(pFunc, EmuXRefFailure);
}
else
{
EmuInstallWrapper(pFunc, OovpaTable[a].lpRedirect);
}
}
}
}
// alert for the situation where an Xref function body is hit
static void EmuXRefFailure()
{
EmuSwapFS(); // Win2k/XP FS
EmuCleanup("XRef-only function body reached. Fatal Error.");
}
// exception handle for that tough final exit :)
int ExitException(LPEXCEPTION_POINTERS e)
{

View File

@ -1156,6 +1156,8 @@ XBSYSAPI EXPORTNUM(190) NTSTATUS NTAPI xboxkrnl::NtCreateFile
if(szBuffer != NULL)
{
//printf("Orig : %s\n", szBuffer);
// trim this off
if(szBuffer[0] == '\\' && szBuffer[1] == '?' && szBuffer[2] == '?' && szBuffer[3] == '\\')
{
@ -1181,7 +1183,7 @@ XBSYSAPI EXPORTNUM(190) NTSTATUS NTAPI xboxkrnl::NtCreateFile
DbgPrintf("EmuKrnl (0x%X): NtCreateFile Corrected path...\n", GetCurrentThreadId());
DbgPrintf(" Org:\"%s\"\n", ObjectAttributes->ObjectName->Buffer);
DbgPrintf(" New:\"$CxbxPath\\TDATA\\%s\"\n", szBuffer);
DbgPrintf(" New:\"$CxbxPath\\EmuDisk\\T\\%s\"\n", szBuffer);
}
else if( (szBuffer[0] == 'U' || szBuffer[0] == 'u') && szBuffer[1] == ':' && szBuffer[2] == '\\')
{
@ -1191,7 +1193,7 @@ XBSYSAPI EXPORTNUM(190) NTSTATUS NTAPI xboxkrnl::NtCreateFile
DbgPrintf("EmuKrnl (0x%X): NtCreateFile Corrected path...\n", GetCurrentThreadId());
DbgPrintf(" Org:\"%s\"\n", ObjectAttributes->ObjectName->Buffer);
DbgPrintf(" New:\"$CxbxPath\\UDATA\\%s\"\n", szBuffer);
DbgPrintf(" New:\"$CxbxPath\\EmuDisk\\U\\%s\"\n", szBuffer);
}
else if( (szBuffer[0] == 'Z' || szBuffer[0] == 'z') && szBuffer[1] == ':' && szBuffer[2] == '\\')
{
@ -1201,29 +1203,32 @@ XBSYSAPI EXPORTNUM(190) NTSTATUS NTAPI xboxkrnl::NtCreateFile
DbgPrintf("EmuKrnl (0x%X): NtCreateFile Corrected path...\n", GetCurrentThreadId());
DbgPrintf(" Org:\"%s\"\n", ObjectAttributes->ObjectName->Buffer);
DbgPrintf(" New:\"$CxbxPath\\CxbxCache\\%s\"\n", szBuffer);
DbgPrintf(" New:\"$CxbxPath\\EmuDisk\\Z\\%s\"\n", szBuffer);
}
//
// TODO: Wildcards are not allowed??
//
{
for(int v=0;szBuffer[v] != '\0';v++)
{
if(szBuffer[v] == '*')
{
if(v > 0)
ReplaceIndex = v-1;
else
ReplaceIndex = v;
if(v > 0) { ReplaceIndex = v-1; }
else { ReplaceIndex = v; }
}
}
// Note: Hack: Not thread safe (if problems occur, create a temp buffer)
if(ReplaceIndex != -1)
{
ReplaceChar = szBuffer[ReplaceIndex];
szBuffer[ReplaceIndex] = '\0';
}
}
// Note: Hack: Not thread safe (if problems occur, create a temp buffer)
if(ReplaceIndex != -1)
{
ReplaceChar = szBuffer[ReplaceIndex];
szBuffer[ReplaceIndex] = '\0';
}
//printf("Aftr : %s\n", szBuffer);
}
wchar_t wszObjectName[160];

View File

@ -37,6 +37,8 @@
#undef FIELD_OFFSET // prevent macro redefinition warnings
#include <windows.h>
extern "C" const char *szHLELastCompileTime = __TIMESTAMP__;
#include "Emu.h"
#include "EmuXTL.h"
#include "HLEDataBase.h"

View File

@ -0,0 +1,676 @@
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->Win32->CxbxKrnl->HLEIntercept.cpp
// *
// * 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>
// *
// * All rights reserved
// *
// ******************************************************************
#define _CXBXKRNL_INTERNAL
#include "Emu.h"
#include "EmuFS.h"
#include "EmuXTL.h"
#include "EmuShared.h"
#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 void EmuXRefFailure();
#include <shlobj.h>
#include <vector>
static std::vector<void *> vCacheOut;
static bool bCacheInp = false;
static std::vector<void *> vCacheInp;
static std::vector<void*>::const_iterator vCacheInpIter;
extern "C" void EmuHLEIntercept
(
Xbe::LibraryVersion *pLibraryVersion,
Xbe::Header *pXbeHeader
)
{
Xbe::Certificate *pCertificate = (Xbe::Certificate*)pXbeHeader->dwCertificateAddr;
char szCacheFileName[260];
DbgPrintf("\n");
DbgPrintf("*******************************************************************************\n");
DbgPrintf("* Cxbx High Level Emulation database last modified %s\n", szHLELastCompileTime);
DbgPrintf("*******************************************************************************\n");
DbgPrintf("\n");
//
// initialize HLE cache file
//
{
SHGetSpecialFolderPath(NULL, szCacheFileName, CSIDL_APPDATA, TRUE);
strcat(szCacheFileName, "\\Cxbx\\");
CreateDirectory(szCacheFileName, NULL);
sint32 spot = -1;
for(int v=0;v<260;v++)
{
if(szCacheFileName[v] == '\\') { spot = v; }
else if(szCacheFileName[v] == '\0') { break; }
}
if(spot != -1) { szCacheFileName[spot] = '\0'; }
//
// create HLECache directory
//
strcpy(&szCacheFileName[spot], "\\HLECache");
CreateDirectory(szCacheFileName, NULL);
//
// open title's cache file
//
sprintf(&szCacheFileName[spot+9], "\\%08x.dat", pCertificate->dwTitleId);
FILE *pCacheFile = fopen(szCacheFileName, "rb");
if(pCacheFile != NULL)
{
bool bVerified = false;
//
// verify last compiled timestamp
//
char szCacheLastCompileTime[64];
memset(szCacheLastCompileTime, 0, 64);
if(fread(szCacheLastCompileTime, 64, 1, pCacheFile) == 1)
{
if(strcmp(szCacheLastCompileTime, szHLELastCompileTime) == 0)
{
bVerified = true;
}
}
//
// load function addresses
//
if(bVerified)
{
while(true)
{
void *cur;
if(fread(&cur, 4, 1, pCacheFile) != 1)
break;
vCacheInp.push_back(cur);
}
bCacheInp = true;
vCacheInpIter = vCacheInp.begin();
DbgPrintf("HLE: Loaded HLE Cache for 0x%.08X\n", pCertificate->dwTitleId);
}
fclose(pCacheFile);
}
}
//
// initialize openxdk emulation (TODO)
//
if(pLibraryVersion == 0)
{
DbgPrintf("HLE: Detected OpenXDK application...\n");
}
//
// initialize Microsoft XDK emulation
//
if(pLibraryVersion != 0)
{
DbgPrintf("HLE: Detected Microsoft XDK application...\n");
uint32 dwLibraryVersions = pXbeHeader->dwLibraryVersions;
uint32 dwHLEEntries = HLEDataBaseSize / sizeof(HLEData);
uint32 LastUnResolvedXRefs = UnResolvedXRefs+1;
uint32 OrigUnResolvedXRefs = UnResolvedXRefs;
for(int p=0;UnResolvedXRefs < LastUnResolvedXRefs;p++)
{
DbgPrintf("HLE: Starting pass #%d...\n", p+1);
LastUnResolvedXRefs = UnResolvedXRefs;
bool bFoundD3D = false;
for(uint32 v=0;v<dwLibraryVersions;v++)
{
uint16 MajorVersion = pLibraryVersion[v].wMajorVersion;
uint16 MinorVersion = pLibraryVersion[v].wMinorVersion;
uint16 BuildVersion = pLibraryVersion[v].wBuildVersion;
uint16 OrigBuildVersion = BuildVersion;
// aliases
if(BuildVersion == 4928) { BuildVersion = 4627; }
if(BuildVersion == 5659) { BuildVersion = 5558; }
char szLibraryName[9] = {0};
for(uint32 c=0;c<8;c++)
{
szLibraryName[c] = pLibraryVersion[v].szName[c];
}
// TODO: HACK: These libraries are packed into one database
if(strcmp(szLibraryName, "D3DX8") == 0)
{
strcpy(szLibraryName, "D3D8");
}
if(strcmp(szLibraryName, "D3D8") == 0)
{
if(bFoundD3D)
{
//DbgPrintf("Redundant\n");
continue;
}
bFoundD3D = true;
}
if(bXRefFirstPass)
{
if(strcmp("XAPILIB", szLibraryName) == 0 && MajorVersion == 1 && MinorVersion == 0 &&
(BuildVersion == 3911 || BuildVersion == 4034 || BuildVersion == 4134 || BuildVersion == 4361
|| BuildVersion == 4432 || BuildVersion == 4627 || BuildVersion == 5558 || BuildVersion == 5849))
{
uint32 lower = pXbeHeader->dwBaseAddr;
uint32 upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
// locate XapiProcessHeap
{
void *pFunc = 0;
uint ProcessHeapOffs;
uint RtlCreateHeapOffs;
if(BuildVersion >= 5849)
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_5849, lower, upper);
ProcessHeapOffs = 0x51;
RtlCreateHeapOffs = 0x4A;
}
else if(BuildVersion >= 5558)
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_5558, lower, upper);
// 5659 has an updated function
if(pFunc == 0)
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_5659, lower, upper);
}
ProcessHeapOffs = 0x51;
RtlCreateHeapOffs = 0x4A;
}
else if(BuildVersion >= 4361)
{
if(OrigBuildVersion == 4928)
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_4928, lower, upper);
ProcessHeapOffs = 0x44;
RtlCreateHeapOffs = 0x3B;
}
else
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_4361, lower, upper);
ProcessHeapOffs = 0x3E;
RtlCreateHeapOffs = 0x37;
}
}
else // 3911, 4034, 4134
{
pFunc = EmuLocateFunction((OOVPA*)&XapiInitProcess_1_0_3911, lower, upper);
ProcessHeapOffs = 0x3E;
RtlCreateHeapOffs = 0x37;
}
if(pFunc != 0)
{
XTL::EmuXapiProcessHeap = *(PVOID**)((uint32)pFunc + ProcessHeapOffs);
XTL::g_pRtlCreateHeap = *(XTL::pfRtlCreateHeap*)((uint32)pFunc + RtlCreateHeapOffs);
XTL::g_pRtlCreateHeap = (XTL::pfRtlCreateHeap)((uint32)pFunc + (uint32)XTL::g_pRtlCreateHeap + RtlCreateHeapOffs + 0x04);
DbgPrintf("HLE: 0x%.08X -> EmuXapiProcessHeap\n", XTL::EmuXapiProcessHeap);
DbgPrintf("HLE: 0x%.08X -> g_pRtlCreateHeap\n", XTL::g_pRtlCreateHeap);
}
}
}
else if(strcmp("D3D8", szLibraryName) == 0 && MajorVersion == 1 && MinorVersion == 0 &&
(BuildVersion == 3925 || BuildVersion == 4134 || BuildVersion == 4361 || BuildVersion == 4432
|| BuildVersion == 4627 || BuildVersion == 5558 || BuildVersion == 5849))
{
uint32 lower = pXbeHeader->dwBaseAddr;
uint32 upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
void *pFunc = 0;
if(BuildVersion == 3925)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetRenderState_CullMode_1_0_3925, lower, upper);
else if(BuildVersion < 5558)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetRenderState_CullMode_1_0_4134, lower, upper);
else
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetRenderState_CullMode_1_0_5558, lower, upper);
// locate D3DDeferredRenderState
if(pFunc != 0)
{
// 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) - 0x19F + 72*4); // TODO: Clean up (?)
patchOffset = 142*4 - 72*4; // TODO: Verify
}
else if(BuildVersion == 4134)
{
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)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);
patchOffset = 142*4 - 82*4;
}
else if(BuildVersion == 4432)
{
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x2B) - 0x204 + 83*4);
patchOffset = 143*4 - 83*4;
}
else if(BuildVersion == 4627)
{
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x2B) - 0x24C + 92*4);
patchOffset = 162*4 - 92*4;
}
else if(BuildVersion == 5558 || BuildVersion == 5849)
{
// WARNING: Not thoroughly tested (just seemed very correct right away)
XTL::EmuD3DDeferredRenderState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x2B) - 0x24C + 92*4);
patchOffset = 162*4 - 92*4;
}
XRefDataBase[XREF_D3DDEVICE] = *(DWORD*)((DWORD)pFunc + 0x03);
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;
for(int v=0;v<44;v++)
{
XTL::EmuD3DDeferredRenderState[v] = X_D3DRS_UNK;
}
DbgPrintf("HLE: 0x%.08X -> EmuD3DDeferredRenderState\n", XTL::EmuD3DDeferredRenderState);
}
else
{
XTL::EmuD3DDeferredRenderState = 0;
EmuWarning("EmuD3DDeferredRenderState was not found!");
}
// locate D3DDeferredTextureState
{
pFunc = 0;
if(BuildVersion == 3925)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetTextureState_TexCoordIndex_1_0_3925, lower, upper);
else if(BuildVersion == 4134)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetTextureState_TexCoordIndex_1_0_4134, lower, upper);
else if(BuildVersion == 4361 || BuildVersion == 4432)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetTextureState_TexCoordIndex_1_0_4361, lower, upper);
else if(BuildVersion == 4627 || BuildVersion == 5558 || BuildVersion == 5849)
pFunc = EmuLocateFunction((OOVPA*)&IDirect3DDevice8_SetTextureState_TexCoordIndex_1_0_4627, lower, upper);
if(pFunc != 0)
{
if(BuildVersion == 3925) // 0x18F180
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x11) - 0x70); // TODO: Verify
else if(BuildVersion == 4134)
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x18) - 0x70); // TODO: Verify
else
XTL::EmuD3DDeferredTextureState = (DWORD*)(*(DWORD*)((uint32)pFunc + 0x19) - 0x70);
for(int s=0;s<4;s++)
{
for(int v=0;v<32;v++)
XTL::EmuD3DDeferredTextureState[v+s*32] = X_D3DTSS_UNK;
}
DbgPrintf("HLE: 0x%.08X -> EmuD3DDeferredTextureState\n", XTL::EmuD3DDeferredTextureState);
}
else
{
XTL::EmuD3DDeferredTextureState = 0;
EmuCleanup("EmuD3DDeferredTextureState was not found!");
}
}
}
}
DbgPrintf("HLE: * Searching HLE database for %s %d.%d.%d...", pLibraryVersion[v].szName, MajorVersion, MinorVersion, BuildVersion);
bool found=false;
for(uint32 d=0;d<dwHLEEntries;d++)
{
if(BuildVersion != HLEDataBase[d].BuildVersion || MinorVersion != HLEDataBase[d].MinorVersion || MajorVersion != HLEDataBase[d].MajorVersion || strcmp(szLibraryName, HLEDataBase[d].Library) != 0)
continue;
found = true;
DbgPrintf("Found\n");
EmuInstallWrappers(HLEDataBase[d].OovpaTable, HLEDataBase[d].OovpaTableSize, pXbeHeader);
}
if(!found) { DbgPrintf("Skipped\n"); }
}
bXRefFirstPass = false;
}
// display Xref summary
DbgPrintf("HLE: Resolved %d cross reference(s)\n", OrigUnResolvedXRefs - UnResolvedXRefs);
}
vCacheInp.empty();
//
// update cache file
//
if(vCacheOut.size() > 0)
{
FILE *pCacheFile = fopen(szCacheFileName, "wb");
if(pCacheFile != NULL)
{
DbgPrintf("HLE: Saving HLE Cache for 0x%.08X...\n", pCertificate->dwTitleId);
//
// write last compiled timestamp
//
char szCacheLastCompileTime[64];
memset(szCacheLastCompileTime, 0, 64);
strcpy(szCacheLastCompileTime, szHLELastCompileTime);
fwrite(szCacheLastCompileTime, 64, 1, pCacheFile);
//
// write function addresses
//
std::vector<void*>::const_iterator cur;
for(cur = vCacheOut.begin();cur != vCacheOut.end(); ++cur)
{
fwrite(&(*cur), 4, 1, pCacheFile);
}
}
fclose(pCacheFile);
}
vCacheOut.empty();
DbgPrintf("\n");
return;
}
// install function interception wrapper
static inline void EmuInstallWrapper(void *FunctionAddr, void *WrapperAddr)
{
uint08 *FuncBytes = (uint08*)FunctionAddr;
*(uint08*)&FuncBytes[0] = 0xE9;
*(uint32*)&FuncBytes[1] = (uint32)WrapperAddr - (uint32)FunctionAddr - 5;
}
// locate the given function, searching within lower and upper bounds
static void *EmuLocateFunction(OOVPA *Oovpa, uint32 lower, uint32 upper)
{
uint32 count = Oovpa->Count;
// Skip out if this is an unnecessary search
if(!bXRefFirstPass && Oovpa->XRefCount == 0 && Oovpa->XRefSaveIndex == (uint08)-1)
return 0;
// large
if(Oovpa->Large == 1)
{
LOOVPA<1> *Loovpa = (LOOVPA<1>*)Oovpa;
upper -= Loovpa->Lovp[count-1].Offset;
// search all of the image memory
for(uint32 cur=lower;cur<upper;cur++)
{
uint32 v;
// check all cross references
for(v=0;v<Loovpa->XRefCount;v++)
{
uint32 Offset = Loovpa->Lovp[v].Offset;
uint32 Value = Loovpa->Lovp[v].Value;
uint32 RealValue = *(uint32*)(cur + Offset);
if(XRefDataBase[Value] == -1)
goto skipout_L; // unsatisfied Xref is not acceptable
if((RealValue + cur + Offset+4 != XRefDataBase[Value]) && (RealValue != XRefDataBase[Value]))
break;
}
// check all pairs, moving on if any do not match
for(v=0;v<count;v++)
{
uint32 Offset = Loovpa->Lovp[v].Offset;
uint32 Value = Loovpa->Lovp[v].Value;
uint08 RealValue = *(uint08*)(cur + Offset);
if(RealValue != Value)
break;
}
// success if we found all pairs
if(v == count)
{
if(Loovpa->XRefSaveIndex != (uint08)-1)
{
if(XRefDataBase[Loovpa->XRefSaveIndex] == -1)
{
UnResolvedXRefs--;
XRefDataBase[Loovpa->XRefSaveIndex] = cur;
return (void*)cur;
}
else
{
return (void*)XRefDataBase[Loovpa->XRefSaveIndex]; // already Found, no bother patching again
}
}
return (void*)cur;
}
skipout_L:;
}
}
// small
else
{
SOOVPA<1> *Soovpa = (SOOVPA<1>*)Oovpa;
upper -= Soovpa->Sovp[count-1].Offset;
// search all of the image memory
for(uint32 cur=lower;cur<upper;cur++)
{
uint32 v;
// check all cross references
for(v=0;v<Soovpa->XRefCount;v++)
{
uint32 Offset = Soovpa->Sovp[v].Offset;
uint32 Value = Soovpa->Sovp[v].Value;
uint32 RealValue = *(uint32*)(cur + Offset);
if(XRefDataBase[Value] == -1)
goto skipout_S; // Unsatisfied XRef is not acceptable
if( (RealValue + cur + Offset + 4 != XRefDataBase[Value]) && (RealValue != XRefDataBase[Value]))
break;
}
// check OV pairs if all xrefs matched
if(v == Soovpa->XRefCount)
{
// check all pairs, moving on if any do not match
for(;v<count;v++)
{
uint32 Offset = Soovpa->Sovp[v].Offset;
uint32 Value = Soovpa->Sovp[v].Value;
uint08 RealValue = *(uint08*)(cur + Offset);
if(RealValue != Value)
break;
}
}
// success if we found all pairs
if(v == count)
{
if(Soovpa->XRefSaveIndex != (uint08)-1)
{
if(XRefDataBase[Soovpa->XRefSaveIndex] == -1)
{
UnResolvedXRefs--;
XRefDataBase[Soovpa->XRefSaveIndex] = cur;
return (void*)cur;
}
else
{
return (void*)XRefDataBase[Soovpa->XRefSaveIndex]; // already Found, no bother patching again
}
}
return (void*)cur;
}
skipout_S:;
}
}
return 0;
}
// install function interception wrappers
static void EmuInstallWrappers(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::Header *pXbeHeader)
{
uint32 lower = pXbeHeader->dwBaseAddr;
uint32 upper = pXbeHeader->dwBaseAddr + pXbeHeader->dwSizeofImage;
// traverse the full OOVPA table
for(uint32 a=0;a<OovpaTableSize/sizeof(OOVPATable);a++)
{
OOVPA *Oovpa = OovpaTable[a].Oovpa;
void *pFunc = NULL;
if(bCacheInp && (vCacheInpIter != vCacheInp.end()))
{
pFunc = (*vCacheInpIter);
++vCacheInpIter;
}
else
{
pFunc = EmuLocateFunction(Oovpa, lower, upper);
vCacheOut.push_back(pFunc);
}
if(pFunc != 0)
{
DbgPrintf("HLE: 0x%.08X -> %s\n", pFunc, OovpaTable[a].szFuncName);
if(OovpaTable[a].lpRedirect == 0)
{
EmuInstallWrapper(pFunc, EmuXRefFailure);
}
else
{
EmuInstallWrapper(pFunc, OovpaTable[a].lpRedirect);
}
}
}
}
// alert for the situation where an Xref function body is hit
static void EmuXRefFailure()
{
EmuSwapFS(); // Win2k/XP FS
EmuCleanup("XRef-only function body reached. Fatal Error.");
}