diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..b92a6e010
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "import/subhook"]
+ path = import/subhook
+ url = https://github.com/Zeex/subhook
diff --git a/appveyor.yml b/appveyor.yml
index 5b87d42dc..c7e6bc723 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -15,3 +15,6 @@ build:
artifacts:
- path: export\Release.zip
- path: export\Debug.zip
+install:
+ # Git clone happens between init and install
+ - cmd: git submodule update --init --recursive
\ No newline at end of file
diff --git a/build/win32/Cxbx.sln b/build/win32/Cxbx.sln
index d97d745e1..d18e9768d 100644
--- a/build/win32/Cxbx.sln
+++ b/build/win32/Cxbx.sln
@@ -1,20 +1,34 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25420.1
+# Visual Studio 15
+VisualStudioVersion = 15.0.26430.6
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cxbx", "Cxbx.vcxproj", "{E7A72D3D-5810-4078-A243-348B59726365}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "subhook", "subhook.vcxproj", "{CD2DDE93-B45E-4D11-876D-D0056C3DD407}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E7A72D3D-5810-4078-A243-348B59726365}.Debug|Win32.ActiveCfg = Debug|Win32
{E7A72D3D-5810-4078-A243-348B59726365}.Debug|Win32.Build.0 = Debug|Win32
+ {E7A72D3D-5810-4078-A243-348B59726365}.Debug|x64.ActiveCfg = Debug|Win32
{E7A72D3D-5810-4078-A243-348B59726365}.Release|Win32.ActiveCfg = Release|Win32
{E7A72D3D-5810-4078-A243-348B59726365}.Release|Win32.Build.0 = Release|Win32
+ {E7A72D3D-5810-4078-A243-348B59726365}.Release|x64.ActiveCfg = Release|Win32
+ {CD2DDE93-B45E-4D11-876D-D0056C3DD407}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CD2DDE93-B45E-4D11-876D-D0056C3DD407}.Debug|Win32.Build.0 = Debug|Win32
+ {CD2DDE93-B45E-4D11-876D-D0056C3DD407}.Debug|x64.ActiveCfg = Debug|x64
+ {CD2DDE93-B45E-4D11-876D-D0056C3DD407}.Debug|x64.Build.0 = Debug|x64
+ {CD2DDE93-B45E-4D11-876D-D0056C3DD407}.Release|Win32.ActiveCfg = Release|Win32
+ {CD2DDE93-B45E-4D11-876D-D0056C3DD407}.Release|Win32.Build.0 = Release|Win32
+ {CD2DDE93-B45E-4D11-876D-D0056C3DD407}.Release|x64.ActiveCfg = Release|x64
+ {CD2DDE93-B45E-4D11-876D-D0056C3DD407}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/build/win32/Cxbx.vcxproj b/build/win32/Cxbx.vcxproj
index 69558bd0c..16c0bf8c6 100644
--- a/build/win32/Cxbx.vcxproj
+++ b/build/win32/Cxbx.vcxproj
@@ -58,10 +58,12 @@
Build
+ $(Configuration)\$(ProjectName)
Build
+ $(Configuration)\$(ProjectName)
@@ -75,7 +77,7 @@
Disabled
- ..\..\src\Common;..\..\src;..\..\src\Common\Win32;..\..\import\stb;%(AdditionalIncludeDirectories);..\..\import\OpenXDK\include;..\..\import\distorm\include;..\..\import\glew-2.0.0\include;..\..\src;..\..\src\Common;..\..\src\Common\Win32
+ ..\..\src\Common;..\..\src;..\..\src\Common\Win32;..\..\import\stb;%(AdditionalIncludeDirectories);..\..\import\OpenXDK\include;..\..\import\distorm\include;..\..\import\glew-2.0.0\include;..\..\import\subhook\
_WIN32_WINNT=0x0601;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebugDLL
@@ -85,6 +87,7 @@
ProgramDatabase
true
StreamingSIMDExtensions2
+ true
_DEBUG;%(PreprocessorDefinitions)
@@ -137,7 +140,7 @@ $(SOLUTIONDIR)Export.bat
MaxSpeed
OnlyExplicitInline
- ..\..\src;..\..\src\Common;..\..\src\Common\Win32\;..\..\import\stb;%(AdditionalIncludeDirectories);..\..\import\OpenXDK\include;..\..\import\distorm\include;..\..\import\glew-2.0.0\include;..\..\src;..\..\src\Common;..\..\src\Common\Win32
+ ..\..\src;..\..\src\Common;..\..\src\Common\Win32\;..\..\import\stb;%(AdditionalIncludeDirectories);..\..\import\OpenXDK\include;..\..\import\distorm\include;..\..\import\glew-2.0.0\include;..\..\src\Common\Win32;..\..\import\subhook\
_WIN32_WINNT=0x0601;WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
true
MultiThreadedDLL
@@ -148,6 +151,7 @@ $(SOLUTIONDIR)Export.bat
ProgramDatabase
true
StreamingSIMDExtensions2
+ true
NDEBUG;%(PreprocessorDefinitions)
@@ -620,6 +624,11 @@ $(SOLUTIONDIR)Export.bat
%(PreprocessorDefinitions)
+
+
+ {cd2dde93-b45e-4d11-876d-d0056c3dd407}
+
+
diff --git a/build/win32/Export.bat b/build/win32/Export.bat
index 1e9345129..81fb17c54 100644
--- a/build/win32/Export.bat
+++ b/build/win32/Export.bat
@@ -1,5 +1,5 @@
cd Release
-..\..\..\import\7za\7za.exe a ..\..\..\export\Release.zip Cxbx.exe glew32.dll ..\..\..\COPYING ..\..\..\README.md
+..\..\..\import\7za\7za.exe a ..\..\..\export\Release.zip Cxbx.exe glew32.dll subhook.dll ..\..\..\COPYING ..\..\..\README.md
cd ..\Debug
-..\..\..\import\7za\7za.exe a ..\..\..\export\Debug.zip Cxbx.exe glew32.dll ..\..\..\COPYING ..\..\..\README.md
+..\..\..\import\7za\7za.exe a ..\..\..\export\Debug.zip Cxbx.exe glew32.dll subhook.dll ..\..\..\COPYING ..\..\..\README.md
cd ..\
\ No newline at end of file
diff --git a/build/win32/subhook.vcxproj b/build/win32/subhook.vcxproj
new file mode 100644
index 000000000..d6b4a29b8
--- /dev/null
+++ b/build/win32/subhook.vcxproj
@@ -0,0 +1,138 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 15.0
+ {CD2DDE93-B45E-4D11-876D-D0056C3DD407}
+ subhook
+ 8.1
+
+
+
+ DynamicLibrary
+ true
+ $(DefaultPlatformToolset)
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ $(DefaultPlatformToolset)
+ true
+ MultiByte
+
+
+ Application
+ true
+ v141
+ MultiByte
+
+
+ Application
+ false
+ v141
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(Configuration)\$(ProjectName)
+
+
+ $(Configuration)\$(ProjectName)
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ _WINDLL;SUBHOOK_IMPLEMENTATION;%(PreprocessorDefinitions)
+
+
+ true
+ true
+
+
+
+
+ Level3
+ Disabled
+ true
+ _WINDLL;SUBHOOK_IMPLEMENTATION;%(PreprocessorDefinitions)
+
+
+
+
+ Level3
+ Disabled
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build/win32/subhook.vcxproj.filters b/build/win32/subhook.vcxproj.filters
new file mode 100644
index 000000000..e8cddc5fd
--- /dev/null
+++ b/build/win32/subhook.vcxproj.filters
@@ -0,0 +1,36 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/import/subhook b/import/subhook
new file mode 160000
index 000000000..8046f66d0
--- /dev/null
+++ b/import/subhook
@@ -0,0 +1 @@
+Subproject commit 8046f66d0e0ca4bdfc7103c721374ad337be092a
diff --git a/src/CxbxKrnl/EmuKrnl.cpp b/src/CxbxKrnl/EmuKrnl.cpp
index 93ec2f9e9..41e9fe71b 100644
--- a/src/CxbxKrnl/EmuKrnl.cpp
+++ b/src/CxbxKrnl/EmuKrnl.cpp
@@ -320,7 +320,20 @@ XBSYSAPI EXPORTNUM(161) xboxkrnl::VOID FASTCALL xboxkrnl::KfLowerIrql
{
LOG_FUNC_ONE_ARG(NewIrql);
- LOG_UNIMPLEMENTED();
+ KPCR* Pcr = KeGetPcr();
+
+ if (NewIrql > Pcr->Irql) {
+ // TODO: Enable this after KeBugCheck is implemented
+ //KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
+ // for (;;);
+
+ CxbxKrnlCleanup("IRQL_NOT_LESS_OR_EQUAL");
+ }
+
+ Pcr->Irql = NewIrql;
+
+ // TODO: Dispatch pending interrupts
+ LOG_INCOMPLETE();
}
// ******************************************************************
diff --git a/src/CxbxKrnl/EmuNV2A.cpp b/src/CxbxKrnl/EmuNV2A.cpp
index c2a616a3a..ac9329ab2 100644
--- a/src/CxbxKrnl/EmuNV2A.cpp
+++ b/src/CxbxKrnl/EmuNV2A.cpp
@@ -32,7 +32,8 @@
// * (c) 2016 Luke Usher
// *
// * EmuNV2A.cpp is heavily based on code from XQEMU
-// * (c) XQEMU Team
+// * Copyright(c) 2012 espes
+// * Copyright(c) 2015 Jannik Vogel
// * https://github.com/espes/xqemu/blob/xbox/hw/xbox/nv2a.c
// *
// * All rights reserved
diff --git a/src/CxbxKrnl/HLEIntercept.cpp b/src/CxbxKrnl/HLEIntercept.cpp
index d43fc62af..8464785eb 100644
--- a/src/CxbxKrnl/HLEIntercept.cpp
+++ b/src/CxbxKrnl/HLEIntercept.cpp
@@ -46,16 +46,18 @@
#include "HLEIntercept.h"
#include "xxhash32.h"
#include
+#include
static xbaddr EmuLocateFunction(OOVPA *Oovpa, xbaddr lower, xbaddr upper);
static void EmuInstallPatches(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe::Header *pXbeHeader);
-static inline void EmuInstallPatch(xbaddr FunctionAddr, void *Patch);
+static inline void EmuInstallPatch(std::string FunctionName, xbaddr FunctionAddr, void *Patch);
#include
#include
#include
std::unordered_map g_SymbolAddresses;
+std::unordered_map g_FunctionHooks;
bool g_HLECacheUsed = false;
uint32 g_BuildVersion;
@@ -67,6 +69,15 @@ bool bLLE_JIT = false; // Set this to true for experimental JIT
bool bXRefFirstPass; // For search speed optimization, set in EmuHLEIntercept, read in EmuLocateFunction
uint32 UnResolvedXRefs; // Tracks XRef location, used (read/write) in EmuHLEIntercept and EmuLocateFunction
+void* GetXboxFunctionPointer(std::string functionName)
+{
+ if (g_FunctionHooks.find(functionName) != g_FunctionHooks.end()) {
+ return g_FunctionHooks[functionName].GetTrampoline();
+ }
+
+ return nullptr;
+}
+
std::string GetDetectedSymbolName(xbaddr address, int *symbolOffset)
{
std::string result = "";
@@ -183,7 +194,7 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
}
else
{
- EmuInstallPatch(location, pFunc);
+ EmuInstallPatch(functionName, location, pFunc);
output << "\t*PATCHED*";
}
}
@@ -625,12 +636,9 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
return;
}
-static inline void EmuInstallPatch(xbaddr FunctionAddr, void *Patch)
+static inline void EmuInstallPatch(std::string FunctionName, xbaddr FunctionAddr, void *Patch)
{
- uint08 *FuncBytes = (uint08*)FunctionAddr;
-
- *(uint08*)&FuncBytes[0] = OPCODE_JMP_E9; // = opcode for JMP rel32 (Jump near, relative, displacement relative to next instruction)
- *(uint32*)&FuncBytes[1] = (uint32)Patch - FunctionAddr - 5;
+ g_FunctionHooks[FunctionName].Install((void*)(FunctionAddr), Patch);
}
static inline void GetXRefEntry(OOVPA *oovpa, int index, OUT uint32 &xref, OUT uint08 &offset)
@@ -871,7 +879,7 @@ static void EmuInstallPatches(OOVPATable *OovpaTable, uint32 OovpaTableSize, Xbe
{
if (addr != nullptr)
{
- EmuInstallPatch(pFunc, addr);
+ EmuInstallPatch(OovpaTable[a].szFuncName, pFunc, addr);
output << "\t*PATCHED*";
}
else
diff --git a/src/CxbxKrnl/HLEIntercept.h b/src/CxbxKrnl/HLEIntercept.h
index d78953165..ef169019a 100644
--- a/src/CxbxKrnl/HLEIntercept.h
+++ b/src/CxbxKrnl/HLEIntercept.h
@@ -41,6 +41,7 @@ extern bool bLLE_JIT; // Set this to true for experimental JIT
void EmuHLEIntercept(Xbe::Header *XbeHeader);
std::string GetDetectedSymbolName(xbaddr address, int *symbolOffset);
+void* GetXboxFunctionPointer(std::string functionName);
#ifdef _DEBUG_TRACE
void VerifyHLEDataBase();