Skip to content

Commit

Permalink
code cleanup, extra debug info
Browse files Browse the repository at this point in the history
  • Loading branch information
SomeCrazyGuy committed Jun 22, 2024
1 parent 3196fa1 commit b72f7ba
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 58 deletions.
1 change: 1 addition & 0 deletions src/d3d11on12ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ extern void DX11_InitializeOrRender(void* dx12_swapchain, void* dx12_commandqueu

const auto index = swapchain->GetCurrentBackBufferIndex();
if (index >= g_buffercount) {
DEBUG("Releasing DX11");
DX11_ReleaseIfInitialized();
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/hook_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ typedef FUNC_PTR* IATEntry;
/// </summary>
/// <param name="dll_name">the dll name (not case sensitive) or null to search all dlls</param>
/// <param name="func_name">the name of the dll function (same as getprocaddress would use)</param>
/// <returns>iatentry* on success, null on failure</returns>
/// <returns>iatentry on success, null on failure</returns>
static IATEntry SearchIAT(const char* dll_name, const char* func_name) {
ASSERT(func_name != NULL);
ASSERT(*func_name != '\0');
Expand Down
122 changes: 68 additions & 54 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "hotkeys.h"
#include "std_api.h"
#include "about_tab.h"
#include "path_manager.h"

#include "d3d11on12ui.h"

Expand Down Expand Up @@ -53,36 +54,13 @@ static uint32_t frame_count_since_init = 0;

#define EveryNFrames(N) ((frame_count_since_init%(N))==0)

static char DLL_DIR[MAX_PATH]{};

extern char* GetPathInDllDir(char* path_max_buffer, const char* filename) {
ASSERT(DLL_DIR[0] != '\0' && "a file was opened before dll dir was setup");

char* p = path_max_buffer;

unsigned i, j;

for (i = 0; DLL_DIR[i]; ++i) {
*p++ = DLL_DIR[i];
}

for (j = 0; filename[j]; ++j) {
*p++ = filename[j];
}

*p = 0;

return path_max_buffer;
}


#ifdef MODMENU_DEBUG
struct FilenameOnly {
const char* name;
uint32_t name_len;
};
static FilenameOnly filename_only(const char* path) {
FilenameOnly ret{};
FilenameOnly ret{ path, 0 };

for (uint32_t i = 0; path[i]; ++i) {
if (path[i] == '/' || path[i] == '\\') {
Expand All @@ -98,16 +76,37 @@ static FilenameOnly filename_only(const char* path) {
return ret;
}



// this assert does not log to file or allocate memory
// its the emergency use only assert for when all else fails
[[noreturn]] static void msg_assert(const char* message) {
MessageBoxA(NULL, message, "BetterConsole SUPER_ASSERT", 0);
abort();
}
#define SUPER_ASSERT(CONDITION) do{if(!(CONDITION))msg_assert(#CONDITION);}while(0)


#include <mutex>
std::mutex logging_mutex;
static thread_local char format_buffer[4096];
static constexpr auto buffer_size = sizeof(format_buffer);
static void write_log(const char* const str) noexcept {
static HANDLE debugfile = INVALID_HANDLE_VALUE;
static thread_local bool is_locked = false;

// drop logs on recursive lock
if (is_locked) return;

logging_mutex.lock();
is_locked = true;

if (debugfile == INVALID_HANDLE_VALUE) {
char path[MAX_PATH];
debugfile = CreateFileA(GetPathInDllDir(path, "BetterConsoleLog.txt"), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
PathInDllDir(path, sizeof(path), "BetterConsoleLog.txt");
debugfile = CreateFileA(path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
SUPER_ASSERT(debugfile != INVALID_HANDLE_VALUE);
TRACE("Writing log to %s", path);
}
if (debugfile != INVALID_HANDLE_VALUE) {
WriteFile(debugfile, str, (DWORD)strnlen(str, 4096), NULL, NULL);
Expand All @@ -117,7 +116,9 @@ static void write_log(const char* const str) noexcept {
MessageBoxA(NULL, "Could not write to 'BetterConsoleLog.txt'", "ASSERTION FAILURE", 0);
abort();
}

logging_mutex.unlock();
is_locked = false;
}
extern void DebugImpl(const char* const filename, const char* const func, int line, const char* const fmt, ...) noexcept {
const auto fn = filename_only(filename);
Expand All @@ -139,7 +140,7 @@ extern void DebugImpl(const char* const filename, const char* const func, int li
write_log(format_buffer);
}

extern void AssertImpl [[noreturn]] (const char* const filename, const char* const func, int line, const char* const text) noexcept {
[[noreturn]] extern void AssertImpl(const char* const filename, const char* const func, int line, const char* const text) noexcept {
const auto fn = filename_only(filename);
snprintf(
format_buffer,
Expand Down Expand Up @@ -297,9 +298,9 @@ static HRESULT FAKE_CreateSwapChainForHwnd(

auto proc = (decltype(OLD_Wndproc))GetWindowLongPtrW(hWnd, GWLP_WNDPROC);
if ((uint64_t)FAKE_Wndproc != (uint64_t)proc) {
OLD_Wndproc = proc;
SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)FAKE_Wndproc);
DEBUG("Input Hook: OLD_Wndproc: %p, Current_Wndproc: %p, NEW_Wndproc: %p", OLD_Wndproc, proc, FAKE_Wndproc);
SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)FAKE_Wndproc);
OLD_Wndproc = proc;
}
else {
DEBUG("WndProc already hooked");
Expand Down Expand Up @@ -353,7 +354,7 @@ static HRESULT FAKE_CreateSwapChainForHwnd(
// This is the solution I came up with. Im just going to copy all
// the vtable functions from whatever IDXGISwapChain that this
// function just created, then replace the vtable pointer of
// every instance of IDXGISwapChain that comes down t he line
// every instance of IDXGISwapChain that comes down the line
// with the new vtable. Its silly but it works.

memcpy(vtable, **(void***)ppSwapChain, sizeof(vtable));
Expand Down Expand Up @@ -480,15 +481,6 @@ static BOOL FAKE_ClipCursor(const RECT* rect) {


static void SetupModMenu() {
// use the directory of the betterconsole dll as the place to put other files
// NOTE: this needs to be done before any other file (logfile/config/console history) is opened
GetModuleFileNameA(self_module_handle, DLL_DIR, MAX_PATH);
char* n = DLL_DIR;
while (*n) ++n;
while ((n != DLL_DIR) && (*n != '\\')) --n;
++n;
*n = 0;

DEBUG("Initializing BetterConsole...");
DEBUG("BetterConsole Version: " BETTERCONSOLE_VERSION);

Expand All @@ -514,8 +506,6 @@ static void SetupModMenu() {
LoadSettingsRegistry();
}

extern "C" __declspec(dllexport) void SFSEPlugin_Load(const SFSEInterface*) {}


static int OnBetterConsoleLoad(const struct better_api_t* api) {
ASSERT(api == &API && "Betterconsole already loaded?? Do you have multiple versions of BetterConsole installed?");
Expand All @@ -538,15 +528,32 @@ static int OnBetterConsoleLoad(const struct better_api_t* api) {
return 0;
}

extern "C" BOOL WINAPI DllMain(HINSTANCE self, DWORD fdwReason, LPVOID) {
if (fdwReason == DLL_PROCESS_ATTACH) {
/* lock the linker/dll loader until hooks are installed, TODO: make sure this code path is fast */
static bool RunHooksOnlyOnce = true;
ASSERT(RunHooksOnlyOnce == true); //i want to know if this assert ever gets triggered
extern "C" __declspec(dllexport) bool SFSEPlugin_Load(const SFSEInterface* sfse) {
TRACE("SFSE Loaded BetterConsole");
return true;
}


HANDLE FAKE_CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
if (dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING) {
dwFlagsAndAttributes &= ~FILE_FLAG_NO_BUFFERING;
dwFlagsAndAttributes &= ~FILE_FLAG_SEQUENTIAL_SCAN;
dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; // these large archives are randomly accessed?
}
return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}

// We are locking the loader here waiting for the dll to be loaded
// make sure this path is fast
extern "C" BOOL WINAPI DllMain(HINSTANCE self, DWORD fdwReason, LPVOID) {
static bool init = false;
if (fdwReason == DLL_PROCESS_ATTACH && (init == false)) {
TRACE("DLL_PROCESS_ATTACH");
init = true;
//while (!IsDebuggerPresent()) Sleep(100);


self_module_handle = self;
PathInitDllMain(self);

// just hook this one function the game needs to display graphics, then lazy hook the rest when it's called later
OLD_CreateDXGIFactory2 = (decltype(OLD_CreateDXGIFactory2))API.Hook->HookFunctionIAT("sl.interposer.dll", "CreateDXGIFactory2", (FUNC_PTR)FAKE_CreateDXGIFactory2);
Expand All @@ -555,14 +562,16 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE self, DWORD fdwReason, LPVOID) {
}
ASSERT(OLD_CreateDXGIFactory2 != NULL);

RunHooksOnlyOnce = false;
// replace CreateFileW with a version that does not respect the FILE_FLAG_NO_BUFFERING flag
API.Hook->HookFunctionIAT(NULL, "CreateFileW", (FUNC_PTR)FAKE_CreateFileW);
}
return TRUE;
}


static HRESULT FAKE_ResizeBuffers(IDXGISwapChain3* This, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) {
if (should_show_ui) {
DEBUG("Releasing DX11");
DX11_ReleaseIfInitialized();
}
DEBUG("ResizeBuffers: %p, BufferCount: %u, Width: %u, Height: %u, NewFormat: %u", This, BufferCount, Width, Height, NewFormat);
Expand Down Expand Up @@ -590,23 +599,22 @@ static HRESULT FAKE_Present(IDXGISwapChain3* This, UINT SyncInterval, UINT Prese

if (command_queue != best_match->Queue) {
command_queue = best_match->Queue;
DEBUG("Releasing DX11");
DX11_ReleaseIfInitialized();
}


if (last_swapchain != This) {
last_swapchain = This;
DEBUG("Releasing DX11");
DX11_ReleaseIfInitialized();
}


if (should_show_ui) {
DX11_InitializeOrRender(This, command_queue);
}
else {
DX11_ReleaseIfInitialized();
}



// keep this detection code in place to detect breaking changes to the hook causing recursive nightmare
static unsigned loop_check = 0;
Expand All @@ -615,7 +623,6 @@ static HRESULT FAKE_Present(IDXGISwapChain3* This, UINT SyncInterval, UINT Prese
auto ret = OLD_Present(This, SyncInterval, PresentFlags);
if (ret == DXGI_ERROR_DEVICE_REMOVED || ret == DXGI_ERROR_DEVICE_RESET) {
DEBUG("DXGI_ERROR_DEVICE_REMOVED || DXGI_ERROR_DEVICE_RESET");
//DX11_ReleaseIfInitialized();
} else if (ret != S_OK) {
DEBUG("Swapchain::Present returned error: %u", ret);
}
Expand Down Expand Up @@ -651,6 +658,7 @@ static LRESULT FAKE_Wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}

if (uMsg == WM_SIZE || uMsg == WM_CLOSE) {
DEBUG("Releasing DX11");
DX11_ReleaseIfInitialized();
}

Expand All @@ -664,11 +672,17 @@ static LRESULT FAKE_Wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

static void OnHotheyActivate(uintptr_t) {
should_show_ui = !should_show_ui;
DEBUG("ui toggled");


if (!should_show_ui) {
//when you close the UI, settings are saved
DEBUG("ui closed");
DX11_ReleaseIfInitialized();
DEBUG("Releasing DX11");
SaveSettingsRegistry();
DEBUG("Settings saved");
}
else {
DEBUG("ui opened");
}

if (GetSettings()->PauseGameWhenOpened) {
Expand Down
3 changes: 1 addition & 2 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#ifdef MODMENU_DEBUG
extern void DebugImpl(const char* const filename, const char* const func, int line, const char* const fmt, ...) noexcept;
extern void AssertImpl [[noreturn]] (const char* const filename, const char* const func, int line, const char* const text) noexcept;
[[noreturn]] extern void AssertImpl (const char* const filename, const char* const func, int line, const char* const text) noexcept;
extern void TraceImpl(const char* const filename, const char* const func, int line, const char* const fmt, ...) noexcept;
#define DEBUG(...) do { DebugImpl(__FILE__, __func__, __LINE__, " " __VA_ARGS__); } while(0)
#define ASSERT(CONDITION) do { if (!(CONDITION)) { AssertImpl(__FILE__, __func__, __LINE__, " " #CONDITION); } } while(0)
Expand Down Expand Up @@ -60,5 +60,4 @@ struct ModMenuSettings {

extern const ModMenuSettings* GetSettings();
extern ModMenuSettings* GetSettingsMutable();
extern char* GetPathInDllDir(char* path_max_buffer, const char* filename);
extern const BetterAPI* GetBetterAPI();
4 changes: 3 additions & 1 deletion src/minhook_unity_build.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
CEXPORT FUNC_PTR minhook_hook_function(FUNC_PTR old_func, FUNC_PTR new_func) {
static unsigned init = 0;
if (!init) {
MH_Initialize();
if (MH_Initialize() != MH_OK) {
return NULL;
}
init = 1;
}
FUNC_PTR ret = NULL;
Expand Down

0 comments on commit b72f7ba

Please sign in to comment.