From f794174b9dc8157c838845a744f07883b6253bdd Mon Sep 17 00:00:00 2001 From: muhopensores <58393267+muhopensores@users.noreply.github.com> Date: Tue, 20 Aug 2024 00:00:44 +0300 Subject: [PATCH] emergency backup commit cause everything breaks if you breathe on it now --- .clang-format | 3 + .gitignore | 1 + CMakeLists.txt | 22 +- README.md | 4 +- dependencies/CMakeLists.txt | 3 +- src/CMakeLists.txt | 10 +- src/Main.cpp | 207 ++++- src/Mod.hpp | 285 +++--- src/ModFramework.cpp | 245 +++-- src/ModFramework.hpp | 8 + src/Mods.cpp | 10 +- src/Sfx.cpp | Bin 694084 -> 694110 bytes src/mods/AreaJump.cpp | 242 +++++ src/mods/AreaJump.hpp | 21 + src/mods/CustomAlolcator.cpp | 1484 ++++++++++++++++++++---------- src/mods/CustomAlolcator.hpp | 132 +-- src/mods/DebugDraw.cpp | 25 +- src/mods/DebugDraw.hpp | 4 +- src/mods/EnemySpawnRate.cpp | 178 +++- src/mods/EnemySpawnRate.hpp | 3 +- src/mods/EnemyStates.cpp | 2 +- src/mods/InertiaThings.cpp | 24 +- src/mods/InputLog.cpp | 2 +- src/mods/PracticeMode.cpp | 6 +- src/mods/PrintfDebugging.cpp | 2 +- src/mods/RgTimer.cpp | 8 +- src/mods/SimpleMod.cpp | 2 +- src/mods/StyleSwitchFX.cpp | 398 ++++++-- src/mods/StyleSwitchFX.hpp | 7 +- src/sdk/Devil3.cpp | 218 ++++- src/sdk/Devil3.hpp | 37 +- src/sdk/ReClass.hpp | 8 +- src/sdk/ReClass_Internal.hpp | 354 ++++--- src/utility/ExceptionHandler.cpp | 17 +- 34 files changed, 2712 insertions(+), 1260 deletions(-) create mode 100644 src/mods/AreaJump.cpp create mode 100644 src/mods/AreaJump.hpp diff --git a/.clang-format b/.clang-format index 9c685a0..ed8c88c 100644 --- a/.clang-format +++ b/.clang-format @@ -3,4 +3,7 @@ AlignConsecutiveAssignments: 'true' AlignOperands: 'true' BreakBeforeBraces: Attach PointerAlignment: Left +IndentWidth: 4 +AccessModifierOffset: -4 +ColumnLimit: 0 ... diff --git a/.gitignore b/.gitignore index 1134797..aa287b7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ build86/ lsp/ compile_commands.json .clangd/ +.cache/ src/Config.hpp \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b1ceef0..16b0dc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,9 @@ include_directories(${CMAKE_SOURCE_DIR}/dependencies/glm) include_directories(${CMAKE_SOURCE_DIR}/dependencies/rpclib/include) include_directories(${CMAKE_SOURCE_DIR}/dependencies/SDL2/include) include_directories(${CMAKE_SOURCE_DIR}/dependencies/DebugDraw) +include_directories(${CMAKE_SOURCE_DIR}/dependencies/meshoptimizer/src) +#temp +include_directories(${CMAKE_SOURCE_DIR}/dependencies/WickedEngine) include_directories($ENV{DXSDK_DIR}/Include) link_directories("$ENV{DXSDK_DIR}/Lib/x86") @@ -33,25 +36,6 @@ endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES) # Disable exceptions # string(REGEX REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") -find_package(Git) -if (Git_FOUND) - execute_process(COMMAND - "${GIT_EXECUTABLE}" log -1 --pretty=\"%h\" - WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" - OUTPUT_VARIABLE GIT_COMMIT_HASH - ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) - - execute_process(COMMAND - "${GIT_EXECUTABLE}" log -1 --date short --pretty=\"%ad\" - WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" - OUTPUT_VARIABLE GIT_COMMITTER_DATE - ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) - set(GIT_HASH ${GIT_COMMIT_HASH}) - set(GIT_DATE ${GIT_COMMITTER_DATE}) -else() - set(GIT_HASH "install_git_exe_bro") - set(GIT_DATE "really") -endif() set(LOG_FILENAME "${CMAKE_PROJECT_NAME}_framework_log.txt") set(LOG_ENTRY "${CMAKE_PROJECT_NAME} ModFramework entry") diff --git a/README.md b/README.md index 62b7e0a..e3b327b 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -wip \ No newline at end of file +**Building +to build this you need to install legacy DirectX SDK headers from https://www.microsoft.com/en-US/download/details.aspx?id=6812 +otherwise just run a coresponding batch file to generate solution and build it using cmake. diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt index 598dbb4..9f574f7 100644 --- a/dependencies/CMakeLists.txt +++ b/dependencies/CMakeLists.txt @@ -39,4 +39,5 @@ add_library(imgui STATIC target_compile_definitions(imgui PUBLIC IMGUI_USER_CONFIG="../src/fw-imgui/imgui_imconfig.hpp") -add_subdirectory(DebugDraw) \ No newline at end of file +add_subdirectory(DebugDraw) +add_subdirectory(meshoptimizer) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dbf1a39..c2cffcb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,7 @@ set(MODS_SRC mods/SimpleMod.hpp + mods/RendererReplace.hpp + mods/RendererReplace.cpp mods/CustomAlolcator.hpp mods/CustomAlolcator.cpp mods/EnemySpawnRate.hpp @@ -43,7 +45,8 @@ set(MODS_SRC mods/EnemyStepCooldown.cpp mods/EnemyStates.hpp mods/EnemyStates.cpp - + mods/AreaJump.hpp + mods/AreaJump.cpp ) set(HOOKS_SRC @@ -102,6 +105,8 @@ set(UTILITY_SRC utility/Thread.hpp utility/Thread.cpp utility/SDLGamepad.hpp + #utility/tgc.h + #utility/tgc.c ) set(FRAMEWORK_SRC @@ -137,7 +142,8 @@ add_library(${CMAKE_PROJECT_NAME} SHARED ) #target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC imgui minhook glm_static shlwapi D3dx9 d3d9 SDL2main SDL2 rpc) -target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC imgui minhook glm_static shlwapi D3dx9 d3d9 SDL2main SDL2) +#target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC imgui minhook glm_static shlwapi D3dx9 d3d9 SDL2main SDL2 WickedEngine_Windows d3d12 dxgi) +target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC imgui minhook glm_static shlwapi D3dx9 d3d9 SDL2main SDL2 meshoptimizer) target_compile_features(${CMAKE_PROJECT_NAME} PUBLIC cxx_std_17) include_directories(${CMAKE_PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/Main.cpp b/src/Main.cpp index 57d5146..6c1cb28 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -1,73 +1,184 @@ -#include #include -#include +#include +#include #include "ModFramework.hpp" +#include "mods/CustomAlolcator.hpp" #include "utility/ExceptionHandler.hpp" +#include "mods/RendererReplace.hpp" static HMODULE g_dinput; static HMODULE g_styleswitcher; - +//static Mod* g_renderer_replace{ nullptr }; +#pragma comment(lib, "mincore") #if 1 extern "C" { - // DirectInput8Create wrapper for dinput8.dll - __declspec(dllexport) HRESULT WINAPI direct_input8_create(HINSTANCE hinst, DWORD dw_version, const IID& riidltf, LPVOID* ppv_out, LPUNKNOWN punk_outer) { - // This needs to be done because when we include dinput.h in DInputHook, - // It is a redefinition, so we assign an export by not using the original name - #pragma comment(linker, "/EXPORT:DirectInput8Create=_direct_input8_create@20") - return ((decltype(direct_input8_create)*)GetProcAddress(g_dinput, "DirectInput8Create"))(hinst, dw_version, riidltf, ppv_out, punk_outer); - } +// DirectInput8Create wrapper for dinput8.dll +__declspec(dllexport) HRESULT WINAPI direct_input8_create(HINSTANCE hinst, DWORD dw_version, const IID& riidltf, LPVOID* ppv_out, LPUNKNOWN punk_outer) { +// This needs to be done because when we include dinput.h in DInputHook, +// It is a redefinition, so we assign an export by not using the original name +#pragma comment(linker, "/EXPORT:DirectInput8Create=_direct_input8_create@20") + return ((decltype(direct_input8_create)*)GetProcAddress(g_dinput, "DirectInput8Create"))(hinst, dw_version, riidltf, ppv_out, punk_outer); +} } #endif -void failed() { - MessageBox(0, "DMC3 ModFramework: Unable to load the original version.dll. Please report this to the developer.", "ModFramework", 0); - ExitProcess(0); +static constexpr uint64_t round_to_pow2_size(uint32_t minimum_size, uint32_t pow2_size) { + uint64_t result = (minimum_size + pow2_size - 1) & ~(pow2_size - 1); + return result; } -void startup_thread() { +void failed() { + MessageBox(0, "DMC3 ModFramework: Unable to load the original version.dll. Please report this to the developer.", "ModFramework", 0); + ExitProcess(0); +} - reframework::setup_exception_handler(); +void WINAPI startup_thread() { #ifndef NDEBUG - AllocConsole(); - HANDLE handleOut = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD consoleMode; - GetConsoleMode( handleOut , &consoleMode); - consoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - consoleMode |= DISABLE_NEWLINE_AUTO_RETURN; - SetConsoleMode( handleOut , consoleMode ); - - freopen("CONIN$", "r", stdin); - freopen("CONOUT$", "w", stdout); - freopen("CONOUT$", "w", stderr); + AllocConsole(); + HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD console_mode; + GetConsoleMode(handle_out, &console_mode); + console_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + console_mode |= DISABLE_NEWLINE_AUTO_RETURN; + SetConsoleMode(handle_out, console_mode); + + FILE* f_inp; + FILE* f_out; + + freopen_s(&f_inp, "CONIN$", "r", stdin); + freopen_s(&f_out, "CONOUT$", "w", stdout); + freopen_s(&f_out, "CONOUT$", "w", stderr); + #endif + #if 1 - wchar_t buffer[MAX_PATH]{ 0 }; - if (GetSystemDirectoryW(buffer, MAX_PATH) != 0) { - // Load the original dinput8.dll - if ((g_dinput = LoadLibraryW((std::wstring{ buffer } + L"\\dinput8.dll").c_str())) == NULL) { - failed(); - } - g_framework = std::make_unique(); - } - else { - failed(); - } + wchar_t buffer[MAX_PATH]{0}; + if (GetSystemDirectoryW(buffer, MAX_PATH) != 0) { + // Load the original dinput8.dll + if ((g_dinput = LoadLibraryW((std::wstring{buffer} + L"\\dinput8.dll").c_str())) == NULL) { + failed(); + } + //g_framework = std::make_unique(); +#ifdef NDEBUG + reframework::setup_exception_handler(); +#endif + } else { + failed(); + } + g_framework = std::make_unique(); #else - g_framework = std::make_unique(); #endif } +HANDLE filemapping {}; +PULONG_PTR page_array = NULL; +ULONG_PTR number_of_pages = NULL; + +static BOOL EnableAWE() { + HANDLE hToken; + TOKEN_PRIVILEGES tp; + + // Open the process token with TOKEN_ADJUST_PRIVILEGES and TOKEN_QUERY + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { + return FALSE; + } + + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + // Lookup the LUID for SeLockMemoryPrivilege + if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) { + CloseHandle(hToken); + return FALSE; + } + + // Adjust the token privileges + if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { + CloseHandle(hToken); + return FALSE; + } + + CloseHandle(hToken); + return TRUE; +} + BOOL APIENTRY DllMain(HMODULE handle, DWORD reason, LPVOID reserved) { - if (reason == DLL_PROCESS_ATTACH) { - g_styleswitcher = LoadLibrary("StyleSwitcher.dll"); + if (reason == DLL_PROCESS_ATTACH) { #ifndef NDEBUG - MessageBox(NULL, "Debug attach opportunity", "DMC3", MB_ICONINFORMATION); + MessageBox(NULL, "Debug attach opportunity", "DMC3", MB_ICONINFORMATION); #endif - CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)startup_thread, nullptr, 0, nullptr); - } - if (reason == DLL_PROCESS_DETACH) { - FreeLibrary(g_styleswitcher); - } - return TRUE; -} \ No newline at end of file + + SYSTEM_INFO info; + MEMORY_BASIC_INFORMATION mbi{}; + VirtualQuery((LPCVOID)0x00C36980, &mbi, sizeof(mbi)); + GetSystemInfo(&info); + DWORD memory_size = 0x8200000; +#if 0 + number_of_pages = memory_size / info.dwPageSize; + page_array = new ULONG_PTR[number_of_pages]; + if(!EnableAWE()) { + fprintf(stderr, "Failed to EnableSEPrivelege\n"); + DWORD err = GetLastError(); + } + if (!AllocateUserPhysicalPages(GetCurrentProcess(), &number_of_pages, page_array)) { + fprintf(stderr, "Failed to AllocateUserPhysicalPage\n"); + DWORD err = GetLastError(); + } + auto lpMemReserved = VirtualAlloc((void*) 0x00c36980, + memory_size, + MEM_RESERVE | MEM_PHYSICAL, + PAGE_READWRITE ); + if (!lpMemReserved) { + return TRUE; + } + PVOID virtual_address = (PVOID)0x00C36980; + if (!MapUserPhysicalPages(lpMemReserved, number_of_pages, page_array)) { + fprintf(stderr, "Failed to MapUserPhysicalPages(0x%X)\n", (DWORD)virtual_address); + DWORD err = GetLastError(); + } + + virtual_address = (PVOID)0x2537000; + if (!MapUserPhysicalPages(virtual_address, number_of_pages, page_array)) { + fprintf(stderr, "Failed to MapUserPhysicalPages(0x%X)\n", (DWORD)virtual_address); + DWORD err = GetLastError(); + } +#endif + + +#if 0 + uint64_t data_size = round_to_pow2_size(0x8200000, info.dwAllocationGranularity); + filemapping = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, + (DWORD)(data_size >> 32), (DWORD)(data_size & 0xffffffff), 0); + + if (filemapping != INVALID_HANDLE_VALUE) { + if(filemapping == nullptr) { goto continuers; } + uint64_t dmc3_offset_p2 = round_to_pow2_size(0x00C36980, info.dwAllocationGranularity); + uint32_t dmc3offset = (dmc3_offset_p2 & 0xffffffff); + if (!MapViewOfFile3(filemapping, 0, (void*)(dmc3offset), + 0, round_to_pow2_size(0x1432AC0, info.dwAllocationGranularity), MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, 0, 0)) { + DWORD er = GetLastError(); + printf("eror with MapViewOfFile3(filemapping, 0, (void*)0x00C36980, 0, 0x1432AC0, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, 0, 0)\n"); + } +#if 0 + if (!MapViewOfFile3(filemapping, 0, (void*)0x2537000, + 0, data_size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, 0, 0)) { + DWORD er = GetLastError(); + printf("eror with MapViewOfFile3(filemapping, 0, (void*)0x2537000, 0, data_size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, 0, 0)\n"); + } +#endif + } +#endif + g_styleswitcher = LoadLibraryA("StyleSwitcher.dll"); + + //g_renderer_replace = new RendererReplace(); + //g_renderer_replace->on_initialize(); + CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)startup_thread, nullptr, 0, nullptr); + } + if (reason == DLL_PROCESS_DETACH) { + + FreeLibrary(g_styleswitcher); + FreeLibrary(g_dinput); + } + return TRUE; +} diff --git a/src/Mod.hpp b/src/Mod.hpp index b3d048d..050117d 100644 --- a/src/Mod.hpp +++ b/src/Mod.hpp @@ -4,14 +4,14 @@ #define DIRECTINPUT_VERSION 0x0800 #include -#include -#include #include +#include +#include #include -#include "sdk/ReClass.hpp" -#include "sdk/Devil3.hpp" +#include "sdk/Devil3.hpp" // NOLINT +#include "sdk/ReClass.hpp" // NOLINT #include "utility/Config.hpp" #include "utility/Patch.hpp" @@ -22,16 +22,15 @@ class IModValue { public: using Ptr = std::unique_ptr; - virtual ~IModValue() {}; - virtual bool draw(std::string_view name) = 0; - virtual void draw_value(std::string_view name) = 0; + virtual ~IModValue(){}; + virtual bool draw(std::string_view name) = 0; + virtual void draw_value(std::string_view name) = 0; virtual void config_load(const utility::Config& cfg) = 0; - virtual void config_save(utility::Config& cfg) = 0; + virtual void config_save(utility::Config& cfg) = 0; }; // Convenience classes for imgui -template -class ModValue : public IModValue { +template class ModValue : public IModValue { public: using Ptr = std::unique_ptr>; @@ -39,13 +38,10 @@ class ModValue : public IModValue { return std::make_unique>(config_name, default_value); } - ModValue(std::string_view config_name, T default_value) - : m_config_name{ config_name }, - m_value{ default_value } - { - } + ModValue(std::string_view config_name, T default_value) + : m_config_name{config_name}, m_value{default_value} {} - virtual ~ModValue() = default;//override {}; + virtual ~ModValue() = default; // override {}; virtual void config_load(const utility::Config& cfg) override { auto v = cfg.get(m_config_name); @@ -59,33 +55,26 @@ class ModValue : public IModValue { cfg.set(m_config_name, m_value); }; - operator T&() { - return m_value; - } + operator T&() { return m_value; } - T& value() { - return m_value; - } + T& value() { return m_value; } - const auto& get_config_name() const { - return m_config_name; - } + const auto& get_config_name() const { return m_config_name; } protected: T m_value{}; - std::string m_config_name{ "Default_ModValue" }; + std::string m_config_name{"Default_ModValue"}; }; class ModToggle : public ModValue { public: using Ptr = std::unique_ptr; - ModToggle(std::string_view config_name, bool default_value) - : ModValue{ config_name, default_value } - { - } + ModToggle(std::string_view config_name, bool default_value) + : ModValue{config_name, default_value} {} - static auto create(std::string_view config_name, bool default_value = false) { + static auto create(std::string_view config_name, + bool default_value = false) { return std::make_unique(config_name, default_value); } @@ -101,19 +90,18 @@ class ModToggle : public ModValue { ImGui::Text("%s: %i", name.data(), m_value); } - bool toggle() { - return m_value = !m_value; - } + bool toggle() { return m_value = !m_value; } }; class ModFloat : public ModValue { public: using Ptr = std::unique_ptr; - ModFloat(std::string_view config_name, float default_value) - : ModValue{ config_name, default_value } { } + ModFloat(std::string_view config_name, float default_value) + : ModValue{config_name, default_value} {} - static auto create(std::string_view config_name, float default_value = 0.0f) { + static auto create(std::string_view config_name, + float default_value = 0.0f) { return std::make_unique(config_name, default_value); } @@ -134,48 +122,46 @@ class ModSlider : public ModFloat { public: using Ptr = std::unique_ptr; - static auto create(std::string_view config_name, float mn = 0.0f, float mx = 1.0f, float default_value = 0.0f) { + static auto create(std::string_view config_name, float mn = 0.0f, + float mx = 1.0f, float default_value = 0.0f) { return std::make_unique(config_name, mn, mx, default_value); } - ModSlider(std::string_view config_name, float mn = 0.0f, float mx = 1.0f, float default_value = 0.0f) - : ModFloat{ config_name, default_value }, - m_range{ mn, mx } - { - } + ModSlider(std::string_view config_name, float mn = 0.0f, float mx = 1.0f, + float default_value = 0.0f) + : ModFloat{config_name, default_value}, m_range{mn, mx} {} bool draw(std::string_view name) override { ImGui::PushID(this); - auto ret = ImGui::SliderFloat(name.data(), &m_value, m_range.x, m_range.y); + auto ret = + ImGui::SliderFloat(name.data(), &m_value, m_range.x, m_range.y); ImGui::PopID(); return ret; } void draw_value(std::string_view name) override { - ImGui::Text("%s: %f [%f, %f]", name.data(), m_value, m_range.x, m_range.y); + ImGui::Text("%s: %f [%f, %f]", name.data(), m_value, m_range.x, + m_range.y); } - auto& range() { - return m_range; - } + auto& range() { return m_range; } protected: - Vector2f m_range{ 0.0f, 1.0f }; + Vector2f m_range{0.0f, 1.0f}; }; class ModInt32 : public ModValue { public: using Ptr = std::unique_ptr; - static auto create(std::string_view config_name, uint32_t default_value = 0) { + static auto create(std::string_view config_name, + uint32_t default_value = 0) { return std::make_unique(config_name, default_value); } ModInt32(std::string_view config_name, uint32_t default_value = 0) - : ModValue{ config_name, static_cast(default_value) } - { - } + : ModValue{config_name, static_cast(default_value)} {} bool draw(std::string_view name) override { ImGui::PushID(this); @@ -190,18 +176,17 @@ class ModInt32 : public ModValue { } }; -class ModKey: public ModInt32 { +class ModKey : public ModInt32 { public: using Ptr = std::unique_ptr; - static auto create(std::string_view config_name, int32_t default_value = UNBOUND_KEY) { + static auto create(std::string_view config_name, + int32_t default_value = UNBOUND_KEY) { return std::make_unique(config_name, default_value); } ModKey(std::string_view config_name, int32_t default_value = UNBOUND_KEY) - : ModInt32{ config_name, static_cast(default_value) } - { - } + : ModInt32{config_name, static_cast(default_value)} {} bool draw(std::string_view name) override { if (name.empty()) { @@ -213,18 +198,16 @@ class ModKey: public ModInt32 { if (ImGui::IsItemHovered()) { WPARAM k = g_framework->get_keyboard_state(); - m_value = is_erase_key(k) ? UNBOUND_KEY : k; + m_value = is_erase_key(k) ? UNBOUND_KEY : k; ImGui::SameLine(); ImGui::Text("Press any key"); - } - else { + } else { ImGui::SameLine(); if (m_value >= 0) { ImGui::Text("%i", m_value); - } - else { + } else { ImGui::Text("Not bound"); } } @@ -271,7 +254,7 @@ class ModKey: public ModInt32 { static constexpr WPARAM UNBOUND_KEY = 0; protected: - bool m_was_key_down{ false }; + bool m_was_key_down{false}; }; class Mod { @@ -279,24 +262,26 @@ class Mod { using ValueList = std::vector>; public: - virtual ~Mod() {}; + virtual ~Mod(){}; virtual std::string_view get_name() const { return "UnknownMod"; }; // can be used for ModValues, like Mod_ValueName - virtual std::string generate_name(std::string_view name) { return std::string{ get_name() } + "_" + name.data(); } - - static void ShowHelpMarker(const char* desc) - { - ImGui::TextDisabled("(?)"); - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextUnformatted(desc); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - } - } - void install_patch_absolute(uintptr_t location, std::unique_ptr& patch, const char* patch_bytes, uint8_t length) { + virtual std::string generate_name(std::string_view name) { + return std::string{get_name()} + "_" + name.data(); + } + + static void show_help_marker(const char* desc) { + ImGui::TextDisabled("(?)"); + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted(desc); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + } + void install_patch_absolute(uintptr_t location, + std::unique_ptr& patch, + const char* patch_bytes, uint8_t length) { spdlog::info("{}: Installing patch at {:x}.\n", get_name(), location); patch.reset(nullptr); std::vector bytes; @@ -306,11 +291,12 @@ class Mod { length--; } patch = Patch::create(location, bytes, true); - //patch.reset(Patch::create_raw(location, bytes, true)); + // patch.reset(Patch::create_raw(location, bytes, true)); } - void install_patch_offset(ptrdiff_t offset, std::unique_ptr& patch, const char* patch_bytes, uint8_t length) { - uintptr_t base = g_framework->get_module().as(); + void install_patch_offset(ptrdiff_t offset, std::unique_ptr& patch, + const char* patch_bytes, uint8_t length) { + uintptr_t base = g_framework->get_module().as(); uintptr_t location = base + offset; spdlog::info("{}: Installing patch at {:x}.\n", get_name(), location); patch.reset(nullptr); @@ -321,82 +307,93 @@ class Mod { length--; } patch = Patch::create(location, bytes, true); - //patch.reset(Patch::create_raw(location, bytes, true)); + // patch.reset(Patch::create_raw(location, bytes, true)); } - // Wrapper for easy install of hooks. - // \param offset : offset from game exe base where hook will be installed - // \param hook : FunctionHook object instance - // \param detour : Function pointer to your naked detour function. - // if your detour function is called my_detour then just pass &my_detour - // \param ret : Pointer to a variable that will get return address - // \param next_instruction_offset : Optional offset to the next instruction to calculate return address automatically - // leave this blank to get return address from minhook, note that minhook copies overwritten bytes automatically. - inline bool install_hook_offset(ptrdiff_t offset, std::unique_ptr& hook, void* detour, uintptr_t* ret, ptrdiff_t next_instruction_offset = 0) { - uintptr_t base = g_framework->get_module().as(); - uintptr_t location = base + offset; + // Wrapper for easy install of hooks. + // \param offset : offset from game exe base where hook will be installed + // \param hook : FunctionHook object instance + // \param detour : Function pointer to your naked detour function. + // if your detour function is called my_detour then just pass &my_detour + // \param ret : Pointer to a variable that will get return address + // \param next_instruction_offset : Optional offset to the next instruction + // to calculate return address automatically leave this blank to get return + // address from minhook, note that minhook copies overwritten bytes + // automatically. + inline bool install_hook_offset(ptrdiff_t offset, + std::unique_ptr& hook, + void* detour, uintptr_t* ret, + ptrdiff_t next_instruction_offset = 0) { + uintptr_t base = g_framework->get_module().as(); + uintptr_t location = base + offset; #ifdef _DEBUG - if (hook) { - throw std::runtime_error("Install hook called multiple times with same instance\n"); - } - printf("Installing offset hook at location: %p\n", location); + if (hook) { + throw std::runtime_error( + "Install hook called multiple times with same instance\n"); + } + printf("Installing offset hook at location: %u\n", location); #endif - hook = std::make_unique(location, detour); - if (!hook->create()) { - spdlog::error("Failed to create hook!"); - return false; - } - - if (next_instruction_offset) { - *ret = location + next_instruction_offset; - } - else { - *ret = hook->get_original(); - } - return true; - } - - // same deal but using absolute address - inline bool install_hook_absolute(uintptr_t location, std::unique_ptr& hook, void* detour, uintptr_t* ret, ptrdiff_t next_instruction_offset = 0) { + hook = std::make_unique(location, detour); + if (!hook->create()) { + spdlog::error("Failed to create hook!"); + return false; + } + + if (next_instruction_offset) { + *ret = location + next_instruction_offset; + } else { + *ret = hook->get_original(); + } + return true; + } + + // same deal but using absolute address + inline bool install_hook_absolute(uintptr_t location, + std::unique_ptr& hook, + void* detour, uintptr_t* ret, + ptrdiff_t next_instruction_offset = 0) { #ifdef _DEBUG - if (hook) { - throw std::runtime_error("Install hook called multiple times with same instance\n"); - } - printf("Installing absolute hook at location: %p\n", location); + if (hook) { + throw std::runtime_error( + "Install hook called multiple times with same instance\n"); + } + printf("Installing absolute hook at location: %u\n", location); #endif - hook = std::make_unique(location, detour); - if (!hook->create()) { - spdlog::error("Failed to create hook!"); - return false; - } - - if (next_instruction_offset) { - *ret = location + next_instruction_offset; - } - else { - *ret = hook->get_original(); - } - return true; - } + hook = std::make_unique(location, detour); + if (!hook->create()) { + spdlog::error("Failed to create hook!"); + return false; + } + + if (next_instruction_offset) { + *ret = location + next_instruction_offset; + } else { + *ret = hook->get_original(); + } + return true; + } // Called when ModFramework::initialize finishes in the first render frame // Returns an error string if it fails virtual std::optional on_initialize() { return std::nullopt; }; - // Functionally equivalent, but on_frame will always get called, on_draw_ui can be disabled by ModFramework - virtual void on_frame() {}; - virtual void on_draw_ui() {}; - virtual void on_draw_debug_ui() {}; + // Functionally equivalent, but on_frame will always get called, on_draw_ui + // can be disabled by ModFramework + virtual void on_frame(){}; + virtual void on_draw_ui(){}; + virtual void on_draw_debug_ui(){}; - virtual void on_config_load(const utility::Config& cfg) {}; - virtual void on_config_save(utility::Config& cfg) {}; + virtual void on_config_load(const utility::Config& cfg){}; + virtual void on_config_save(utility::Config& cfg){}; // Game-specific callbacks /* virtual void on_pre_update_transform(RETransform* transform) {}; virtual void on_update_transform(RETransform* transform) {}; - virtual void on_pre_update_camera_controller(RopewayPlayerCameraController* controller) {}; - virtual void on_update_camera_controller(RopewayPlayerCameraController* controller) {}; - virtual void on_pre_update_camera_controller2(RopewayPlayerCameraController* controller) {}; - virtual void on_update_camera_controller2(RopewayPlayerCameraController* controller) {}; + virtual void on_pre_update_camera_controller(RopewayPlayerCameraController* + controller) {}; virtual void + on_update_camera_controller(RopewayPlayerCameraController* controller) {}; + virtual void on_pre_update_camera_controller2(RopewayPlayerCameraController* + controller) {}; virtual void + on_update_camera_controller2(RopewayPlayerCameraController* controller) {}; */ }; diff --git a/src/ModFramework.cpp b/src/ModFramework.cpp index d5f4622..716b220 100644 --- a/src/ModFramework.cpp +++ b/src/ModFramework.cpp @@ -4,10 +4,9 @@ #include - // ours with XInput removed -#include "fw-imgui/imgui_impl_win32.h" #include "fw-imgui/imgui_impl_dx9.h" +#include "fw-imgui/imgui_impl_win32.h" #include "utility/Module.hpp" @@ -21,17 +20,16 @@ #include "PromptFontCompressed.cpp" #include "PromptFontGlyphs.hpp" -#include "utility/Thread.hpp" #include "utility/ExceptionHandler.hpp" +#include "utility/Thread.hpp" extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); std::unique_ptr g_framework{}; ModFramework::ModFramework() - : m_game_module{ GetModuleHandle(0) }, - m_logger{ spdlog::basic_logger_mt("ModFramework", LOG_FILENAME, true) } -{ + : m_game_module{GetModuleHandle(0)}, + m_logger{spdlog::basic_logger_mt("ModFramework", LOG_FILENAME, true)} { spdlog::set_default_logger(m_logger); spdlog::flush_on(spdlog::level::info); spdlog::info(LOG_ENTRY); @@ -39,8 +37,8 @@ ModFramework::ModFramework() #ifdef DEBUG spdlog::set_level(spdlog::level::debug); #endif - // WARNING(): i hacked on init for time critical stuff here - // TimeCritical init stuff + // WARNING(): i hacked on init for time critical stuff here + // TimeCritical init stuff #if 0 std::thread init_thread([this]() { m_mods = std::make_unique(); @@ -72,20 +70,19 @@ ModFramework::ModFramework() if (e) { if (e->empty()) { m_error = "An unknown error has occurred."; - } - else { + } else { m_error = *e; } } utils::ResumeThreads(threads); FunctionHook::set_mh_skip_locks(FALSE); #endif - /*std::this_thread::sleep_for(std::chrono::seconds(1));*/ + /*std::this_thread::sleep_for(std::chrono::seconds(1));*/ m_d3d9_hook = std::make_unique(); - m_d3d9_hook->on_reset ([this](D3D9Hook& hook) { on_reset(); }); - m_d3d9_hook->on_end_scene([this](D3D9Hook& hook) { on_frame(); }); + m_d3d9_hook->on_reset([this](D3D9Hook& hook) { on_reset(); }); + m_d3d9_hook->on_end_scene([this](D3D9Hook& hook) { on_frame(); }); m_valid = m_d3d9_hook->hook(); @@ -95,33 +92,28 @@ ModFramework::ModFramework() } ModFramework::~ModFramework() { - } -void SetVisibleCursorWINAPI(bool visible) -{ +void set_visible_cursor_winapi(bool visible) { - CURSORINFO info = { sizeof(CURSORINFO), 0, nullptr, {} }; - if (!GetCursorInfo(&info)) - { - throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "GetCursorInfo"); - } + CURSORINFO info = {sizeof(CURSORINFO), 0, nullptr, {}}; + if (!GetCursorInfo(&info)) { + throw std::system_error(std::error_code(static_cast(GetLastError()), std::system_category()), "GetCursorInfo"); + } - bool isvisible = (info.flags & CURSOR_SHOWING) != 0; - if (isvisible != visible) - { - ShowCursor(visible); - } + bool isvisible = (info.flags & CURSOR_SHOWING) != 0; + if (isvisible != visible) { + ShowCursor(visible); + } } -static bool IsCursorVisibleWINAPI() { - CURSORINFO info = { sizeof(CURSORINFO), 0, nullptr, {} }; - if (!GetCursorInfo(&info)) - { - throw std::exception("GetCursorInfo"); - } +static bool is_cursor_visible_winapi() { + CURSORINFO info = {sizeof(CURSORINFO), 0, nullptr, {}}; + if (!GetCursorInfo(&info)) { + throw std::exception("GetCursorInfo"); + } - return (info.flags & CURSOR_SHOWING) != 0; + return (info.flags & CURSOR_SHOWING) != 0; } void ModFramework::on_frame() { @@ -138,15 +130,18 @@ void ModFramework::on_frame() { return; } - //SetVisibleCursorWINAPI(m_draw_ui); + // SetVisibleCursorWINAPI(m_draw_ui); - ImGui_ImplDX9_NewFrame(); + ImGui_ImplDX9_NewFrame(); ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); if (m_error.empty() && m_game_data_initialized) { m_mods->on_frame(); - m_mods->on_draw_custom_imgui_window(); + m_mods->on_draw_custom_imgui_window(); + if (m_draw_debug_ui) { + m_mods->on_draw_debug_ui(); + } } draw_ui(); @@ -154,25 +149,27 @@ void ModFramework::on_frame() { ImGui::EndFrame(); ImGui::Render(); - ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData()); + ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData()); - //ID3D11DeviceContext* context = nullptr; - //m_d3d11_hook->get_device()->GetImmediateContext(&context); + // ID3D11DeviceContext* context = nullptr; + // m_d3d11_hook->get_device()->GetImmediateContext(&context); - //context->OMSetRenderTargets(1, &m_main_render_target_view, NULL); + // context->OMSetRenderTargets(1, &m_main_render_target_view, NULL); - //ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + // ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); } void ModFramework::on_reset() { spdlog::info("Reset!"); - if (!m_initialized) { return; } - ImGui_ImplDX9_Shutdown(); - ImGui_ImplWin32_Shutdown(); - ImGui_ImplDX9_InvalidateDeviceObjects(); - //ImGui_ImplDX9_InvalidateDeviceObjects(); + if (!m_initialized) { + return; + } + ImGui_ImplDX9_Shutdown(); + ImGui_ImplWin32_Shutdown(); + ImGui_ImplDX9_InvalidateDeviceObjects(); + // ImGui_ImplDX9_InvalidateDeviceObjects(); // Crashes if we don't release it at this point. - //cleanup_render_target(); + // cleanup_render_target(); m_initialized = false; } @@ -182,37 +179,37 @@ bool ModFramework::on_message(HWND wnd, UINT message, WPARAM w_param, LPARAM l_p return true; } - if (message == WM_KILLFOCUS) { - printf("WINDOW Killfocus\n"); - m_window_focused = false; - } - if (message == WM_SETFOCUS) { - printf("WINDOW Setfocus\n"); - m_window_focused = true; - } - - if (message == WM_KEYDOWN) { - - m_last_key = w_param; - - if (w_param == VK_INSERT) { - m_draw_ui = !m_draw_ui; - } - if (w_param == UIButton::ui_button_get_wparam()) { - m_draw_ui = !m_draw_ui; - } - } - /*if (message == WM_MOUSEMOVE) { - m_draw_cursor = true; - int cur_x = GET_X_LPARAM(l_param); - int cur_y = GET_Y_LPARAM(l_param); - - m_mouse_x_dt = cur_x - m_mouse_x; - m_mouse_y_dt = cur_y - m_mouse_y; - m_mouse_x = cur_x; - m_mouse_y = cur_y; - m_last_mouse_move_timestamp = std::chrono::high_resolution_clock::now(); - }*/ + if (message == WM_KILLFOCUS) { + printf("WINDOW Killfocus\n"); + m_window_focused = false; + } + if (message == WM_SETFOCUS) { + printf("WINDOW Setfocus\n"); + m_window_focused = true; + } + + if (message == WM_KEYDOWN) { + + m_last_key = w_param; + + if (w_param == VK_INSERT) { + m_draw_ui = !m_draw_ui; + } + if (w_param == UIButton::ui_button_get_wparam()) { + m_draw_ui = !m_draw_ui; + } + } + /*if (message == WM_MOUSEMOVE) { + m_draw_cursor = true; + int cur_x = GET_X_LPARAM(l_param); + int cur_y = GET_Y_LPARAM(l_param); + + m_mouse_x_dt = cur_x - m_mouse_x; + m_mouse_y_dt = cur_y - m_mouse_y; + m_mouse_x = cur_x; + m_mouse_y = cur_y; + m_last_mouse_move_timestamp = std::chrono::high_resolution_clock::now(); + }*/ if (m_draw_ui && ImGui_ImplWin32_WndProcHandler(wnd, message, w_param, l_param) != 0) { // If the user is interacting with the UI we block the message from going to the game. @@ -259,40 +256,41 @@ void ModFramework::save_config() { } void ModFramework::draw_ui() { - //std::lock_guard _{ m_input_mutex }; + // std::lock_guard _{ m_input_mutex }; if (!m_draw_ui) { - //m_dinput_hook->acknowledge_input(); - //ImGui::GetIO().MouseDrawCursor = false; + // m_dinput_hook->acknowledge_input(); + // ImGui::GetIO().MouseDrawCursor = false; return; } auto& io = ImGui::GetIO(); - ImGui::SetNextWindowPos(ImVec2(50, 50), ImGuiCond_::ImGuiCond_Once); ImGui::SetNextWindowSize(ImVec2(410, 600), ImGuiCond_::ImGuiCond_Once); ImGui::Begin("ModFramework", &m_draw_ui); #ifdef GIT_HASH - ImGui::Text("Version: %s", GIT_HASH); - ImGui::Text("Date: %s", GIT_DATE); + ImGui::Text("Version: %s", GIT_HASH); + ImGui::Text("Date: %s", GIT_DATE); #endif ImGui::Text("Menu Key: Insert"); - - if (ImGui::Button("Save config")) { - save_config(); - } + + if (ImGui::Button("Save config")) { + save_config(); + }; + ImGui::SameLine(); + + ImGui::Checkbox("Draw debug window", &m_draw_debug_ui); + draw_about(); if (m_error.empty() && m_game_data_initialized) { m_mods->on_draw_ui(); - } - else if (!m_game_data_initialized) { + } else if (!m_game_data_initialized) { ImGui::TextWrapped("ModFramework is currently initializing..."); - } - else if(!m_error.empty()) { + } else if (!m_error.empty()) { ImGui::TextWrapped("ModFramework error: %s", m_error.c_str()); } @@ -307,18 +305,18 @@ void ModFramework::draw_about() { ImGui::TreePush("About"); ImGui::Text("Authors: Siyan, endneo, cheburrat0r, deepdarkkapustka"); - ImGui::Text("https://github.com/muhopensores/dmc3-inputs-thing/"); - ImGui::NewLine(); + ImGui::Text("https://github.com/muhopensores/dmc3-inputs-thing/"); + ImGui::NewLine(); ImGui::Text("Inspired by RE2Framework/Kanan project."); ImGui::Text("https://github.com/praydog/RE2-Mod-Framework"); ImGui::Text("https://github.com/cursey/kanan-new"); if (ImGui::CollapsingHeader("Licenses")) { ImGui::TreePush("Licenses"); - - if (ImGui::CollapsingHeader("PromptFont")) { - ImGui::TextWrapped(license::prompt_font); - } + + if (ImGui::CollapsingHeader("PromptFont")) { + ImGui::TextWrapped(license::prompt_font); + } if (ImGui::CollapsingHeader("glm")) { ImGui::TextWrapped(license::glm); @@ -347,7 +345,7 @@ bool ModFramework::initialize() { return true; } #ifdef NDEBUG - //reframework::setup_exception_handler(); + // reframework::setup_exception_handler(); #endif spdlog::info("Attempting to initialize"); @@ -360,22 +358,21 @@ bool ModFramework::initialize() { return false; } - D3DDEVICE_CREATION_PARAMETERS devParams{ 0 }; - auto hr = device->GetCreationParameters(&devParams); - if (SUCCEEDED(hr)) { - if (devParams.hFocusWindow) { - spdlog::info("[D3D Device init] D3DDEVICE_CREATION_PARAMETERS hFocusWindow={0:x}\n", (void*)devParams.hFocusWindow); - m_wnd = devParams.hFocusWindow; - } - else { - spdlog::info("[D3D Device present] D3DDEVICE_CREATION_PARAMETERS hFocusWindow= is NULL\n"); - return false; - } - } + D3DDEVICE_CREATION_PARAMETERS dev_params{0}; + auto hr = device->GetCreationParameters(&dev_params); + if (SUCCEEDED(hr)) { + if (dev_params.hFocusWindow) { + spdlog::info("[D3D Device init] D3DDEVICE_CREATION_PARAMETERS hFocusWindow={0:x}\n", (void*)dev_params.hFocusWindow); + m_wnd = dev_params.hFocusWindow; + } else { + spdlog::info("[D3D Device present] D3DDEVICE_CREATION_PARAMETERS hFocusWindow= is NULL\n"); + return false; + } + } // Explicitly call destructor first m_windows_message_hook.reset(); - m_windows_message_hook = std::make_unique(m_wnd); + m_windows_message_hook = std::make_unique(m_wnd); m_windows_message_hook->on_message = [this](auto wnd, auto msg, auto wParam, auto lParam) { return on_message(wnd, msg, wParam, lParam); }; @@ -392,10 +389,6 @@ bool ModFramework::initialize() { #endif #endif - //spdlog::info("Creating render target"); - - //create_render_target(); - spdlog::info("Window Handle: 0x{0:x}", (uintptr_t)m_wnd); spdlog::info("Initializing ImGui"); @@ -416,11 +409,13 @@ bool ModFramework::initialize() { return false; } - // NOTE(): this font stuff needs to be done on init - static const ImWchar icons_ranges[] = { 0x20, 0xFF, ICON_MIN_PF, ICON_MAX_PF, 0 }; // Will not be copied by AddFont* so keep in scope. - auto io = ImGui::GetIO(); - io.Fonts->AddFontDefault(); - m_prompt_font = io.Fonts->AddFontFromMemoryCompressedTTF(PFont_compressed_data, PFont_compressed_size, 32.0f, NULL, icons_ranges); + // NOTE(): this font stuff needs to be done on init + static const ImWchar icons_ranges[] = {0x20, 0xFF, ICON_MIN_PF, ICON_MAX_PF, 0}; // Will not be copied by AddFont* so keep in scope. + + auto io = ImGui::GetIO(); + io.Fonts->AddFontDefault(); + m_prompt_font = io.Fonts->AddFontFromMemoryCompressedTTF(PFont_compressed_data, PFont_compressed_size, 32.0f, NULL, icons_ranges); + ImGui::StyleColorsDark(); if (m_first_frame) { @@ -430,15 +425,14 @@ bool ModFramework::initialize() { // Game specific initialization stuff std::thread init_thread([this]() { - //m_mods = std::make_unique(); - m_mods->load_mods(); + // m_mods = std::make_unique(); + m_mods->load_mods(); auto e = m_mods->on_initialize(); if (e) { if (e->empty()) { m_error = "An unknown error has occurred."; - } - else { + } else { m_error = *e; } } @@ -468,4 +462,3 @@ void ModFramework::cleanup_render_target() { m_main_render_target_view = nullptr; }*/ } - diff --git a/src/ModFramework.hpp b/src/ModFramework.hpp index 5428586..b6af981 100644 --- a/src/ModFramework.hpp +++ b/src/ModFramework.hpp @@ -3,6 +3,7 @@ #include class Mods; +class Mod; #include "D3D9Hook.hpp" #include "WindowsMessageHook.hpp" @@ -63,6 +64,7 @@ class ModFramework { void save_config(); + Mod* m_rr; private: void draw_ui(); void draw_about(); @@ -77,6 +79,12 @@ class ModFramework { bool m_draw_ui{ false }; bool m_draw_cursor{ true }; bool m_window_focused{ true }; +#ifndef NDEBUG + bool m_draw_debug_ui{ true }; +#else + bool m_draw_debug_ui{ false }; +#endif // !NDEBUG + std::atomic m_game_data_initialized{ false }; std::mutex m_input_mutex{}; diff --git a/src/Mods.cpp b/src/Mods.cpp index d722910..7d0a002 100644 --- a/src/Mods.cpp +++ b/src/Mods.cpp @@ -23,6 +23,8 @@ #include "mods/EnemyStates.hpp" #include "mods/EnemySpawnRate.hpp" #include "mods/CustomAlolcator.hpp" +#include "mods/RendererReplace.hpp" +#include "mods/AreaJump.hpp" //#include "mods/StyleSwitcherInfo.hpp" //#include "mods/CameraHack.hpp" @@ -43,6 +45,7 @@ void Mods::load_time_critical_mods() { } void Mods::load_mods() { +#if 1 m_mods.emplace_back(std::make_unique()); m_mods.emplace_back(std::make_unique()); m_mods.emplace_back(std::make_unique()); @@ -60,9 +63,11 @@ void Mods::load_mods() { m_mods.emplace_back(std::make_unique()); //m_mods.emplace_back(std::make_unique()); // crashes half the time on boot, will replace m_mods.emplace_back(std::make_unique()); + m_mods.emplace_back(std::make_unique()); +#endif #ifndef _NDEBUG - m_mods.emplace_back(std::make_unique()); + //m_mods.emplace_back(std::make_unique()); #endif // _DEBUG //m_mods.emplace_back(std::make_unique()); //m_mods.emplace_back(std::make_unique()); @@ -104,9 +109,11 @@ void Mods::on_draw_ui() const { for (auto& mod : m_mods) { mod->on_draw_ui(); } + g_framework->m_rr->on_draw_ui(); } void Mods::on_draw_custom_imgui_window() const { +#if 0 PracticeMode* p = dynamic_cast(m_mods[6].get()); // epic footguns akimbo InputLog* l = dynamic_cast(m_mods[9].get()); // epic footguns akimbo part2 DebugDraw* d = dynamic_cast(m_mods[10].get()); // epic footguns akimbo part3 @@ -115,4 +122,5 @@ void Mods::on_draw_custom_imgui_window() const { l->custom_imgui_window(); d->custom_imgui_window(); t->custom_imgui_window(); +#endif } \ No newline at end of file diff --git a/src/Sfx.cpp b/src/Sfx.cpp index 0f902833e62affa6b32c7768b01c14fc35111056..7f8fb2d1a4970d7b9d31a31dc73c16baf0e3a651 100644 GIT binary patch delta 74 zcmX@IPV3$}ErI|4lo>J^(ijvN3>bJBxELClTA3JInSdm7D-%mA6Kg9ITPqWLD-%a6 X6X#YYF1zUh$_%Ltc?>CFZ6GZG&-oAz delta 48 zcmcb&PV2}zEvEnf8U room_items = { + Room { 0, "Dante's Office" }, + Room { 1, "Dante's Office: Front" }, + Room { 2, "66 Slum Avenue" }, + Room { 3, "Bullseye" }, + Room { 4, "Love Planet" }, + Room { 5, "13th Avenue" }, + Room { 6, "Ice Guardian's Chamber" }, + Room { 7, "Love Planet" }, + Room { 8, "13th Avenue: Aftermath" }, + Room { 9, "Dante's Office: Front" }, + Room { 10, "Dante's Office: Front" }, + Room { 11, "66 Slum Avenue" }, + Room { 12, "Credits" }, + Room { 100, "Chamber of Echoes" }, + Room { 101, "Entranceway" }, + Room { 102, "Living Statue Room" }, + Room { 103, "Silence Statuary" }, + Room { 104, "Chamber of Sins" }, + Room { 105, "Cursed Skull Chamber" }, + Room { 106, "Sun & Moon Chamber" }, + Room { 107, "Ice Guardian's Chamber" }, + Room { 108, "Entranceway" }, + Room { 109, "Chamber of Sins" }, + Room { 110, "Incandescent Space" }, + Room { 111, "Giantwalker Chamber" }, + Room { 112, "Endless Infernum" }, + Room { 113, "Surge of Fortunas" }, + Room { 114, "Heavenrise Chamber" }, + Room { 115, "The Divine Library" }, + Room { 116, "Incandescent Space" }, + Room { 117, "Endless Infernum" }, + Room { 118, "Surge of Fortunas" }, + Room { 119, "High-fly Zone" }, + Room { 120, "Azure Garden" }, + Room { 121, "Firestorm Chamber" }, + Room { 122, "Mute Goddess' Chamber" }, + Room { 123, "Chamber of 3 Trials" }, + Room { 124, "Trial of the Warrior" }, + Room { 125, "Trial of Skill" }, + Room { 126, "Trial of Wisdom" }, + Room { 127, "The Dark Corridor" }, + Room { 128, "God-cube Chamber" }, + Room { 129, "Tri-sealed Antechamber" }, + Room { 130, "Trial of the Warrior" }, + Room { 131, "Trial of Skill" }, + Room { 132, "Trial of Wisdom" }, + Room { 133, "The Dark Corridor" }, + Room { 134, "Pitch-black Void" }, + Room { 135, "Skull Spire" }, + Room { 136, "Tranquil Souls Room" }, + Room { 137, "Lift Room" }, + Room { 138, "Moonlight Mile" }, + Room { 139, "Apparition Incarnate" }, + Room { 140, "Pitch-black Void" }, + Room { 141, "Skull Spire" }, + Room { 142, "Peak of Darkness" }, + Room { 143, "Dark-pact Chamber" }, + Room { 144, "Peak of Darkness" }, + Room { 145, "Astral Chamber" }, + Room { 146, "Waking Sun Chamber" }, + Room { 200, "Forbidden Land: Front" }, + Room { 201, "The Rotating Bridge" }, + Room { 202, "Provisions Storeroom" }, + Room { 203, "Subterranean Garden" }, + Room { 204, "Subground Water Vein" }, + Room { 205, "Rounded Pathway" }, + Room { 206, "Subterranean Lake" }, + Room { 207, "Rounded Pathway" }, + Room { 208, "Provisions Storeroom" }, + Room { 209, "Limestone Cavern" }, + Room { 210, "Sunken Opera House" }, + Room { 211, "Marble Throughway" }, + Room { 212, "Gears of Madness" }, + Room { 213, "Altar of Evil Pathway" }, + Room { 214, "Altar of Evil" }, + Room { 215, "Debug Room" }, + Room { 216, "Temperance Wagon" }, + Room { 217, "Torture Chamber" }, + Room { 218, "Spiral Corridor" }, + Room { 219, "Devilsprout Lift" }, + Room { 220, "Debug Room" }, + Room { 221, "Subterran Garden" }, + Room { 222, "Upper Subterran Garden" }, + Room { 223, "Debug Room" }, + Room { 224, "Rounded Pathway" }, + Room { 225, "Subterran Lake" }, + Room { 226, "Top Subterria Lack" }, + Room { 227, "Rounded Pathway" }, + Room { 228, "Underground Arena" }, + Room { 229, "Effervescence Corridor" }, + Room { 230, "Spiral Staircase" }, + Room { 231, "Top Obsidian Path" }, + Room { 232, "Obsidian Path" }, + Room { 233, "Vestibule" }, + Room { 234, "Lair of Judgement" }, + Room { 235, "Underwater Elevator" }, + Room { 236, "Hell's Highway" }, + Room { 237, "Lair of Judgement Ruins" }, + Room { 238, "Underground Arena" }, + Room { 239, "Temperance Wagon" }, + Room { 240, "Temperance Wagon" }, + Room { 241, "Lux-luminous Corridor" }, + Room { 300, "Leviathan's Stomach" }, + Room { 301, "Leviathan's Intestines" }, + Room { 302, "Leviathan's Heartcore" }, + Room { 303, "Leviathan's Intestines" }, + Room { 304, "Leviathan's Intestines" }, + Room { 305, "Leviathan's Retina" }, + Room { 306, "Leviathan's Intestines" }, + Room { 307, "Leviathan's Intestines" }, + Room { 308, "Leviathan's Stomach" }, + Room { 309, "Leviathan's Intestines" }, + Room { 310, "Leviathan's Heartcore (Debug Room)" }, + Room { 311, "Leviathan's Intestines" }, + Room { 312, "Leviathan's Intestines" }, + Room { 313, "Leviathan's Retina" }, + Room { 400, "Unsacred Hellgate" }, + Room { 401, "Damned Chess Board" }, + Room { 402, "Road to Despair" }, + Room { 403, "Lost Souls Nirvana" }, + Room { 404, "Infinity Nirvana" }, + Room { 405, "Nirvana of Illusions" }, + Room { 406, "Room of Fallen Ones" }, + Room { 407, "Debug Room" }, + Room { 408, "End of the Line" }, + Room { 409, "Forbidden Nirvana" }, + Room { 410, "No use" }, + Room { 411, "Unsacred Hellgate" }, + Room { 412, "Ice Guardian Reborn" }, + Room { 413, "Giantwalker Reborn" }, + Room { 414, "Firestorm Reborn" }, + Room { 415, "Lightning Witch Reborn" }, + Room { 416, "Lightbeast Reborn" }, + Room { 417, "Timesteed Reborn" }, + Room { 418, "Deathvoid Reborn" }, + Room { 419, "Evil God-beast Reborn" }, + Room { 420, "Demon Army Reborn" }, + Room { 421, "Forbidden Nirvana" }, + Room { 422, "Demon Clown Chamber" }, + Room { 423, "Bloody Palace" }, + Room { 424, "Bloody Palace" }, + Room { 425, "Bloody Palace" }, + Room { 426, "Bloody Palace" }, + Room { 427, "Bloody Palace" }, + Room { 428, "Bloody Palace" }, + Room { 429, "Bloody Palace" }, + Room { 430, "Bloody Palace" }, + Room { 431, "Bloody Palace" }, + Room { 432, "Bloody Palace" }, + Room { 433, "Bloody Palace Boss" }, + Room { 434, "Bloody Palace Boss" }, + Room { 435, "Bloody Palace Boss" }, + Room { 436, "Bloody Palace Boss" }, + Room { 437, "Bloody Palace Boss" }, + Room { 438, "Bloody Palace Boss" }, + Room { 439, "Bloody Palace Boss" }, + Room { 440, "Bloody Palace Boss" }, + Room { 441, "Bloody Palace Boss" }, + Room { 442, "Bloody Palace Boss" }, + Room { 443, "Bloody Palace Boss" }, + Room { 444, "Bloody Palace Boss" }, + Room { 445, "Bloody Palace Boss" }, + Room { 446, "Bloody Palace Boss" }, + Room { 447, "Bloody Palace Boss" }, + Room { 448, "Demon Clown Chamber" }, + Room { 449, "Demon Clown Chamber" }, + Room { 600, "Secret Mission" }, + Room { 601, "Secret Mission" }, + Room { 602, "Secret Mission" }, + Room { 603, "Secret Mission" }, + Room { 604, "Secret Mission" }, + Room { 605, "Secret Mission" }, + Room { 606, "Secret Mission" }, + Room { 607, "Secret Mission" }, + Room { 608, "Secret Mission" }, + Room { 609, "Secret Mission" }, + Room { 610, "Secret Mission" }, + Room { 611, "Secret Mission" }, + Room { 900, "Debug Room" }, + Room { 901, "Debug Room" }, + Room { 902, "Debug Room" }, + Room { 903, "Debug Room" }, + Room { 904, "Debug Room" }, + Room { 905, "Debug Room" }, + Room { 906, "Debug Room" }, + Room { 907, "Debug Room" }, + Room { 908, "Debug Room" }, + Room { 909, "Debug Room" }, + Room { 910, "Debug Room" } +}; + +std::optional AreaJump::on_initialize() { + // uintptr_t base = g_framework->get_module().as(); + return Mod::on_initialize(); +} + +void AreaJump::on_draw_ui() { + if (!ImGui::CollapsingHeader(get_name().data())) { + return; + } + static char filter_inputbox[MAX_PATH] = {0}; + + ImGui::InputText("Filter: ", filter_inputbox, MAX_PATH); + + int item_current_idx = 0; + if (ImGui::BeginListBox("##Room Codes Listbox")) { + for (size_t n = 0; n < room_items.size(); n++) { + const bool is_selected = (item_current_idx == n); + + // sigh + char buffer[MAX_PATH]; + int result = snprintf(buffer, sizeof(buffer), "%d - %s", room_items[n].id, room_items[n].name); + IM_ASSERT(result > 0); // encoding error + IM_ASSERT(result < MAX_PATH); // output was truncated or null terminator didnt fit in + + bool filtered = std::strstr(buffer, filter_inputbox) == 0; + + if(filtered) { continue; } + + if (ImGui::Selectable(buffer, is_selected)) { + item_current_idx = n; + devil3_sdk::area_jump(room_items[n].id); + } + + // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) + if (is_selected) { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndListBox(); + } +} \ No newline at end of file diff --git a/src/mods/AreaJump.hpp b/src/mods/AreaJump.hpp new file mode 100644 index 0000000..0bf75c7 --- /dev/null +++ b/src/mods/AreaJump.hpp @@ -0,0 +1,21 @@ +#pragma once +#include "Mod.hpp" +#include "sdk/ReClass.hpp" + +class AreaJump : public Mod { +public: + AreaJump() = default; + // mod name string for config + std::string_view get_name() const override { return "AreaJump"; } + // called by m_mods->init() you'd want to override this + std::optional on_initialize() override; + + + //void on_frame() override; + void on_draw_ui() override; + //void on_draw_debug_ui() override; +private: + // function hook instance for our detour, convinient wrapper + // around minhook + // std::unique_ptr m_function_hook; +}; \ No newline at end of file diff --git a/src/mods/CustomAlolcator.cpp b/src/mods/CustomAlolcator.cpp index c82cd50..daa320e 100644 --- a/src/mods/CustomAlolcator.cpp +++ b/src/mods/CustomAlolcator.cpp @@ -1,126 +1,38 @@ -#include "CustomAlolcator.hpp" - - -// File stuff for memory arena save/load -// cool wrappers for winapi file from some handmade hero repo on github idk -// what loicense this code has might switch to fopen or something if its not cool mr.casey - -inline std::uint32_t -SafeTruncateUInt64(std::uint64_t Value) -{ - IM_ASSERT(Value <= 0xFFFFFFFF); - std::uint32_t Result = (std::uint32_t)Value; - return(Result); -} +#include "CustomAlolcator.hpp" // NOLINT +#include +#include +#include +#include +#include + +#include // ImageNtHeader +#pragma comment(lib, "dbghelp.lib") +#include "StyleSwitchFX.hpp" +// to check if allocation succeded in other mods (LDK so far) +CustomAlolcator* g_custom_alolcator{nullptr}; +bool g_mem_patch_applied{false}; -struct File { - LPVOID Contents; - size_t ContentsSize; +struct DataSectionInfo { + uintptr_t g_data_section_start {0}; + size_t g_data_section_size {0}; }; -static void -DEBUGPlatformFreeFileMemory(void* Memory) -{ - if (Memory) - { - VirtualFree(Memory, 0, MEM_RELEASE); - } -} - -static File -DEBUGPlatformReadEntireFile(char* Filename) -{ - File Result{}; - HANDLE FileHandle = CreateFileA(Filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); - if (FileHandle != INVALID_HANDLE_VALUE) - { - LARGE_INTEGER FileSize; - if (GetFileSizeEx(FileHandle, &FileSize)) - { - auto FileSize32 = SafeTruncateUInt64(FileSize.QuadPart); - Result.Contents = VirtualAlloc(0, FileSize32, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - if (Result.Contents) - { - DWORD BytesRead; - if (ReadFile(FileHandle, Result.Contents, FileSize32, &BytesRead, 0) && - (FileSize32 == BytesRead)) - { - // NOTE(casey): File read successfully - Result.ContentsSize = FileSize32; - } - else - { - // TODO(casey): Logging - DEBUGPlatformFreeFileMemory(Result.Contents); - Result.Contents = 0; - } - } - else - { - // TODO(casey): Logging - } - } - else - { - // TODO(casey): Logging - } - - CloseHandle(FileHandle); - } - else - { - // TODO(casey): Logging - } - - return(Result); -} - -static bool -DEBUGPlatformWriteEntireFile(char* Filename, uint32_t MemorySize, void* Memory) -{ - bool Result = false; - - HANDLE FileHandle = CreateFileA(Filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); - if (FileHandle != INVALID_HANDLE_VALUE) - { - DWORD BytesWritten; - if (WriteFile(FileHandle, Memory, MemorySize, &BytesWritten, 0)) - { - // NOTE(casey): File read successfully - Result = (BytesWritten == MemorySize); - } - else - { - // TODO(casey): Logging - } - - CloseHandle(FileHandle); - } - else - { - // TODO(casey): Logging - } - - return(Result); -} - - -// to check if allocation succeded in other mods (LDK so far) -CustomAlolcator* g_custom_alolcator{ nullptr }; +DataSectionInfo g_data_section_info; // size literals constexpr std::size_t operator""_KiB(unsigned long long int x) { - return 1024ULL * x; + return 1024ULL * x; } constexpr std::size_t operator""_MiB(unsigned long long int x) { - return 1024_KiB * x; + return 1024_KiB * x; } constexpr std::size_t operator""_GiB(unsigned long long int x) { - return 1024_MiB * x; + return 1024_MiB * x; } +namespace memory { // code stolen from gingerBills article on memory allocators // https://www.gingerbill.org/article/2019/02/08/memory-allocation-strategies-002/ @@ -128,9 +40,10 @@ constexpr std::size_t operator""_GiB(unsigned long long int x) { #include #if !defined(__cplusplus) -#if (defined(_MSC_VER) && _MSC_VER < 1800) || (!defined(_MSC_VER) && !defined(__STDC_VERSION__)) +#if (defined(_MSC_VER) && _MSC_VER < 1800) || \ + (!defined(_MSC_VER) && !defined(__STDC_VERSION__)) #ifndef true -#define true (0 == 0) +#define true (0 == 0) #endif #ifndef false #define false (0 != 0) @@ -141,503 +54,1078 @@ typedef unsigned char bool; #endif #endif -#include #include +#include #include -bool is_power_of_two(uintptr_t x) { - return (x & (x - 1)) == 0; -} +static bool is_power_of_two(uintptr_t x) { return (x & (x - 1)) == 0; } -uintptr_t align_forward(uintptr_t ptr, size_t align) { - uintptr_t p, a, modulo; +static uintptr_t align_forward(uintptr_t ptr, size_t align) { + uintptr_t p, a, modulo; - assert(is_power_of_two(align)); + assert(is_power_of_two(align)); - p = ptr; - a = (uintptr_t)align; - // Same as (p % a) but faster as 'a' is a power of two - modulo = p & (a - 1); - //modulo = p & (a - 1); + p = ptr; + a = (uintptr_t)align; + // Same as (p % a) but faster as 'a' is a power of two + modulo = p & (a - 1); + // modulo = p & (a - 1); - if (modulo != 0) { - // If 'p' address is not aligned, push the address to the - // next value which is aligned - p += a - modulo; - } - return p; + if (modulo != 0) { + // If 'p' address is not aligned, push the address to the + // next value which is aligned + p += a - modulo; + } + return p; } #ifndef DEFAULT_ALIGNMENT -#define DEFAULT_ALIGNMENT (2*sizeof(void *)) +#define DEFAULT_ALIGNMENT (2 * sizeof(void*)) #endif typedef struct Arena Arena; struct Arena { - unsigned char* buf; - size_t buf_len; - size_t prev_offset; // This will be useful for later on - size_t curr_offset; + unsigned char* buf; + size_t buf_len; + size_t prev_offset; // This will be useful for later on + size_t curr_offset; }; -void arena_init(Arena* a, void* backing_buffer, size_t backing_buffer_length) { - a->buf = (unsigned char*)backing_buffer; - a->buf_len = backing_buffer_length; - a->curr_offset = 0; - a->prev_offset = 0; -#if 0 // was checking for float math fucking up 0x7ff8dead is NaN when interpreted as float, the more you know +static void arena_init(Arena* a, void* backing_buffer, size_t backing_buffer_length) { + a->buf = (unsigned char*)backing_buffer; + a->buf_len = backing_buffer_length; + a->curr_offset = 0; + a->prev_offset = 0; +#if 0 // was checking for float math fucking up 0x7ff8dead is NaN when + // interpreted as float, the more you know uint32_t* iter = (uint32_t*)a->buf; for (size_t i = 0; i < (a->buf_len / sizeof(int)); i++) { - iter[i] = 0x7ff8de00; + iter[i] = 0x7ff8dead; } #endif } +static void* arena_alloc_align(Arena* a, size_t size, size_t align) { + // Align 'curr_offset' forward to the specified alignment + uintptr_t curr_ptr = (uintptr_t)a->buf + (uintptr_t)a->curr_offset; + uintptr_t offset = align_forward(curr_ptr, align); + offset -= (uintptr_t)a->buf; // Change to relative offset -void* arena_alloc_align(Arena* a, size_t size, size_t align) { - // Align 'curr_offset' forward to the specified alignment - uintptr_t curr_ptr = (uintptr_t)a->buf + (uintptr_t)a->curr_offset; - uintptr_t offset = align_forward(curr_ptr, align); - offset -= (uintptr_t)a->buf; // Change to relative offset - - // Check to see if the backing memory has space left - if (offset + size <= a->buf_len) { - void* ptr = &a->buf[offset]; - a->prev_offset = offset; - a->curr_offset = offset + size; + // Check to see if the backing memory has space left + if (offset + size <= a->buf_len) { + void* ptr = &a->buf[offset]; + a->prev_offset = offset; + a->curr_offset = offset + size; - // Zero new memory by default + // Zero new memory by default #ifndef _NDEBUG - //memset(ptr, 0, size); + // memset(ptr, 0, size); #else #endif - return ptr; - } - // Return NULL if the arena is out of memory (or handle differently) - return NULL; + return ptr; + } + // Return NULL if the arena is out of memory (or handle differently) + return NULL; } // Because C doesn't have default parameters -void* arena_alloc(Arena* a, size_t size) { - return arena_alloc_align(a, size, DEFAULT_ALIGNMENT); +static void* arena_alloc(Arena* a, size_t size) { + return arena_alloc_align(a, size, DEFAULT_ALIGNMENT); } -void arena_free(Arena* a, void* ptr) { - // Do nothing +static void arena_free(Arena* a, void* ptr) { + // Do nothing } -void* arena_resize_align(Arena* a, void* old_memory, size_t old_size, size_t new_size, size_t align) { - unsigned char* old_mem = (unsigned char*)old_memory; +static void* arena_resize_align(Arena* a, void* old_memory, size_t old_size, + size_t new_size, size_t align) { + unsigned char* old_mem = (unsigned char*)old_memory; + + assert(is_power_of_two(align)); + + if (old_mem == NULL || old_size == 0) { + return arena_alloc_align(a, new_size, align); + } + if (a->buf <= old_mem && old_mem < a->buf + a->buf_len) { + if (a->buf + a->prev_offset == old_mem) { + a->curr_offset = a->prev_offset + new_size; + if (new_size > old_size) { + // Zero the new memory by default + memset(&a->buf[a->curr_offset], 0, new_size - old_size); + } + return old_memory; + } + void* new_memory = arena_alloc_align(a, new_size, align); + size_t copy_size = old_size < new_size ? old_size : new_size; + // Copy across old memory to the new memory + memmove(new_memory, old_memory, copy_size); + return new_memory; + } + assert(0 && "Memory is out of bounds of the buffer in this arena"); + return NULL; +} - assert(is_power_of_two(align)); +// Because C doesn't have default parameters +static void* arena_resize(Arena* a, void* old_memory, size_t old_size, + size_t new_size) { + return arena_resize_align(a, old_memory, old_size, new_size, + DEFAULT_ALIGNMENT); +} - if (old_mem == NULL || old_size == 0) { - return arena_alloc_align(a, new_size, align); - } - else if (a->buf <= old_mem && old_mem < a->buf + a->buf_len) { - if (a->buf + a->prev_offset == old_mem) { - a->curr_offset = a->prev_offset + new_size; - if (new_size > old_size) { - // Zero the new memory by default - memset(&a->buf[a->curr_offset], 0, new_size - old_size); - } - return old_memory; - } - else { - void* new_memory = arena_alloc_align(a, new_size, align); - size_t copy_size = old_size < new_size ? old_size : new_size; - // Copy across old memory to the new memory - memmove(new_memory, old_memory, copy_size); - return new_memory; - } +static void arena_free_all(Arena* a) { + a->curr_offset = 0; + a->prev_offset = 0; +} - } - else { - assert(0 && "Memory is out of bounds of the buffer in this arena"); - return NULL; - } +Arena g_bigass_arena = {0}; +} // namespace memory + +#pragma region FILE_ROUTINES + +static inline std::uint32_t +SafeTruncateUInt64(std::uint64_t Value) +{ + IM_ASSERT(Value <= 0xFFFFFFFF); + std::uint32_t Result = (std::uint32_t)Value; + return(Result); } -// Because C doesn't have default parameters -void* arena_resize(Arena* a, void* old_memory, size_t old_size, size_t new_size) { - return arena_resize_align(a, old_memory, old_size, new_size, DEFAULT_ALIGNMENT); +struct File { + LPVOID Contents; + size_t ContentsSize; +}; + +static void +DEBUGPlatformFreeFileMemory(void* Memory) +{ + if (Memory) + { + VirtualFree(Memory, 0, MEM_RELEASE); + } } -void arena_free_all(Arena* a) { - a->curr_offset = 0; - a->prev_offset = 0; +static File +DEBUGPlatformReadEntireFile(char* Filename) +{ + File Result{}; + HANDLE FileHandle = CreateFileA(Filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if (FileHandle != INVALID_HANDLE_VALUE) + { + LARGE_INTEGER FileSize; + if (GetFileSizeEx(FileHandle, &FileSize)) + { + auto FileSize32 = SafeTruncateUInt64(FileSize.QuadPart); + Result.Contents = VirtualAlloc(0, FileSize32, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (Result.Contents) + { + DWORD BytesRead; + if (ReadFile(FileHandle, Result.Contents, FileSize32, &BytesRead, 0) && + (FileSize32 == BytesRead)) + { + // NOTE(casey): File read successfully + Result.ContentsSize = FileSize32; + } + else + { + // TODO(casey): Logging + DEBUGPlatformFreeFileMemory(Result.Contents); + Result.Contents = 0; + } + } + else + { + // TODO(casey): Logging + } + } + else + { + // TODO(casey): Logging + } + + CloseHandle(FileHandle); + } + else + { + // TODO(casey): Logging + } + + return(Result); } -// Extra Features -typedef struct Temp_Arena_Memory Temp_Arena_Memory; -struct Temp_Arena_Memory { - Arena* arena; - size_t prev_offset; - size_t curr_offset; -}; +static bool +DEBUGPlatformWriteEntireFile(char* Filename, uint32_t MemorySize, void* Memory) +{ + bool Result = false; + + HANDLE FileHandle = CreateFileA(Filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); + if (FileHandle != INVALID_HANDLE_VALUE) + { + DWORD BytesWritten; + if (WriteFile(FileHandle, Memory, MemorySize, &BytesWritten, 0)) + { + // NOTE(casey): File read successfully + Result = (BytesWritten == MemorySize); + } + else + { + // TODO(casey): Logging + } + + CloseHandle(FileHandle); + } + else + { + // TODO(casey): Logging + } + + return(Result); +} +#pragma endregion + + +#pragma region POSSIBLE_TEXTURE_FIX +static uint32_t g_numtextures {0}; +static void release_textures() { + + TextureTableEntry* tex_entry = (TextureTableEntry*)0x252F750; + TextureTableEntry* tex_entry_iter = tex_entry; + // release everytexture before loading + for(;;) { + if (tex_entry_iter->ptrD3Texture == NULL || tex_entry_iter->ptrTextureData == NULL) { + break; + } + auto tp = tex_entry_iter->ptrD3Texture->texturePointer; + if (!tp) { + tex_entry_iter++; + continue; + } + HRESULT hr = tp->Release(); + if (FAILED(hr)) { + printf("failed to release texture at index: %X", (uintptr_t)tex_entry_iter); + } + tex_entry_iter++; + + } +} +static void load_textures() { + TextureTableEntry* tex_entry = (TextureTableEntry*)0x252F750; + // create and load textures + auto device = g_framework->get_d3d9_device(); + for (uint32_t i = 0; i < g_numtextures; i++) { + Devil3Texture* t = tex_entry[i].ptrD3Texture; + if (!t) { + continue; + } + char buffer[MAX_PATH] = {0}; + sprintf(buffer, "texdump\\texture_%X.dds", (uintptr_t)t); + //HRESULT hr = device->CreateTexture(t->width, t->height, 1u, NULL, t->format, D3DPOOL_SYSTEMMEM, &t->texturePointer, NULL); + //HRESULT hr = D3DXCreateTextureFromFileExA(device, buffer, t->width, t->height, 1u, NULL, t->format, D3DPOOL_SYSTEMMEM, ) + HRESULT hr = D3DXCreateTextureFromFileA(device, buffer, &t->texturePointer); + //t->dirty = false; + if (FAILED(hr)) { + printf("failed to create texture from file at: %X\n", (uintptr_t)t); + } + } +} +static void save_textures() { + TextureTableEntry* tex_entry = (TextureTableEntry*)0x252F750; + g_numtextures = 0; + for (;;) { + if (tex_entry->ptrD3Texture == NULL || tex_entry->ptrTextureData == NULL) { + break; + } + char buffer[MAX_PATH] = {0}; + sprintf(buffer, "texdump\\texture_%X.dds", (uintptr_t)tex_entry->ptrD3Texture); + HRESULT hr = D3DXSaveTextureToFileA(buffer, D3DXIFF_DDS, tex_entry->ptrD3Texture->texturePointer, NULL); + if(FAILED(hr)) { + printf("error saving texture:%X\n", (uintptr_t)tex_entry->ptrD3Texture); + } + g_numtextures += 1; + tex_entry++; + } +} + +std::vector g_texture_pointers = {}; +static uintptr_t detour_d3d9_load_texture_jump_back {0}; -Temp_Arena_Memory temp_arena_memory_begin(Arena* a) { - Temp_Arena_Memory temp; - temp.arena = a; - temp.prev_offset = a->prev_offset; - temp.curr_offset = a->curr_offset; - return temp; +static void add_texture_pointer(Devil3Texture* ecx) { + if(std::any_of(g_texture_pointers.begin(), g_texture_pointers.end(), [ecx](Devil3Texture* a){ return ecx == a;})) { + return; + } + g_texture_pointers.push_back(ecx); } -void temp_arena_memory_end(Temp_Arena_Memory temp) { - temp.arena->prev_offset = temp.prev_offset; - temp.arena->curr_offset = temp.curr_offset; +static void clear_texture_pointers() { + g_texture_pointers.clear(); } -#if 0 -int main(int argc, char** argv) { - int i; - unsigned char backing_buffer[256]; - Arena a = { 0 }; - arena_init(&a, backing_buffer, 256); +static __declspec(naked) void detour_d3d9_load_texture_sub_006E0B10(void) { + __asm { + pushad + push ecx + call add_texture_pointer + pop ecx + popad + originalCode: + sub esp, 0Ch + push esi + mov esi, ecx + jmp DWORD PTR [detour_d3d9_load_texture_jump_back] + } +} - for (i = 0; i < 10; i++) { - int* x; - float* f; - char* str; +#pragma endregion - // Reset all arena offsets for each loop - arena_free_all(&a); - x = (int*)arena_alloc(&a, sizeof(int)); - f = (float*)arena_alloc(&a, sizeof(float)); - str = arena_alloc(&a, 10); +#pragma region SAVE_STATE +enum class SaveStateCommand { + SS_CMD_NOOP, + SS_CMD_SAVE, + SS_CMD_LOAD_QUEUE, + SS_CMD_LOAD_QUEUED, + SS_CMD_LOAD, +}; - *x = 123; - *f = 987; - memmove(str, "Hellope", 7); - printf("%p: %d\n", x, *x); - printf("%p: %f\n", f, *f); - printf("%p: %s\n", str, str); +SaveStateCommand g_save_state_command {SaveStateCommand::SS_CMD_NOOP}; +static uintptr_t detour_game_main_jmp_back {0}; +static BOOL* g_game_update_flag = (BOOL*)0x00833220; +static bool g_skip_textures = false; + +static void save_state_callback() { + BOOL backup_update_flag = *g_game_update_flag; + LPCRITICAL_SECTION cs = (LPCRITICAL_SECTION)0x0252F358; + BYTE* someshit = (BYTE*)0x0081FC90; + IDirect3DDevice9 **g_D3D9_device_dword_252F374 = (IDirect3DDevice9 **)0x0252F374; + IDirect3DDevice9* backup_d3d_device9 = *g_D3D9_device_dword_252F374; + CSceneGameMain* scn = devil3_sdk::get_main_scene(); + switch (g_save_state_command) + { + case SaveStateCommand::SS_CMD_SAVE: + EnterCriticalSection(cs); + // pause before saving + *g_game_update_flag = 1; + // arena + DEBUGPlatformWriteEntireFile("g_bigass_arena.ass", memory::g_bigass_arena.buf_len, memory::g_bigass_arena.buf); + // data section + DEBUGPlatformWriteEntireFile("g_data_section.ass", g_data_section_info.g_data_section_size, (void*)g_data_section_info.g_data_section_start); + if(scn) { + DEBUGPlatformWriteEntireFile("g_current_area", sizeof(uint16_t), &scn->currentLevel); + } + save_textures(); + g_save_state_command = SaveStateCommand::SS_CMD_NOOP; + // restore update flag after saving + *g_game_update_flag = backup_update_flag; + LeaveCriticalSection(cs); + return; + case SaveStateCommand::SS_CMD_LOAD: + // pause before loading + *g_game_update_flag = 1; + + + EnterCriticalSection(cs); + + release_textures(); + + // load arena memory + { + File memdump = DEBUGPlatformReadEntireFile("g_bigass_arena.ass"); + unsigned long* w_iter = (unsigned long*)memory::g_bigass_arena.buf; + unsigned long* r_iter = (unsigned long*)memdump.Contents; + + for (unsigned long long i = 0; i < (memory::g_bigass_arena.buf_len / sizeof(unsigned long)); i++) { + while (InterlockedCompareExchange(&w_iter[i], r_iter[i], w_iter[i]) != w_iter[i]) { + } + } + DEBUGPlatformFreeFileMemory(memdump.Contents); + } +#if 1 + // load data section memory + { + File datadump = DEBUGPlatformReadEntireFile("g_data_section.ass"); + unsigned long* w_iter = (unsigned long *)g_data_section_info.g_data_section_start; + unsigned long* r_iter = (unsigned long *)datadump.Contents; + + for (unsigned long long i = 0; i < (g_data_section_info.g_data_section_size / sizeof(unsigned long)); i++) { + while (InterlockedCompareExchange(&w_iter[i], r_iter[i], w_iter[i]) != w_iter[i]) { + } + } + DEBUGPlatformFreeFileMemory(datadump.Contents); + } +#endif + load_textures(); - str = arena_resize(&a, str, 10, 16); - memmove(str + 7, " world!", 7); - printf("%p: %s\n", str, str); - } + // restore game update flag + *g_game_update_flag = backup_update_flag; + *g_D3D9_device_dword_252F374 = backup_d3d_device9; + *someshit = 3; + //devil3_sdk::area_jump(scn->currentLevel); +#if 0 + for(Devil3Texture* pointer: g_texture_pointers) { + pointer->texturePointer->UnlockRect(0); + if(SUCCEEDED(pointer->texturePointer->Release())) { + pointer->dirty = false; + } + } +#endif - arena_free_all(&a); + LeaveCriticalSection(cs); + g_save_state_command = SaveStateCommand::SS_CMD_NOOP; + return; + + case SaveStateCommand::SS_CMD_LOAD_QUEUE: + File area = DEBUGPlatformReadEntireFile("g_current_area.ass"); + devil3_sdk::area_jump((uint16_t)area.Contents); + DEBUGPlatformFreeFileMemory(area.Contents); + g_save_state_command = SaveStateCommand::SS_CMD_LOAD_QUEUED; + clear_texture_pointers(); + return; + case SaveStateCommand::SS_CMD_NOOP: + clear_texture_pointers(); + return; + default: + break; + } + IM_ASSERT("save_state_callback() UNREACHEABLE"); +} - return 0; +static __declspec(naked) void detour_game_main_callback(void) { + __asm { + pushad + call save_state_callback + popad + originalCode: + mov eax, DWORD PTR [g_game_update_flag] + mov al, BYTE PTR [eax] + jmp DWORD PTR [detour_game_main_jmp_back] + } } -#endif -static Arena g_bigass_arena = {0}; +#pragma endregion +#pragma region SCENE_LOADING + +static void scene_loaded_callback() { + style_switch_efx_clear_textures(); + style_switch_efx_load_textures(); + if(g_save_state_command == SaveStateCommand::SS_CMD_LOAD_QUEUED) { + g_save_state_command = SaveStateCommand::SS_CMD_LOAD; + } +} + +static uintptr_t detour_scene_loaded_jump_back {}; +static __declspec(naked) void detour_scene_loaded(void) { + __asm { + pushad + call scene_loaded_callback + popad + originalCode: + mov [ecx+18738h], dl + jmp DWORD PTR [detour_scene_loaded_jump_back] + } +} +#pragma endregion static __declspec(naked) void push_16megs(void) { - _asm { + _asm { push (16*1024*1024); // cant use cool constexpr size literals here smh - } + } } static __declspec(naked) void push_32megs(void) { - _asm { + _asm { push(32 * 1024 * 1024); // cant use cool constexpr size literals here smh - } + } } static __declspec(naked) void push_xmegs(void) { - _asm { - push(55 * 1024 * 1024); // cant use cool constexpr size literals here smh - } + _asm { + push 1432AA0h; // cant use cool constexpr size literals here smh + } } static __declspec(naked) void push_64megs(void) { - _asm { + _asm { push(64 * 1024 * 1024); // cant use cool constexpr size literals here smh - } + } } static __declspec(naked) void push_128megs(void) { - _asm { + _asm { push(128 * 1024 * 1024); // cant use cool constexpr size literals here smh - } + } } -//dmc3se.exe + 25B806 -static __declspec(naked) void g_bigass_arena_push_asm(void) { - _asm { - push g_bigass_arena - } -} -// dmc3se.exe+25B80B +// dmc3se.exe+25B80B static __declspec(naked) void push_00000800_asm(void) { - _asm { + _asm { push 0x000800 - } + } } -// dmc3se.exe+25B82C -static __declspec(naked) void push_002B0000_asm(void) { - _asm { +// dmc3se.exe+25B82C +static __declspec(naked) void push_002b0000_asm(void) { + _asm { push 0x2B0000 - } + } } -// dmc3se.exe+25B852 -static __declspec(naked) void push_001309C0_asm(void) { - _asm { +// dmc3se.exe+25B852 +static __declspec(naked) void push_001309c0_asm(void) { + _asm { push 0x1309C0 - } + } } -static void load_save_state(void) { - static File memdump = DEBUGPlatformReadEntireFile("g_bigass_arena.ass"); - unsigned long long* w_iter = (unsigned long long*)g_bigass_arena.buf; - unsigned long long* r_iter = (unsigned long long*)memdump.Contents; - for (unsigned long long i = 0; i < (g_bigass_arena.buf_len / sizeof(unsigned long long)); i++) { - while (InterlockedCompareExchange(&w_iter[i], r_iter[i], w_iter[i]) != w_iter[i]) { - } - } - //DEBUGPlatformFreeFileMemory(memdump.Contents); +#if 0 // VirtualAlloc2 didnt work either :( + +static inline char* align_upwards(const char* stack, size_t align) { + assert(align > 0 && (align & (align - 1)) == 0); /* Power of 2 */ + assert(stack != 0); + + auto addr = reinterpret_cast(stack); + if (addr % align != 0) + addr += align - addr % align; + assert(addr >= reinterpret_cast(stack)); + return reinterpret_cast(addr); } -std::optional CustomAlolcator::on_initialize() { - - // WARNING(): dirty hack to only init once here: - static bool init = false; - if (init) { - return Mod::on_initialize(); - } - init = true; +static inline char* align_downwards(const char* stack, size_t align) { + assert(align > 0 && (align & (align - 1)) == 0); /* Power of 2 */ + assert(stack != 0); - g_custom_alolcator = this; + auto addr = reinterpret_cast(stack); + addr -= addr % align; + assert(addr <= reinterpret_cast(stack)); + return reinterpret_cast(addr); +} +// based on: +// https://stackoverflow.com/questions/54223343/virtualalloc2-with-memextendedparameteraddressrequirements-always-produces-error +LPVOID bounded_virtual_alloc(uintptr_t min, uintptr_t max, size_t size, SYSTEM_INFO& sys_info) noexcept { + + return nullptr; + + MEM_ADDRESS_REQUIREMENTS address_reqs = {0}; + MEM_EXTENDED_PARAMETER param = {0}; + + address_reqs.Alignment = 0; // any alignment + address_reqs.LowestStartingAddress = (PVOID)min; // PAGE_SIZE aligned + address_reqs.HighestEndingAddress = (PVOID)(max - 1); // PAGE_SIZE aligned, exclusive so -1 + + param.Type = MemExtendedParameterAddressRequirements; + param.Pointer = &address_reqs; + + HMODULE kernelbase_handle = LoadLibrary("kernelbase.dll"); + if (kernelbase_handle) { + auto p_virtual_alloc2 = (decltype(&::VirtualAlloc2))GetProcAddress(kernelbase_handle, "VirtualAlloc2"); + if (p_virtual_alloc2 != nullptr) { + return p_virtual_alloc2(GetCurrentProcess(), (PVOID)0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, ¶m, 1); + } + } + // NOTE(): slowest path slowest path + MessageBoxA(NULL, "Could not find VirtualAlloc2 in kernelbase.dll, will try to allocate in a loop so it would be slow", "CustomAlolcator WARNING", MB_ICONINFORMATION); + const LPVOID capcops_range = (LPVOID)0x0FFFFFFF; // we can only address like 256 mbs :( + LPVOID lp_address = (LPVOID)min; + size_t dw_size = (size_t)align_downwards((char*)(size_t)capcops_range - (size_t)lp_address, sys_info.dwAllocationGranularity); + DWORD fl_allocation_type = MEM_COMMIT | MEM_RESERVE; + DWORD fl_protect = PAGE_READWRITE; // idk capcom might be cuhrazy enough to write code in there, ask for executable just to be "safe" + LPVOID lp_memory = NULL; + while (lp_memory == NULL) { + lp_memory = VirtualAlloc((LPVOID)lp_address, dw_size, fl_allocation_type, fl_protect); + lp_address = (LPVOID)((DWORD_PTR)lp_address + sys_info.dwAllocationGranularity); + dw_size = dw_size - sys_info.dwAllocationGranularity; + if ((lp_address >= capcops_range) || (dw_size <= 1)) { + break; + } + } + return lp_memory; +} - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - LPVOID lpMinimumApplicationAddress = sysInfo.lpMinimumApplicationAddress; - LPVOID lpMaximumApplicationAddress = sysInfo.lpMaximumApplicationAddress; - printf("lpMinimumApplicationAddress=%p;\tlpMaximumApplicationAddress=%p\n", lpMinimumApplicationAddress, lpMaximumApplicationAddress); -#if 0 - //dmc3se.exe+2D0D2E - 81 E3 FFFFFF0F - and ebx,0FFFFFFF - const LPVOID capcops_range = (LPVOID)0x0FFFFFFF; // we can only address like 256 mbs :( - LPVOID lpAddress = (void*)(1024_MiB >> 0);//(void*)(2048*sysInfo.dwAllocationGranularity);//(void*)align_forward(1_GiB, DEFAULT_ALIGNMENT); // any address doesnt fucking work wth microsoft?! - int32_t dwSize = 1024_MiB - (int32_t)lpMinimumApplicationAddress; - DWORD flAllocationType = MEM_COMMIT | MEM_RESERVE; - DWORD flProtect = PAGE_EXECUTE_READWRITE; // idk capcom might be cuhrazy enough to write code in there, ask for executable just to be "safe" - LPVOID lpMemory = NULL; - int i = 0; - lpMemory = VirtualAlloc(lpAddress, (size_t)512_MiB, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); -#else - const LPVOID capcops_range = (LPVOID)0x0FFFFFFF; // we can only address like 256 mbs :( - LPVOID lpAddress = lpMinimumApplicationAddress;//(void*)(2048*sysInfo.dwAllocationGranularity);//(void*)align_forward(1_GiB, DEFAULT_ALIGNMENT); // any address doesnt fucking work wth microsoft?! - int32_t dwSize = 512_MiB - (int32_t)lpMinimumApplicationAddress; - DWORD flAllocationType = MEM_COMMIT | MEM_RESERVE; - DWORD flProtect = PAGE_EXECUTE_READWRITE; // idk capcom might be cuhrazy enough to write code in there, ask for executable just to be "safe" - LPVOID lpMemory = NULL; - int i = 0; - while (lpMemory == NULL) - { - lpMemory = VirtualAlloc((LPVOID)lpAddress, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - lpAddress = (LPVOID)((DWORD_PTR)lpAddress + sysInfo.dwPageSize); - dwSize = dwSize - sysInfo.dwPageSize; - if ((lpAddress >= capcops_range) || (dwSize <= 1)) { - break; - } - printf("VirtualAlloc loop lpAddress=%p; dwSize=%d\n", lpAddress, dwSize); +void custom_alolcator_virtual_alloc_in_capcom_range() noexcept { + SYSTEM_INFO sys_info; + GetSystemInfo(&sys_info); + + const LPVOID capcops_range = (LPVOID)0x0FFFFFFF; + // migh as well allign here + static size_t dw_size = (size_t)align_upwards((char*)1024_MiB, sys_info.dwAllocationGranularity); + + uint32_t min = (uint32_t)align_upwards((char*)sys_info.lpMinimumApplicationAddress, sys_info.dwAllocationGranularity); + uint32_t max = (uint32_t)align_downwards((char*)capcops_range, sys_info.dwAllocationGranularity); + + LPVOID lp_memory = bounded_virtual_alloc(min, max, dw_size, sys_info); + + IM_ASSERT((lp_memory != NULL) && "Failed to VirtualAlloc memory for CustomAlolcator"); + HMODULE hModule = GetModuleHandle(NULL); // Get handle to current module + IMAGE_NT_HEADERS* pNtHdr = ImageNtHeader(hModule); + IMAGE_SECTION_HEADER* pSectionHdr = (IMAGE_SECTION_HEADER*)(pNtHdr + 1); + + for (int i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++) + { + char* name = (char*)pSectionHdr->Name; + if (memcmp(name, ".buffer", 7) == 0) + { + // Section found + // pSectionHdr->VirtualAddress contains the RVA (Relative Virtual Address) of the section + // hModule is the base address of the module + char* sectionAddress = (char*)hModule + pSectionHdr->VirtualAddress; + // pSectionHdr->Misc.VirtualSize contains the size of the section + int sectionSize = pSectionHdr->Misc.VirtualSize; + + // Do something with sectionAddress and sectionSize + arena_init(&g_bigass_arena, sectionAddress, sectionSize); + arena_free_all(&g_bigass_arena); + // pad cause capcops like to do [eax-4] + static constexpr auto offset_into_an_alloc = 64; + void* unused = arena_alloc(&g_bigass_arena, offset_into_an_alloc); + IM_ASSERT((unused != NULL) && "Arena alloc returned a null pointer"); + return; + } + pSectionHdr++; + } +// arena_init(&g_bigass_arena, lp_memory, dw_size); +// arena_free_all(&g_bigass_arena); + + // pad cause capcops like to do [eax-4] + static constexpr auto offset_into_an_alloc = 64; + void* unused = arena_alloc(&g_bigass_arena, offset_into_an_alloc); + IM_ASSERT((unused != NULL) && "Arena alloc returned a null pointer"); + /* +bruh: + g_alloc_hook = std::make_unique(0x6D4580, &CustomAlolcator::sub_6d4580); + + if (!g_alloc_hook->create()) { + IM_ASSERT("Arena alloc returned a null pointer"); + } + */ - } +} #endif - //IM_ASSERT((lpAddress < lpMaximumApplicationAddress) && (lpAddress > lpMinimumApplicationAddress)); - IM_ASSERT(lpMemory != NULL); - if (lpMemory == NULL) { - printf("Virtual alloc failed with code 0x%X.\n", GetLastError()); - printf("failed to virtual alloc\n"); - return "failed to allocate memory arena"; - } - printf("\n================= COOL MEMORY ARENA start: %p =================\n", lpMemory); - printf("\n================= COOL MEMORY ARENA size: %d =================\n", dwSize); - //__debugbreak(); - m_alloc_hook = std::make_unique(0x6D4580, &sub_6D4580); +static void find_pe_section_init_arena() noexcept { + HMODULE h_module = GetModuleHandle(NULL); + IMAGE_NT_HEADERS* p_nt_hdr = ImageNtHeader(h_module); // get PE info + IMAGE_SECTION_HEADER* p_section_hdr = (IMAGE_SECTION_HEADER*)(p_nt_hdr + 1); + + for (int i = 0; i < p_nt_hdr->FileHeader.NumberOfSections; i++) { + char* name = (char*)p_section_hdr->Name; + if (memcmp(name, ".data", 6) == 0) { + g_data_section_info.g_data_section_start = (uintptr_t)h_module + p_section_hdr->VirtualAddress; + g_data_section_info.g_data_section_size = p_section_hdr->Misc.VirtualSize; + } + if (memcmp(name, ".reloc", 7) == 0) { // assume we added specific section in PE segments + // Section found + // pSectionHdr->VirtualAddress contains the RVA (Relative Virtual Address) of the section + // hModule is the base address of the module + char* section_address = (char*)h_module + p_section_hdr->VirtualAddress; + + // pSectionHdr->Misc.VirtualSize contains the size of the section + int section_size = p_section_hdr->Misc.VirtualSize; + + // Do something with sectionAddress and sectionSize + memory::arena_init(&memory::g_bigass_arena, section_address, section_size); + memory::arena_free_all(&memory::g_bigass_arena); + +#ifndef NDEBUG + printf("memory_arena_size: %zu\n", section_size); +#endif + + // pad a bit just in case + static constexpr auto pad = 64; + void* unused = memory::arena_alloc(&memory::g_bigass_arena, pad); + IM_ASSERT((unused != NULL) && "Arena alloc returned a null pointer"); +#ifndef NDEBUG + printf("arena_alloc: %zu\n", unused); +#endif + return; + } + p_section_hdr++; + } + IM_ASSERT(".reloc section was not found in the dmc3se.exe PE header"); + // TODO(): warn the user or mark something in imgui menu idk +} - arena_init(&g_bigass_arena, lpMemory, dwSize); - arena_free_all(&g_bigass_arena); +static constexpr uint64_t round_to_pow2_size(uint32_t minimum_size, uint32_t pow2_size) { + uint64_t result = (minimum_size + pow2_size - 1) & ~(pow2_size - 1); + return result; +} - // pad cause capcops like to do [eax-4] - static constexpr auto offset_into_an_alloc = 1024; - void* unused = arena_alloc(&g_bigass_arena, offset_into_an_alloc); +std::optional CustomAlolcator::on_initialize() { - IM_ASSERT(unused != NULL); + // WARNING(): dirty hack to only init once here: + static bool init = false; + if (init) { + return Mod::on_initialize(); + } + init = true; + + g_custom_alolcator = this; + + m_alloc_hook = std::make_unique(0x6D4580, &sub_6d4580); + m_heap_control_sub_6D0E30_hook = std::make_unique(0x006D0E30, &heap_control_something_sub_6D0E30); + bool nice = m_heap_control_sub_6D0E30_hook->create(); + + //m_sub_65B880_hook = std::make_unique(0x0065B880, &sub_65B880_internal); + //nice = m_sub_65B880_hook->create(); + + if (!m_alloc_hook->create()) { + return "Failed to install alolcator hook"; + } + + install_patch_absolute(0x65B806, patch01, (char*)&push_32megs, 5); // going above 64 here crashes ui shit idk + install_patch_absolute(0x65B810, patch02, (char*)&push_32megs, 5); // same + install_patch_absolute(0x65B82C, patch03, (char*)&push_64megs, 5); // push 002B0000 default + install_patch_absolute(0x65B836, patch04, (char*)&push_64megs, 5); // push 002B0000 default + install_patch_absolute(0x65B852, patch05, (char*)&push_32megs, 5); // push 001309C0 default + install_patch_absolute(0x65B85C, patch06, (char*)&push_32megs, 5); // push 001309C0 default + install_patch_absolute(0x6D53B2, patch07, (char*)&push_xmegs, 5); // push 00000800 default + + find_pe_section_init_arena(); + + + // main game loop? + install_hook_absolute(0x403580, m_main_sub_00403580_hook, &detour_game_main_callback, &detour_game_main_jmp_back, 5); - if (!m_alloc_hook->create()) { - return "Failed to install alolcator hook"; - } #if 1 - install_patch_absolute(0x65B806, patch01, (char*)&push_64megs, 5); // going above 16 here crashes ui shit idk - install_patch_absolute(0x65B810, patch02, (char*)&push_64megs, 5); // same - - install_patch_absolute(0x65B82C, patch03, (char*)&push_64megs, 5); // push 002B0000 default - install_patch_absolute(0x65B836, patch04, (char*)&push_64megs, 5); // push 002B0000 default - - install_patch_absolute(0x65B852, patch05, (char*)&push_32megs, 5); // push 001309C0 default - install_patch_absolute(0x65B85C, patch06, (char*)&push_32megs, 5); // push 001309C0 default - - // second bunch - install_patch_absolute(0x6D53B2, patch07, (char*)&push_32megs, 5); // push 00000800 default - install_patch_absolute(0x6D5420, patch08, (char*)&push_32megs, 5); // push 0000021C default - install_patch_absolute(0x6D5455, patch09, (char*)&push_32megs, 5); // push 00000221 default - install_patch_absolute(0x6D54A0, patch10, (char*)&push_32megs, 5); // push 00000FC0 default - install_patch_absolute(0x6D54AD, patch11, (char*)&push_32megs, 5); // push 00000FCF default - - + // texture loading routine + install_hook_absolute(0x006E0B10, m_d3d9_load_texture_hook_sub_006E0B10, + &detour_d3d9_load_texture_sub_006E0B10, &detour_d3d9_load_texture_jump_back, 6); #endif - /* - patch01 = Patch::create(0x65B806, (char*)&g_bigass_arena_push_asm, true); // address - patch02 = Patch::create(0x65B80B, {0x68, 0x00, 0x08, 0x00, 0x00}, true); // push 00000800 default - patch03 = Patch::create(0x65B810, (char*)&g_bigass_arena_push_asm, true); // address - patch04 = Patch::create(0x65B82C, {0x68, 0x00, 0x00, 0x00, 0x2B}, true); // push 002B0000 default - patch05 = Patch::create(0x65B80B, {0x68, 0x00, 0x08, 0x00, 0x00}, true); // push 00000800 default - patch06 = Patch::create(0x65B836, {0x68, 0x00, 0x08, 0x00, 0x00}, true); // push 00000800 default - patch07 = Patch::create(0x65B852, {0x68, 0xC0, 0x09, 0x13, 0x00}, true); // push 001309C0 default - patch08 = Patch::create(0x65B85C, {0x68, 0xC0, 0x09, 0x13, 0x00}, true); // push 001309C0 default - */ - // hack to check if we running more memory patch outside - mem_patch_applied = true; + //HRESULT __fastcall CustomAlolcator::d3d_sets_texture_maybe_sub_6E0DF0(Devil3Texture* texture) { + m_hook_d3d_sets_texture_maybe_sub_6E0DF0 = std::make_unique(0x006E0DF0, &d3d_sets_texture_maybe_sub_6E0DF0); + m_hook_d3d_sets_texture_maybe_sub_6E0DF0->create(); + + install_hook_absolute(0x005E02C3, m_scene_loaded_sub_005E02C0, &detour_scene_loaded, &detour_scene_loaded_jump_back, 6); +#if 0 // TODO(): in case someone contributes full custom memory allocator + // second bunch + install_patch_absolute(0x6D5420, patch08, (char*)&push_32megs, 5); // push 0000021C default + install_patch_absolute(0x6D5455, patch09, (char*)&push_32megs, 5); // push 00000221 default + install_patch_absolute(0x6D54A0, patch10, (char*)&push_32megs, 5); // push 00000FC0 default + install_patch_absolute(0x6D54AD, patch11, (char*)&push_32megs, 5); // push 00000FCF default + // sound fx shit i think + patch01 = Patch::create(0x65B806, (char*)&g_bigass_arena_push_asm, true); //address + patch02 = Patch::create(0x65B80B, {0x68, 0x00, 0x08, 0x00, 0x00}, true); // push 00000800 default + patch03 = Patch::create(0x65B810, (char*)&g_bigass_arena_push_asm, true); // address + patch04 = Patch::create(0x65B82C, {0x68, 0x00, 0x00, 0x00, 0x2B}, true); // push 002B0000 default + patch05 = Patch::create(0x65B80B, {0x68, 0x00, 0x08, 0x00, 0x00}, true); // push 00000800 default + patch06 = Patch::create(0x65B836, {0x68, 0x00, 0x08, 0x00, 0x00}, true); // push 00000800 default + patch07 = Patch::create(0x65B852, {0x68, 0xC0, 0x09, 0x13, 0x00}, true); // push 001309C0 default + patch08 = Patch::create(0x65B85C, {0x68, 0xC0, 0x09, 0x13, 0x00}, true); // push 001309C0 default +#endif + // hack to check if we running more memory patch outside + g_mem_patch_applied = true; - return Mod::on_initialize(); -} + //DWORD oldprotect{}; + //VirtualProtect((void*)0x00C36980, 0x800, PAGE_NOACCESS, &oldprotect); + //VirtualProtect((void*)0x01C8A600, 0x80000, PAGE_NOACCESS, &oldprotect); + //VirtualProtect((void*)0x01F38A80, 0x1309C0, PAGE_NOACCESS, &oldprotect); -#define sub_6D4AF0(name) \ - char __cdecl name(uint32_t*, uint32_t) + return Mod::on_initialize(); +} + +#define sub_6D4AF0(name) char __cdecl name(uint32_t*, uint32_t) typedef sub_6D4AF0(sub_6D4AF0_t); -static sub_6D4AF0_t* sub_6D4AF0_ = (sub_6D4AF0_t*)0x6D4AF0; +static sub_6D4AF0_t* sub_6d4af0 = (sub_6D4AF0_t*)0x6D4AF0; +uintptr_t __fastcall CustomAlolcator::sub_6d4580_internal(SomeMemoryManagerShit* p_this, uintptr_t unused, size_t size) noexcept { +#if 1 + if ((size != 32_MiB) && (size != 64_MiB)) { + return m_alloc_hook->get_original()(p_this, unused, size); + } +#endif // TEMP + struct SomeStackFramePointerMaybe* ptr1; // eax + int ptr3; // edi + ptr1 = p_this->ptr1; + if (p_this->ptr1) { + if (p_this->uint1 == ptr1->uint1) { + ptr3 = (int)ptr1->ptr3; + sub_6d4af0(&size, ptr1->uint2); // aligns per buffer or some shit + + auto res = memory::arena_alloc(&memory::g_bigass_arena, size); //(char*)p_this->ptr1->ptr3 + (unsigned int)size; + IM_ASSERT((res != NULL) && "arena_alloc failed!"); + static bool onceflag = false; + if (!onceflag) { + p_this->ptr1->ptr1 = res; + p_this->ptr1->ptr3 = (void*)((uintptr_t)res + (uintptr_t)size); //(char*)p_this->ptr1->ptr3 + (unsigned int)size; + } + else { + p_this->ptr1->ptr3 = res; //(char*)p_this->ptr1->ptr3 + (unsigned int)size; + } + IM_ASSERT(((uint32_t)p_this->ptr1->ptr3 >> 0x1C == 0x0) && "Allocation got outside the range addressable by CAPCOMs restriction. Try again and hope executable gets mapped into lower memory location"); -/* -int __thiscall our_malloc_thing_sub_6D4580(SomeMemoryManagerShit *this, void *size, void *a3) -{ - struct SomeStackFramePointerMaybe *ptr1; // eax - int ptr3; // edi - - ptr1 = this->ptr1; - if ( this->ptr1 ) - { - if ( this->uint1 == ptr1->uint1 ) - { - ptr3 = (int)ptr1->ptr3; - if ( (void *)((unsigned int)size + ptr3) <= ptr1->ptr2 ) - { - sub_6D4AF0((int *)&size, ptr1->uint2); // aligns per buffer or some shit - this->ptr1->ptr3 = (char *)this->ptr1->ptr3 + (unsigned int)size; - return ptr3; - } - else - { - debugLogOrDebugSprintf_sub_6D4B20(0, aFalse, aCTestprojectDe_14, 0x8Bu); - return 0; - } - } - else - { - debugLogOrDebugSprintf_sub_6D4B20(0, aFalse, aCTestprojectDe_14, 0x84u); - return 0; - } - } - else - { - debugLogOrDebugSprintf_sub_6D4B20(0, aFalse, aCTestprojectDe_14, 0x7Eu); - return 0; - } -} -*/ - -uintptr_t __fastcall CustomAlolcator::sub_6D4580_internal(SomeMemoryManagerShit* p_this, uintptr_t unused, uintptr_t size) { - struct SomeStackFramePointerMaybe* ptr1; // eax - int ptr3; // edi - //uintptr_t res = (uintptr_t)arena_alloc_align(&g_bigass_arena, unused*2,32); - ptr1 = p_this->ptr1; - if (p_this->ptr1) - { - if (p_this->uint1 == ptr1->uint1) - { - ptr3 = (int)ptr1->ptr3; - ptr1->ptr2 = (void*)g_bigass_arena.buf_len; - //if ((void*)((unsigned int)size + ptr3) <= ptr1->ptr2) - //{ - auto backupsize = size; - sub_6D4AF0_(&size, ptr1->uint2); // aligns per buffer or some shit - - - p_this->ptr1->ptr3 = arena_alloc(&g_bigass_arena, size);//(char*)p_this->ptr1->ptr3 + (unsigned int)size; - IM_ASSERT(p_this->ptr1->ptr3 != NULL); #ifndef _NDEBUG - printf("sub_6D4580(this=%p, unk=%x, size?=%x)\n", (void*)p_this, unused, size); - printf("g_bigass_arena->size_left= %d\n", (g_bigass_arena.buf_len - g_bigass_arena.curr_offset)); - printf("arena_alloc >> 0x1C=%d\n", (uint32_t)p_this->ptr1->ptr3 >> 0x1C); + printf("sub_6D4580(this=%p, unk=%x, size?=%x)\n", (void*)p_this, unused, size); + printf("g_bigass_arena->size_left= %d\n", (memory::g_bigass_arena.buf_len - memory::g_bigass_arena.curr_offset)); + printf("arena_alloc >> 0x1C=%d\n", (uint32_t)p_this->ptr1->ptr3 >> 0x1C); #endif - return (uintptr_t)p_this->ptr1->ptr3; - //} - //else - //{ - // printf("Memory manager error 00\n"); - // //debugLogOrDebugSprintf_sub_6D4B20(0, aFalse, aCTestprojectDe_14, 0x8Bu); - // return 0; - //} - } - else - { - printf("Memory manager error 01\n"); - //debugLogOrDebugSprintf_sub_6D4B20(0, aFalse, aCTestprojectDe_14, 0x84u); - return 0; - } - } - else - { - printf("Memory manager error 01\n"); - //debugLogOrDebugSprintf_sub_6D4B20(0, aFalse, aCTestprojectDe_14, 0x7Eu); - return 0; - } -#if 0 + return (uintptr_t)res; + } #ifndef _NDEBUG - printf("sub_6D4580(this=%p, unk=%d, size?=%d)\n", (void*)p_this, unused, size); - printf("g_bigass_arena->size_left= %d\n", (g_bigass_arena.buf_len - g_bigass_arena.curr_offset)); - IM_ASSERT(res != NULL && "oh no arena_alloc returned a NULL "); -#endif - if (res == NULL) { // call orig in case we ran out of 1 gig or some wacky shit happens - res = m_alloc_hook->get_original()(p_this, unused, size); - } + printf("Memory manager error 01\n"); +#endif // !_NDEBUG + return 0; + } +#ifndef _NDEBUG + printf("Memory manager error 01\n"); +#endif // !_NDEBUG + return 0; +} - return res; -#endif - //return (uintptr_t)arena_alloc(&g_bigass_arena,a3); -} - -uintptr_t __fastcall CustomAlolcator::sub_6D4580(SomeMemoryManagerShit* p_this, uintptr_t size, uintptr_t unused) { - return g_custom_alolcator->sub_6D4580_internal(p_this, size, unused); -} - -// during load -//void CustomAlolcator::on_config_load(const utility::Config &cfg) { -// for (IModValue& option : m_options) { -// option.config_load(cfg); -// } -//} -// during save -//void CustomAlolcator::on_config_save(utility::Config &cfg) { -// for (IModValue& option : m_options) { -// option.config_save(cfg); -// } -//} -// do something every frame -//void CustomAlolcator::on_frame() {} -// will show up in debug window, dump ImGui widgets you want here -//void CustomAlolcator::on_draw_debug_ui() {} +uintptr_t __fastcall CustomAlolcator::sub_6d4580(SomeMemoryManagerShit* p_this, uintptr_t unused, size_t size) noexcept { + return g_custom_alolcator->sub_6d4580_internal(p_this, unused, size); +} + +struct benis { + void* a1; + void* a2; + void* a3; +}; + +int32_t* g1; +int32_t g2; +uintptr_t __cdecl CustomAlolcator::heap_control_something_sub_6D0E30_internal(uint32_t a1) noexcept { + // 0x6d0e30 + return 0; + int32_t v1{}; // bp-52, 0x6d0e30 + g1 = &v1; + int32_t v2{}; // bp-56, 0x6d0e30 + int32_t* v3 = &v2; // 0x6d0e39 + benis v4; // bp-44, 0x6d0e30 + //__asm_rep_stosd_memset((char*)&v4, 0, 11); + uintptr_t(_cdecl * sub_6C72F0)(int32_t*, int, int, int, int) = (uintptr_t(_cdecl *)(int32_t*, int, int, int, int))0x006C72F0; + int (_cdecl *sub_6C7440)(int a1, int a2) = (int(_cdecl *)(int a1, int a2))0x006C7440; + int32_t* (__cdecl * sub_6C73E0)(int32_t * a1, int32_t a2, int32_t a3, int32_t a4) = (int32_t * (__cdecl *)(int32_t * a1, int32_t a2, int32_t a3, int32_t a4))0x006C73E0; + int32_t* (__cdecl * sub_6CDFF0)(int32_t a1, int32_t * a2, int32_t a3) = (int32_t * (__cdecl *)(int32_t a1, int32_t * a2, int32_t a3))0x006CDFF0; + v4.a1 = (void*)a1; + int32_t v5 = 16 * a1; // 0x6d0e4d + int32_t v6 = *(int32_t*)(v5 + (int32_t)0x0252CA10 + 12); // 0x6d0e63 + int32_t* v7 = (int32_t*)(v3 - 4); + int32_t* v8 = (int32_t*)(v3 + 24); + int32_t* v9 = (int32_t*)(v3 + 20); + int32_t* v10 = (int32_t*)(v3 + 28); + int32_t v11 = *(int32_t*)(v5 + (int32_t)0x0252CA10 + 8); // 0x6d0e7b + int32_t v12 = v6 + 16; // 0x6d0e7b + int32_t v13 = v6; // 0x6d0e7b + int32_t v14; // 0x6d0e30 + int32_t v15; // 0x6d0e30 + int32_t v16; // 0x6d0e30 + while (true) { + lab_0x6d0e7f: + // 0x6d0e7f + v16 = v13; + v15 = v12; + uint32_t v17 = *(int32_t*)v11; // 0x6d0e7f + v14 = v17; + v12 = v15; + v13 = v16; + switch (v17 / 0x10000000) { + case 15: { + goto lab_0x6d0eb6; + } + case 0: { + goto lab_0x6d0ea8; + } + default: { + // 0x6d0e8d + *v7 = *v3 + 12; + v13 = *v8; + v12 = *v9; + v14 = *(int32_t*)*v10; + goto lab_0x6d0ea8; + } + } + } +lab_0x6d0eb6:; + int32_t* v18 = (int32_t*)(v3 + 16); // 0x6d0eb6 + if (v15 == *v18 + 16) { + // 0x6d0f51 + return (uintptr_t)v15; + } + int32_t v19 = 4; // 0x6d0ece + switch (*g1) { + case 1: { + // 0x6d0edc + v19 = 13; + } + case 0: { + lab_0x6d0efd:; + // 0x6d0efd + int32_t* v20; // 0x6d0e30 + int32_t* v21; // 0x6d0e30 + int32_t* v22; // 0x6d0e30 + int32_t* v23; // 0x6d0e30 + int32_t* v24; // 0x6d0e30 + int32_t* v25; // 0x6d0e30 + int32_t v26; // 0x6d0e30 + if (v15 == v16 + 16) { + // 0x6d0f2a + *v9 = v16; + v23 = (int32_t*)(v3 - 28); + v22 = (int32_t*)(v3 - 24); + v21 = (int32_t*)(v3 - 20); + v20 = (int32_t*)(v3 - 16); + v25 = (int32_t*)(v3 - 12); + v24 = (int32_t*)(v3 - 8); + v26 = v16; + } + else { + // 0x6d0f0b + *v7 = 0; + int32_t v27 = (v15 - v16 >> 4) - 1; // 0x6d0f0d + int32_t* v28 = (int32_t*)(v3 - 8); + *v28 = 0; + int32_t* v29 = (int32_t*)(v3 - 12); + *v29 = v15; + int32_t* v30 = (int32_t*)(v3 - 16); + *v30 = v27; + int32_t* v31 = (int32_t*)(v3 - 20); + *v31 = v16; + sub_6C72F0(&g2, (int32_t)&g2, (int32_t)&g2, (int32_t)&g2, (int32_t)&g2); + int32_t* v32 = (int32_t*)(v3 - 24); + *v32 = v27; + int32_t* v33 = (int32_t*)(v3 - 28); + *v33 = *v8; + sub_6C7440((int32_t)&g2, (int32_t)&g2); + v23 = v33; + v22 = v32; + v21 = v31; + v20 = v30; + v25 = v29; + v24 = v28; + v26 = *v9; + } + // 0x6d0f2e + *v7 = 0; + *v24 = 1; + *v25 = 0; + *v20 = v26; + sub_6C73E0(&g2, (int32_t)&g2, (int32_t)&g2, (int32_t)&g2); + *v21 = v19; + *v22 = *v9; + *v23 = *v18; + int32_t* v34 = sub_6CDFF0((int32_t)&g2, &g2, (int32_t)&g2); // 0x6d0f49 + // 0x6d0f51 + return (uintptr_t)v34; + } + case 2: { + // 0x6d0ee3 + v19 = 15; + // branch (via goto) -> 0x6d0efd + goto lab_0x6d0efd; + } + case 3: { + // 0x6d0eea + v19 = 19; + // branch (via goto) -> 0x6d0efd + goto lab_0x6d0efd; + } + case 4: { + // 0x6d0ef1 + v19 = 22; + // branch (via goto) -> 0x6d0efd + goto lab_0x6d0efd; + } + case 5: { + // 0x6d0ef8 + v19 = 25; + // branch (via goto) -> 0x6d0efd + goto lab_0x6d0efd; + } + default: { + // 0x6d0f51 + return (uintptr_t)v15; + } + } +lab_0x6d0ea8: + // 0x6d0ea8 + v11 = v14 & 0xfffffff; + *v10 = v11; + goto lab_0x6d0e7f; +} + +uintptr_t __cdecl CustomAlolcator::heap_control_something_sub_6D0E30(uint32_t a1) noexcept { + return g_custom_alolcator->heap_control_something_sub_6D0E30_internal(a1); +} + +void* __cdecl CustomAlolcator::sub_65B880(int a1, size_t sz, int a3) { + return malloc(sz + 10_KiB); +} + +void* CustomAlolcator::sub_65B880_internal(int a1, size_t sz, int a3) +{ + return g_custom_alolcator->sub_65B880(a1, sz, a3); +} + +HRESULT CustomAlolcator::d3d_sets_texture_maybe_sub_6E0DF0_internal(Devil3Texture* texture) { + auto original_func = (decltype(CustomAlolcator::d3d_sets_texture_maybe_sub_6E0DF0)*)m_hook_d3d_sets_texture_maybe_sub_6E0DF0->get_original(); + + if (g_skip_textures) { + if (texture->texturePointer) { + texture->texturePointer->Release(); + texture->texturePointer = NULL; + } + return 0x80004005; + } + HRESULT res = original_func(texture); + return res; +} + +HRESULT __fastcall CustomAlolcator::d3d_sets_texture_maybe_sub_6E0DF0(Devil3Texture* texture) { + return g_custom_alolcator->d3d_sets_texture_maybe_sub_6E0DF0_internal(texture); +} + +void CustomAlolcator::on_config_load(const utility::Config& cfg) { + for (IModValue& option : m_options) { + option.config_load(cfg); + } +} + +void CustomAlolcator::on_config_save(utility::Config& cfg) { + for (IModValue& option : m_options) { + option.config_save(cfg); + } +} + +void CustomAlolcator::on_draw_debug_ui() { + + void* base = memory::g_bigass_arena.buf; + size_t size = memory::g_bigass_arena.buf_len; + size_t cursor = memory::g_bigass_arena.curr_offset; + size_t sz_left = size - cursor; + + + ImGui::Text("Memory allocator:\n\tbase=%p\n\tsize=%zu\n\tcursor=%zu\n\tsize_left=%zu\n\t", base, size / 1024, cursor, sz_left / 1024); + + ImGui::Text("texture_num: %zu", g_texture_pointers.size()); + ImGui::Checkbox("skip_textures", &g_skip_textures); + + if (ImGui::TreeNode("texture_list")) { + for (Devil3Texture* texture : g_texture_pointers) { + if (ImGui::TreeNode((void*)texture, "Texture %p", texture)) { + ImGui::InputInt("width", (int*)&texture->width); + ImGui::InputInt("height", (int*)&texture->height); + ImGui::Text("decodeDataPointer: %p", texture->decodeDataPointer); + ImGui::Text("decodeFunctionPointer: %p", texture->decodeFunctionPointer); + ImGui::InputInt("format", (int*)&texture->format); + if (ImGui::TreeNode((void*)texture->texturePointer, "d3dtexture %p", texture->texturePointer)) { + ImGui::Image(texture->texturePointer, ImVec2(texture->width, texture->height)); + ImGui::TreePop(); + } + ImGui::Checkbox("dirty", &texture->dirty); + ImGui::TreePop(); + } + } + ImGui::TreePop(); + } +} // will show up in main window, dump ImGui widgets you want here + void CustomAlolcator::on_draw_ui() { - if (ImGui::CollapsingHeader("Memory Alolcator Adjustments")) { - ImGui::Text("TODOOOOO"); - if (ImGui::Button("Dump memory")) { - DEBUGPlatformWriteEntireFile("g_bigass_arena.ass", g_bigass_arena.buf_len, g_bigass_arena.buf); - } - if (ImGui::Button("Load memory")) { - load_save_state(); - } - } -} \ No newline at end of file + if (ImGui::CollapsingHeader("Memory Alolcator Adjustments")) { + if (ImGui::Button("Dump memory")) { + g_save_state_command = SaveStateCommand::SS_CMD_SAVE; + } + if (ImGui::Button("Load memory")) { + g_save_state_command = SaveStateCommand::SS_CMD_LOAD; + } + } +} diff --git a/src/mods/CustomAlolcator.hpp b/src/mods/CustomAlolcator.hpp index 6b104e4..4338f5c 100644 --- a/src/mods/CustomAlolcator.hpp +++ b/src/mods/CustomAlolcator.hpp @@ -5,73 +5,83 @@ // Created with ReClass.NET 1.2 by KN4CK3R -class SomeMemoryManagerShit -{ +class SomeMemoryManagerShit { public: - class SomeStackFramePointerMaybe* ptr1; //0x0000 - void* ptr2; //0x0004 - uint32_t uint1; //0x0008 - char pad_000C[52]; //0x000C -}; //Size: 0x0040 - -class SomeStackFramePointerMaybe -{ -public: - void* ptr1; //0x0000 - void* ptr2; //0x0004 - void* ptr3; //0x0008 - void* ptr4; //0x000C - uint32_t uint1; //0x0010 - uint32_t uint2; //0x0014 - uint32_t uint3; //0x0018 - uint32_t uint4; //0x001C - void* ptrEnd1; //0x0020 - void* ptrEnd2; //0x0024 - uint32_t uint5; //0x0028 -}; //Size: 0x002C + class SomeStackFramePointerMaybe* ptr1; // 0x0000 + void* ptr2; // 0x0004 + uint32_t uint1; // 0x0008 + char pad_000c[52]; // 0x000C +}; // Size: 0x0040 +class SomeStackFramePointerMaybe { +public: + void* ptr1; // 0x0000 + void* ptr2; // 0x0004 + void* ptr3; // 0x0008 + void* ptr4; // 0x000C + uint32_t uint1; // 0x0010 + uint32_t uint2; // 0x0014 + uint32_t uint3; // 0x0018 + uint32_t uint4; // 0x001C + void* ptr_end1; // 0x0020 + void* ptr_end2; // 0x0024 + uint32_t uint5; // 0x0028 +}; // Size: 0x002C class CustomAlolcator : public Mod { public: - CustomAlolcator() = default; - // mod name string for config - std::string_view get_name() const override { return "CustomAlolcator"; } - // called by m_mods->init() you'd want to override this - std::optional on_initialize() override; - - // Override this things if you want to store values in the config file - //void on_config_load(const utility::Config& cfg) override; - //void on_config_save(utility::Config& cfg) override; - - // on_frame() is called every frame regardless whether the gui shows up. - //void on_frame() override; - // on_draw_ui() is called only when the gui shows up - // you are in the imgui window here. - void on_draw_ui() override; - // on_draw_debug_ui() is called when debug window shows up - //void on_draw_debug_ui() override; - bool mem_patch_applied{ false }; - - std::unique_ptr patch01; - std::unique_ptr patch02; - std::unique_ptr patch03; - std::unique_ptr patch04; - std::unique_ptr patch05; - std::unique_ptr patch06; - std::unique_ptr patch07; - std::unique_ptr patch08; - std::unique_ptr patch09; - std::unique_ptr patch10; - std::unique_ptr patch11; + CustomAlolcator() = default; -protected: - uintptr_t __fastcall sub_6D4580_internal(SomeMemoryManagerShit* p_this, uintptr_t unused, uintptr_t size); - static uintptr_t __fastcall sub_6D4580(SomeMemoryManagerShit* p_this, uintptr_t unused, uintptr_t size); + std::string_view get_name() const override { return "CustomAlolcator"; } + std::optional on_initialize() override; + + void on_config_load(const utility::Config& cfg) override; + void on_config_save(utility::Config& cfg) override; + + // void on_frame() override; + void on_draw_ui() override; + void on_draw_debug_ui() override; + + std::unique_ptr patch01; + std::unique_ptr patch02; + std::unique_ptr patch03; + std::unique_ptr patch04; + std::unique_ptr patch05; + std::unique_ptr patch06; + std::unique_ptr patch07; + std::unique_ptr patch08; + std::unique_ptr patch09; + std::unique_ptr patch10; + std::unique_ptr patch11; + +public: + uintptr_t __fastcall sub_6d4580_internal(SomeMemoryManagerShit* p_this, uintptr_t unused, size_t size) noexcept; + static uintptr_t __fastcall sub_6d4580(SomeMemoryManagerShit* p_this, uintptr_t unused, size_t size) noexcept; + + uintptr_t __cdecl heap_control_something_sub_6D0E30_internal(uint32_t a1) noexcept; + static uintptr_t __cdecl heap_control_something_sub_6D0E30(uint32_t a1) noexcept; + + void* __cdecl sub_65B880(int a1, size_t sz, int a3); + static void* sub_65B880_internal(int a1, size_t sz, int a3); private: - std::unique_ptr m_alloc_hook; - // function hook instance for our detour, convinient wrapper - // around minhook - // std::unique_ptr m_function_hook; + std::unique_ptr m_heap_control_sub_6D0E30_hook; + std::unique_ptr m_sub_65B880_hook; + + std::unique_ptr m_main_sub_00403580_hook; + std::unique_ptr m_d3d9_load_texture_hook_sub_006E0B10; + std::unique_ptr m_hook_d3d_sets_texture_maybe_sub_6E0DF0; + + std::unique_ptr m_scene_loaded_sub_005E02C0; + + std::unique_ptr m_alloc_hook; + const ModToggle::Ptr m_custom_alolcator_enabled { ModToggle::create(generate_name("CustomAlolcatorEnabled")) }; + + ValueList m_options{ + *m_custom_alolcator_enabled + }; +protected: + HRESULT d3d_sets_texture_maybe_sub_6E0DF0_internal(Devil3Texture* texture); + static HRESULT __fastcall d3d_sets_texture_maybe_sub_6E0DF0(Devil3Texture* texture); }; -extern CustomAlolcator* g_custom_alolcator; // NOTE(): WARNING WARNING big global NOT static i repeat NOT STATIC \ No newline at end of file +extern bool g_mem_patch_applied; diff --git a/src/mods/DebugDraw.cpp b/src/mods/DebugDraw.cpp index b616eb0..8dd9794 100644 --- a/src/mods/DebugDraw.cpp +++ b/src/mods/DebugDraw.cpp @@ -12,11 +12,13 @@ bool g_enabled = false; constexpr int STRIDE_MAGIC = 6; +static float g_overlay_opacity = 0.88f; + using Microsoft::WRL::ComPtr; std::optional world_to_screen(const Vector3f& world_pos) { #if 0 - cCameraCtrl* camera = Devil3SDK::get_cam_ctrl(); + cCameraCtrl* camera = devil3_sdk::get_cam_ctrl(); auto& transform = camera->transform; auto right = Vector3f{ transform[0][0], transform[0][1], transform[0][2] }; auto up = Vector3f{ transform[1][0], transform[1][1], transform[1][2] }; @@ -24,7 +26,7 @@ std::optional world_to_screen(const Vector3f& world_pos) { auto origin = Vector3f{ transform[3][0], transform[3][1], transform[3][2] }; auto delta = world_pos - origin; - Vector2f window = Devil3SDK::get_window_dimensions(); + Vector2f window = devil3_sdk::get_window_dimensions(); float z = glm::dot(forward, delta); if (z <= 0.0f) { @@ -45,10 +47,10 @@ std::optional world_to_screen(const Vector3f& world_pos) { return Vector2{ (int)((1.0f + x) * width * 0.5f), (int)((1.0f - y) * height * 0.5f) }; #else - cCameraCtrl* camera = Devil3SDK::get_cam_ctrl(); + cCameraCtrl* camera = devil3_sdk::get_cam_ctrl(); if (!camera || camera == (cCameraCtrl*)-1) { return Vector2{ 0.0f, 0.0f }; }; - Vector2f window = Devil3SDK::get_window_dimensions(); + Vector2f window = devil3_sdk::get_window_dimensions(); float near_plane = 0.1f; //nearest distance from which you can see float far_plane = 100.f; //you cant see more @@ -177,7 +179,7 @@ class RenderInterfaceD3D9 final ImColor( (int)(lines[v].line.r * 255.0f), (int)(lines[v].line.g * 255.0f), - (int)(lines[v].line.b * 255.0f), 64), 0, 0.5f); + (int)(lines[v].line.b * 255.0f), 64), 0, g_overlay_opacity); //draw_list->AddLine(p1, p2, ImColor((int)(lines[v].line.r * 255.0f), (int)(lines[v].line.g * 255.0f), (int)(lines[v].line.b * 255.0f), 64), 0.06f); //draw_list->PathLineTo(p2); @@ -330,7 +332,7 @@ std::optional DebugDraw::on_initialize() { void DebugDraw::custom_imgui_window() { if (!g_enabled) { return; } - CPlDante* pl = Devil3SDK::get_pl_dante(); + CPlDante* pl = devil3_sdk::get_pl_dante(); // keeping capcom traditions of typoing member fields like a motehfckure auto screen = world_to_screen(pl->Poistion); if (!screen.has_value()) { return; } @@ -341,6 +343,14 @@ void DebugDraw::custom_imgui_window() dd::flush(dd_context, ImGui::GetIO().DeltaTime); } +void DebugDraw::on_config_load(const utility::Config& cfg) { + g_overlay_opacity = cfg.get("DebugDrawOverlayOpacity").value_or(0.88f); +} + +void DebugDraw::on_config_save(utility::Config& cfg) { + cfg.set("DebugDrawOverlayOpacity", g_overlay_opacity); +} + // during load //void DebugDraw::on_config_load(const utility::Config &cfg) { // for (IModValue& option : m_options) { @@ -361,8 +371,7 @@ void DebugDraw::custom_imgui_window() void DebugDraw::on_draw_ui() { if (ImGui::CollapsingHeader("Hitspheres")) { ImGui::Checkbox("debug draw hitspheres", &g_enabled); - /*ImGui::Checkbox("g_invert_forward", &g_invert_forward); - ImGui::InputFloat("fov", &g_fov, 0.01f);*/ + ImGui::InputFloat("debug overlay opacity", &g_overlay_opacity, 0.01f); } } diff --git a/src/mods/DebugDraw.hpp b/src/mods/DebugDraw.hpp index 5081b28..8dfafdf 100644 --- a/src/mods/DebugDraw.hpp +++ b/src/mods/DebugDraw.hpp @@ -12,8 +12,8 @@ class DebugDraw : public Mod { void custom_imgui_window(); // Override this things if you want to store values in the config file - //void on_config_load(const utility::Config& cfg) override; - //void on_config_save(utility::Config& cfg) override; + void on_config_load(const utility::Config& cfg) override; + void on_config_save(utility::Config& cfg) override; // on_frame() is called every frame regardless whether the gui shows up. //void on_frame() override; diff --git a/src/mods/EnemySpawnRate.cpp b/src/mods/EnemySpawnRate.cpp index b9745ef..8933c72 100644 --- a/src/mods/EnemySpawnRate.cpp +++ b/src/mods/EnemySpawnRate.cpp @@ -1,11 +1,8 @@ #include "EnemySpawnRate.hpp" +#include - - -#include #include -// clang-format off -// only in clang/icl mode on x64, sorry +#include /* static naked void detour() { __asm { @@ -15,78 +12,161 @@ static naked void detour() { } } */ + +// clang-format off +static uintptr_t collision_handles_hack_jmp_ret{0x0041BD3D}; +static int32_t g_current_collision_handles {0}; +static _declspec(naked) void collision_handles_hack() { + __asm { + // we only get 0x64 collision handles for any level + // store it to check for overflowing this number + // so the game doesnt crash with too much enemies + mov DWORD PTR [g_current_collision_handles], eax + originalCode: + lea edx, [eax + eax * 2] + shl edx, 4 + jmp qword ptr [collision_handles_hack_jmp_ret] + } +} // clang-format on -static EnemySpawnRate* g_spawn_rate_mod{ nullptr }; -static int GUY_MULTIPLIER{ 3 }; + +static EnemySpawnRate* g_spawn_rate_mod{nullptr}; +static int GUY_MULTIPLIER{1}; +static bool LDK_BOSSFIGHTS{false}; +static int BOSS_MULTIPLIER{1}; + std::optional EnemySpawnRate::on_initialize() { - g_spawn_rate_mod = this; - m_spawn_guy_hook = std::make_unique(0x0054ED10, &spawn_a_guy_sub_54ED10); - + g_spawn_rate_mod = this; + m_spawn_guy_hook = std::make_unique(0x0054ED10, &spawn_a_guy_sub_54ED10); + m_collision_handles_hook = std::make_unique(0x0041BD37, &collision_handles_hack); - if (m_spawn_guy_hook->create() ) { - return Mod::on_initialize(); - } - else { - return "Failed to install hook for spawn multiplier"; - } + if (m_spawn_guy_hook->create() && m_collision_handles_hook->create()) { + return Mod::on_initialize(); + } + + return "Failed to install hook for spawn multiplier"; } // during load -//void EnemySpawnRate::on_config_load(const utility::Config &cfg) { +// void EnemySpawnRate::on_config_load(const utility::Config &cfg) { // for (IModValue& option : m_options) { // option.config_load(cfg); // } //} // during save -//void EnemySpawnRate::on_config_save(utility::Config &cfg) { +// void EnemySpawnRate::on_config_save(utility::Config &cfg) { // for (IModValue& option : m_options) { // option.config_save(cfg); // } //} // do something every frame -//void EnemySpawnRate::on_frame() {} +// void EnemySpawnRate::on_frame() {} // will show up in debug window, dump ImGui widgets you want here -//void EnemySpawnRate::on_draw_debug_ui() {} +// void EnemySpawnRate::on_draw_debug_ui() {} // will show up in main window, dump ImGui widgets you want here void EnemySpawnRate::on_draw_ui() { - if (ImGui::CollapsingHeader("bootleg ldk")) { - ImGui::DragInt("multiplier", &GUY_MULTIPLIER, 1, 0, 10); - } + if (ImGui::CollapsingHeader("bootleg LDK")) { + ImGui::DragInt("dudes multiplier", &GUY_MULTIPLIER, 1, 0, 5); + if (ImGui::Checkbox("Legendary DANK knight", &LDK_BOSSFIGHTS)) { + + } + if (LDK_BOSSFIGHTS) { + ImGui::DragInt("bosses multiplier", &BOSS_MULTIPLIER, 1, 0, 5); + } + } } -uintptr_t __fastcall EnemySpawnRate::spawn_a_guy_sub_54ED10_internal(uintptr_t p_this, float* a2, uintptr_t a3) -{ - uintptr_t res = NULL; - for (int32_t i = 0; i < GUY_MULTIPLIER; i++) { - res = m_spawn_guy_hook->get_original()(p_this, a2, a3); - std::this_thread::sleep_for(std::chrono::milliseconds(12)); - if (!res) { - MessageBox(NULL, "spawn_guy returned nullptr", "wew", MB_ICONERROR); - break; - } - } - return res; +void EnemySpawnRate::on_draw_debug_ui() { + ImGui::Text("collision_handles= 0x%x", g_current_collision_handles); +} + +// listing vtables here +static constexpr std::array bugged_enemies { + 0x73E98C, // Giga-Pete | CEm023 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : IComAction : IComActionState + 0x742914, // Clown | CEm037 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : CComAction : IComAction : IComActionState + 0x74072C, // Horse | CEm029 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : CComAction : IComAction : IComActionState + 0x741470, // Clone | CEm031 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : CComAction : IComAction : IComActionState + 0x74182C, // Blob | CEm032 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : CComAction : IComAction : IComActionState + 0x73F268, // Dog | CEm025 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : IComAction : IComActionState +}; + +// nullptr dereferences in collision related logic for enemies below +// or some other weird shit that crashes the game eventually +static constexpr std::array weird_enemies { + uintptr_t(0x73DA90), // Birds | CEm014 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : CComAction : IComAction : IComActionState + uintptr_t(0x73E108), // ChessPiese | CEm017 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : CComAction : IComAction : IComActionState + uintptr_t(0x73E6D0), // ChessKing? | CEm021 : CEm017 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : CComAction : IComAction : IComActionState +}; + +static constexpr std::array boss_enemies { + uintptr_t(0x73FEC8), // Nevan | CEm028 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : CComAction : IComAction : IComActionState + uintptr_t(0x74107c), // Beowulf | CEm028 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : CComAction : IComAction : IComActionState + uintptr_t(0x73f744), // A&R | CEm026 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : CComAction : IComAction : IComActionState + uintptr_t(0x74248C), // Vergil | CEm035 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : IComAction : IComActionState + uintptr_t(0x741e38), // Lady | CEm034 : CNonPlayer : CActor : CWork : IActor : ICollisionHandle : INonPlayer : CCom : ICom : IComAction : IComActionState +}; + +uintptr_t __fastcall EnemySpawnRate::spawn_a_guy_sub_54ED10_internal(uintptr_t p_this, float* a2, uintptr_t a3) { + uintptr_t res = NULL; + res = m_spawn_guy_hook->get_original()(p_this, a2, a3); + int multiplier = GUY_MULTIPLIER; + if (!res) { + return res; + } + uintptr_t vtable_pointer = *(uintptr_t*)res; +#ifndef _NDEBUG + printf("enemy ptr: %" PRIxPTR ", enemy vtable: %" PRIxPTR ";\n", res, vtable_pointer); +#endif // !_NDEBUG + + // check for bugged enemies + for (uintptr_t enemy : bugged_enemies) { + if (vtable_pointer == enemy) { + return res; + } + } + + // only double the weird enemies + for (uintptr_t enemy : weird_enemies) { + if (vtable_pointer == enemy) { + res = m_spawn_guy_hook->get_original()(p_this, a2, a3); + return res; + } + } + + // boss fights mode + for (uintptr_t enemy : boss_enemies) { + if (vtable_pointer == enemy && LDK_BOSSFIGHTS) { + multiplier = BOSS_MULTIPLIER; + } + } + + for (int i = 0; i < multiplier - 1; i++) { + // std::this_thread::sleep_for(std::chrono::milliseconds(12)); + res = m_spawn_guy_hook->get_original()(p_this, a2, a3); + if (!res) { + spdlog::error("[{}] spawn_guy returned nullptr", this->get_name()); + break; + } + } + return res; } static uint64_t mul_and_check_overflow(uint64_t a, uint64_t b) { - uint32_t result = 0; - if ((b > 0 && a <= INT_MAX / b && a >= INT_MIN / b) || - (b == 0) || - (b == -1 && a >= -INT_MAX) || - (b < -1 && a >= INT_MAX / b && a <= INT_MIN / b)) - { - result = a * b; - } - else - { - result = 0xDEADBEEF; - } - return result; + uint32_t result = 0; + if ((b > 0 && a <= INT_MAX / b && a >= INT_MIN / b) || + (b == 0) || + (b == -1 && a >= -INT_MAX) || + (b < -1 && a >= INT_MAX / b && a <= INT_MIN / b)) { + result = a * b; + } else { + result = 0xDEADBEEF; + } + return result; } uintptr_t __fastcall EnemySpawnRate::spawn_a_guy_sub_54ED10(uintptr_t p_this, float* a2, uintptr_t a3) { - return g_spawn_rate_mod->spawn_a_guy_sub_54ED10_internal(p_this, a2, a3); + return g_spawn_rate_mod->spawn_a_guy_sub_54ED10_internal(p_this, a2, a3); } #if 0 diff --git a/src/mods/EnemySpawnRate.hpp b/src/mods/EnemySpawnRate.hpp index c7ef60b..e440f64 100644 --- a/src/mods/EnemySpawnRate.hpp +++ b/src/mods/EnemySpawnRate.hpp @@ -32,13 +32,14 @@ class EnemySpawnRate : public Mod { // you are in the imgui window here. void on_draw_ui() override; // on_draw_debug_ui() is called when debug window shows up - //void on_draw_debug_ui() override; + void on_draw_debug_ui() override; protected: uintptr_t __fastcall spawn_a_guy_sub_54ED10_internal(uintptr_t p_this, float* a2, uintptr_t a3); static uintptr_t __fastcall spawn_a_guy_sub_54ED10(uintptr_t p_this, float* a2, uintptr_t a3); private: std::unique_ptr m_spawn_guy_hook; + std::unique_ptr m_collision_handles_hook; // function hook instance for our detour, convinient wrapper // around minhook // std::unique_ptr m_function_hook; diff --git a/src/mods/EnemyStates.cpp b/src/mods/EnemyStates.cpp index 8c1c95f..bb35146 100644 --- a/src/mods/EnemyStates.cpp +++ b/src/mods/EnemyStates.cpp @@ -193,7 +193,7 @@ void EnemyStates::on_draw_ui() { // do something every frame void EnemyStates::on_frame() { if (hotkey_enabled) { - // uint16_t input = Devil3SDK::get_buttons_pressed(); + // uint16_t input = devil3_sdk::get_buttons_pressed(); // uint8_t inputByte1 = *(uint8_t*)0x01C8EFF4; // uint8_t inputByte2 = *(uint8_t*)0x01C8EFF5; // if (input != g_prev_input && input) { diff --git a/src/mods/InertiaThings.cpp b/src/mods/InertiaThings.cpp index 2005699..82d3903 100644 --- a/src/mods/InertiaThings.cpp +++ b/src/mods/InertiaThings.cpp @@ -100,7 +100,7 @@ std::optional InertiaThings::on_initialize() { } static void debug_log_anim(const char* function) { - short cur_anim = Devil3SDK::pl_dante_get_human_anim_table()->current_anim; + short cur_anim = devil3_sdk::pl_dante_get_human_anim_table()->current_anim; printf("[%s] have this current_anim:(%d)\n", function, cur_anim); } @@ -135,7 +135,7 @@ void InertiaThings::on_draw_ui() { ImGui::Checkbox("Show debug stats", &m_stats); if (m_stats) { ImGui::Text("cached_vel: %f", chached_velocity); - CPlDante* c_pl_dante = Devil3SDK::get_pl_dante(); + CPlDante* c_pl_dante = devil3_sdk::get_pl_dante(); if (c_pl_dante) { ImGui::Text("Player data:"); @@ -150,7 +150,7 @@ void InertiaThings::on_draw_ui() { ImGui::Text("someOtherdirection: %d", c_pl_dante->someOtherDirection); } - auto human_atbl = Devil3SDK::pl_dante_get_human_anim_table(); + auto human_atbl = devil3_sdk::pl_dante_get_human_anim_table(); ImGui::Text("Animation data:"); ImGui::Text("current_anim: %d", human_atbl->current_anim); ImGui::Text("bank_id: %d", human_atbl->bank_id); @@ -160,7 +160,7 @@ void InertiaThings::on_draw_ui() { ImGui::Text("anim_frame: %f", human_atbl->anim_frame); ImGui::Text("loop_point: %f", human_atbl->loop_point); - auto dt1_atbl = Devil3SDK::pl_dante_get_dt1_anim_table(); + auto dt1_atbl = devil3_sdk::pl_dante_get_dt1_anim_table(); ImGui::Text("DT1 Animation data:"); ImGui::Text("bank_id: %d", dt1_atbl->bank_id); ImGui::Text("motion: %d", dt1_atbl->motion_id); @@ -169,7 +169,7 @@ void InertiaThings::on_draw_ui() { ImGui::Text("anim_frame: %f", dt1_atbl->anim_frame); ImGui::Text("loop_point: %f", dt1_atbl->loop_point); - auto dt2_atbl = Devil3SDK::pl_dante_get_dt2_anim_table(); + auto dt2_atbl = devil3_sdk::pl_dante_get_dt2_anim_table(); ImGui::Text("DT2 Animation data:"); ImGui::Text("bank_id: %d", dt2_atbl->bank_id); ImGui::Text("motion: %d", dt2_atbl->motion_id); @@ -217,16 +217,16 @@ void __fastcall InertiaThings::plr_veloicty_set_sub_5A6210_internal(CPlDante * p _set_velocity orig_fn = (_set_velocity)m_vel_set_hook->get_original(); orig_fn(p_this, vel_m, vel_d); - if (!Devil3SDK::pl_dante_is_grounded() || !Devil3SDK::pl_dante_is_air()) { + if (!devil3_sdk::pl_dante_is_grounded() || !devil3_sdk::pl_dante_is_air()) { chached_velocity = 0.0f; return; } auto predicate = [](MOTION_ID id) { - return Devil3SDK::pl_dante_check_animation_id(id); + return devil3_sdk::pl_dante_check_animation_id(id); }; - if (Devil3SDK::pl_dante_check_animation_id(MOTION_ID::AIR_HIKE)) { + if (devil3_sdk::pl_dante_check_animation_id(MOTION_ID::AIR_HIKE)) { if (p_this->momentumMagnitude > 0.01f) { chached_velocity = p_this->momentumMagnitude; } @@ -247,7 +247,7 @@ void __fastcall InertiaThings::plr_veloicty_set_sub_5A6210_internal(CPlDante * p #endif check = std::any_of(m_moves_dont_touch.begin(), m_moves_dont_touch.end(), predicate); - if (check || Devil3SDK::pl_dante_is_air()) { return; } + if (check || devil3_sdk::pl_dante_is_air()) { return; } /*auto predicate = [](MOTION_ID id) { return id == uass.current_anim; }; const bool check = std::any_of(m_moves_dont_touch.begin(), m_moves_dont_touch.end(), predicate); @@ -281,7 +281,7 @@ void __fastcall InertiaThings::plr_velocity_zero_sub_5A6230_internal(CPlDante * };*/ auto predicate = [](MOTION_ID id) { - return Devil3SDK::pl_dante_check_animation_id(id); + return devil3_sdk::pl_dante_check_animation_id(id); }; const bool check = std::any_of(m_moves_should_zero.begin(), m_moves_should_zero.end(), predicate); @@ -313,8 +313,8 @@ void __fastcall InertiaThings::plr_velocity_lookup_table_something_sub_5A4CB0_in debug_log_anim(__FUNCTION__); #endif - auto predicate = [](MOTION_ID id) { return Devil3SDK::pl_dante_check_animation_id(id); }; - if (Devil3SDK::pl_dante_check_animation_id(MOTION_ID::AIR_HIKE)) { + auto predicate = [](MOTION_ID id) { return devil3_sdk::pl_dante_check_animation_id(id); }; + if (devil3_sdk::pl_dante_check_animation_id(MOTION_ID::AIR_HIKE)) { if (chached_velocity > 0.01f) { chached_velocity = p_this->momentumMagnitude; } diff --git a/src/mods/InputLog.cpp b/src/mods/InputLog.cpp index eb61e2f..25e6b6b 100644 --- a/src/mods/InputLog.cpp +++ b/src/mods/InputLog.cpp @@ -102,7 +102,7 @@ void InputLog::on_config_save(utility::Config &cfg) { void InputLog::on_frame() { if (!m_enabled->value()) { return; } - uint16_t input = Devil3SDK::get_buttons_pressed(); + uint16_t input = devil3_sdk::get_buttons_pressed(); if (input != g_prev_input && input) { diff --git a/src/mods/PracticeMode.cpp b/src/mods/PracticeMode.cpp index 0db43d7..4149e59 100644 --- a/src/mods/PracticeMode.cpp +++ b/src/mods/PracticeMode.cpp @@ -147,7 +147,7 @@ void PracticeMode::on_frame() { if (!(m_always_launch_tgl->value())) { g_should_launch = 0; return; } - /*bool ground = Devil3SDK::pl_dante_is_grounded();*/ + /*bool ground = devil3_sdk::pl_dante_is_grounded();*/ g_should_launch = !(*g_char_state_ptr == 11 || *g_char_state_ptr == 13); } // will show up in debug window, dump ImGui widgets you want here @@ -158,9 +158,9 @@ void PracticeMode::on_draw_ui() { return; } m_always_launch_tgl->draw("DMD always launch when on ground"); ImGui::SameLine(); - ShowHelpMarker("Always launch enemies when you are standing on the ground to practice air DMD combos"); + show_help_marker("Always launch enemies when you are standing on the ground to practice air DMD combos"); m_overlay_enabled->draw("Enable practice overlay"); ImGui::SameLine(); - ShowHelpMarker("Move overlay window into your prefered location by dragging"); + show_help_marker("Move overlay window into your prefered location by dragging"); } /* diff --git a/src/mods/PrintfDebugging.cpp b/src/mods/PrintfDebugging.cpp index 3b060e6..c85a12e 100644 --- a/src/mods/PrintfDebugging.cpp +++ b/src/mods/PrintfDebugging.cpp @@ -22,7 +22,7 @@ static __declspec(naked) void log_detour1() { std::optional PrintfDebugging::on_initialize() { // uintptr_t base = g_framework->get_module().as(); //TODO(): wip -#if 0 +#if 1 if (!install_hook_absolute(0x004023CF, m_debug_log_hook1, &log_detour1, &g_log_printf1, 5)) { spdlog::error("[{}] failed to initialize", get_name()); return "Failed to initialize PrintfDebugging"; diff --git a/src/mods/RgTimer.cpp b/src/mods/RgTimer.cpp index df7ed40..183c6b4 100644 --- a/src/mods/RgTimer.cpp +++ b/src/mods/RgTimer.cpp @@ -30,7 +30,7 @@ static bool g_show_releases = false; static bool g_show_rg_window = false; static void my_rg_release_callback() { - static CPlDante* pl = Devil3SDK::get_pl_dante(); + static CPlDante* pl = devil3_sdk::get_pl_dante(); g_dif = pl->release_timer / 1.20f; g_release_lock = 8; } @@ -111,7 +111,7 @@ float inverse_smoothstep(float x) { static float g_release_timer_back = 0.0f; void RgTimer::on_frame() { - static CPlDante* pl = Devil3SDK::get_pl_dante(); + static CPlDante* pl = devil3_sdk::get_pl_dante(); if (*(uint32_t*)pl == 0x744D38) { g_pl_block_timer = pl->block_timer; //printf("[%d] release_timer=%f\n", g_frame, pl->release_timer); @@ -282,7 +282,7 @@ void RgTimer::custom_imgui_window() { ImGui::PopID(); } #endif - static CPlDante* pl = Devil3SDK::get_pl_dante(); + static CPlDante* pl = devil3_sdk::get_pl_dante(); ImGui::Text("difference guard: %d frames", g_guard_frame - g_input_guard_frame); ImGui::Text("difference release: %f frames", g_dif); @@ -295,7 +295,7 @@ void RgTimer::custom_imgui_window() { ImGui::Checkbox("Show releases on timeline", &g_show_releases); #if 0 - static CPlDante* pl = Devil3SDK::get_pl_dante(); + static CPlDante* pl = devil3_sdk::get_pl_dante(); ImGui::Text("pl_release_timer: %f", pl->release_timer); ImGui::Text("g_dif %f", g_dif); ImGui::Text("g_release_lock %d", g_release_lock); diff --git a/src/mods/SimpleMod.cpp b/src/mods/SimpleMod.cpp index d6308ee..da5468b 100644 --- a/src/mods/SimpleMod.cpp +++ b/src/mods/SimpleMod.cpp @@ -43,7 +43,7 @@ void SimpleMod::on_draw_ui() { if (ImGui::Button("SimpleMod Button")) { int a1 = wew(03, vfx_index, 0, 8); if (a1) { - CPlDante* pl = (CPlDante*)0x01C8A600; + CPlDante* pl = devil3_sdk::get_pl_dante(); int a2 = wew2(pl); int colorama = ImGui::ColorConvertFloat4ToU32(ImVec4(col[0], col[1],col[2],col[3])); __asm { diff --git a/src/mods/StyleSwitchFX.cpp b/src/mods/StyleSwitchFX.cpp index 5d8357b..2b83c09 100644 --- a/src/mods/StyleSwitchFX.cpp +++ b/src/mods/StyleSwitchFX.cpp @@ -2,11 +2,19 @@ #include "utility/Scan.hpp" #include "utility/Compressed.hpp" #include "../Sfx.cpp" +#include "d3dx9.h" -static CPlDante* g_char_ptr = nullptr; -static cCameraCtrl* g_cam_ptr = nullptr; +static CPlDante* g_char_ptr = nullptr; +static cCameraCtrl* g_cam_ptr = nullptr; +static Devil3Texture* g_texture = nullptr; +static IDirect3DTexture9* g_texture_original = nullptr; + +std::mutex g_style_switch_mutex {}; + +static constexpr void* GET_PL_DANTE_TEXTURE_DECODE() { + return (void*)0x024F9640; +} -#pragma comment(lib, "Winmm.lib") #ifdef SND_HACK #define SND_CREATE_VOX(name) VoxObj* name() typedef SND_CREATE_VOX(snd_create_vox); @@ -25,8 +33,39 @@ static int prev_style; static int* current_style = (int*)0xB6B220; static bool g_enable_mod; static bool g_enable_sound; +static bool g_enable_textures; +static bool g_textures_not_found{false}; static uintptr_t detour_jmpback; +struct SfxPreset { + const char* name; + int16_t a1,a2; + int a3 = 7; +}; + +static std::array sfx_presets = { + SfxPreset { "Electricity SFX", 0, 63, 0 }, + SfxPreset { "CLANG", 0, 75, 0 }, + SfxPreset { "Crazy Combo start SFX", 0, 80, 0 }, + SfxPreset { "Enemy DT SFX", 0, 90, 0 }, + SfxPreset { "Player DT start SFX", 1, 80, 0 }, + //SfxPreset { "Custom", -1, -1, -1 } +}; + +static SfxPreset g_sfx_preset = sfx_presets[0]; + +struct VfxPreset { + const char* name; + uint8_t id; + int bank, a3; +}; + +std::array vfx_presets = { + VfxPreset { "Crazy Combo fx", 144, 3, 8 }, + VfxPreset { "Circly thing fx", 218, 3, 8 }, + VfxPreset { "DT fx", 0xDC, 3, 8 }, +}; + enum DANTE_STYLES { SWORDMASTER, GUNSLINGER, TRICKSTER, ROYALGUARD, QUICKSILVER, GERMANWORD, STYLE_MAX }; @@ -53,6 +92,8 @@ static std::array g_style_colors{ glm::vec4(0.941f, 0.065f, 0.658, 1.0f), // german word }; +static std::array g_style_textures {}; + static void play_effect(int style) { typedef int(__cdecl* cEffectBase_sub_67FE80)(char a1, int a2, int *a3, int a4); static cEffectBase_sub_67FE80 c_efb_1 = (cEffectBase_sub_67FE80)0x67FE80; @@ -63,7 +104,7 @@ static void play_effect(int style) { //int* current_style = (int*)0xB6B220; int a1 = c_efb_1(g_vfx_bank, g_vfx_id, 0, g_vfx_a3); if (a1) { - CPlDante* pl = (CPlDante*)0x01C8A600; + CPlDante* pl = (CPlDante*)g_char_ptr; int a2 = c_efb_2(pl); int colorama = ImGui::ColorConvertFloat4ToU32(g_style_colors[style]); __asm { @@ -105,115 +146,277 @@ static __declspec(naked) void detour() { // clang-format on #endif +void style_switch_efx_clear_textures() { + if(!g_enable_textures) {return;} + auto device = g_framework->get_d3d9_device(); + HRESULT hr{}; + for (IDirect3DTexture9* texture : g_style_textures) { + if (texture) { + texture->Release(); + texture = nullptr; + } + } + if (g_texture_original) { + g_texture_original->Release(); + g_texture_original = nullptr; + } + if(g_texture) { + g_texture = nullptr; + } +} + +void style_switch_efx_load_textures() { + if(!g_enable_textures) {return;} + auto device = g_framework->get_d3d9_device(); + HRESULT hr{}; + hr = D3DXCreateTextureFromFileA(device, "native\\texture\\SM.dds", &g_style_textures[SWORDMASTER]); + assert(SUCCEEDED(hr)); + if(FAILED(hr)) { + g_enable_textures = false; + g_textures_not_found = true; + } + hr = D3DXCreateTextureFromFileA(device, "native\\texture\\TS.dds", &g_style_textures[TRICKSTER]); + assert(SUCCEEDED(hr)); + hr = D3DXCreateTextureFromFileA(device, "native\\texture\\GS.dds", &g_style_textures[GUNSLINGER]); + assert(SUCCEEDED(hr)); + hr = D3DXCreateTextureFromFileA(device, "native\\texture\\RG.dds", &g_style_textures[ROYALGUARD]); + assert(SUCCEEDED(hr)); + hr = D3DXCreateTextureFromFileA(device, "native\\texture\\QS.dds", &g_style_textures[QUICKSILVER]); + assert(SUCCEEDED(hr)); + hr = D3DXCreateTextureFromFileA(device, "native\\texture\\DG.dds", &g_style_textures[GERMANWORD]); + assert(SUCCEEDED(hr)); +} + std::optional StyleSwitchFX::on_initialize() { - // TODOOOOO(important): add soloud audio - g_char_ptr = (CPlDante*)0x1C8A600; - //g_cam_ptr = (CCameraCtrl*)0x01371978; + // TODOOOOO(important): add soloud audio + // g_char_ptr = (CPlDante*)0x1C8A600; + g_char_ptr = devil3_sdk::get_pl_dante(); + srand(time(0)); + // g_cam_ptr = (CCameraCtrl*)0x01371978; + + // m_sound_file_mem = utility::DecompressFileFromMemory(sfx_compressed_data,sfx_compressed_size); - //m_sound_file_mem = utility::DecompressFileFromMemory(sfx_compressed_data,sfx_compressed_size); - #ifdef SND_TODO - HMODULE snd = GetModuleHandle("snd.drv"); - if (!snd) { - spdlog::info("[StyleSwitchFX]: snd.drv not found\n"); - printf("[StyleSwitchFX]: snd.drv not found\n"); - return Mod::on_initialize(); - } - FARPROC snd_proc = GetProcAddress(snd, "IsSndDrvSexy"); - if (!snd_proc) { - spdlog::info("[StyleSwitchFX]: not using custom snd.drv\n"); - printf("[StyleSwitchFX]: not using custom snd.drv\n"); - return Mod::on_initialize(); - } + HMODULE snd = GetModuleHandle("snd.drv"); + if (!snd) { + spdlog::info("[StyleSwitchFX]: snd.drv not found\n"); + printf("[StyleSwitchFX]: snd.drv not found\n"); + return Mod::on_initialize(); + } + FARPROC snd_proc = GetProcAddress(snd, "IsSndDrvSexy"); + if (!snd_proc) { + spdlog::info("[StyleSwitchFX]: not using custom snd.drv\n"); + printf("[StyleSwitchFX]: not using custom snd.drv\n"); + return Mod::on_initialize(); + } - SndCreateVox = (snd_create_vox *)GetProcAddress(snd, "CreateVox"); - if (!SndCreateVox) { - spdlog::info("[StyleSwitchFX]: could not GetProcAddress of CreateVox. this should not happen\n"); - printf("[StyleSwitchFX]: could not GetProcAddress of CreateVox. this should not happen\n"); - return Mod::on_initialize(); - } - m_vox = SndCreateVox(); - if (m_vox) { - spdlog::info("Got VoxObj from snd.drv! Nice\n"); - printf("Got VoxObj from snd.drv! Nice\n"); - } + SndCreateVox = (snd_create_vox*)GetProcAddress(snd, "CreateVox"); + if (!SndCreateVox) { + spdlog::info("[StyleSwitchFX]: could not GetProcAddress of CreateVox. this should not happen\n"); + printf("[StyleSwitchFX]: could not GetProcAddress of CreateVox. this should not happen\n"); + return Mod::on_initialize(); + } + m_vox = SndCreateVox(); + if (m_vox) { + spdlog::info("Got VoxObj from snd.drv! Nice\n"); + printf("Got VoxObj from snd.drv! Nice\n"); + } +#endif +#if 0 + auto decompressed = utility::DecompressFileFromMemoryWithSize(sfx_compressed_data, sfx_compressed_size); + m_sound_file_mem = std::get<0>(decompressed); + m_sound_file_mem_size = std::get<1>(decompressed); #endif - auto decompressed= utility::DecompressFileFromMemoryWithSize(sfx_compressed_data,sfx_compressed_size); - m_sound_file_mem = std::get<0>(decompressed); - m_sound_file_mem_size = std::get<1>(decompressed); #ifdef SND_TODO - m_vox->load_mem((unsigned char*)m_sound_file_mem, m_sound_file_mem_size); - m_vox->set_volume(1.0f); + m_vox->load_mem((unsigned char*)m_sound_file_mem, m_sound_file_mem_size); + m_vox->set_volume(1.0f); #endif - return Mod::on_initialize(); + style_switch_efx_load_textures(); + return Mod::on_initialize(); } // during load -void StyleSwitchFX::on_config_load(const utility::Config &cfg) { - g_enable_mod = cfg.get("StyleSwitchFXenabled").value_or(false); - g_enable_sound = cfg.get("StyleSwitchSoundEnabled").value_or(false); - - for (int i = 0; i < DANTE_STYLES::STYLE_MAX; i++) { - g_style_colors[i] = cfg.get(g_style_names[i]).value_or(g_default_colors[i]); - } +void StyleSwitchFX::on_config_load(const utility::Config& cfg) { + g_enable_mod = cfg.get("StyleSwitchFXenabled").value_or(false); + g_enable_sound = cfg.get("StyleSwitchSoundEnabled").value_or(false); + g_enable_textures = cfg.get("StyleSwitchTexturesEnabled").value_or(false); + + g_vfx_id = cfg.get("StyleSwitchVfxId").value_or(218); + g_vfx_bank = cfg.get("StyleSwitchVfxBank").value_or(3); + g_vfx_a3 = cfg.get("StyleSwitchVfxIdk").value_or(8); + + g_sfx_preset.a1 = cfg.get("StyleSwitchSfxBank").value_or(0); + g_sfx_preset.a2 = cfg.get("StyleSwitchSfxId").value_or(63); + g_sfx_preset.a3 = cfg.get("StyleSwitchSfxIdk").value_or(0); + + for (int i = 0; i < DANTE_STYLES::STYLE_MAX; i++) { + g_style_colors[i] = cfg.get(g_style_names[i]).value_or(g_default_colors[i]); + } } + // during save -void StyleSwitchFX::on_config_save(utility::Config &cfg) { - cfg.set("StyleSwitchFXenabled", g_enable_mod); - cfg.set("StyleSwitchSoundEnabled", g_enable_sound); +void StyleSwitchFX::on_config_save(utility::Config& cfg) { + cfg.set("StyleSwitchFXenabled", g_enable_mod); + cfg.set("StyleSwitchSoundEnabled", g_enable_sound); + cfg.set("StyleSwitchTexturesEnabled", g_enable_textures); - for (int i = 0; i < DANTE_STYLES::STYLE_MAX; i++) { - cfg.set(g_style_names[i], g_style_colors[i]); - } + cfg.set("StyleSwitchVfxId", g_vfx_id); + cfg.set("StyleSwitchVfxBank", g_vfx_bank); + cfg.set("StyleSwitchVfxIdk", g_vfx_a3); + + cfg.set("StyleSwitchSfxId", g_sfx_preset.a1); + cfg.set("StyleSwitchSfxBank", g_sfx_preset.a2); + cfg.set ("StyleSwitchSfxIdk", g_sfx_preset.a3); + + for (int i = 0; i < DANTE_STYLES::STYLE_MAX; i++) { + cfg.set(g_style_names[i], g_style_colors[i]); + } } // do something every frame void StyleSwitchFX::on_frame() { - if (!g_enable_mod) { return; } - if ((g_char_ptr->pad_0000) != 0x744D38) { return; } - if (*current_style != prev_style) { - play_effect(*current_style); - play_sound(); - prev_style = *current_style; - } + if (!g_enable_mod) { + return; + } + if ((g_char_ptr->pad_0000) != 0x744D38) { + g_texture = nullptr; + return; + } + if (*current_style != prev_style) { + if (g_vfx_id == 218) { + g_vfx_a3 = 1; + play_effect(*current_style); + g_vfx_a3 = 2; + play_effect(*current_style); + } + else { + play_effect(*current_style); + } + play_sound(); + change_texture(*current_style); + prev_style = *current_style; + } +} + +static int16_t safe_truncate_to_int16(int value) { + if (value >= std::numeric_limits::min() && value <= std::numeric_limits::max()) { + return static_cast(value); + } else { + // Handle overflow/underflow + if (value > std::numeric_limits::max()) { + return std::numeric_limits::max(); + } else { + return std::numeric_limits::min(); + } + } } + // will show up in debug window, dump ImGui widgets you want here -//void StyleSwitchFX::on_draw_debug_ui() {} +// void StyleSwitchFX::on_draw_debug_ui() {} void StyleSwitchFX::on_draw_ui() { - if (!ImGui::CollapsingHeader(get_name().data())) { - return; - } - ImGui::InputInt("g_vfx_id", &g_vfx_id); - ImGui::InputInt("g_vfx_bank", &g_vfx_bank); - ImGui::InputInt("g_vfx_a3", &g_vfx_a3); + if (!ImGui::CollapsingHeader(get_name().data())) { + return; + } + + ImGui::Checkbox("Enable style switch effects", &g_enable_mod); + if (g_enable_mod) { + + int item_current_idx = 0; + static int selected_combobox_index = 0; + if (ImGui::BeginCombo("VFX preset", vfx_presets[selected_combobox_index].name)) { + for (size_t i = 0; i < vfx_presets.size(); i++) { + const bool is_selected = (item_current_idx == i); + + if (ImGui::Selectable(vfx_presets[i].name, is_selected)) { + item_current_idx = i; + selected_combobox_index = i; + g_vfx_id = vfx_presets[i].id; + g_vfx_bank = vfx_presets[i].bank; + g_vfx_a3 = vfx_presets[i].a3; + } + if (is_selected) { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndCombo(); + } + ImGui::InputInt("g_vfx_id", &g_vfx_id); + ImGui::InputInt("g_vfx_bank", &g_vfx_bank); + ImGui::InputInt("g_vfx_a3", &g_vfx_a3); + } + + ImGui::Checkbox("Enable sound effect", &g_enable_sound); + if (g_enable_sound) { + int item_current_idx = 0; + static int selected_combobox_index = 0; + if (ImGui::BeginCombo("SFX preset", sfx_presets[selected_combobox_index].name)) { + for (size_t i = 0; i < sfx_presets.size(); i++) { + const bool is_selected = (item_current_idx == i); - ImGui::Checkbox("Enable style switch effects", &g_enable_mod); - - ImGui::Checkbox("Enable sound effect", &g_enable_sound); + if (ImGui::Selectable(sfx_presets[i].name, is_selected)) { + item_current_idx = i; + g_sfx_preset.name = sfx_presets[i].name; + g_sfx_preset.a1 = sfx_presets[i].a1; + g_sfx_preset.a2 = sfx_presets[i].a2; + g_sfx_preset.a3 = sfx_presets[i].a3; + } + if (is_selected) { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndCombo(); + } + int pa1 = g_sfx_preset.a1; + int pa2 = g_sfx_preset.a2; + + if (ImGui::InputInt("sfx bank", &pa1)) { + g_sfx_preset.a1 = safe_truncate_to_int16(pa1); + } + if (ImGui::InputInt("sfx id", &pa2)) { + g_sfx_preset.a2 = safe_truncate_to_int16(pa2); + } + ImGui::InputInt("idk", &g_sfx_preset.a3); + ImGui::SameLine(); + + if (ImGui::Button("test play sound")) { + devil3_sdk::play_sound(g_sfx_preset.a1, g_sfx_preset.a2, g_sfx_preset.a3); + } + } + + if (g_textures_not_found) { + ImGui::Text("Could not load coat textures from DMC3_ROOT\\native\\texture"); + ImGui::Text("Check for permission errors if the files are there, or something idk"); + } + else { + ImGui::Checkbox("Change coat color along with style", &g_enable_textures); + } #if SND_TODO - if (m_vox != nullptr) { - static float snd_volume = 1.0f; - if (ImGui::DragFloat("Audio volume", &snd_volume,0.1f,0.0f,10.0f)) { - snd_volume = glm::clamp(snd_volume, 0.0f, 10.0f); - m_vox->set_volume(snd_volume); - } - ImGui::Checkbox("3D audio effects", &m_3d_audio); - } + if (m_vox != nullptr) { + static float snd_volume = 1.0f; + if (ImGui::DragFloat("Audio volume", &snd_volume, 0.1f, 0.0f, 10.0f)) { + snd_volume = glm::clamp(snd_volume, 0.0f, 10.0f); + m_vox->set_volume(snd_volume); + } + ImGui::Checkbox("3D audio effects", &m_3d_audio); + } #endif - - ImGui::Text("Customize style colors"); - for (int i = 0; i < STYLE_MAX; i++) { - ImGui::ColorEdit3(g_style_names[i], (float*)&g_style_colors[i]); - } + ImGui::Text("Customize style colors"); + + for (int i = 0; i < STYLE_MAX; i++) { + ImGui::ColorEdit3(g_style_names[i], (float*)&g_style_colors[i]); + } } void StyleSwitchFX::play_sound() { if (!g_enable_sound) { return; } + + devil3_sdk::play_sound(g_sfx_preset.a1, g_sfx_preset.a2, rand() % 3); + #if SND_TODO if (m_vox) { - cCameraCtrl* camera = Devil3SDK::get_cam_ctrl(); + cCameraCtrl* camera = devil3_sdk::get_cam_ctrl(); if (!camera || camera == (cCameraCtrl*)-1) { return; }; g_cam_ptr = camera; //glm::vec3 at = g_char_ptr->Poistion - g_cam_ptr->pos; @@ -235,8 +438,37 @@ void StyleSwitchFX::play_sound() } else { #endif - PlaySound((LPCSTR)m_sound_file_mem, NULL, SND_MEMORY | SND_ASYNC); + //PlaySound((LPCSTR)m_sound_file_mem, NULL, SND_MEMORY | SND_ASYNC); #ifdef SND_TODO } #endif } + +void StyleSwitchFX::change_texture(int style) { + // const std::lock_guard lock(g_style_switch_mutex); + if (g_textures_not_found) { + return; + } + if (!g_enable_textures) { + return; + } + if (!g_texture) { + + TextureTableEntry* tex_entry = (TextureTableEntry*)0x252F750; + while (tex_entry->ptrD3Texture != NULL) { + if (tex_entry->ptrD3Texture->decodeDataPointer == GET_PL_DANTE_TEXTURE_DECODE() && tex_entry->ptrD3Texture->texturePointer) { + g_texture = tex_entry->ptrD3Texture; + g_texture_original = g_texture->texturePointer; + break; + } + tex_entry++; + } + } + if (!g_texture) { + return; + } + + while (InterlockedCompareExchange((volatile unsigned int*)&g_texture->texturePointer, (unsigned int)g_style_textures[style], (unsigned int)g_texture->texturePointer) != (unsigned int)g_style_textures[style]) { + } + // tp->Release(); +} diff --git a/src/mods/StyleSwitchFX.hpp b/src/mods/StyleSwitchFX.hpp index ef908bb..cdcecfb 100644 --- a/src/mods/StyleSwitchFX.hpp +++ b/src/mods/StyleSwitchFX.hpp @@ -33,6 +33,11 @@ class StyleSwitchFX : public Mod { void* m_sound_file_mem; unsigned int m_sound_file_mem_size; void play_sound(); + void change_texture(int style); //VoxObj* //m_vox = nullptr; //bool m_3d_audio = false; -}; \ No newline at end of file +}; + +extern std::mutex g_style_switch_mutex; +void style_switch_efx_clear_textures(); +void style_switch_efx_load_textures(); diff --git a/src/sdk/Devil3.cpp b/src/sdk/Devil3.cpp index 07214be..48d5473 100644 --- a/src/sdk/Devil3.cpp +++ b/src/sdk/Devil3.cpp @@ -1,89 +1,215 @@ #include "Devil3.hpp" +#include "mods/CustomAlolcator.hpp" +#if 0 struct dante_anim_table { - CCharTableMgrPart* human = (CCharTableMgrPart*)0x01C8E7D8; - CCharTableMgrPart* dt1 = (CCharTableMgrPart*)0x01C8EB18; - CCharTableMgrPart* dt2 = (CCharTableMgrPart*)0x01C8EA48; + CCharTableMgrPart* human = (CCharTableMgrPart*)0x41D8; // 0x01C8E7D8; + CCharTableMgrPart* dt1 = (CCharTableMgrPart*)0x4518; // 0x01C8EB18; + CCharTableMgrPart* dt2 = (CCharTableMgrPart*)0x4448; // 0x01C8EA48; }; static dante_anim_table g_dante_table; -uint16_t Devil3SDK::get_buttons_pressed() { - uint16_t* ptr = (uint16_t*)0x01C8EFF4; - return *ptr; +uint16_t devil3_sdk::get_buttons_pressed() { + uint16_t* ptr = (uint16_t*)0x01C8EFF4; + return *ptr; } -CPlDante* Devil3SDK::get_pl_dante() { - return (CPlDante*)0x1C8A600; +CPlDante* devil3_sdk::get_pl_dante() { + if (g_mem_patch_applied) { + return (CPlDante*)0x04557540; + } + return (CPlDante*)0x1C8A600; } -cCameraCtrl* Devil3SDK::get_cam_ctrl() { - static cCameraCtrl** camera_ptr_ptr = (cCameraCtrl**)0x00B6BAAC; - return *camera_ptr_ptr; +cCameraCtrl* devil3_sdk::get_cam_ctrl() { + static cCameraCtrl** camera_ptr_ptr = (cCameraCtrl**)0x00B6BAAC; + return *camera_ptr_ptr; } -Vector2f Devil3SDK::get_window_dimensions() { - return Vector2f{ *(float*)0x00832914, *(float*)0x00832918}; +Vector2f devil3_sdk::get_window_dimensions() { + return Vector2f{*(float*)0x00832914, *(float*)0x00832918}; } -const int Devil3SDK::get_pl_dante_style() -{ - static int* current_style = (int*)0xB6B220; - return *current_style; + +const int devil3_sdk::get_pl_dante_style() { + static int* current_style = (int*)0xB6B220; + return *current_style; } -const char Devil3SDK::get_pl_state() -{ - static char* pl_state = (char*)0x01C8EDDE; - return *pl_state; +const char devil3_sdk::get_pl_state() { + static char* pl_state = (char*)((uintptr_t)get_pl_dante() + (ptrdiff_t)0x47DE); + return *pl_state; } -const bool Devil3SDK::pl_dante_is_air() { - static char* air = (char*)0x01C8A673; - return *air != 0; +const bool devil3_sdk::pl_dante_is_air() { + static char* air = (char*)((uintptr_t)get_pl_dante() + (ptrdiff_t)0x73); + //static char* air = (char*)0x01C8A673; + return *air != 0; } -const bool Devil3SDK::pl_dante_is_grounded() { +const bool devil3_sdk::pl_dante_is_grounded() { #if 0 char state = get_pl_state(); return ( (state == 11) || (state == 13)); #else - static bool* grounded = (bool*)0x01C8C958; - return !*grounded; + static bool* grounded = (bool*)((uintptr_t)get_pl_dante() + (ptrdiff_t)0x2358); + return !*grounded; #endif } -const bool Devil3SDK::pl_is_dt_check() +const bool devil3_sdk::pl_is_dt_check() { + static const bool* pl_dt = (bool*)((uintptr_t)get_pl_dante() + (ptrdiff_t)0x2817); + return *pl_dt; +} + +CCharTableMgrPart* devil3_sdk::pl_dante_get_human_anim_table() { + auto base = get_pl_dante(); + return (CCharTableMgrPart*)((uintptr_t)base + (uintptr_t)g_dante_table.human); +} + +CCharTableMgrPart* devil3_sdk::pl_dante_get_dt1_anim_table() { + auto base = get_pl_dante(); + return (CCharTableMgrPart*)((uintptr_t)base + (uintptr_t)g_dante_table.dt1); +} + +CCharTableMgrPart* devil3_sdk::pl_dante_get_dt2_anim_table() { + auto base = get_pl_dante(); + return (CCharTableMgrPart*)((uintptr_t)base + (uintptr_t)g_dante_table.dt2); +} + +const bool devil3_sdk::pl_dante_check_animation_id(uint16_t id) { + auto table_human = pl_dante_get_human_anim_table(); + auto table_dt1 = pl_dante_get_dt1_anim_table(); + auto table_dt2 = pl_dante_get_dt2_anim_table(); + + if (IsBadReadPtr(&table_human->current_anim, sizeof(short)) || + IsBadReadPtr(&table_dt1->current_anim, sizeof(short)) || + IsBadReadPtr(&table_dt2->current_anim, sizeof(short))) { + + return false; + } + return ( + ((id == table_human->current_anim) && !pl_is_dt_check()) || + ((id == table_dt1->current_anim) && pl_is_dt_check()) || + ((id == table_dt2->current_anim) && pl_is_dt_check())); +} +#else +struct dante_anim_table { + CCharTableMgrPart* human = (CCharTableMgrPart*)0x01C8E7D8; + CCharTableMgrPart* dt1 = (CCharTableMgrPart*)0x01C8EB18; + CCharTableMgrPart* dt2 = (CCharTableMgrPart*)0x01C8EA48; +}; + +static dante_anim_table g_dante_table; + +uint16_t devil3_sdk::get_buttons_pressed() { + uint16_t* ptr = (uint16_t*)0x01C8EFF4; + return *ptr; +} + +CPlDante* devil3_sdk::get_pl_dante() { + return (CPlDante*)0x1C8A600; +} + +cCameraCtrl* devil3_sdk::get_cam_ctrl() { + static cCameraCtrl** camera_ptr_ptr = (cCameraCtrl**)0x00B6BAAC; + return *camera_ptr_ptr; +} + +Vector2f devil3_sdk::get_window_dimensions() { + return Vector2f{ *(float*)0x00832914, *(float*)0x00832918}; +} +const int devil3_sdk::get_pl_dante_style() { - static const bool* pl_dt = (bool*)0x1C8CE17; - return *pl_dt; + static int* current_style = (int*)0xB6B220; + return *current_style; } -CCharTableMgrPart * Devil3SDK::pl_dante_get_human_anim_table() +const char devil3_sdk::get_pl_state() { - return g_dante_table.human; + static char* pl_state = (char*)0x01C8EDDE; + return *pl_state; +} + +const bool devil3_sdk::pl_dante_is_air() { + static char* air = (char*)0x01C8A673; + return *air != 0; +} +const bool devil3_sdk::pl_dante_is_grounded() { +#if 0 + char state = get_pl_state(); + return ( + (state == 11) || + (state == 13)); +#else + static bool* grounded = (bool*)0x01C8C958; + return !*grounded; +#endif } -CCharTableMgrPart * Devil3SDK::pl_dante_get_dt1_anim_table() +const bool devil3_sdk::pl_is_dt_check() { - return g_dante_table.dt1; + static const bool* pl_dt = (bool*)0x1C8CE17; + return *pl_dt; } -CCharTableMgrPart * Devil3SDK::pl_dante_get_dt2_anim_table() +CCharTableMgrPart * devil3_sdk::pl_dante_get_human_anim_table() { - return g_dante_table.dt2; + return g_dante_table.human; } -const bool Devil3SDK::pl_dante_check_animation_id(uint16_t id) +CCharTableMgrPart * devil3_sdk::pl_dante_get_dt1_anim_table() { - if ( IsBadReadPtr(&g_dante_table.human->current_anim, sizeof(short)) || - IsBadReadPtr(&g_dante_table.dt1->current_anim, sizeof(short)) || - IsBadReadPtr(&g_dante_table.dt2->current_anim, sizeof(short)) ) { + return g_dante_table.dt1; +} - return false; - } - return ( - ((id == g_dante_table.human->current_anim) && !pl_is_dt_check()) || - ((id == g_dante_table.dt1->current_anim) && pl_is_dt_check()) || - ((id == g_dante_table.dt2->current_anim) && pl_is_dt_check())); +CCharTableMgrPart * devil3_sdk::pl_dante_get_dt2_anim_table() +{ + return g_dante_table.dt2; +} + +const bool devil3_sdk::pl_dante_check_animation_id(uint16_t id) +{ + if ( IsBadReadPtr(&g_dante_table.human->current_anim, sizeof(short)) || + IsBadReadPtr(&g_dante_table.dt1->current_anim, sizeof(short)) || + IsBadReadPtr(&g_dante_table.dt2->current_anim, sizeof(short)) ) { + + return false; + } + return ( + ((id == g_dante_table.human->current_anim) && !pl_is_dt_check()) || + ((id == g_dante_table.dt1->current_anim) && pl_is_dt_check()) || + ((id == g_dante_table.dt2->current_anim) && pl_is_dt_check())); +} +#endif + + +CSceneGameMain* devil3_sdk::get_main_scene() { + CSceneGameMain* scn = (CSceneGameMain*)0x2C72840; + if (scn->vtable != 0x7462C4) { + return nullptr; + } + return scn; // TODO(): memory patch offset, vanilla game would be different +} + +void devil3_sdk::area_jump(uint16_t id) { + CSceneGameMain* scn = get_main_scene(); + + if (!scn) { + return; + } + + scn->cGameW_ptr->cEvtMiss_ptr->next_map = id; + scn->cGameW_ptr->cEvtMiss_ptr->current_map = id; + + scn->flag_state = GAME_STATE::GAME_MAIN_DOOR; + scn->screen_effect = SCREEN_EFFECT::DOOR; +} + +void devil3_sdk::play_sound(unsigned __int16 a1, unsigned __int16 a2, int a3) { + typedef unsigned int(__cdecl * PlaySoundMaybeSub409A50Ptr)(unsigned __int16 a1, unsigned __int16 a2, int a3); + static PlaySoundMaybeSub409A50Ptr fptr_d3_play_sound = (PlaySoundMaybeSub409A50Ptr)0x00409A50; + + fptr_d3_play_sound(a1, a2, a3); } diff --git a/src/sdk/Devil3.hpp b/src/sdk/Devil3.hpp index c10e2fc..35e6703 100644 --- a/src/sdk/Devil3.hpp +++ b/src/sdk/Devil3.hpp @@ -1,22 +1,27 @@ #pragma once #include "ReClass.hpp" -namespace Devil3SDK { - uint16_t get_buttons_pressed(); - CPlDante* get_pl_dante(); - cCameraCtrl* get_cam_ctrl(); - const int get_pl_dante_style(); - const char get_pl_state(); +namespace devil3_sdk { - Vector2f get_window_dimensions(); +uint16_t get_buttons_pressed(); +CPlDante* get_pl_dante(); +cCameraCtrl* get_cam_ctrl(); +const int get_pl_dante_style(); +const char get_pl_state(); - const bool pl_dante_check_animation_id(uint16_t id); - const bool pl_dante_is_grounded(); - const bool pl_dante_is_air(); - - const bool pl_is_dt_check(); +Vector2f get_window_dimensions(); - CCharTableMgrPart* pl_dante_get_human_anim_table(); - CCharTableMgrPart* pl_dante_get_dt1_anim_table(); - CCharTableMgrPart* pl_dante_get_dt2_anim_table(); -} \ No newline at end of file +const bool pl_dante_check_animation_id(uint16_t id); +const bool pl_dante_is_grounded(); +const bool pl_dante_is_air(); + +const bool pl_is_dt_check(); + +CCharTableMgrPart* pl_dante_get_human_anim_table(); +CCharTableMgrPart* pl_dante_get_dt1_anim_table(); +CCharTableMgrPart* pl_dante_get_dt2_anim_table(); + +CSceneGameMain* get_main_scene(); +void area_jump(uint16_t id); +void play_sound(unsigned __int16 a1, unsigned __int16 a2, int a3); +} // namespace devil3_sdk diff --git a/src/sdk/ReClass.hpp b/src/sdk/ReClass.hpp index bc65362..a064dff 100644 --- a/src/sdk/ReClass.hpp +++ b/src/sdk/ReClass.hpp @@ -1,11 +1,11 @@ #pragma once -#include #include "Math.hpp" #include "d3d9.h" - +#include +// NOLINTBEGIN #pragma pack(push, r1, 1) #include "ReClass_Internal.hpp" #pragma pack(pop, r1) - -#include "Enums_Internal.hpp" \ No newline at end of file +// NOLINTEND +#include "Enums_Internal.hpp" diff --git a/src/sdk/ReClass_Internal.hpp b/src/sdk/ReClass_Internal.hpp index 824e39f..15f7fbf 100644 --- a/src/sdk/ReClass_Internal.hpp +++ b/src/sdk/ReClass_Internal.hpp @@ -1,152 +1,258 @@ +// #include "sdk/Math.hpp" +// #include // Created with ReClass.NET 1.1 by KN4CK3R -class kbStruct -{ +class kbStruct { public: - char pad_0000[4]; //0x0000 - float health; //0x0004 - float knockback; //0x0008 - float stun; //0x000C - char pad_0010[308]; //0x0010 -}; //Size: 0x0144 + char pad_0000[4]; // 0x0000 + float health; // 0x0004 + float knockback; // 0x0008 + float stun; // 0x000C + char pad_0010[308]; // 0x0010 +}; // Size: 0x0144 static_assert(sizeof(kbStruct) == 0x144); -class CDamageCalc -{ +class CDamageCalc { public: - char pad_0000[4]; //0x0000 - class N0000029C *ptrTable; //0x0004 - class kbStruct *ptrKb; //0x0008 - class N00000274 *enemyPtr; //0x000C - char pad_0010[48]; //0x0010 -}; //Size: 0x0040 + char pad_0000[4]; // 0x0000 + class N0000029C* ptrTable; // 0x0004 + class kbStruct* ptrKb; // 0x0008 + class N00000274* enemyPtr; // 0x000C + char pad_0010[48]; // 0x0010 +}; // Size: 0x0040 static_assert(sizeof(CDamageCalc) == 0x40); -class CPlDante -{ +class CPlDante { public: - int pad_0000; //0x0000 - uint8_t unkFlag; //0x0004 - char pad_0005[11]; //0x0005 - float workrate; //0x0010 - float speed; //0x0014 - char pad_0018[52]; //0x0018 - Vector4 Poistion; //0x004C - Vector4 DeltaP; //0x005C - char pad_006C[4]; //0x006C - float weightMaybe; //0x0070 - char pad_0074[24]; //0x0074 - uint16_t angle; //0x008C - char pad_008E[110]; //0x008E - Vector4 somePosVector; //0x00FC - Vector4 somePrevPosVector; //0x010C - Matrix4x4 TransformMatrix; //0x011C - float momentumMagnitude; //0x015C cm - float momentumDelta; //0x0160 - char pad_0164[9736]; //0x0164 - class VelLookupTable *velocityLookupTable; //0x276C 0x276c zeroesUpMomentum_sub_5A4CB20 - char pad_2770[32]; //0x2770 - uint32_t animationStatus01; //0x2790 - char pad_2794[4]; //0x2794 - uint32_t animationStatusPrev; //0x2798 - char pad_279C[4]; //0x279C - uint8_t animationFlagUnk; //0x27A0 - char pad_27A1[35]; //0x27A1 - float someAnimationVelocityFloat; //0x27C4 walking when below 2 - char pad_27C8[144]; //0x27C8 - uint16_t stickDirection; //0x2858 - uint16_t someOtherDirection; //0x285A - uint16_t anotherDirection; //0x285C - uint16_t idkDirection; //0x285E - uint16_t viewDirection; //0x2860 - char pad_2862[22]; //0x2862 - uint8_t N00000AD3; //0x2878 - uint8_t N00000FDA; //0x2879 - char pad_287A[2]; //0x287A - uint32_t N00000AD4; //0x287C 0x287c edx at start zeroesUpMomentum_sub_5A4CB0ú - char pad_2880[5044]; //0x2880 - uint32_t rg_meter_uint; //0x3C34 - float rg_meter_flt; //0x3C38 - float block_timer; //0x3C3C - float release_timer; //0x3C40 - char pad_3C44[108]; //0x3C44 -}; //Size: 0x3CB0 + int pad_0000; // 0x0000 + uint8_t unkFlag; // 0x0004 + char pad_0005[11]; // 0x0005 + float workrate; // 0x0010 + float speed; // 0x0014 + char pad_0018[52]; // 0x0018 + Vector4 Poistion; // 0x004C + Vector4 DeltaP; // 0x005C + char pad_006C[4]; // 0x006C + float weightMaybe; // 0x0070 + char pad_0074[24]; // 0x0074 + uint16_t angle; // 0x008C + char pad_008E[110]; // 0x008E + Vector4 somePosVector; // 0x00FC + Vector4 somePrevPosVector; // 0x010C + Matrix4x4 TransformMatrix; // 0x011C + float momentumMagnitude; // 0x015C cm + float momentumDelta; // 0x0160 + char pad_0164[9736]; // 0x0164 + class VelLookupTable* velocityLookupTable; // 0x276C 0x276c zeroesUpMomentum_sub_5A4CB20 + char pad_2770[32]; // 0x2770 + uint32_t animationStatus01; // 0x2790 + char pad_2794[4]; // 0x2794 + uint32_t animationStatusPrev; // 0x2798 + char pad_279C[4]; // 0x279C + uint8_t animationFlagUnk; // 0x27A0 + char pad_27A1[35]; // 0x27A1 + float someAnimationVelocityFloat; // 0x27C4 walking when below 2 + char pad_27C8[144]; // 0x27C8 + uint16_t stickDirection; // 0x2858 + uint16_t someOtherDirection; // 0x285A + uint16_t anotherDirection; // 0x285C + uint16_t idkDirection; // 0x285E + uint16_t viewDirection; // 0x2860 + char pad_2862[22]; // 0x2862 + uint8_t N00000AD3; // 0x2878 + uint8_t N00000FDA; // 0x2879 + char pad_287A[2]; // 0x287A + uint32_t N00000AD4; // 0x287C 0x287c edx at start zeroesUpMomentum_sub_5A4CB0ú + char pad_2880[5044]; // 0x2880 + uint32_t rg_meter_uint; // 0x3C34 + float rg_meter_flt; // 0x3C38 + float block_timer; // 0x3C3C + float release_timer; // 0x3C40 + char pad_3C44[108]; // 0x3C44 +}; // Size: 0x3CB0 static_assert(sizeof(CPlDante) == 0x3CB0); +class devil3StaticPxShaderArray { +public: + class devil3pxShader* shaders[6]; // 0x0000 + char pad_0018[60]; // 0x0018 +}; // Size: 0x0054 +// static_assert(sizeof(devil3StaticPxShaderArray) == 0x54); + +class devil3pxShader { +public: + char pad_0000[4]; // 0x0000 + char name[32]; // 0x0004 + char pad_0024[256]; // 0x0024 + IDirect3DPixelShader9* pShader; // 0x0124 +}; // Size: 0x0128 +static_assert(sizeof(devil3pxShader) == 0x128); + +class CCharTableMgrPart { +public: + union { + struct { + uint8_t bank_id; // 0x0000 + uint8_t motion_id; // 0x0001 + }; + uint16_t current_anim; // 0x0000 + }; + char pad_0002[6]; // 0x0002 + float time; // 0x0008 + char pad_000C[104]; // 0x000C + float anim_frame; // 0x0074 + float loop_point; // 0x0078 +}; // Size: 0x007C +static_assert(sizeof(CCharTableMgrPart) == 0x7C); + +class cCameraCtrl { +public: + Vector3 upVector; // 0x0004 + float fltUnused0; // 0x0010 + float FOV; // 0x0014 + float roll_radians; // 0x0018 + Matrix4x4 transform; // 0x001C + Vector4 pos; // 0x005C + Vector4 lookat; // 0x006C + friend int cCameraCtrl__something_idk_sub_416880(cCameraCtrl& this_ptr); + virtual void Function0(); + virtual void Function1(); + virtual void Function2(); + virtual void Function3(); + virtual void Function4(); + virtual void Function5(); + virtual void Function6(); + virtual void Function7(); + virtual void Function8(); + virtual void Function9(); +}; // Size: 0x007C +static_assert(sizeof(cCameraCtrl) == 0x7C); + +class cCameraPlayer { +public: + char pad_0000[4]; // 0x0000 + Vector3 up; // 0x0004 + float fltUnused; // 0x0010 + float FOV; // 0x0014 + float roll_radians; // 0x0018 + Vector4 q1; // 0x001C + Vector4 q2; // 0x002C + Matrix4x4 N00000A9F; // 0x003C + char pad_007C[1056]; // 0x007C +}; // Size: 0x049C +static_assert(sizeof(cCameraPlayer) == 0x49C); + +// Created with ReClass.NET 1.2 by KN4CK3R +enum class GAME_STATE : int32_t +{ + GAME_MAIN_CUSTOMIZE = 9, + GAME_MAIN_DEAD = 6, + GAME_MAIN_DELETE = 11, + GAME_MAIN_DOOR = 2, + GAME_MAIN_END = 12, + GAME_MAIN_ITEMGET = 7, + GAME_MAIN_MAIN = 1, + GAME_MAIN_MESSAGE = 8, + GAME_MAIN_OPTIONS = 5, + GAME_MAIN_PAUSE = 3, + GAME_MAIN_SAVE = 10, + GAME_MAIN_STATUS = 4, + UNK = 0 +}; +enum class SCREEN_EFFECT : int32_t +{ + DOOR = 1, + IDK = 3, + MISSION_END = 2, + NONE = 0 +}; -class devil3StaticPxShaderArray +class CSceneGameMain { public: - class devil3pxShader *shaders[6]; //0x0000 - char pad_0018[60]; //0x0018 -}; //Size: 0x0054 -//static_assert(sizeof(devil3StaticPxShaderArray) == 0x54); + uint32_t vtable; //0x0000 for now- just to check vtable pointer + // this probably has some useful virtual functions that i cba to reverse + char pad_0004[8]; //0x0004 + class CGameW *cGameW_ptr; //0x000C + uint16_t currentLevel; //0x0010 + char pad_0012[6]; //0x0012 + GAME_STATE flag_state; //0x0018 + char pad_001C[12]; //0x001C + SCREEN_EFFECT screen_effect; //0x0028 + char pad_002C[1040]; //0x002C +}; //Size: 0x043C -class devil3pxShader +class CGameW { public: - char pad_0000[4]; //0x0000 - char name[32]; //0x0004 - char pad_0024[256]; //0x0024 - IDirect3DPixelShader9* pShader; //0x0124 -}; //Size: 0x0128 -static_assert(sizeof(devil3pxShader) == 0x128); + char pad_0000[4]; //0x0000 + class CEventMission *cEvtMiss_ptr; //0x0004 +}; //Size: 0x0008 -class CCharTableMgrPart +class CEventMission { public: - union { - struct { - uint8_t bank_id; //0x0000 - uint8_t motion_id; //0x0001 - }; - uint16_t current_anim; //0x0000 - }; - char pad_0002[6]; //0x0002 - float time; //0x0008 - char pad_000C[104]; //0x000C - float anim_frame; //0x0074 - float loop_point; //0x0078 -}; //Size: 0x007C -static_assert(sizeof(CCharTableMgrPart) == 0x7C); + char pad_0000[244]; //0x0000 + uint16_t current_map; //0x00F4 + uint16_t N00000A3F; //0x00F6 + uint16_t next_map; //0x00F8 + uint16_t N00000A42; //0x00FA + char pad_00FC[4]; //0x00FC +}; //Size: 0x0100 -class cCameraCtrl +struct Devil3Texture +{ + char pad_0000[4]; + uint32_t width; + uint32_t height; + void *decodeDataPointer; + void *decodeFunctionPointer; + D3DFORMAT format; + IDirect3DTexture9* texturePointer; + bool dirty; + char pad_0020[2080]; +}; + +#pragma region WIP +// Created with ReClass.NET 1.2 by KN4CK3R + +class TextureTableEntry { public: - Vector3 upVector; //0x0004 - float fltUnused0; //0x0010 - float FOV; //0x0014 - float roll_radians; //0x0018 - Matrix4x4 transform; //0x001C - Vector4 pos; //0x005C - Vector4 lookat; //0x006C - friend static int cCameraCtrl__something_idk_sub_416880(cCameraCtrl& this_ptr); - virtual void Function0(); - virtual void Function1(); - virtual void Function2(); - virtual void Function3(); - virtual void Function4(); - virtual void Function5(); - virtual void Function6(); - virtual void Function7(); - virtual void Function8(); - virtual void Function9(); -}; //Size: 0x007C -static_assert(sizeof(cCameraCtrl) == 0x7C); + class TextureData *ptrTextureData; //0x0000 + class Devil3Texture *ptrD3Texture; //0x0004 +}; //Size: 0x0008 -class cCameraPlayer +class TextureTable { public: - char pad_0000[4]; //0x0000 - Vector3 up; //0x0004 - float fltUnused; //0x0010 - float FOV; //0x0014 - float roll_radians; //0x0018 - Vector4 q1; //0x001C - Vector4 q2; //0x002C - Matrix4x4 N00000A9F; //0x003C - char pad_007C[1056]; //0x007C -}; //Size: 0x049C -static_assert(sizeof(cCameraPlayer) == 0x49C); + class TextureTableEntry* textures; //0x0000 +}; //Size: 0x0208 + +class unkTextureData +{ +public: + char pad_0000[4]; //0x0000 +}; //Size: 0x0004 + +class N000000F9 +{ +public: + char pad_0000[4]; //0x0000 +}; //Size: 0x0004 + +class N0000011E +{ +public: + char pad_0000[4]; //0x0000 +}; //Size: 0x0004 + +class TextureData +{ +public: + char pad_0000[260]; //0x0000 +}; //Size: 0x0104 + +#pragma endregion diff --git a/src/utility/ExceptionHandler.cpp b/src/utility/ExceptionHandler.cpp index ac732f9..4865f59 100644 --- a/src/utility/ExceptionHandler.cpp +++ b/src/utility/ExceptionHandler.cpp @@ -34,7 +34,20 @@ LONG WINAPI reframework::global_exception_handler(struct _EXCEPTION_POINTERS* ei const auto module_within = utility::get_module_within(ei->ContextRecord->Eip); if (module_within) { - +#if 0 + if (*module_within == g_framework->get_module()) { + printf("Attempting to fix capcom pointer crash\n"); + ei->ContextRecord->Ecx = get_reg(ei->ContextRecord->Ecx); + ei->ContextRecord->Edx = get_reg(ei->ContextRecord->Edx); + ei->ContextRecord->Eax = get_reg(ei->ContextRecord->Eax); + ei->ContextRecord->Ebx = get_reg(ei->ContextRecord->Ebx); + ei->ContextRecord->Ebp = get_reg(ei->ContextRecord->Ebp); + ei->ContextRecord->Esi = get_reg(ei->ContextRecord->Esi); + ei->ContextRecord->Edi = get_reg(ei->ContextRecord->Edi); + ei->ContextRecord->Eip -= 5; + return EXCEPTION_CONTINUE_EXECUTION; + } +#endif const auto module_path = utility::get_module_path(*module_within); if (module_path) { @@ -100,5 +113,5 @@ LONG WINAPI reframework::global_exception_handler(struct _EXCEPTION_POINTERS* ei } void reframework::setup_exception_handler() { - //SetUnhandledExceptionFilter(global_exception_handler); + SetUnhandledExceptionFilter(global_exception_handler); }