-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d3caf0b
commit 5f46f12
Showing
21 changed files
with
723 additions
and
539 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#include <Windows.h> | ||
#include <MinHook.h> | ||
|
||
#include "ModLoader.h" | ||
|
||
static VOID(WINAPI* s_GetStartupInfoA)(LPSTARTUPINFOA); | ||
|
||
static VOID WINAPI StartupInfoW(LPSTARTUPINFOA lpStartupInfo) | ||
{ | ||
auto& loader = ModLoader::GetInstance(); | ||
|
||
if (!loader.IsInitialized()) | ||
{ | ||
loader.Initialize(); | ||
} | ||
|
||
return s_GetStartupInfoA(lpStartupInfo); | ||
} | ||
|
||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | ||
{ | ||
if (fdwReason == DLL_PROCESS_ATTACH) | ||
{ | ||
MH_Initialize(); | ||
|
||
// Insert an early hook on GetStartupInfoA which will be called when the executable is done unpacking | ||
// Some of the executables are packed, so we can't immediately insert our hooks | ||
MH_CreateHookApi(L"kernel32", "GetStartupInfoA", StartupInfoW, (void**)&s_GetStartupInfoA); | ||
MH_EnableHook(MH_ALL_HOOKS); | ||
} | ||
|
||
return TRUE; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
#include "ModLoader.h" | ||
|
||
#include <Windows.h> | ||
#include <MinHook.h> | ||
#include <Hooking.Patterns.h> | ||
|
||
#include "cdc/FileSystem.h" | ||
#include "cdc/MultiFileSystem.h" | ||
#include "file/MultiFileSystem.h" | ||
#include "file/HookFileSystem.h" | ||
#include "util/Hooking.h" | ||
|
||
static void* s_getFS = nullptr; | ||
static void* s_target = nullptr; | ||
|
||
static cdc::FileSystem** s_diskFS = nullptr; | ||
|
||
// Gets the current file system | ||
static cdc::FileSystem* GetFS() noexcept | ||
{ | ||
return Hooking::CallReturn<cdc::FileSystem*>(s_getFS); | ||
} | ||
|
||
// Insert the hook file system and remove the current hook | ||
template<typename FileSystem> | ||
static void InsertAndUnhook() noexcept | ||
{ | ||
if (std::is_same<FileSystem, MultiFileSystem>()) | ||
{ | ||
// Create new multi file system if it doesn't exist in current game | ||
auto multiFileSystem = new MultiFileSystem(); | ||
|
||
// Override the default file system with ours | ||
*(cdc::FileSystem**)((char*)s_getFS + 1) = multiFileSystem; | ||
} | ||
|
||
// Create the hook file system | ||
auto fileSystem = new HookFileSystem(*s_diskFS); | ||
|
||
// Add it to the system | ||
auto multiFileSystem = (FileSystem*)GetFS(); | ||
multiFileSystem->Add(fileSystem, false, true); | ||
|
||
// Now GTFO so we don't trigger any DRM which might be hanging around | ||
MH_RemoveHook(s_target); | ||
} | ||
|
||
// Hooks | ||
static void(*s_InitArchive)(); | ||
static bool(*s_InitPatchArchive)(const char*); | ||
static void(__thiscall* s_InitDlcSystem)(void*); | ||
|
||
// TR7 and TRA | ||
static void InitArchive() | ||
{ | ||
s_InitArchive(); | ||
|
||
InsertAndUnhook<MultiFileSystem>(); | ||
} | ||
|
||
// TR8 | ||
static bool InitPatchArchive(const char* name) | ||
{ | ||
auto ret = s_InitPatchArchive(name); | ||
|
||
InsertAndUnhook<cdc::MultiFileSystem>(); | ||
|
||
return ret; | ||
} | ||
|
||
// LCGOL | ||
static void __fastcall InitDlcSystem(void* _this) | ||
{ | ||
s_InitDlcSystem(_this); | ||
|
||
InsertAndUnhook<cdc::MultiFileSystem>(); | ||
} | ||
|
||
ModLoader::~ModLoader() noexcept | ||
{ | ||
MH_Uninitialize(); | ||
} | ||
|
||
ModLoader& ModLoader::GetInstance() noexcept | ||
{ | ||
static ModLoader instance; | ||
return instance; | ||
} | ||
|
||
void ModLoader::Initialize() noexcept | ||
{ | ||
m_initialized = true; | ||
|
||
// Scan for all patterns | ||
auto getFS = hook::pattern("E8 ? ? ? ? 50 8D 4C 24 08 6A 00 51").count_hint(1); | ||
|
||
auto initArchive = hook::pattern("84 C0 75 0B 68 ? ? ? ? E8 ? ? ? ? 59 C3").count_hint(1); | ||
auto initPatch = hook::pattern("56 57 E8 ? ? ? ? 8B 7C 24 0C 8B").count_hint(1); | ||
auto initDlc = hook::pattern("8B 0E 6A 00 6A 00 52 E8 ? ? ? ? A1").count_hint(1); | ||
|
||
if (getFS.empty() || !(initArchive.empty() || initPatch.empty() || initDlc.empty())) | ||
{ | ||
ShowError(); | ||
|
||
return; | ||
} | ||
|
||
s_getFS = Hooking::GetAddress(getFS.get_first()); | ||
|
||
// Insert hooks | ||
if (!initArchive.empty()) | ||
{ | ||
s_target = initArchive.get_first(-68); | ||
|
||
MH_CreateHook(s_target, InitArchive, (void**)&s_InitArchive); | ||
} | ||
|
||
if (!initPatch.empty()) | ||
{ | ||
s_target = initPatch.get_first(); | ||
|
||
MH_CreateHook(s_target, InitPatchArchive, (void**)&s_InitPatchArchive); | ||
} | ||
|
||
if (!initDlc.empty()) | ||
{ | ||
s_target = initDlc.get_first(-88); | ||
|
||
MH_CreateHook(s_target, InitDlcSystem, (void**)&s_InitDlcSystem); | ||
} | ||
|
||
// Find the disk file system | ||
auto legend = hook::pattern("8B 15 ? ? ? ? 33 C9 89 4C 24 01").count_hint(1); | ||
auto underworld = hook::pattern("8B 0D ? ? ? ? 89 35 ? ? ? ? 3B CE").count_hint(1); | ||
|
||
if (legend.empty() && underworld.empty()) | ||
{ | ||
ShowError(); | ||
|
||
return; | ||
} | ||
|
||
if (!legend.empty()) | ||
{ | ||
s_diskFS = *legend.get_first<cdc::FileSystem**>(2); | ||
} | ||
|
||
if (!underworld.empty()) | ||
{ | ||
s_diskFS = *underworld.get_first<cdc::FileSystem**>(8); | ||
} | ||
|
||
MH_EnableHook(MH_ALL_HOOKS); | ||
} | ||
|
||
void ModLoader::ShowError() const noexcept | ||
{ | ||
MessageBoxA( | ||
NULL, | ||
"This version is not compatible, please open an issue on GitHub if this game is listed as supported.", | ||
"Gane not compatible", | ||
MB_OK | MB_ICONERROR); | ||
} | ||
|
||
bool ModLoader::IsInitialized() const noexcept | ||
{ | ||
return m_initialized; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#pragma once | ||
|
||
class ModLoader | ||
{ | ||
private: | ||
|
||
bool m_initialized = false; | ||
|
||
~ModLoader() noexcept; | ||
|
||
void ShowError() const noexcept; | ||
|
||
public: | ||
static ModLoader& GetInstance() noexcept; | ||
|
||
void Initialize() noexcept; | ||
bool IsInitialized() const noexcept; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#pragma once | ||
|
||
namespace cdc | ||
{ | ||
class FileRequest | ||
{ | ||
public: | ||
enum Status | ||
{ | ||
SETUP, | ||
QUEUED, | ||
PROCESSING, | ||
DONE, | ||
CANCELLED | ||
}; | ||
|
||
enum Priority | ||
{ | ||
HIGH, | ||
NORMAL, | ||
LOW | ||
}; | ||
|
||
virtual void AddRef() = 0; | ||
virtual void Release() = 0; | ||
virtual void SetCompressedSize(unsigned int size) = 0; | ||
virtual void SetUncompressed() = 0; | ||
virtual void SetSize(unsigned int size) = 0; | ||
virtual Status GetStatus() = 0; | ||
virtual void Submit(Priority priority) = 0; | ||
virtual void Cancel() = 0; | ||
virtual float Completed() = 0; | ||
}; | ||
|
||
class FileReceiver | ||
{ | ||
public: | ||
virtual int ReceiveData(const char* data, unsigned int dataSize, unsigned int requestOffset) = 0; | ||
virtual void ReceiveStarted(FileRequest* request, unsigned int requestSize) = 0; | ||
virtual void ReceiveCancelled(FileRequest* request) = 0; | ||
virtual void ReceiveDone(FileRequest* request) = 0; | ||
}; | ||
|
||
class File | ||
{ | ||
public: | ||
virtual FileRequest* RequestRead(FileReceiver* receiver, const char* fileName, unsigned int startOffset) = 0; | ||
virtual unsigned int GetSize() = 0; | ||
}; | ||
|
||
class FileSystem | ||
{ | ||
public: | ||
enum Status | ||
{ | ||
IDLE, | ||
BUSY | ||
}; | ||
|
||
virtual FileRequest* RequestRead(FileReceiver* receiver, const char* fileName, unsigned int startOffset) = 0; | ||
virtual File* OpenFile(const char* fileName) = 0; | ||
virtual bool FileExists(const char* fileName) = 0; | ||
virtual unsigned int GetFileSize(const char* fileName) = 0; | ||
virtual void SetSpecialisationMask(unsigned int specMask) = 0; | ||
virtual unsigned int GetSpecialisationMask() = 0; | ||
virtual Status GetStatus() = 0; | ||
virtual void Update() = 0; | ||
virtual void Synchronize() = 0; | ||
|
||
virtual void Suspend() = 0; | ||
virtual bool Resume() = 0; | ||
virtual bool IsSuspended() = 0; | ||
virtual char* GetBufferPointer(FileRequest* request, unsigned int* bytesLocked) = 0; | ||
virtual void ResetBufferPointer(cdc::FileRequest* request) = 0; | ||
|
||
virtual ~FileSystem() { }; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#include "MultiFileSystem.h" | ||
|
||
#include "util/Hooking.h" | ||
|
||
#include <Hooking.Patterns.h> | ||
|
||
void cdc::MultiFileSystem::Add(FileSystem* fileSystem, bool bReprioritize, bool bAddToFront) | ||
{ | ||
auto func = hook::get_pattern<void>("80 7C 24 0C 00 8B C1 74 5A 53"); | ||
|
||
Hooking::ThisCall(func, this, fileSystem, bReprioritize, bAddToFront); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#pragma once | ||
|
||
#include "FileSystem.h" | ||
|
||
namespace cdc | ||
{ | ||
class MultiFileSystem | ||
{ | ||
public: | ||
void Add(FileSystem* fileSystem, bool bReprioritize, bool bAddToFront); | ||
}; | ||
} |
Oops, something went wrong.