From 778b6e8f9f1bc314bc05c8905318442dc43af81b Mon Sep 17 00:00:00 2001 From: PlayDay <18056374+playday3008@users.noreply.github.com> Date: Tue, 6 Jan 2026 16:23:33 +0100 Subject: [PATCH 1/4] Replace VS Solution with CMake, also removed PCH --- .gitignore | 8 ++ CMakeLists.txt | 153 +++++++++++++++++++++++++ CodeRedGenerator.sln | 31 ------ CodeRedGenerator.vcxproj | 166 ---------------------------- CodeRedGenerator.vcxproj.filters | 94 ---------------- CodeRedGenerator.vcxproj.user | 4 - Engine/Dishonered/Configuration.cpp | 2 + Engine/Dishonered/Configuration.hpp | 4 +- Engine/Dishonered/GameDefines.hpp | 38 +++---- Engine/Dishonered/PiecesOfCode.hpp | 1 + Engine/Engine.hpp | 12 +- Engine/Template/Configuration.cpp | 2 + Engine/Template/Configuration.hpp | 4 +- Engine/Template/GameDefines.hpp | 38 +++---- Engine/Template/PiecesOfCode.hpp | 1 + Framework/Member.hpp | 3 + Framework/Printer.cpp | 2 +- Framework/Printer.hpp | 6 +- dllmain.cpp | 15 ++- dllmain.hpp | 2 +- pch.cpp | 1 - pch.hpp | 17 --- 22 files changed, 237 insertions(+), 367 deletions(-) create mode 100644 .gitignore create mode 100644 CMakeLists.txt delete mode 100644 CodeRedGenerator.sln delete mode 100644 CodeRedGenerator.vcxproj delete mode 100644 CodeRedGenerator.vcxproj.filters delete mode 100644 CodeRedGenerator.vcxproj.user delete mode 100644 pch.cpp delete mode 100644 pch.hpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c30e365 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# MacOS Cache +.DS_Store + +# Cache files +.cache/ + +# Build output +build/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..31272b0 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,153 @@ +# Specify the minimum CMake version +cmake_minimum_required(VERSION 3.20) + +# --------------------- +# Project Configuration +# --------------------- + +# Define the project +project(CodeRedGenerator + DESCRIPTION "Unreal Engine 3 SDK Generator" + VERSION 1.1.7 + LANGUAGES CXX C) + +# Generate compile_commands.json for IDE integration +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Set C++ language standard to C++20, C17 +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_C_STANDARD 17) +set(CMAKE_C_STANDARD_REQUIRED ON) + +# Enable all, extra, and pedantic warnings +if(MSVC) + add_compile_options(/W4) +else() + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# -------------------- +# Engine Configuration +# -------------------- + +# Auto-detect available engines +file(GLOB ENGINE_DIRS + LIST_DIRECTORIES TRUE + "${CMAKE_CURRENT_SOURCE_DIR}/Engine/*") + +set(AVAILABLE_ENGINES "") +foreach(DIR ${ENGINE_DIRS}) + if(IS_DIRECTORY ${DIR}) + get_filename_component(ENGINE_NAME ${DIR} NAME) + list(APPEND AVAILABLE_ENGINES ${ENGINE_NAME}) + endif() +endforeach() + +if(NOT AVAILABLE_ENGINES) + message(FATAL_ERROR "No engine directories found in Engine/") +endif() + +# Set default engine to the "Template" engine if it exists, otherwise the first available engine +if("Template" IN_LIST AVAILABLE_ENGINES) + set(DEFAULT_ENGINE "Template") +else() + list(GET AVAILABLE_ENGINES 0 DEFAULT_ENGINE) +endif() + +# Option to select the engine +set(ENGINE "${DEFAULT_ENGINE}" CACHE STRING "Select the engine to build with") +set_property(CACHE ENGINE PROPERTY STRINGS ${ENGINE_DIRS}) + +# Validate selected engine +list(FIND AVAILABLE_ENGINES "${ENGINE}" ENGINE_INDEX) +if(ENGINE_INDEX EQUAL -1) + string(REPLACE ";" ", " ENGINES_STR "${AVAILABLE_ENGINES}") + message(FATAL_ERROR "Invalid ENGINE value: ${ENGINE}. Available engines: ${ENGINES_STR}") +endif() + +message(STATUS "Using engine: ${ENGINE}") + +# ------------------- +# Build Configuration +# ------------------- + +# Source files +set(SOURCES + dllmain.cpp + Framework/Member.cpp + Framework/Printer.cpp + Engine/Engine.cpp + Engine/${ENGINE}/Configuration.cpp + Engine/${ENGINE}/GameDefines.cpp + Engine/${ENGINE}/PiecesOfCode.cpp +) + +# Header files +set(HEADERS + dllmain.hpp + Framework/Member.hpp + Framework/Printer.hpp + Engine/Engine.hpp + Engine/${ENGINE}/Configuration.hpp + Engine/${ENGINE}/GameDefines.hpp + Engine/${ENGINE}/PiecesOfCode.hpp +) + +# Create shared library (DLL) +add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS}) + +# Define the selected engine +target_compile_definitions(${PROJECT_NAME} PRIVATE ENGINE=${ENGINE}) + +# Include directories +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + +# Platform-specific settings +if(WIN32) + # Unicode character set + target_compile_definitions(${PROJECT_NAME} PRIVATE + UNICODE + _UNICODE + _CONSOLE + $<$:_DEBUG> + $<$:NDEBUG> + ) + + # Add WIN32 definition for 32-bit builds + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + target_compile_definitions(${PROJECT_NAME} PRIVATE WIN32) + endif() + + # MSVC-specific settings + if(MSVC) + # Warning level 3 + target_compile_options(${PROJECT_NAME} PRIVATE /W3) + + # SDL checks + target_compile_options(${PROJECT_NAME} PRIVATE /sdl) + + # Conformance mode + target_compile_options(${PROJECT_NAME} PRIVATE /permissive-) + + # Release optimizations + target_compile_options(${PROJECT_NAME} PRIVATE + $<$:/Gy> # Function-level linking + $<$:/Oi> # Intrinsic functions + ) + + # Linker settings + target_link_options(${PROJECT_NAME} PRIVATE + /SUBSYSTEM:CONSOLE + $<$:/OPT:REF> # Optimize references + $<$:/OPT:ICF> # COMDAT folding + ) + endif() +endif() + +# Set output directory +set_target_properties(${PROJECT_NAME} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib +) diff --git a/CodeRedGenerator.sln b/CodeRedGenerator.sln deleted file mode 100644 index 9d83263..0000000 --- a/CodeRedGenerator.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.3.32929.385 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CodeRedGenerator", "CodeRedGenerator.vcxproj", "{A023646C-04F2-4DA2-8E90-7F7974D9B1F0}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A023646C-04F2-4DA2-8E90-7F7974D9B1F0}.Debug|x64.ActiveCfg = Debug|x64 - {A023646C-04F2-4DA2-8E90-7F7974D9B1F0}.Debug|x64.Build.0 = Debug|x64 - {A023646C-04F2-4DA2-8E90-7F7974D9B1F0}.Debug|x86.ActiveCfg = Debug|Win32 - {A023646C-04F2-4DA2-8E90-7F7974D9B1F0}.Debug|x86.Build.0 = Debug|Win32 - {A023646C-04F2-4DA2-8E90-7F7974D9B1F0}.Release|x64.ActiveCfg = Release|x64 - {A023646C-04F2-4DA2-8E90-7F7974D9B1F0}.Release|x64.Build.0 = Release|x64 - {A023646C-04F2-4DA2-8E90-7F7974D9B1F0}.Release|x86.ActiveCfg = Release|Win32 - {A023646C-04F2-4DA2-8E90-7F7974D9B1F0}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {9CCB137F-4105-4720-8D88-3D2E95DA465C} - EndGlobalSection -EndGlobal diff --git a/CodeRedGenerator.vcxproj b/CodeRedGenerator.vcxproj deleted file mode 100644 index 90f6aff..0000000 --- a/CodeRedGenerator.vcxproj +++ /dev/null @@ -1,166 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {a023646c-04f2-4da2-8e90-7f7974d9b1f0} - CodeRedGenerator - 10.0 - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - stdcpp20 - stdc17 - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - stdcpp20 - stdc17 - - - Console - true - true - true - - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - stdcpp20 - stdc17 - - - Console - true - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - stdcpp20 - stdc17 - - - Console - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CodeRedGenerator.vcxproj.filters b/CodeRedGenerator.vcxproj.filters deleted file mode 100644 index 4dccb35..0000000 --- a/CodeRedGenerator.vcxproj.filters +++ /dev/null @@ -1,94 +0,0 @@ - - - - - {648e9363-7c33-4996-9a3d-af04cd4ab306} - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {7d231ced-cda7-4c6d-a2fb-53b16a91b865} - - - {a20e86da-a02e-4059-b881-99b17e7ea477} - - - {b83839af-c722-41d1-8066-a179934937ed} - - - {3beb0f8b-1c3e-44fb-9ab8-bc9c7aa9dd90} - - - - - Engine - - - Engine\Template - - - Engine\Template - - - Engine\Template - - - Source Files - - - Source Files - - - Framework - - - Engine\Dishonered - - - Engine\Dishonered - - - Engine\Dishonered - - - Framework - - - - - Engine - - - Engine\Template - - - Engine\Template - - - Engine\Template - - - Header Files - - - Header Files - - - Framework - - - Engine\Dishonered - - - Engine\Dishonered - - - Engine\Dishonered - - - Framework - - - \ No newline at end of file diff --git a/CodeRedGenerator.vcxproj.user b/CodeRedGenerator.vcxproj.user deleted file mode 100644 index 88a5509..0000000 --- a/CodeRedGenerator.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Engine/Dishonered/Configuration.cpp b/Engine/Dishonered/Configuration.cpp index 0ef2221..97cdc55 100644 --- a/Engine/Dishonered/Configuration.cpp +++ b/Engine/Dishonered/Configuration.cpp @@ -1,6 +1,8 @@ #include "Configuration.hpp" #include "PiecesOfCode.hpp" +#include + /* # ========================================================================================= # # Cosmetics diff --git a/Engine/Dishonered/Configuration.hpp b/Engine/Dishonered/Configuration.hpp index d694b88..2835048 100644 --- a/Engine/Dishonered/Configuration.hpp +++ b/Engine/Dishonered/Configuration.hpp @@ -1,6 +1,8 @@ #pragma once -#include + #include +#include +#include #include /* diff --git a/Engine/Dishonered/GameDefines.hpp b/Engine/Dishonered/GameDefines.hpp index cea3c13..f93ef75 100644 --- a/Engine/Dishonered/GameDefines.hpp +++ b/Engine/Dishonered/GameDefines.hpp @@ -1,17 +1,15 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + #include "Configuration.hpp" #include "../../Framework/Member.hpp" +#include +#include +#include + +#include +#include + /* # ========================================================================================= # # Flags @@ -540,6 +538,13 @@ class TArray } }; +// FPointer +// (0x0000 - 0x0004) +struct FPointer +{ + uintptr_t Dummy; // 0x0000 (0x04) +}; + // THIS CLASS CAN BE GAME SPECIFIC, MOST GAMES WILL GENERATE A STRUCT MIRROR! template class TMap @@ -578,7 +583,7 @@ class TMap MaxBits(0), FirstFreeIndex(0), NumFreeIndices(0), - Hash(nullptr), + Hash(NULL), InlineHash(0), HashSize(0) { @@ -591,7 +596,7 @@ class TMap MaxBits(0), FirstFreeIndex(0), NumFreeIndices(0), - Hash(nullptr), + Hash(NULL), InlineHash(0), HashSize(0) { @@ -604,7 +609,7 @@ class TMap MaxBits(0), FirstFreeIndex(0), NumFreeIndices(0), - Hash(nullptr), + Hash(NULL), InlineHash(0), HashSize(0) { @@ -1099,13 +1104,6 @@ struct FScriptDelegate class FName FunctionName; // 0x0004 (0x08) }; -// FPointer -// (0x0000 - 0x0004) -struct FPointer -{ - uintptr_t Dummy; // 0x0000 (0x04) -}; - // FQWord // (0x0000 - 0x0008) struct FQWord diff --git a/Engine/Dishonered/PiecesOfCode.hpp b/Engine/Dishonered/PiecesOfCode.hpp index 45f63e7..d67d300 100644 --- a/Engine/Dishonered/PiecesOfCode.hpp +++ b/Engine/Dishonered/PiecesOfCode.hpp @@ -1,4 +1,5 @@ #pragma once + #include /* diff --git a/Engine/Engine.hpp b/Engine/Engine.hpp index a78b05b..4b45aa5 100644 --- a/Engine/Engine.hpp +++ b/Engine/Engine.hpp @@ -1,9 +1,15 @@ #pragma once + #include -// Here is where you include your custom engine files, only "GameDefines.hpp" and "PiecesOfCode.hpp" is needed. -#include "Template/GameDefines.hpp" -#include "Template/PiecesOfCode.hpp" +// Preprocessor helpers for computed includes +#define STRINGIFY_IMPL(x) #x +#define STRINGIFY(x) STRINGIFY_IMPL(x) +#define ENGINE_INCLUDE(file) STRINGIFY(ENGINE/file) + +// Engine files are included based on build tool's "ENGINE" option (e.g., -DENGINE=Template), only "GameDefines.hpp" and "PiecesOfCode.hpp" is needed. +#include ENGINE_INCLUDE(GameDefines.hpp) +#include ENGINE_INCLUDE(PiecesOfCode.hpp) /* # ========================================================================================= # diff --git a/Engine/Template/Configuration.cpp b/Engine/Template/Configuration.cpp index bdf49b7..8cd98f7 100644 --- a/Engine/Template/Configuration.cpp +++ b/Engine/Template/Configuration.cpp @@ -1,6 +1,8 @@ #include "Configuration.hpp" #include "PiecesOfCode.hpp" +#include + /* # ========================================================================================= # # Cosmetics diff --git a/Engine/Template/Configuration.hpp b/Engine/Template/Configuration.hpp index cc6de19..e752ab4 100644 --- a/Engine/Template/Configuration.hpp +++ b/Engine/Template/Configuration.hpp @@ -1,6 +1,8 @@ #pragma once -#include + #include +#include +#include #include /* diff --git a/Engine/Template/GameDefines.hpp b/Engine/Template/GameDefines.hpp index f7c5353..52e579e 100644 --- a/Engine/Template/GameDefines.hpp +++ b/Engine/Template/GameDefines.hpp @@ -1,17 +1,15 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + #include "Configuration.hpp" #include "../../Framework/Member.hpp" +#include +#include +#include + +#include +#include + /* # ========================================================================================= # # Flags @@ -541,6 +539,13 @@ class TArray } }; +// FPointer +// (0x0000 - 0x0004) +struct FPointer +{ + uintptr_t Dummy; // 0x0000 (0x04) +}; + // THIS CLASS CAN BE GAME SPECIFIC, MOST GAMES WILL GENERATE A STRUCT MIRROR! template class TMap @@ -580,7 +585,7 @@ class TMap FirstFreeIndex(0), NumFreeIndices(0), InlineHash(0), - Hash(nullptr), + Hash(NULL), HashCount(0) { @@ -593,7 +598,7 @@ class TMap FirstFreeIndex(0), NumFreeIndices(0), InlineHash(0), - Hash(nullptr), + Hash(NULL), HashCount(0) { assign(other); @@ -606,7 +611,7 @@ class TMap FirstFreeIndex(0), NumFreeIndices(0), InlineHash(0), - Hash(nullptr), + Hash(NULL), HashCount(0) { assign(other); @@ -1100,13 +1105,6 @@ struct FScriptDelegate class FName FunctionName; // 0x0004 (0x08) }; -// FPointer -// (0x0000 - 0x0004) -struct FPointer -{ - uintptr_t Dummy; // 0x0000 (0x04) -}; - // FQWord // (0x0000 - 0x0008) struct FQWord diff --git a/Engine/Template/PiecesOfCode.hpp b/Engine/Template/PiecesOfCode.hpp index 45f63e7..d67d300 100644 --- a/Engine/Template/PiecesOfCode.hpp +++ b/Engine/Template/PiecesOfCode.hpp @@ -1,4 +1,5 @@ #pragma once + #include /* diff --git a/Framework/Member.hpp b/Framework/Member.hpp index ddd3fac..2737055 100644 --- a/Framework/Member.hpp +++ b/Framework/Member.hpp @@ -1,4 +1,7 @@ #pragma once + +#include + #include #include #include diff --git a/Framework/Printer.cpp b/Framework/Printer.cpp index 4484916..5d3f78d 100644 --- a/Framework/Printer.cpp +++ b/Framework/Printer.cpp @@ -70,7 +70,7 @@ namespace Printer while (replacePos != std::string::npos) { - baseStr.replace(replacePos, strToReplace.length(), replaceWithStr); + baseStr.replace(replacePos, replaceLength, replaceWithStr); replacePos = baseStr.find(strToReplace); } } diff --git a/Framework/Printer.hpp b/Framework/Printer.hpp index 1680f43..62d6c3f 100644 --- a/Framework/Printer.hpp +++ b/Framework/Printer.hpp @@ -1,10 +1,10 @@ #pragma once -#include -#include + +#include + #include #include #include -#include #include enum class EWidthTypes : uint32_t diff --git a/dllmain.cpp b/dllmain.cpp index 482415d..c6523ec 100644 --- a/dllmain.cpp +++ b/dllmain.cpp @@ -1,5 +1,8 @@ #include "dllmain.hpp" +#include +#include + static constexpr uint32_t UNKNOWN_DATA_SPACING = 2; static constexpr uint32_t LOG_FILE_SPACING = 75; static constexpr uint32_t CONST_VALUE_SPACING = 175; @@ -3783,19 +3786,23 @@ namespace Generator } } -void OnAttach(HMODULE hModule) +DWORD OnAttach(HMODULE hModule) { DisableThreadLibraryCalls(hModule); Generator::GenerateSDK(); Generator::DumpInstances(true, true); + + FreeLibraryAndExitThread(hModule, 0); + return 0; } -BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { - switch (ul_reason_for_call) + (void)lpReserved; + switch (dwReason) { case DLL_PROCESS_ATTACH: - CreateThread(nullptr, 0, reinterpret_cast(OnAttach), nullptr, 0, nullptr); + CreateThread(nullptr, 0, reinterpret_cast(OnAttach), hModule, 0, nullptr); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: diff --git a/dllmain.hpp b/dllmain.hpp index 8288551..1775b98 100644 --- a/dllmain.hpp +++ b/dllmain.hpp @@ -1,5 +1,5 @@ #pragma once -#include "pch.hpp" + #include "Framework/Printer.hpp" #include "Engine/Engine.hpp" diff --git a/pch.cpp b/pch.cpp deleted file mode 100644 index 7f3196a..0000000 --- a/pch.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pch.hpp" \ No newline at end of file diff --git a/pch.hpp b/pch.hpp deleted file mode 100644 index 0bbf0b7..0000000 --- a/pch.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#pragma comment(lib, "Psapi.lib") \ No newline at end of file From a5359c8df4ef03848d9c12689094b0251a9f5d90 Mon Sep 17 00:00:00 2001 From: PlayDay <18056374+playday3008@users.noreply.github.com> Date: Tue, 6 Jan 2026 16:24:54 +0100 Subject: [PATCH 2/4] Resturucture project directories to separate source and header files --- CMakeLists.txt | 35 ++++++++++--------- .../Dishonered/Configuration.cpp | 0 .../Dishonered/Configuration.hpp | 0 {Engine => engine}/Dishonered/GameDefines.cpp | 0 {Engine => engine}/Dishonered/GameDefines.hpp | 2 +- .../Dishonered/PiecesOfCode.cpp | 0 .../Dishonered/PiecesOfCode.hpp | 0 {Engine => engine}/Template/Configuration.cpp | 0 {Engine => engine}/Template/Configuration.hpp | 0 {Engine => engine}/Template/GameDefines.cpp | 0 {Engine => engine}/Template/GameDefines.hpp | 2 +- {Engine => engine}/Template/PiecesOfCode.cpp | 0 {Engine => engine}/Template/PiecesOfCode.hpp | 0 {Engine => include}/Engine.hpp | 0 {Framework => include/Framework}/Member.hpp | 0 {Framework => include/Framework}/Printer.hpp | 0 dllmain.hpp => include/dllmain.hpp | 4 +-- {Engine => src}/Engine.cpp | 2 +- {Framework => src/Framework}/Member.cpp | 2 +- {Framework => src/Framework}/Printer.cpp | 4 +-- dllmain.cpp => src/dllmain.cpp | 2 +- 21 files changed, 27 insertions(+), 26 deletions(-) rename {Engine => engine}/Dishonered/Configuration.cpp (100%) rename {Engine => engine}/Dishonered/Configuration.hpp (100%) rename {Engine => engine}/Dishonered/GameDefines.cpp (100%) rename {Engine => engine}/Dishonered/GameDefines.hpp (99%) rename {Engine => engine}/Dishonered/PiecesOfCode.cpp (100%) rename {Engine => engine}/Dishonered/PiecesOfCode.hpp (100%) rename {Engine => engine}/Template/Configuration.cpp (100%) rename {Engine => engine}/Template/Configuration.hpp (100%) rename {Engine => engine}/Template/GameDefines.cpp (100%) rename {Engine => engine}/Template/GameDefines.hpp (99%) rename {Engine => engine}/Template/PiecesOfCode.cpp (100%) rename {Engine => engine}/Template/PiecesOfCode.hpp (100%) rename {Engine => include}/Engine.hpp (100%) rename {Framework => include/Framework}/Member.hpp (100%) rename {Framework => include/Framework}/Printer.hpp (100%) rename dllmain.hpp => include/dllmain.hpp (99%) rename {Engine => src}/Engine.cpp (97%) rename {Framework => src/Framework}/Member.cpp (99%) rename {Framework => src/Framework}/Printer.cpp (99%) rename dllmain.cpp => src/dllmain.cpp (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 31272b0..4994f97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,7 @@ endif() # Auto-detect available engines file(GLOB ENGINE_DIRS LIST_DIRECTORIES TRUE - "${CMAKE_CURRENT_SOURCE_DIR}/Engine/*") + "${CMAKE_CURRENT_SOURCE_DIR}/engine/*") set(AVAILABLE_ENGINES "") foreach(DIR ${ENGINE_DIRS}) @@ -45,7 +45,7 @@ foreach(DIR ${ENGINE_DIRS}) endforeach() if(NOT AVAILABLE_ENGINES) - message(FATAL_ERROR "No engine directories found in Engine/") + message(FATAL_ERROR "No engine directories found in engine/") endif() # Set default engine to the "Template" engine if it exists, otherwise the first available engine @@ -74,24 +74,24 @@ message(STATUS "Using engine: ${ENGINE}") # Source files set(SOURCES - dllmain.cpp - Framework/Member.cpp - Framework/Printer.cpp - Engine/Engine.cpp - Engine/${ENGINE}/Configuration.cpp - Engine/${ENGINE}/GameDefines.cpp - Engine/${ENGINE}/PiecesOfCode.cpp + src/dllmain.cpp + src/Framework/Member.cpp + src/Framework/Printer.cpp + src/Engine.cpp + engine/${ENGINE}/Configuration.cpp + engine/${ENGINE}/GameDefines.cpp + engine/${ENGINE}/PiecesOfCode.cpp ) # Header files set(HEADERS - dllmain.hpp - Framework/Member.hpp - Framework/Printer.hpp - Engine/Engine.hpp - Engine/${ENGINE}/Configuration.hpp - Engine/${ENGINE}/GameDefines.hpp - Engine/${ENGINE}/PiecesOfCode.hpp + include/dllmain.hpp + include/Framework/Member.hpp + include/Framework/Printer.hpp + include/Engine.hpp + engine/${ENGINE}/Configuration.hpp + engine/${ENGINE}/GameDefines.hpp + engine/${ENGINE}/PiecesOfCode.hpp ) # Create shared library (DLL) @@ -101,7 +101,8 @@ add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS}) target_compile_definitions(${PROJECT_NAME} PRIVATE ENGINE=${ENGINE}) # Include directories -target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/engine) # Platform-specific settings if(WIN32) diff --git a/Engine/Dishonered/Configuration.cpp b/engine/Dishonered/Configuration.cpp similarity index 100% rename from Engine/Dishonered/Configuration.cpp rename to engine/Dishonered/Configuration.cpp diff --git a/Engine/Dishonered/Configuration.hpp b/engine/Dishonered/Configuration.hpp similarity index 100% rename from Engine/Dishonered/Configuration.hpp rename to engine/Dishonered/Configuration.hpp diff --git a/Engine/Dishonered/GameDefines.cpp b/engine/Dishonered/GameDefines.cpp similarity index 100% rename from Engine/Dishonered/GameDefines.cpp rename to engine/Dishonered/GameDefines.cpp diff --git a/Engine/Dishonered/GameDefines.hpp b/engine/Dishonered/GameDefines.hpp similarity index 99% rename from Engine/Dishonered/GameDefines.hpp rename to engine/Dishonered/GameDefines.hpp index f93ef75..1ceed15 100644 --- a/Engine/Dishonered/GameDefines.hpp +++ b/engine/Dishonered/GameDefines.hpp @@ -1,7 +1,7 @@ #pragma once #include "Configuration.hpp" -#include "../../Framework/Member.hpp" +#include #include #include diff --git a/Engine/Dishonered/PiecesOfCode.cpp b/engine/Dishonered/PiecesOfCode.cpp similarity index 100% rename from Engine/Dishonered/PiecesOfCode.cpp rename to engine/Dishonered/PiecesOfCode.cpp diff --git a/Engine/Dishonered/PiecesOfCode.hpp b/engine/Dishonered/PiecesOfCode.hpp similarity index 100% rename from Engine/Dishonered/PiecesOfCode.hpp rename to engine/Dishonered/PiecesOfCode.hpp diff --git a/Engine/Template/Configuration.cpp b/engine/Template/Configuration.cpp similarity index 100% rename from Engine/Template/Configuration.cpp rename to engine/Template/Configuration.cpp diff --git a/Engine/Template/Configuration.hpp b/engine/Template/Configuration.hpp similarity index 100% rename from Engine/Template/Configuration.hpp rename to engine/Template/Configuration.hpp diff --git a/Engine/Template/GameDefines.cpp b/engine/Template/GameDefines.cpp similarity index 100% rename from Engine/Template/GameDefines.cpp rename to engine/Template/GameDefines.cpp diff --git a/Engine/Template/GameDefines.hpp b/engine/Template/GameDefines.hpp similarity index 99% rename from Engine/Template/GameDefines.hpp rename to engine/Template/GameDefines.hpp index 52e579e..11d7077 100644 --- a/Engine/Template/GameDefines.hpp +++ b/engine/Template/GameDefines.hpp @@ -1,7 +1,7 @@ #pragma once #include "Configuration.hpp" -#include "../../Framework/Member.hpp" +#include #include #include diff --git a/Engine/Template/PiecesOfCode.cpp b/engine/Template/PiecesOfCode.cpp similarity index 100% rename from Engine/Template/PiecesOfCode.cpp rename to engine/Template/PiecesOfCode.cpp diff --git a/Engine/Template/PiecesOfCode.hpp b/engine/Template/PiecesOfCode.hpp similarity index 100% rename from Engine/Template/PiecesOfCode.hpp rename to engine/Template/PiecesOfCode.hpp diff --git a/Engine/Engine.hpp b/include/Engine.hpp similarity index 100% rename from Engine/Engine.hpp rename to include/Engine.hpp diff --git a/Framework/Member.hpp b/include/Framework/Member.hpp similarity index 100% rename from Framework/Member.hpp rename to include/Framework/Member.hpp diff --git a/Framework/Printer.hpp b/include/Framework/Printer.hpp similarity index 100% rename from Framework/Printer.hpp rename to include/Framework/Printer.hpp diff --git a/dllmain.hpp b/include/dllmain.hpp similarity index 99% rename from dllmain.hpp rename to include/dllmain.hpp index 1775b98..fc9336f 100644 --- a/dllmain.hpp +++ b/include/dllmain.hpp @@ -1,7 +1,7 @@ #pragma once -#include "Framework/Printer.hpp" -#include "Engine/Engine.hpp" +#include +#include class UnrealObject { diff --git a/Engine/Engine.cpp b/src/Engine.cpp similarity index 97% rename from Engine/Engine.cpp rename to src/Engine.cpp index d72eb80..3def255 100644 --- a/Engine/Engine.cpp +++ b/src/Engine.cpp @@ -1,4 +1,4 @@ -#include "Engine.hpp" +#include /* # ========================================================================================= # diff --git a/Framework/Member.cpp b/src/Framework/Member.cpp similarity index 99% rename from Framework/Member.cpp rename to src/Framework/Member.cpp index ce3b1ca..ccb0285 100644 --- a/Framework/Member.cpp +++ b/src/Framework/Member.cpp @@ -1,4 +1,4 @@ -#include "../Engine/Engine.hpp" +#include /* # ========================================================================================= # diff --git a/Framework/Printer.cpp b/src/Framework/Printer.cpp similarity index 99% rename from Framework/Printer.cpp rename to src/Framework/Printer.cpp index 5d3f78d..87cd1cf 100644 --- a/Framework/Printer.cpp +++ b/src/Framework/Printer.cpp @@ -1,5 +1,5 @@ -#include "Printer.hpp" -#include "../Engine/Engine.hpp" +#include +#include namespace Printer { diff --git a/dllmain.cpp b/src/dllmain.cpp similarity index 99% rename from dllmain.cpp rename to src/dllmain.cpp index c6523ec..0e8a18b 100644 --- a/dllmain.cpp +++ b/src/dllmain.cpp @@ -1,4 +1,4 @@ -#include "dllmain.hpp" +#include #include #include From cb0df58e3a1aa8ee628d98f2b3772decc4557109 Mon Sep 17 00:00:00 2001 From: PlayDay <18056374+playday3008@users.noreply.github.com> Date: Tue, 6 Jan 2026 16:46:14 +0100 Subject: [PATCH 3/4] Update the README and CMakeLists.txt to reflect recent changes - Renamed Dishonered to Dishonored --- CMakeLists.txt | 2 +- README.md | 29 ++++++++++++------- .../Configuration.cpp | 2 +- .../Configuration.hpp | 0 .../GameDefines.cpp | 0 .../GameDefines.hpp | 0 .../PiecesOfCode.cpp | 0 .../PiecesOfCode.hpp | 0 8 files changed, 20 insertions(+), 13 deletions(-) rename engine/{Dishonered => Dishonored}/Configuration.cpp (99%) rename engine/{Dishonered => Dishonored}/Configuration.hpp (100%) rename engine/{Dishonered => Dishonored}/GameDefines.cpp (100%) rename engine/{Dishonered => Dishonored}/GameDefines.hpp (100%) rename engine/{Dishonered => Dishonored}/PiecesOfCode.cpp (100%) rename engine/{Dishonered => Dishonored}/PiecesOfCode.hpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4994f97..50f6f80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.20) # Define the project project(CodeRedGenerator DESCRIPTION "Unreal Engine 3 SDK Generator" - VERSION 1.1.7 + VERSION 1.2.0 LANGUAGES CXX C) # Generate compile_commands.json for IDE integration diff --git a/README.md b/README.md index b7fdf3c..4ee3ec3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## CodeRed Generator 3 (v1.1.7) +## CodeRed Generator 3 (v1.2.0) This is a C++20 Unreal Engine 3 SDK generator that was originally based off the source of [TheFeckless's UE3 SDK Generator](https://www.unknowncheats.me/forum/unreal-engine-3-a/71911-thefeckless-ue3-sdk-generator.html). It has since grown into its own project which utilizes C++20, strings, filesystem paths, and modern file streams; along with converting legacy UE3 features to more modern and user friendly ones while still being compatible with UE3. @@ -11,7 +11,7 @@ Final generated SDK is plug and play, just `#include "SdkHeaders.hpp"` in your p You have the option to generate an SDK using either offsets or patterns for GObjects and GNames. - **Class Alignment** -Full support for both x32 bit and x64 bit games, just change the `Alignment` value in `Configuration.cpp`. +Full support for both x32 bit and x64 bit games, just change the `Alignment` value in [Configuration.cpp](engine/Template/Configuration.cpp). - **Full Customization** You have full customization over the final generated SDK, use enum classes, remove native flags, class alignment, and even comment spacing. @@ -19,15 +19,16 @@ You have full customization over the final generated SDK, use enum classes, remo ### Requirements - ISO C++20 Standard. -- Visual Studio or another Windows based compiler (For Windows header files, along with the PSAPI library). +- CMake 3.20 or higher. +- A Windows-based compiler such as MSVC or MinGW (for Windows header files and the PSAPI library). ## Getting Started -Included in this project is a template folder located in `Engine/Template`, to get started copy and paste this folder and rename it to the game you would like to use. To generate from your newly created engine folder don't forget to change the includes in the `Engine.hpp` file. +Included in this project is a template folder located in [engine/Template](engine/Template), to get started copy and paste this folder and rename it to the game you would like to use. -In the `Configuration.hpp` file there are two defines, one is `NO_LOGGING` which disables writing to a log file, and another define called `UTF16`. If your game is using wide characters you will need to uncomment this define out, if not `UTF8` will be used by default. +In the [Configuration.hpp](engine/Template/Configuration.hpp) file there are two defines, one is `NO_LOGGING` which disables writing to a log file, and another define called `UTF16`. If your game is using wide characters you will need to uncomment this define out, if not `UTF8` will be used by default. -Any further configuration **MUST BE DONE IN THE `Configuration.cpp` ONLY!** This file contains everything from class alignment, process event settings, global patterns and offsets, your games name and version, and most importantly the directory used for SDK generation. +Any further configuration **MUST BE DONE IN THE [Configuration.cpp](engine/Template/Configuration.cpp) ONLY!** This file contains everything from class alignment, process event settings, global patterns and offsets, your games name and version, and most importantly the directory used for SDK generation. ![](https://i.imgur.com/q2tFJ7I.png) @@ -37,16 +38,22 @@ Any further configuration **MUST BE DONE IN THE `Configuration.cpp` ONLY!** This ## Generation -Once you have your custom engine folder setup, all that's left is to fill out your class and struct fields for your game. This generator uses a unique `REGISTER_MEMBER` macro to define class/struct members. This is very important for your final generated SDK as it's used to calculate offsets and unknown data all automatically, without needing to modify your `PiecesOfCode.cpp` unlike in Feckless's generator. +Once you have your custom engine folder setup, all that's left is to fill out your class and struct fields for your game. This generator uses a unique `REGISTER_MEMBER` macro to define class/struct members. This is very important for your final generated SDK as it's used to calculate offsets and unknown data all automatically, without needing to modify your [PiecesOfCode.cpp](engine/Template/PiecesOfCode.cpp) unlike in Feckless's generator. Any class/struct member outside of whats in the `EMemberTypes` does NOT need to be registered with the `REGISTER_MEMBER` macro, so feel free to place padding or buffers in between. ![](https://i.imgur.com/k9vawPv.png) -Once all your classes are filled out and you've made the necessary changes in `Configuration.cpp`, double check you didn't forget to set an out path in `Configuration.cpp` and have the right files included in `Engine.hpp`. After that just compile as a DLL and manually inject into your game, generation will start automatically and will prompt you when it is completed. +Once all your classes are filled out and you've made the necessary changes in [Configuration.cpp](engine/Template/Configuration.cpp), double check you didn't forget to set an output path. After that build the project and manually inject the DLL into your game. Generation will start automatically and will prompt you when it is completed. ## Changelog +### v1.2.0 +- Replaced Visual Studio solution with CMake for cross-compiler support. +- Restructured project directories: source files are now in [src/](src/), headers in [include/](include/), and engine configurations in [engine/](engine/). +- Removed precompiled headers (PCH) for simpler builds. +- CMake auto-detects available engines and allows selection via `-DENGINE=`. + ### v1.1.7 - Removed the "UnrealProperty::CantMemcpy" function in favor of the new one "UnrealProperty::ShouldMemcpy()". - Fixed there being a trailing semicolon generated in the "GenerateFunctionCode" function. @@ -61,8 +68,8 @@ Once all your classes are filled out and you've made the necessary changes in `C - Moved the "CreateValidName" and "CreateWindowsFunction" functions inside of the "UnrealObject" class. - Fixed the comment spacing for classes using the struct spacing instead of class spacing from your config file. -### v1.1.4 -- Added a new engine folder for Dishonered, which contains all needed fields to generate an sdk for that game. +### v1.1.4 +- Added a new engine folder for Dishonored, which contains all needed fields to generate an sdk for that game. - Added extra safety checks for the string helper functions in "Printer.hpp/cpp". - Fixed the object flag values in "GameDefines.hpp" and also "PiecesOfCodes.cpp". - Updated the "FindClass" and "FindFunction" functions slightly. @@ -149,4 +156,4 @@ Once all your classes are filled out and you've made the necessary changes in `C - Decided to replace the "ZeroMemory" macro with use memset instead, "ZeroMemory" calls this anyway. ### v1.0.1 -- Added an include for "Windows.h" in the generated "GameDefines.hpp" file, this is needed for the "ZeroMemory" maco. \ No newline at end of file +- Added an include for "Windows.h" in the generated "GameDefines.hpp" file, this is needed for the "ZeroMemory" maco. diff --git a/engine/Dishonered/Configuration.cpp b/engine/Dishonored/Configuration.cpp similarity index 99% rename from engine/Dishonered/Configuration.cpp rename to engine/Dishonored/Configuration.cpp index 97cdc55..f5c6155 100644 --- a/engine/Dishonered/Configuration.cpp +++ b/engine/Dishonored/Configuration.cpp @@ -287,7 +287,7 @@ const std::string& GConfig::GetGNameMask() */ // Mainly just used for the printed headers at the top of each generated file. -std::string GConfig::m_gameNameLong = "Dishonered"; +std::string GConfig::m_gameNameLong = "Dishonored"; // This is used for the output folder name, along with the printed headers at the top of each file. std::string GConfig::m_gameNameShort = "DSDK"; diff --git a/engine/Dishonered/Configuration.hpp b/engine/Dishonored/Configuration.hpp similarity index 100% rename from engine/Dishonered/Configuration.hpp rename to engine/Dishonored/Configuration.hpp diff --git a/engine/Dishonered/GameDefines.cpp b/engine/Dishonored/GameDefines.cpp similarity index 100% rename from engine/Dishonered/GameDefines.cpp rename to engine/Dishonored/GameDefines.cpp diff --git a/engine/Dishonered/GameDefines.hpp b/engine/Dishonored/GameDefines.hpp similarity index 100% rename from engine/Dishonered/GameDefines.hpp rename to engine/Dishonored/GameDefines.hpp diff --git a/engine/Dishonered/PiecesOfCode.cpp b/engine/Dishonored/PiecesOfCode.cpp similarity index 100% rename from engine/Dishonered/PiecesOfCode.cpp rename to engine/Dishonored/PiecesOfCode.cpp diff --git a/engine/Dishonered/PiecesOfCode.hpp b/engine/Dishonored/PiecesOfCode.hpp similarity index 100% rename from engine/Dishonered/PiecesOfCode.hpp rename to engine/Dishonored/PiecesOfCode.hpp From 6e1de0d59548c3cba6cb12544b7b54f818582381 Mon Sep 17 00:00:00 2001 From: PlayDay <18056374+playday3008@users.noreply.github.com> Date: Wed, 7 Jan 2026 05:04:46 +0100 Subject: [PATCH 4/4] Enhance project structure and code quality - Updated .gitignore to include Visual Studio and CMake generated files. - Modified CMakeLists.txt to improve project organization, add versioning, and enhance compiler settings. - Introduced utils.hpp and utils.cpp for utility functions, including message box handling. - Added version.hpp.in for project versioning macros. --- .gitignore | 18 ++ .vscode/settings.json | 5 + CMakeLists.txt | 214 ++++++++++++++----- CMakeSettings.json | 92 ++++++++ engine/Dishonored/GameDefines.hpp | 14 +- engine/Dishonored/PiecesOfCode.cpp | 6 +- engine/Template/GameDefines.hpp | 6 +- engine/Template/PiecesOfCode.cpp | 6 +- include/Engine.hpp | 18 +- include/dllmain.hpp | 8 +- include/utils.hpp | 17 ++ src/Engine.cpp | 21 +- src/dllmain.cpp | 147 +++++-------- src/utils.cpp | 325 +++++++++++++++++++++++++++++ version.hpp.in | 6 + 15 files changed, 724 insertions(+), 179 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 CMakeSettings.json create mode 100644 include/utils.hpp create mode 100644 src/utils.cpp create mode 100644 version.hpp.in diff --git a/.gitignore b/.gitignore index c30e365..3d1917d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,23 @@ # Cache files .cache/ +# Visual Studio cache/options directory +.vs + +# CMake generated files +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps +CMakeUserPresets.json +include/version.hpp + # Build output build/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..40f70cf --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cmake.configureArgs": [ + "-DCMAKE_SYSTEM_NAME=Windows" + ] +} diff --git a/CMakeLists.txt b/CMakeLists.txt index 50f6f80..8479852 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,8 +9,11 @@ cmake_minimum_required(VERSION 3.20) project(CodeRedGenerator DESCRIPTION "Unreal Engine 3 SDK Generator" VERSION 1.2.0 + HOMEPAGE_URL "https://github.com/CodeRedModding/CodeRed-Generator" LANGUAGES CXX C) +configure_file(version.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/include/version.hpp @ONLY) + # Generate compile_commands.json for IDE integration set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -20,11 +23,16 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD 17) set(CMAKE_C_STANDARD_REQUIRED ON) +# Organize targets into folders in IDEs that support it +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + # Enable all, extra, and pedantic warnings -if(MSVC) +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") add_compile_options(/W4) -else() +elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") add_compile_options(-Wall -Wextra -Wpedantic) +else() + message(WARNING "Unknown compiler: ${CMAKE_CXX_COMPILER_ID}. Warning flags not set.") endif() # -------------------- @@ -57,7 +65,7 @@ endif() # Option to select the engine set(ENGINE "${DEFAULT_ENGINE}" CACHE STRING "Select the engine to build with") -set_property(CACHE ENGINE PROPERTY STRINGS ${ENGINE_DIRS}) +set_property(CACHE ENGINE PROPERTY STRINGS ${AVAILABLE_ENGINES}) # Validate selected engine list(FIND AVAILABLE_ENGINES "${ENGINE}" ENGINE_INDEX) @@ -72,30 +80,52 @@ message(STATUS "Using engine: ${ENGINE}") # Build Configuration # ------------------- +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + # Source files set(SOURCES - src/dllmain.cpp - src/Framework/Member.cpp - src/Framework/Printer.cpp - src/Engine.cpp - engine/${ENGINE}/Configuration.cpp - engine/${ENGINE}/GameDefines.cpp - engine/${ENGINE}/PiecesOfCode.cpp + "src/dllmain.cpp" + "src/utils.cpp" + "src/Framework/Member.cpp" + "src/Framework/Printer.cpp" + "src/Engine.cpp" ) # Header files set(HEADERS - include/dllmain.hpp - include/Framework/Member.hpp - include/Framework/Printer.hpp - include/Engine.hpp - engine/${ENGINE}/Configuration.hpp - engine/${ENGINE}/GameDefines.hpp - engine/${ENGINE}/PiecesOfCode.hpp + "include/version.hpp" + "include/dllmain.hpp" + "include/utils.hpp" + "include/Framework/Member.hpp" + "include/Framework/Printer.hpp" + "include/Engine.hpp" ) +# Engine files +set(ENGINE_SOURCES + "engine/${ENGINE}/Configuration.cpp" + "engine/${ENGINE}/GameDefines.cpp" + "engine/${ENGINE}/PiecesOfCode.cpp" +) +set(ENGINE_HEADERS + "engine/${ENGINE}/Configuration.hpp" + "engine/${ENGINE}/GameDefines.hpp" + "engine/${ENGINE}/PiecesOfCode.hpp" +) + +# Organize source and header files into groups for IDEs +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/engine" + PREFIX "Engine Files" + FILES ${ENGINE_SOURCES} ${ENGINE_HEADERS}) +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/src" + PREFIX "Source Files" + FILES ${SOURCES}) +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/include" + PREFIX "Header Files" + FILES ${HEADERS}) + # Create shared library (DLL) -add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS}) +add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS} ${ENGINE_SOURCES} ${ENGINE_HEADERS}) # Define the selected engine target_compile_definitions(${PROJECT_NAME} PRIVATE ENGINE=${ENGINE}) @@ -104,48 +134,138 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE ENGINE=${ENGINE}) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/engine) -# Platform-specific settings -if(WIN32) - # Unicode character set +# -------------------------- +# Compiler-Specific Settings +# -------------------------- + +# Compiler definitions +target_compile_definitions(${PROJECT_NAME} PRIVATE + $<$:_DEBUG> +) + +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # Compiler definitions target_compile_definitions(${PROJECT_NAME} PRIVATE - UNICODE - _UNICODE - _CONSOLE $<$:_DEBUG> - $<$:NDEBUG> + _CONSOLE + _WINDLL + _UNICODE + UNICODE ) - # Add WIN32 definition for 32-bit builds - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - target_compile_definitions(${PROJECT_NAME} PRIVATE WIN32) - endif() + # Compiler options + target_compile_options(${PROJECT_NAME} PRIVATE + /fp:precise # Precise floating-point model + /Gd # __cdecl calling convention + /GS # Buffer security checks + /Oy- # Disable frame pointer omission + /permissive- # Standards conformance + /sdl # SDL (Security Development Lifecycle) checks + /Zc:wchar_t # Treat wchar_t as a native type + /Zc:inline # Enforce inline semantics + /Zc:forScope # Enforce for-scope semantics + + # Enable optimizations + $<$:/GL> + $<$:/GL> + $<$:/GL> - # MSVC-specific settings - if(MSVC) - # Warning level 3 - target_compile_options(${PROJECT_NAME} PRIVATE /W3) + # Function-level linking + $<$:/Gy> + $<$:/Gy> + $<$:/Gy> - # SDL checks - target_compile_options(${PROJECT_NAME} PRIVATE /sdl) + # Intrinsic functions + $<$:/Oi> + $<$:/Oi> + ) - # Conformance mode - target_compile_options(${PROJECT_NAME} PRIVATE /permissive-) + # Linker definitions + target_link_options(${PROJECT_NAME} PRIVATE + /NXCOMPAT # Non-executable memory protection + /SUBSYSTEM:CONSOLE # Console subsystem + $<$:/SAFESEH> - # Release optimizations - target_compile_options(${PROJECT_NAME} PRIVATE - $<$:/Gy> # Function-level linking - $<$:/Oi> # Intrinsic functions - ) + # Incremental linking + $<$:/LTCG:incremental> + $<$:/LTCG:incremental> + $<$:/LTCG:incremental> + + # Optimization settings + $<$:/OPT:REF> + $<$:/OPT:ICF> + $<$:/OPT:REF> + $<$:/OPT:ICF> + $<$:/OPT:REF> + $<$:/OPT:ICF> + ) +elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + # Compiler options + target_compile_options(${PROJECT_NAME} PRIVATE + -fms-extensions # Enable MS extensions + -fstack-protector-strong # Buffer security checks (equivalent to /GS) + -fno-omit-frame-pointer # Disable frame pointer omission (equivalent to /Oy-) + + # Enable optimizations for Release builds + $<$:-flto=auto> + $<$:-flto=auto> + $<$:-flto=auto> - # Linker settings - target_link_options(${PROJECT_NAME} PRIVATE - /SUBSYSTEM:CONSOLE - $<$:/OPT:REF> # Optimize references - $<$:/OPT:ICF> # COMDAT folding + # Function-level linking (equivalent to /Gy) + $<$:-ffunction-sections> + $<$:-fdata-sections> + $<$:-ffunction-sections> + $<$:-fdata-sections> + $<$:-ffunction-sections> + $<$:-fdata-sections> + ) + + # Linker options + target_link_options(${PROJECT_NAME} PRIVATE + # Link-time optimization for Release builds + $<$:-flto=auto> + $<$:-flto=auto> + $<$:-flto=auto> + + # Dead code elimination (equivalent to /OPT:REF and /OPT:ICF) + $<$:-Wl,--gc-sections> + $<$:-Wl,--gc-sections> + $<$:-Wl,--gc-sections> + -fno-use-linker-plugin + ) + + #if MinGW, disable linker plugin usage + if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_link_libraries(${PROJECT_NAME} PRIVATE + -fno-use-linker-plugin ) endif() +else() + message(WARNING "Unknown compiler: ${CMAKE_CXX_COMPILER_ID}. Compiler-specific settings not applied.") endif() +# -------------------------- +# Platform-Specific Settings +# -------------------------- + +if(WIN32) + # Link against necessary system libraries + target_link_libraries(${PROJECT_NAME} PRIVATE + psapi + ) +elseif(UNIX) + # Link against necessary system libraries + target_link_libraries(${PROJECT_NAME} PRIVATE + pthread + ) +else() + message(WARNING "Unknown platform: ${CMAKE_SYSTEM_NAME}. Platform-specific settings not applied.") +endif() + +# -------------------- +# Output Configuration +# -------------------- + # Set output directory set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 0000000..de6465a --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,92 @@ +{ + "configurations": [ + { + "name": "x86-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x86" ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + "name": "x86-Release", + "generator": "Ninja", + "configurationType": "Release", + "inheritEnvironments": [ "msvc_x86" ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + "name": "x86-RelWithDebInfo", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "inheritEnvironments": [ "msvc_x86" ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + "name": "x86-MinSizeRel", + "generator": "Ninja", + "configurationType": "MinSizeRel", + "inheritEnvironments": [ "msvc_x86" ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64" ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "Release", + "inheritEnvironments": [ "msvc_x64" ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + "name": "x64-RelWithDebInfo", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "inheritEnvironments": [ "msvc_x64" ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + "name": "x64-MinSizeRel", + "generator": "Ninja", + "configurationType": "MinSizeRel", + "inheritEnvironments": [ "msvc_x64" ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + } + ] +} \ No newline at end of file diff --git a/engine/Dishonored/GameDefines.hpp b/engine/Dishonored/GameDefines.hpp index 1ceed15..c49dff6 100644 --- a/engine/Dishonored/GameDefines.hpp +++ b/engine/Dishonored/GameDefines.hpp @@ -4,8 +4,6 @@ #include #include -#include -#include #include #include @@ -578,12 +576,12 @@ class TMap public: TMap() : - IndirectData(NULL), + IndirectData(0), NumBits(0), MaxBits(0), FirstFreeIndex(0), NumFreeIndices(0), - Hash(NULL), + Hash(0), InlineHash(0), HashSize(0) { @@ -591,12 +589,12 @@ class TMap } TMap(struct FMap_Mirror& other) : - IndirectData(NULL), + IndirectData(0), NumBits(0), MaxBits(0), FirstFreeIndex(0), NumFreeIndices(0), - Hash(NULL), + Hash(0), InlineHash(0), HashSize(0) { @@ -604,12 +602,12 @@ class TMap } TMap(const TMap& other) : - IndirectData(NULL), + IndirectData(0), NumBits(0), MaxBits(0), FirstFreeIndex(0), NumFreeIndices(0), - Hash(NULL), + Hash(0), InlineHash(0), HashSize(0) { diff --git a/engine/Dishonored/PiecesOfCode.cpp b/engine/Dishonored/PiecesOfCode.cpp index 99a7099..abcd486 100644 --- a/engine/Dishonored/PiecesOfCode.cpp +++ b/engine/Dishonored/PiecesOfCode.cpp @@ -271,7 +271,7 @@ namespace PiecesOfCode "\t\tMaxBits(0),\n" "\t\tFirstFreeIndex(0),\n" "\t\tNumFreeIndices(0),\n" - "\t\tHash(nullptr),\n" + "\t\tHash(NULL),\n" "\t\tInlineHash(0),\n" "\t\tHashSize(0)\n" "\t{\n" @@ -284,7 +284,7 @@ namespace PiecesOfCode "\t\tMaxBits(0),\n" "\t\tFirstFreeIndex(0),\n" "\t\tNumFreeIndices(0),\n" - "\t\tHash(nullptr),\n" + "\t\tHash(NULL),\n" "\t\tInlineHash(0),\n" "\t\tHashSize(0)\n" "\t{\n" @@ -297,7 +297,7 @@ namespace PiecesOfCode "\t\tMaxBits(0),\n" "\t\tFirstFreeIndex(0),\n" "\t\tNumFreeIndices(0),\n" - "\t\tHash(nullptr),\n" + "\t\tHash(NULL),\n" "\t\tInlineHash(0),\n" "\t\tHashSize(0)\n" "\t{\n" diff --git a/engine/Template/GameDefines.hpp b/engine/Template/GameDefines.hpp index 11d7077..1c692fa 100644 --- a/engine/Template/GameDefines.hpp +++ b/engine/Template/GameDefines.hpp @@ -579,7 +579,7 @@ class TMap public: TMap() : - IndirectData(NULL), + IndirectData(0), NumBits(0), MaxBits(0), FirstFreeIndex(0), @@ -592,7 +592,7 @@ class TMap } TMap(struct FMap_Mirror& other) : - IndirectData(NULL), + IndirectData(0), NumBits(0), MaxBits(0), FirstFreeIndex(0), @@ -605,7 +605,7 @@ class TMap } TMap(const TMap& other) : - IndirectData(NULL), + IndirectData(0), NumBits(0), MaxBits(0), FirstFreeIndex(0), diff --git a/engine/Template/PiecesOfCode.cpp b/engine/Template/PiecesOfCode.cpp index 8e889d6..40e82cc 100644 --- a/engine/Template/PiecesOfCode.cpp +++ b/engine/Template/PiecesOfCode.cpp @@ -271,7 +271,7 @@ namespace PiecesOfCode "\t\tFirstFreeIndex(0),\n" "\t\tNumFreeIndices(0),\n" "\t\tInlineHash(0),\n" - "\t\tHash(nullptr),\n" + "\t\tHash(NULL),\n" "\t\tHashCount(0)\n" "\t{\n" "\n" @@ -284,7 +284,7 @@ namespace PiecesOfCode "\t\tFirstFreeIndex(0),\n" "\t\tNumFreeIndices(0),\n" "\t\tInlineHash(0),\n" - "\t\tHash(nullptr),\n" + "\t\tHash(NULL),\n" "\t\tHashCount(0)\n" "\t{\n" "\t\tassign(other);\n" @@ -297,7 +297,7 @@ namespace PiecesOfCode "\t\tFirstFreeIndex(0),\n" "\t\tNumFreeIndices(0),\n" "\t\tInlineHash(0),\n" - "\t\tHash(nullptr),\n" + "\t\tHash(NULL),\n" "\t\tHashCount(0)\n" "\t{\n" "\t\tassign(other);\n" diff --git a/include/Engine.hpp b/include/Engine.hpp index 4b45aa5..8fcc199 100644 --- a/include/Engine.hpp +++ b/include/Engine.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include // Preprocessor helpers for computed includes #define STRINGIFY_IMPL(x) #x @@ -22,16 +22,16 @@ class GEngine { private: - static std::string m_name; - static std::string m_version; - static std::string m_credits; - static std::string m_links; + static std::string_view m_name; + static std::string_view m_version; + static std::string_view m_credits; + static std::string_view m_links; public: - static const std::string& GetName(); - static const std::string& GetVersion(); - static const std::string& GetCredits(); - static const std::string& GetLinks(); + static const std::string_view& GetName(); + static const std::string_view& GetVersion(); + static const std::string_view& GetCredits(); + static const std::string_view& GetLinks(); public: GEngine() = delete; diff --git a/include/dllmain.hpp b/include/dllmain.hpp index fc9336f..a8c23cf 100644 --- a/include/dllmain.hpp +++ b/include/dllmain.hpp @@ -177,9 +177,9 @@ class GLogger namespace Utils { - void MessageboxInfo(const std::string& message); - void MessageboxWarn(const std::string& message); - void MessageboxError(const std::string& message); + void MessageBoxInfo(const std::string_view& message); + void MessageBoxWarn(const std::string_view& message); + void MessageBoxError(const std::string_view& message); bool SortProperty(const UnrealProperty& unrealPropA, const UnrealProperty& unrealPropB); bool SortPropertyPair(const std::pair& pairA, const std::pair& pairB); @@ -193,7 +193,7 @@ namespace Retrievers uintptr_t GetBaseAddress(); uintptr_t GetOffset(void* pointer); - uintptr_t FindPattern(const uint8_t* pattern, const std::string& mask); + uintptr_t FindPattern(const std::basic_string_view& pattern, const std::string_view& mask); } namespace ConstGenerator diff --git a/include/utils.hpp b/include/utils.hpp new file mode 100644 index 0000000..da97932 --- /dev/null +++ b/include/utils.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +namespace Utils +{ + void MessageBoxInfo(const std::string_view& message); + void MessageBoxWarn(const std::string_view& message); + void MessageBoxError(const std::string_view& message); +} + +namespace Retrievers +{ + uintptr_t GetBaseAddress(); + uintptr_t FindPattern(const std::basic_string_view& pattern, const std::string_view& mask); +} diff --git a/src/Engine.cpp b/src/Engine.cpp index 3def255..ec037d5 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -1,35 +1,34 @@ #include +#include + /* # ========================================================================================= # # Engine # ========================================================================================= # */ -std::string GEngine::m_name = "CodeRedGenerator"; - -std::string GEngine::m_version = "v1.1.7"; - -std::string GEngine::m_credits = "ItsBranK, TheFeckless"; - -std::string GEngine::m_links = "www.github.com/CodeRedModding/CodeRed-Generator"; +std::string_view GEngine::m_name = PROJECT_NAME; +std::string_view GEngine::m_version = PROJECT_VERSION; +std::string_view GEngine::m_credits = PROJECT_AUTHORS; +std::string_view GEngine::m_links = PROJECT_HOMEPAGE_URL; -const std::string& GEngine::GetName() +const std::string_view& GEngine::GetName() { return m_name; } -const std::string& GEngine::GetVersion() +const std::string_view& GEngine::GetVersion() { return m_version; } -const std::string& GEngine::GetCredits() +const std::string_view& GEngine::GetCredits() { return m_credits; } -const std::string& GEngine::GetLinks() +const std::string_view& GEngine::GetLinks() { return m_links; } diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 0e8a18b..dc435aa 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -1,7 +1,6 @@ #include -#include -#include +#include static constexpr uint32_t UNKNOWN_DATA_SPACING = 2; static constexpr uint32_t LOG_FILE_SPACING = 75; @@ -959,12 +958,12 @@ bool GLogger::Open() if (std::filesystem::exists(fullDirectory)) { - m_file.open(fullDirectory / (GEngine::GetName() + ".log")); + m_file.open(fullDirectory / (std::format("{}.log", GEngine::GetName()))); return true; } else { - Utils::MessageboxError("Error: Failed to create the log file, might not have the right permissions or your directory is invalid!"); + Utils::MessageBoxError("Error: Failed to create the log file, might not have the right permissions or your directory is invalid!"); } } #endif @@ -1053,34 +1052,6 @@ void GLogger::LogStructPadding(class UScriptStruct* uScriptStruct, size_t paddin namespace Utils { - void MessageboxExt(const std::string& message, uint32_t flags) - { -#ifdef _WIN32 - MessageBoxA(NULL, message.c_str(), GEngine::GetName().c_str(), flags); -#endif - } - - void MessageboxInfo(const std::string& message) - { -#ifdef _WIN32 - MessageboxExt(message, (MB_OK | MB_ICONINFORMATION)); -#endif - } - - void MessageboxWarn(const std::string& message) - { -#ifdef _WIN32 - MessageboxExt(message, (MB_OK | MB_ICONWARNING)); -#endif - } - - void MessageboxError(const std::string& message) - { -#ifdef _WIN32 - MessageboxExt(message, (MB_OK | MB_ICONERROR)); -#endif - } - bool SortProperty(const UnrealProperty& unrealPropA, const UnrealProperty& unrealPropB) { if (unrealPropA.Property && unrealPropB.Property) @@ -1270,11 +1241,6 @@ namespace Retrievers } } - uintptr_t GetBaseAddress() - { - return reinterpret_cast(GetModuleHandle(NULL)); - } - uintptr_t GetOffset(void* pointer) { uintptr_t baseAddress = GetBaseAddress(); @@ -1285,45 +1251,7 @@ namespace Retrievers return (address - baseAddress); } - return NULL; - } - - uintptr_t FindPattern(const uint8_t* pattern, const std::string& mask) - { - if (pattern && !mask.empty()) - { - MODULEINFO miInfos; - ZeroMemory(&miInfos, sizeof(MODULEINFO)); - - HMODULE hModule = GetModuleHandle(NULL); - K32GetModuleInformation(GetCurrentProcess(), hModule, &miInfos, sizeof(MODULEINFO)); - - uintptr_t start = reinterpret_cast(hModule); - uintptr_t end = (start + miInfos.SizeOfImage); - - size_t currentPos = 0; - size_t maskLength = (mask.length() - 1); - - for (uintptr_t retAddress = start; retAddress < end; retAddress++) - { - if (*reinterpret_cast(retAddress) == pattern[currentPos] || mask[currentPos] == '?') - { - if (currentPos == maskLength) - { - return (retAddress - maskLength); - } - - currentPos++; - } - else - { - retAddress -= currentPos; - currentPos = 0; - } - } - } - - return NULL; + return 0; } } @@ -1616,7 +1544,7 @@ namespace StructGenerator #ifndef NO_LOGGING GLogger::Log("Error: No registered members found for struct type \"" + Member::GetName(structType) + "\"!"); #endif - Utils::MessageboxError("Error: No registered members found for struct type \"" + Member::GetName(structType) + "\"!"); + Utils::MessageBoxError("Error: No registered members found for struct type \"" + Member::GetName(structType) + "\"!"); } } } @@ -2120,7 +2048,7 @@ namespace ClassGenerator #ifndef NO_LOGGING GLogger::LogClassSize(uClass, localSize); #endif - Utils::MessageboxError("Error: Incorrect class size detected for \"" + Member::GetName(classType) + "\", check the log file for more details!"); + Utils::MessageBoxError("Error: Incorrect class size detected for \"" + Member::GetName(classType) + "\", check the log file for more details!"); } } else @@ -2128,7 +2056,7 @@ namespace ClassGenerator #ifndef NO_LOGGING GLogger::Log("Error: No registered members found for class \"" + uClass->GetName() + "\"!"); #endif - Utils::MessageboxError("Error: No registered members found for \"" + Member::GetName(classType) + "\"!"); + Utils::MessageBoxError("Error: No registered members found for \"" + Member::GetName(classType) + "\"!"); } } } @@ -2715,7 +2643,7 @@ namespace FunctionGenerator else { stream << "\n\t// FIX PROCESSEVENT IN CONFIGURATION.CPP, INVALID INDEX"; - Utils::MessageboxWarn("Warning: ProcessEvent is not configured correctly in \"Configuration.cpp\", you set \"UsingIndex\" to true yet you did not provide a valid index for process event!"); + Utils::MessageBoxWarn("Warning: ProcessEvent is not configured correctly in \"Configuration.cpp\", you set \"UsingIndex\" to true yet you did not provide a valid index for process event!"); } if (processEventAddress) @@ -2742,7 +2670,7 @@ namespace FunctionGenerator else { stream << "\n\t// FIX PROCESSEVENT IN CONFIGURATION.CPP, INVALID ADDRESS"; - Utils::MessageboxWarn("Warning: ProcessEvent is not configured correctly in \"Configuration.cpp\", failed to find a valid address!"); + Utils::MessageBoxWarn("Warning: ProcessEvent is not configured correctly in \"Configuration.cpp\", failed to find a valid address!"); } } @@ -3493,7 +3421,7 @@ namespace Generator } else { - Utils::MessageboxError("Failed locate the given directory, cannot generate an SDK!"); + Utils::MessageBoxError("Failed locate the given directory, cannot generate an SDK!"); } } @@ -3510,7 +3438,7 @@ namespace Generator { if (Initialize(true)) { - Utils::MessageboxInfo("SDK generation has started, do not close the game until prompted to do so!"); + Utils::MessageBoxInfo("SDK generation has started, do not close the game until prompted to do so!"); std::chrono::time_point startTime = std::chrono::system_clock::now(); ProcessPackages(headerDirectory); @@ -3527,12 +3455,12 @@ namespace Generator GLogger::Close(); #endif - Utils::MessageboxInfo("SDK generation complete, finished in " + formattedTime + " seconds!"); + Utils::MessageBoxInfo("SDK generation complete, finished in " + formattedTime + " seconds!"); } } else { - Utils::MessageboxError("Failed to create the desired directory, cannot generate an SDK!"); + Utils::MessageBoxError("Failed to create the desired directory, cannot generate an SDK!"); } } @@ -3540,7 +3468,7 @@ namespace Generator { if (!GConfig::HasOutputPath()) { - Utils::MessageboxError("Looks like you forgot to set an output path for the generator! Please edit the output path in \"Configuration.cpp\" and recompile."); + Utils::MessageBoxError("Looks like you forgot to set an output path for the generator! Please edit the output path in \"Configuration.cpp\" and recompile."); return false; } @@ -3622,7 +3550,7 @@ namespace Generator } else { - Utils::MessageboxError("Failed to validate GObject & GNames, please make sure you have them configured properly in \"Configuration.cpp\"!"); + Utils::MessageBoxError("Failed to validate GObject & GNames, please make sure you have them configured properly in \"Configuration.cpp\"!"); return false; } } @@ -3657,7 +3585,7 @@ namespace Generator DumpGObjects(); } - Utils::MessageboxInfo("Finished dumping instances!"); + Utils::MessageBoxInfo("Finished dumping instances!"); } } @@ -3786,11 +3714,22 @@ namespace Generator } } -DWORD OnAttach(HMODULE hModule) +void Start() { - DisableThreadLibraryCalls(hModule); + Utils::MessageBoxInfo("Ready to generate SDK!"); Generator::GenerateSDK(); Generator::DumpInstances(true, true); +} + +#ifdef _WIN32 + +#include + +DWORD OnAttach(HMODULE hModule) +{ + DisableThreadLibraryCalls(hModule); + + Start(); FreeLibraryAndExitThread(hModule, 0); return 0; @@ -3810,4 +3749,30 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) break; } return TRUE; -} \ No newline at end of file +} + +#elif __linux__ + +#include + +void* OnAttach(void* arg) +{ + (void)arg; + + Start(); + + pthread_exit(nullptr); + return nullptr; +} + +__attribute__((constructor)) void DllMain() +{ + pthread_t thread; + pthread_create(&thread, nullptr, OnAttach, nullptr); +} + +#else + +#error Unsupported platform! + +#endif diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..0d2fa59 --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,325 @@ +#include + +#include + +#ifdef _WIN32 + +#include +#include + +namespace Utils +{ + void MessageBoxExt(const std::string_view& message, uint32_t flags) + { + MessageBoxA(NULL, message.data(), GEngine::GetName().data(), flags); + } + + void MessageBoxInfo(const std::string_view& message) + { + MessageBoxExt(message, (MB_OK | MB_ICONINFORMATION)); + } + + void MessageBoxWarn(const std::string_view& message) + { + MessageBoxExt(message, (MB_OK | MB_ICONWARNING)); + } + + void MessageBoxError(const std::string_view& message) + { + MessageBoxExt(message, (MB_OK | MB_ICONERROR)); + } +} + +namespace Retrievers +{ + uintptr_t GetBaseAddress() + { + return reinterpret_cast(GetModuleHandle(NULL)); + } + + uintptr_t FindPattern(const std::basic_string_view& pattern, const std::string_view& mask) + { + if (!pattern.empty() && !mask.empty()) + { + MODULEINFO miInfos; + ZeroMemory(&miInfos, sizeof(MODULEINFO)); + + HMODULE hModule = GetModuleHandle(NULL); + K32GetModuleInformation(GetCurrentProcess(), hModule, &miInfos, sizeof(MODULEINFO)); + + uintptr_t start = reinterpret_cast(hModule); + uintptr_t end = (start + miInfos.SizeOfImage); + + size_t currentPos = 0; + size_t maskLength = (mask.length() - 1); + + for (uintptr_t retAddress = start; retAddress < end; retAddress++) + { + if (*reinterpret_cast(retAddress) == pattern[currentPos] || mask[currentPos] == '?') + { + if (currentPos == maskLength) + { + return (retAddress - maskLength); + } + + currentPos++; + } + else + { + retAddress -= currentPos; + currentPos = 0; + } + } + } + + return 0; + } +} + +#elif __linux__ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace Utils +{ + namespace + { + enum MessageBoxLevel : uint8_t + { + Info = 0, + Warn = 1, + Error = 2, + }; + + bool TryExec(const std::vector& args) + { + pid_t pid = fork(); + + if (pid == -1) + { + return false; + } + + if (pid == 0) + { + // Child process: redirect stderr to /dev/null + int devnull = open("/dev/null", O_WRONLY); + if (devnull != -1) + { + dup2(devnull, STDERR_FILENO); + close(devnull); + } + + execvp(args[0], const_cast(args.data())); + _exit(127); + } + + // Parent process: wait for child + int status; + waitpid(pid, &status, 0); + + return WIFEXITED(status) && WEXITSTATUS(status) == 0; + } + } + + void MessageBoxExt(const std::string_view& message, MessageBoxLevel level) + { + std::string_view title(GEngine::GetName()); + std::string_view msg(message); + + // Blocking dialog commands (ordered by preference) + std::array commands = { + std::vector{ + "kdialog", std::array{"--msgbox", "--sorry", "--error"}[level], + msg.data(), "--title", title.data(), nullptr + }, + std::vector{ + "zenity", std::array{"--info", "--warning", "--error"}[level], + "--title", title.data(), "--text", msg.data(), nullptr + }, + std::vector{ + "notify-send", "-t", "0", "-w", + "-u", std::array{"normal", "critical", "critical"}[level], + "-a", title.data(), msg.data(), nullptr + }, + std::vector{ + "xmessage", "-buttons", "OK:0", + "-title", title.data(), msg.data(), nullptr + } + }; + + for (const auto& args : commands) + { + if (TryExec(args)) + return; + } + + // Fallback to stderr + std::cerr << "[" << title << "] " << msg << std::endl; + } + + void MessageBoxInfo(const std::string_view& message) + { + MessageBoxExt(message, MessageBoxLevel::Info); + } + + void MessageBoxWarn(const std::string_view& message) + { + MessageBoxExt(message, MessageBoxLevel::Warn); + } + + void MessageBoxError(const std::string_view& message) + { + MessageBoxExt(message, MessageBoxLevel::Error); + } +} + +namespace Retrievers +{ + namespace + { + struct ProcMapsEntry + { + ProcMapsEntry(std::string& line) + { + parse(line); + } + + uintptr_t start; + uintptr_t end; + struct + { + bool r; + bool w; + bool x; + bool s; + } perms; + uintptr_t offset; + struct + { + uint16_t major; + uint16_t minor; + } dev; + uint64_t inode; + std::string pathname; + + void parse(std::string& line) + { + this->pathname.resize(4096, '\0'); + char perms[4] = {0}; + sscanf(line.data(), "%tx-%tx %4c %tx %02hx:%02hx %lu %s", + &this->start, &this->end, + perms, &this->offset, + &this->dev.major, &this->dev.minor, + &this->inode, this->pathname.data()); + this->parse_perms(perms); + this->pathname.shrink_to_fit(); + } + + private: + void parse_perms(const char perms[4]) + { + this->perms.r = (perms[0] == 'r'); + this->perms.w = (perms[1] == 'w'); + this->perms.x = (perms[2] == 'x'); + this->perms.s = (perms[3] == 's' || perms[3] == 'S'); + } + }; + } + + uintptr_t GetBaseAddress() + { + std::ifstream input("/proc/self/maps"); + + for (std::string line; std::getline(input, line);) { + // Parse the proc_pid_maps line + ProcMapsEntry entry(line); + + // Check if this line corresponds to the main executable + if (entry.inode != 0 && std::filesystem::equivalent(entry.pathname, "/proc/self/exe")) { + return entry.start; + } + } + + assert(false && "Failed to find base address from /proc/self/maps"); + + return 0; + } + + uintptr_t FindPattern(const std::basic_string_view& pattern, const std::string_view& mask) + { + if (pattern.empty() || mask.empty()) + { + return 0; + } + + std::ifstream input("/proc/self/maps"); + uintptr_t start = 0; + uintptr_t end = 0; + + // Find the executable's memory range + for (std::string line; std::getline(input, line);) + { + ProcMapsEntry entry(line); + + // Only scan readable segments of the main executable + if (entry.inode != 0 && entry.perms.r && + std::filesystem::equivalent(entry.pathname, "/proc/self/exe")) + { + if (start == 0 || entry.start < start) + start = entry.start; + if (entry.end > end) + end = entry.end; + } + } + + if (start == 0 || end == 0) + { + return 0; + } + + // Pattern matching (same algorithm as Windows) + size_t currentPos = 0; + size_t maskLength = (mask.length() - 1); + + for (uintptr_t retAddress = start; retAddress < end; retAddress++) + { + if (*reinterpret_cast(retAddress) == pattern[currentPos] || mask[currentPos] == '?') + { + if (currentPos == maskLength) + { + return (retAddress - maskLength); + } + + currentPos++; + } + else + { + retAddress -= currentPos; + currentPos = 0; + } + } + + return 0; + } +} + +#else + +#error "Unsupported platform" + +#endif diff --git a/version.hpp.in b/version.hpp.in new file mode 100644 index 0000000..d15409f --- /dev/null +++ b/version.hpp.in @@ -0,0 +1,6 @@ +#pragma once + +#define PROJECT_NAME "@PROJECT_NAME@" +#define PROJECT_VERSION "@PROJECT_VERSION@" +#define PROJECT_AUTHORS "ItsBranK, TheFeckless" +#define PROJECT_HOMEPAGE_URL "@PROJECT_HOMEPAGE_URL@"