-
Notifications
You must be signed in to change notification settings - Fork 3
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
Showing
7 changed files
with
594 additions
and
12 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,68 @@ | ||
#pragma once | ||
#include <windows.h> | ||
#include <TlHelp32.h> | ||
|
||
#include <cstdio> | ||
#include <string> | ||
|
||
|
||
typedef unsigned char byte; | ||
typedef signed long int32; | ||
typedef unsigned long uint32; | ||
typedef signed long long int64; | ||
typedef unsigned long long uint64; | ||
typedef wchar_t wchar; | ||
|
||
|
||
namespace Common | ||
{ | ||
void OpenConsole() | ||
{ | ||
AllocConsole(); | ||
|
||
freopen_s((FILE**)stdout, "CONOUT$", "w", stdout); | ||
freopen_s((FILE**)stderr, "CONOUT$", "w", stderr); | ||
|
||
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); | ||
CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo; | ||
GetConsoleScreenBufferInfo(console, &lpConsoleScreenBufferInfo); | ||
SetConsoleScreenBufferSize(console, { lpConsoleScreenBufferInfo.dwSize.X, 30000 }); | ||
} | ||
|
||
void CloseConsole() | ||
{ | ||
FreeConsole(); | ||
} | ||
|
||
// loosely based on https://stackoverflow.com/q/26572459 | ||
byte* GetModuleBaseAddress(wchar* moduleName) | ||
{ | ||
auto pid = GetCurrentProcessId(); | ||
|
||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); | ||
byte* baseAddress = nullptr; | ||
|
||
if (INVALID_HANDLE_VALUE != snapshot) | ||
{ | ||
MODULEENTRY32 moduleEntry = { 0 }; | ||
moduleEntry.dwSize = sizeof(MODULEENTRY32); | ||
|
||
if (Module32First(snapshot, &moduleEntry)) | ||
{ | ||
do | ||
{ | ||
if (0 == wcscmp(moduleEntry.szModule, moduleName)) | ||
{ | ||
baseAddress = moduleEntry.modBaseAddr; | ||
break; | ||
} | ||
} while (Module32Next(snapshot, &moduleEntry)); | ||
} | ||
CloseHandle(snapshot); | ||
} | ||
|
||
return baseAddress; | ||
} | ||
} | ||
|
||
#define writeln(msg,...) fwprintf_s(stdout, L"LENE::" msg "\n", __VA_ARGS__) |
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,169 @@ | ||
#pragma once | ||
|
||
|
||
#pragma region Plugin-side utilities | ||
|
||
/// Game versions for SpiSupportDecl. | ||
/// Not convertible with LEGameVersion or SPIGameVersion!!! | ||
|
||
#define SPI_GAME_LEL (1 << 0) | ||
#define SPI_GAME_LE1 (1 << 1) | ||
#define SPI_GAME_LE2 (1 << 2) | ||
#define SPI_GAME_LE3 (1 << 3) | ||
|
||
|
||
/// SPI version macros. | ||
/// Duplicate the stuff in version.h!!! | ||
|
||
#define SPI_VERSION_ANY 3 | ||
#define SPI_VERSION_LATEST 3 | ||
|
||
/// Plugin-side definition which marks the dll as supporting SPI. | ||
#define SPI_PLUGINSIDE_SUPPORT(NAME,AUTHOR,VERSION,GAME_FLAGS,SPIMINVER) \ | ||
extern "C" __declspec(dllexport) void SpiSupportDecl(wchar_t** name, wchar_t** author, wchar_t** version, int* gameIndexFlags, int* spiMinVersion) \ | ||
{ *name = NAME; *author = AUTHOR; *version = VERSION; *gameIndexFlags = GAME_FLAGS; *spiMinVersion = SPIMINVER; } | ||
|
||
/// Plugin-side definition which marks the dll for being loaded | ||
/// at the earliest possible moment. | ||
#define SPI_PLUGINSIDE_PRELOAD extern "C" __declspec(dllexport) bool SpiShouldPreload(void) { return true; } | ||
/// Plugin-side definition which marks the dll for being loaded | ||
/// only after DRM has finished decrypting the game. | ||
#define SPI_PLUGINSIDE_POSTLOAD extern "C" __declspec(dllexport) bool SpiShouldPreload(void) { return false; } | ||
|
||
/// Plugin-side definition which marks the dll for running | ||
/// its attach point sequentially during game startup. | ||
#define SPI_PLUGINSIDE_SEQATTACH extern "C" __declspec(dllexport) bool SpiShouldSpawnThread(void) { return false; } | ||
/// Plugin-side definition which marks the dll for running | ||
/// its attach point asynchronously during game startup. | ||
#define SPI_PLUGINSIDE_ASYNCATTACH extern "C" __declspec(dllexport) bool SpiShouldSpawnThread(void) { return true; } | ||
|
||
/// Plugin-side boilerplate macro for defining the plugin attach point. | ||
/// This is run when the plugin is loaded by SPI (!), not when the DLL itself is loaded. | ||
#define SPI_IMPLEMENT_ATTACH extern "C" __declspec(dllexport) bool SpiOnAttach(ISharedProxyInterface* InterfacePtr) | ||
/// Plugin-side boilerplate macro for defining the plugin detach point. | ||
/// This *should* run when the plugin is unloaded by SPI (!), not when the DLL itself is unloaded. | ||
/// WARNING: DO NOT RELY ON THIS BEING RUN | ||
#define SPI_IMPLEMENT_DETACH extern "C" __declspec(dllexport) bool SpiOnDetach(ISharedProxyInterface* InterfacePtr) | ||
|
||
#pragma endregion | ||
|
||
|
||
#pragma region Error codes | ||
|
||
/// <summary> | ||
/// Return value for all public SPI functions. | ||
/// - 0 is illegal to return, | ||
/// - 1 means success, | ||
/// - [10; 100) mean failures, | ||
/// - [100; ...) mean that normal operation is no longer possible. | ||
/// </summary> | ||
enum class SPIReturn : short | ||
{ | ||
// Adding stuff here requires adding stuff to MakeReturnCodeText() !!! | ||
Undefined = 0, | ||
Success = 1, | ||
FailureGeneric = 10, | ||
FailureDuplicacy = 11, | ||
FailureHooking = 12, | ||
FailureInvalidParam = 13, | ||
FailureUnsupportedYet = 14, | ||
FailureDeprecated = 15, | ||
FailurePatternInvalid = 16, | ||
FailurePatternTooLong = 17, | ||
ErrorFatal = 100, | ||
ErrorWinApi = 115, | ||
}; | ||
|
||
/// <summary> | ||
/// Get a string describing an SPIReturn code. | ||
/// </summary> | ||
/// <returns>A const wide string</returns> | ||
const wchar_t* SPIReturnToString(SPIReturn code) | ||
{ | ||
switch (code) | ||
{ | ||
case SPIReturn::Undefined: return L"Undefined - illegal return code"; | ||
case SPIReturn::Success: return L"Success - yay!"; | ||
case SPIReturn::FailureGeneric: return L"FailureGeneric - unspecified error"; | ||
case SPIReturn::FailureDuplicacy: return L"FailureDuplicacy - something unique was not unique, or something that should have existed didn't"; | ||
case SPIReturn::FailureHooking: return L"FailureHooking - injection code returned an error"; | ||
case SPIReturn::FailureInvalidParam: return L"FailureInvalidParam - illegal parameter passed to an SPI method"; | ||
case SPIReturn::FailureUnsupportedYet: return L"FailureUnsupportedYet - feature is defined in SPI but not yet provided"; | ||
case SPIReturn::FailureDeprecated: return L"FailureDeprecated - feature is defined in SPI but must not be used"; | ||
case SPIReturn::FailurePatternInvalid: return L"FailurePatternInvalid - provided pattern was ill-formed"; | ||
case SPIReturn::FailurePatternTooLong: return L"FailurePatternTooLong - provided pattern is too long"; | ||
case SPIReturn::ErrorFatal: return L"ErrorFatal - unspecified error AFTER WHICH EXECUTION CANNOT CONTINUE"; | ||
case SPIReturn::ErrorWinApi: return L"ErrorWinApi - a call to Win API function failed, check GetLastError()"; | ||
default: return L"UNRECOGNIZED RETURN CODE - CONTACT DEVELOPERS"; | ||
} | ||
} | ||
|
||
#pragma endregion | ||
|
||
|
||
#pragma region The public-facing interface | ||
|
||
#define SPIDECL [[nodiscard]] __declspec(noinline) virtual SPIReturn | ||
#define SPIDEFN virtual SPIReturn | ||
|
||
/// Game versions for GetHostGame. | ||
/// Not interchangable with LEGameVersion!!! | ||
enum class SPIGameVersion | ||
{ | ||
Launcher = 0, | ||
LE1 = 1, | ||
LE2 = 2, | ||
LE3 = 3 | ||
}; | ||
|
||
/// <summary> | ||
/// SPI declaration for use in ASI mods. | ||
/// </summary> | ||
class ISharedProxyInterface | ||
{ | ||
public: | ||
/// <summary> | ||
/// Get version of the SPI implementation provided by the host proxy. | ||
/// </summary> | ||
/// <param name="outVersionPtr">Output value for the version.</param> | ||
/// <returns>An appropriate <see cref="SPIReturn"/> code.</returns> | ||
SPIDECL GetVersion(unsigned long* outVersionPtr) = 0; | ||
/// <summary> | ||
/// Get if the host proxy was built in debug or release mode. | ||
/// </summary> | ||
/// <param name="outIsRelease">Output value for the build mode.</param> | ||
/// <returns>An appropriate <see cref="SPIReturn"/> code.</returns> | ||
SPIDECL GetBuildMode(bool* outIsRelease) = 0; | ||
/// <summary> | ||
/// Get the game this host proxy is attached to (1 - 3 or Launcher). | ||
/// </summary> | ||
/// <param name="outGameVersion">Output value for the game.</param> | ||
/// <returns>An appropriate <see cref="SPIReturn"/> code.</returns> | ||
SPIDECL GetHostGame(SPIGameVersion* outGameVersion) = 0; | ||
|
||
/// <summary> | ||
/// Search the main game module for a PEiD-style pattern. | ||
/// </summary> | ||
/// <param name="outOffsetPtr">Output value for the offset, set to NULL if not found.</param> | ||
/// <param name="combinedPattern">PEiD-style pattern specifying 100 bytes (299 chars + \0) at most.</param> | ||
/// <returns>An appropriate <see cref="SPIReturn"/> code.</returns> | ||
SPIDECL FindPattern(void** outOffsetPtr, char* combinedPattern) = 0; | ||
|
||
/// <summary> | ||
/// Use bink proxy's built-in injection library to detour a procedure. | ||
/// </summary> | ||
/// <param name="name">Name of the hook used for logging purposes.</param> | ||
/// <param name="target">Pointer to detour.</param> | ||
/// <param name="detour">Pointer to what to detour the target with.</param> | ||
/// <param name="original">Pointer to where to write out the original procedure.</param> | ||
/// <returns>An appropriate <see cref="SPIReturn"/> code.</returns> | ||
SPIDECL InstallHook(const char* name, void* target, void* detour, void** original) = 0; | ||
/// <summary> | ||
/// Remove a hook installed by <see cref="ISharedProxyInterface::InstallHook"/>. | ||
/// </summary> | ||
/// <param name="name">Name of the hook to remove.</param> | ||
/// <returns>An appropriate <see cref="SPIReturn"/> code.</returns> | ||
SPIDECL UninstallHook(const char* name) = 0; | ||
}; | ||
|
||
#pragma endregion |
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
22 changes: 22 additions & 0 deletions
22
LE3StreamingLevelsHUD/LE1StreamingLevelsHUD.vcxproj.filters
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,22 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<ItemGroup> | ||
<Filter Include="Source Files"> | ||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> | ||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions> | ||
</Filter> | ||
<Filter Include="Header Files"> | ||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> | ||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions> | ||
</Filter> | ||
<Filter Include="Resource Files"> | ||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> | ||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> | ||
</Filter> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ClCompile Include="LE1StreamingLevelsHUD.cpp"> | ||
<Filter>Source Files</Filter> | ||
</ClCompile> | ||
</ItemGroup> | ||
</Project> |
Oops, something went wrong.