diff --git a/CMakeLists.txt b/CMakeLists.txt index 3065b1d..fe5c4ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,6 @@ cmake_minimum_required(VERSION 3.25.0) set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake CACHE STRING "") set(CMAKE_EXPORT_COMPILE_COMMANDS true) -# set(CMAKE_GENERATOR_TOOLSET "v140" CACHE STRING "Platform Toolset" FORCE) - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) @@ -12,16 +10,12 @@ include(AutoCCache) project(KProject) +set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) + set(CMAKE_CXX_STANDARD 20) -# set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") -# set(CMAKE_CXX_FLAGS_RELEASE "/MT") set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") -# find_package(Catch2 CONFIG REQUIRED) -# target_link_libraries(main PRIVATE Catch2::Catch2 Catch2::Catch2WithMain) - find_package(minhook CONFIG REQUIRED) - find_package(spdlog CONFIG REQUIRED) set(TARGET "kpatch") @@ -30,7 +24,7 @@ set(TARGET_OUTPUT_NAME "kpatch") add_library(${TARGET} SHARED ${TARGET_SRC}) set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${TARGET_OUTPUT_NAME}) target_include_directories(${TARGET} PRIVATE ${CMAKE_SOURCE_DIR}/include) -target_link_libraries(${TARGET} PUBLIC spdlog::spdlog) +target_link_libraries(${TARGET} PRIVATE spdlog::spdlog_header_only) # target_link_libraries(${TARGET} PUBLIC minhook::minhook) diff --git a/justfile b/justfile index e1ba2f4..a280383 100644 --- a/justfile +++ b/justfile @@ -17,7 +17,12 @@ config: build: cmake --build --preset {{preset}} --config Release - cp -f ./build/x86-release-msvc/bin/Release/kpatch.dll "{{TARGET}}/kpatch.asi" + +copy: build + cd ./build/x86-release-msvc/bin/Release && \ + cp -f kpatch.dll "{{TARGET}}/kpatch.asi" && \ + cp -f fmt.dll "{{TARGET}}/" + cp -f third/version.dll "{{TARGET}}/" @run: ./build/{{preset}}/bin/{{target}} diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 0ab9cb6..0d4fd89 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -1,15 +1,18 @@ -#include "stdafx.h" -#include "helper.hpp" +#define SPDLOG_WCHAR_TO_UTF8_SUPPORT #include -#include -#include +#include + +#include +#include + +#include "helper.hpp" HMODULE baseModule = GetModuleHandle(NULL); HMODULE thisModule; // Fix DLL // Version std::string sFixName = "L4D2Fix"; -std::string sFixVer = "0.0.1"; +std::string sFixVer = "1.1.0"; std::string sLogFile = sFixName + ".log"; // Logger @@ -18,8 +21,7 @@ std::filesystem::path sExePath; std::string sExeName; std::filesystem::path sThisModulePath; -void Logging() -{ +void Logging() { // Get this module path WCHAR thisModulePath[_MAX_PATH] = { 0 }; GetModuleFileNameW(thisModule, thisModulePath, MAX_PATH); @@ -34,52 +36,67 @@ void Logging() sExePath = sExePath.remove_filename(); // spdlog initialisation - { - try { - // Create 10MB truncated logger - auto logger = spdlog::rotating_logger_mt(sFixName, sLogFile, 1048576 * 5, 3); - spdlog::set_default_logger(logger); + try { + auto logger = spdlog::basic_logger_mt(sFixName, sLogFile, true); + spdlog::set_default_logger(logger); - spdlog::flush_on(spdlog::level::debug); - spdlog::info("----------"); - spdlog::info("{} v{} loaded.", sFixName.c_str(), sFixVer.c_str()); - spdlog::info("----------"); - spdlog::info("Log file: {}", sThisModulePath.string() + sLogFile); - spdlog::info("----------"); + auto start_time = std::chrono::system_clock::now(); - // Log module details - spdlog::info("Module Name: {0:s}", sExeName.c_str()); - spdlog::info("Module Path: {0:s}", sExePath.string()); - spdlog::info("Module Address: 0x{0:x}", (uintptr_t)baseModule); - spdlog::info("Module Timestamp: {0:d}", Memory::ModuleTimestamp(baseModule)); - spdlog::info("----------"); - } - catch (const spdlog::spdlog_ex& ex) { - AllocConsole(); - FILE* dummy; - freopen_s(&dummy, "CONOUT$", "w", stdout); - std::cout << "Log initialisation failed: " << ex.what() << std::endl; - FreeLibraryAndExitThread(baseModule, 1); - } + spdlog::flush_on(spdlog::level::debug); + spdlog::info("----------"); + spdlog::info("Date: {}", std::chrono::system_clock::to_time_t(start_time)); + spdlog::info("{} v{} loaded.", sFixName.c_str(), sFixVer.c_str()); + spdlog::info("----------"); + spdlog::info("Log file: {}", sThisModulePath.string() + sLogFile); + spdlog::info("----------"); + + // Log module details + spdlog::info("Module Name: {0:s}", sExeName.c_str()); + spdlog::info("Module Path: {0:s}", sExePath.string()); + spdlog::info("Module Address: 0x{0:x}", (uintptr_t)baseModule); + spdlog::info("Module Timestamp: {0:d}", Memory::ModuleTimestamp(baseModule)); + spdlog::info("----------"); + } catch (const spdlog::spdlog_ex &ex) { + AllocConsole(); + FILE *dummy; + freopen_s(&dummy, "CONOUT$", "w", stdout); + std::cout << "Log initialisation failed: " << ex.what() << std::endl; + FreeLibraryAndExitThread(baseModule, 1); } } DWORD __stdcall Main(void*) { Logging(); std::filesystem::path startup_check = L"success.txt"; - // MessageBoxW(NULL, L"警告:这是测试版补丁,设定为必定会炸,用于检测补丁是否正确应用。", L"L4D2 Fix", MB_OK); + // MessageBoxW(NULL, L"警告:这是测试版补丁,设定为必定会炸,用于检测补丁是否正确应用。", L"L4D2 Fix", MB_OK|MB_SYSTEMMODAL|MB_ICONWARNING); if (!std::filesystem::exists(startup_check)) { - MessageBoxW(NULL, L"这是一个启动测试,用于检验补丁是否正常运行。\n请注意由于修改内存,请不要进 VAC 服,后果未知。\n本弹窗仅首次启动出现,后续运行情况参见 L4D2Fix.log 日志文件。\n\n关注B站 5050 直播间,谢谢喵 by KurikoMoe!", L"L4D2 Fix", MB_OK); + MessageBoxW( + NULL, + L"这是一个启动测试,用于检验补丁是否正常运行。\n请注意由于修改内存,请不要进 VAC 服,后果自负。\n本弹窗仅首次启动出现,后续运行情况参见 L4D2Fix.log 日志文件。\n\n关注B站 5050 直播间,谢谢喵 by KurikoMoe!", + L"L4D2 Fix", MB_OK); } - auto hDll = LoadLibraryW(L"shaderapidx9.dll"); + std::wstring cmdline = GetCommandLineW(); + spdlog::info(L"Startup commandline: {}", cmdline.c_str()); + + std::wstring dllName; + std::transform(cmdline.cbegin(), cmdline.cend(), cmdline.begin(), ::tolower); + + if (cmdline.find(L"-vulkan") != std::wstring::npos) { + dllName = L"shaderapivk.dll"; + spdlog::info(L"Detected Vulkan: using {}", dllName); + } else { + dllName = L"shaderapidx9.dll"; + } + auto hDll = LoadLibraryW(dllName.c_str()); if (hDll == nullptr) { - MessageBoxW(NULL, L"Failed to load shaderapidx9.dll!", L"L4D2 Fix", MB_OK); + MessageBoxW(NULL, std::format(L"Failed to load {}!", dllName).c_str(), L"L4D2 Fix", MB_OK|MB_SYSTEMMODAL|MB_ICONSTOP); + exit(-1); } - auto f = [&](const char* tag, const char* pattern, size_t offset, size_t w_offset) { + auto f = [&](const wchar_t* tag, const char* pattern, size_t offset, size_t w_offset) { std::uint8_t* ptr = Memory::PatternScan(hDll, pattern); constexpr uint32_t new_buffer_size = 0x020000; @@ -87,25 +104,25 @@ DWORD __stdcall Main(void*) { if (ptr != nullptr) { Memory::Write((uintptr_t)(ptr + w_offset), new_buffer_size); - spdlog::info("Modified the vertex max buffer shaderapidx9.dll: {}", tag); + spdlog::info(L"Modified the vertex max buffer {}: {}", dllName, tag); return ptr; } - spdlog::error("Pattern scan failed for shaderapidx9.dll: {}", tag); + spdlog::error(L"Pattern scan failed for {}: {}", dllName, tag); return (uint8_t*)nullptr; }; // CreateEmptyColorMesh - auto ptr1 = f("CreateEmptyColorMesh", "68 ?? ?? ?? ?? 68 00 80 00 00 6A 04", 0, 6); + auto ptr1 = f(L"CreateEmptyColorMesh", "68 ?? ?? ?? ?? 68 00 80 00 00 6A 04", 0, 6); - auto ptr1_1 = f("CreateEmptyColorMesh Later", "68 00 80 00 00 50 8B", (size_t)ptr1, 1); + auto ptr1_1 = f(L"CreateEmptyColorMesh Later", "68 00 80 00 00 50 8B", (size_t)ptr1, 1); // CreateVertexIDBuffer - auto ptr2 = f("CreateVertexIDBuffer", "68 ?? ?? ?? ?? 68 00 80 00 00 6A 04", (size_t)ptr1_1, 6); - auto ptr2_1 = f("CreateVertexIDBuffer Later", "68 00 80 00 00 50 8B", (size_t)ptr2, 1); + auto ptr2 = f(L"CreateVertexIDBuffer", "68 ?? ?? ?? ?? 68 00 80 00 00 6A 04", (size_t)ptr1_1, 6); + auto ptr2_1 = f(L"CreateVertexIDBuffer Later", "68 00 80 00 00 50 8B", (size_t)ptr2, 1); // Not known - auto ptr3 = f("Unknown", "0F B6 C0 50 68 00 80 00 00 53 8B CF E8 ?? ?? ?? ??", (size_t)ptr1, 5); + auto ptr3 = f(L"Unknown", "0F B6 C0 50 68 00 80 00 00 53 8B CF E8 ?? ?? ?? ??", (size_t)ptr1, 5); if (ptr1 == nullptr || ptr1_1 == nullptr @@ -128,12 +145,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: Main(nullptr); - // HANDLE mainHandle = CreateThread(NULL, 0, Main, 0, CREATE_SUSPENDED, 0); - // if (mainHandle) { - // SetThreadPriority(mainHandle, THREAD_PRIORITY_TIME_CRITICAL); - // ResumeThread(mainHandle); - // CloseHandle(mainHandle); - // } break; } return TRUE; diff --git a/src/stdafx.h b/src/stdafx.h index 8fc1c1b..86fb00d 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -7,6 +7,7 @@ #include #include #include -#include #include #include +#include +#include