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();