├── .clang-format ├── .gitattributes ├── .github └── workflows │ ├── main.yml │ └── release.yml ├── .gitignore ├── CMake └── BuildInfo.cmake ├── CMakeLists.txt ├── CMakePresets.json ├── DOCUMENT.md ├── INSTALL.md ├── LICENSE ├── README.md ├── build_info.h.in ├── config └── LuaBackend.toml ├── external └── include │ └── crcpp │ └── CRC.h └── src ├── ConsoleLib.cpp ├── ConsoleLib.h ├── DCInstance.cpp ├── DCInstance.h ├── LuaBackend.cpp ├── LuaBackend.h ├── MemoryLib.h ├── config.cpp ├── config.h ├── game_info.h ├── header_text.cpp ├── header_text.h ├── lua_exec.cpp ├── lua_exec.h ├── main_dll.cpp └── wil_extra.h /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: LLVM 4 | PointerAlignment: Left 5 | --- 6 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | external/** linguist-vendored 4 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - '**' 7 | pull_request: 8 | workflow_dispatch: 9 | 10 | jobs: 11 | build: 12 | runs-on: windows-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v3 16 | - name: Setup MSBuild 17 | uses: microsoft/setup-msbuild@v1 18 | - name: vcpkg build 19 | uses: johnwason/vcpkg-action@v6 20 | id: vcpkg 21 | with: 22 | pkgs: pkgconf ztd-text wil tomlplusplus sol2 lua discord-rpc 23 | triplet: x64-windows-static 24 | token: ${{ github.token }} 25 | github-binarycache: true 26 | - name: Build Solution 27 | run: | 28 | cmake ${{ steps.vcpkg.outputs.vcpkg-cmake-config }} -S . -B build 29 | cmake --build build --config Release 30 | - name: Copy Artifacts 31 | run: | 32 | mkdir artifacts 33 | cp build/Release/DBGHELP.dll artifacts 34 | cp config/LuaBackend.toml artifacts 35 | - name: Upload DBGHELP 36 | uses: actions/upload-artifact@v4 37 | with: 38 | name: DBGHELP 39 | path: artifacts 40 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*.*.*" 7 | 8 | jobs: 9 | release: 10 | runs-on: windows-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v3 14 | - name: Setup MSBuild 15 | uses: microsoft/setup-msbuild@v1 16 | - name: vcpkg build 17 | uses: johnwason/vcpkg-action@v6 18 | id: vcpkg 19 | with: 20 | pkgs: pkgconf ztd-text wil tomlplusplus sol2 lua discord-rpc 21 | triplet: x64-windows-static 22 | token: ${{ github.token }} 23 | github-binarycache: true 24 | - name: Build Solution 25 | run: | 26 | cmake ${{ steps.vcpkg.outputs.vcpkg-cmake-config }} -S . -B build -DPROGRAM_VERSION:STRING="${{github.ref_name}}" 27 | cmake --build build --config Release 28 | - name: Compress Artifacts 29 | run: | 30 | 7z a DBGHELP.zip ./build/Release/DBGHELP.dll ./config/LuaBackend.toml 31 | - name: Automatic Release 32 | uses: marvinpinto/action-automatic-releases@latest 33 | with: 34 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 35 | prerelease: false 36 | draft: true 37 | files: | 38 | DBGHELP.zip 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,cmake 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,cmake 3 | 4 | ### CMake ### 5 | CMakeLists.txt.user 6 | CMakeCache.txt 7 | CMakeFiles 8 | CMakeScripts 9 | Testing 10 | Makefile 11 | cmake_install.cmake 12 | install_manifest.txt 13 | compile_commands.json 14 | CTestTestfile.cmake 15 | _deps 16 | 17 | ### CMake Patch ### 18 | # External projects 19 | *-prefix/ 20 | 21 | ### VisualStudioCode ### 22 | .vscode/* 23 | !.vscode/settings.json 24 | !.vscode/tasks.json 25 | !.vscode/launch.json 26 | !.vscode/extensions.json 27 | !.vscode/*.code-snippets 28 | 29 | # Local History for Visual Studio Code 30 | .history/ 31 | 32 | # Built Visual Studio Code Extensions 33 | *.vsix 34 | 35 | ### VisualStudioCode Patch ### 36 | # Ignore all local history of files 37 | .history 38 | .ionide 39 | 40 | # End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,cmake 41 | 42 | .cache/ 43 | build/ 44 | -------------------------------------------------------------------------------- /CMake/BuildInfo.cmake: -------------------------------------------------------------------------------- 1 | set(INSTALL_DIR "" CACHE STRING "Install directory for configured files") 2 | set(PROGRAM_VERSION "" CACHE STRING "Version override for build info") 3 | 4 | set(USING_GIT_VERSION FALSE) 5 | 6 | if(NOT INSTALL_DIR) 7 | message(FATAL_ERROR "Install directory not specified") 8 | endif() 9 | 10 | find_package(Git QUIET) 11 | if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git") 12 | if(NOT PROGRAM_VERSION) 13 | execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --dirty --abbrev=7 --exclude "*" 14 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 15 | OUTPUT_STRIP_TRAILING_WHITESPACE 16 | RESULT_VARIABLE GIT_VERSION_RESULT 17 | OUTPUT_VARIABLE PROGRAM_VERSION) 18 | if (NOT GIT_VERSION_RESULT EQUAL "0") 19 | message(FATAL_ERROR "git describe --always --dirty --abbrev=7 --exclude \"*\" failed with ${GIT_VERSION_RESULT}") 20 | else() 21 | set(USING_GIT_VERSION TRUE) 22 | endif() 23 | endif() 24 | endif() 25 | 26 | if(NOT PROGRAM_VERSION) 27 | message(FATAL_ERROR "Program version not defined") 28 | else() 29 | if (USING_GIT_VERSION) 30 | message(STATUS "Using git program version: " ${PROGRAM_VERSION}) 31 | else() 32 | message(STATUS "Using overrided program version: " ${PROGRAM_VERSION}) 33 | endif() 34 | endif() 35 | 36 | configure_file(build_info.h.in "${INSTALL_DIR}/build_info.h" @ONLY) 37 | 38 | unset(INSTALL_DIR CACHE) 39 | unset(PROGRAM_VERSION CACHE) 40 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7...3.27) 2 | 3 | if(${CMAKE_VERSION} VERSION_LESS 3.12) 4 | cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) 5 | endif() 6 | 7 | project(LuaBackendHook LANGUAGES CXX) 8 | 9 | set(PROGRAM_VERSION "" CACHE STRING "Program version override") 10 | 11 | set(CMAKE_CXX_STANDARD 20) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | set(CMAKE_CXX_EXTENSIONS OFF) 14 | 15 | # Statically link CRT 16 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") 17 | 18 | find_package(ztd.text CONFIG REQUIRED) 19 | find_package(ztd.cuneicode CONFIG REQUIRED) 20 | 21 | find_package(wil CONFIG REQUIRED) 22 | 23 | find_package(PkgConfig REQUIRED) 24 | pkg_check_modules(tomlplusplus REQUIRED IMPORTED_TARGET tomlplusplus) 25 | 26 | find_package(sol2 CONFIG REQUIRED) 27 | find_package(Lua REQUIRED) 28 | 29 | find_library(DISCORD_RPC_LIBRARY_DEBUG discord-rpc 30 | PATHS ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/debug/lib 31 | NO_DEFAULT_PATH 32 | REQUIRED) 33 | 34 | find_library(DISCORD_RPC_LIBRARY_RELEASE discord-rpc 35 | PATHS ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib 36 | NO_DEFAULT_PATH 37 | REQUIRED) 38 | 39 | set(SOURCE 40 | src/main_dll.cpp 41 | src/config.cpp 42 | src/lua_exec.cpp 43 | src/header_text.cpp 44 | src/ConsoleLib.cpp 45 | src/DCInstance.cpp 46 | src/LuaBackend.cpp 47 | src/config.h 48 | src/game_info.h 49 | src/lua_exec.h 50 | src/wil_extra.h 51 | src/header_text.h 52 | src/ConsoleLib.h 53 | src/DCInstance.h 54 | src/LuaBackend.h 55 | src/MemoryLib.h 56 | ) 57 | 58 | add_custom_target(clang-format 59 | COMMAND clang-format -i -style=file ${SOURCE} 60 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 61 | ) 62 | 63 | add_custom_target(build-info 64 | COMMAND ${CMAKE_COMMAND} 65 | -DPROGRAM_VERSION:STRING=${PROGRAM_VERSION} 66 | -DINSTALL_DIR:STRING=${CMAKE_CURRENT_BINARY_DIR} 67 | -P CMake/BuildInfo.cmake 68 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 69 | VERBATIM 70 | ) 71 | 72 | add_library(DBGHELP SHARED ${SOURCE}) 73 | add_dependencies(DBGHELP build-info) 74 | 75 | if(MSVC) 76 | # FUTURE(Sirius902) ZTD_STD_LIBRARY_RANGES is broken currently on MSVC 77 | target_compile_options(DBGHELP PRIVATE -W4 -WX -DZTD_STD_LIBRARY_RANGES=0) 78 | else() 79 | target_compile_options(DBGHELP PRIVATE -Wall -Wextra -Wpedantic) 80 | endif() 81 | 82 | # FUTURE(Sirius902) Use tomlplusplus as header only because of weird linking issues 83 | target_compile_definitions(DBGHELP PRIVATE -DUNICODE -D_UNICODE -DTOML_HEADER_ONLY=1) 84 | target_include_directories(DBGHELP PRIVATE 85 | external/include 86 | ${LUA_INCLUDE_DIR} 87 | ${CMAKE_CURRENT_BINARY_DIR} 88 | ) 89 | target_link_libraries(DBGHELP PRIVATE 90 | ztd.text 91 | WIL::WIL 92 | sol2 93 | ${LUA_LIBRARIES} 94 | $<$:${DISCORD_RPC_LIBRARY_DEBUG}> 95 | $<$:${DISCORD_RPC_LIBRARY_RELEASE}> 96 | ) 97 | 98 | unset(PROGRAM_VERSION CACHE) 99 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "configurePresets": [ 4 | { 5 | "name": "default", 6 | "generator": "Visual Studio 17 2022", 7 | "binaryDir": "${sourceDir}/build", 8 | "cacheVariables": { 9 | "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", 10 | "VCPKG_TARGET_TRIPLET": "x64-windows-static" 11 | } 12 | }, 13 | { 14 | "name": "ninja", 15 | "generator": "Ninja", 16 | "binaryDir": "${sourceDir}/build", 17 | "cacheVariables": { 18 | "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", 19 | "VCPKG_TARGET_TRIPLET": "x64-windows-static" 20 | } 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /DOCUMENT.md: -------------------------------------------------------------------------------- 1 | ## LuaBackend Cheatsheet v5.0 2 | 3 | --- 4 | 5 | ## Global Variables 6 | 7 | - ``GAME_ID`` => Returns the current game's CRC32 checksum as an integer. This checksum is generated from the process name at this moment. 8 | - ``LUA_NAME`` => The name of your Lua script, used by functions such as ConsolePrint. It is the filename of your Lua by default. 9 | - ``SCRIPT_PATH`` => Returns the path which Lua scripts are loaded from as a string. Ex: ``"C:\Users\Topaz\Desktop\LuaBackend\scripts"`` 10 | - ``CHEATS_PATH`` => Always returns ``"NOT_AVAILABLE"`` 11 | - ``ENGINE_VERSION`` => Returns the LuaBackend's engine version as a float. Ex: ``4.1`` 12 | - ``ENGINE_TYPE`` => Always returns ``"BACKEND"`` 13 | 14 | ## Memory Functions 15 | 16 | ### Read\[XXXX\](Address, Absolute = false) / ReadString(Address, Length, Absolute = false) 17 | 18 | Reads a certain value from **Address**. Returns the read value. If reading a String, length must also be declared. 19 | The "**XXXX**" is a placeholder for the value type. 20 | 21 | If **Absolute** is true, the address is taken as written and base address is not added into it. 22 | 23 | List of types available: Byte, Short, Int, Long, Float, String, Boolean 24 | 25 | Example: 26 | ```lua 27 | local _tempInt = ReadInt(0xDEADB00) -- Read an integer from address GameModule+0xDEADB00 28 | local _tempByte = ReadByte(0xB007555) -- Read a byte from address GameModule+0xB007555 29 | ``` 30 | 31 | ### Write\[XXXX\](Address, Value, Absolute = false) 32 | 33 | Writes **Value** to **Address** calculated relative to the base address. 34 | The "**\[XXXX\]**" is a placeholder for the value type. 35 | 36 | If **Absolute** is true, the address is taken as written and base address is not added into it. 37 | 38 | List of types available: Byte, Short, Int, Long, Float, String, Boolean 39 | 40 | Example: 41 | ```lua 42 | WriteShort(0xDEADB00, 0xFFFF) -- Write 0xFFFF to GameModule+0xDEADB00 43 | WriteBoolean(0xB007555, true) -- Write true to GameModule+0xB007555 44 | ``` 45 | 46 | ### Read\[XXXX\]A(Address) / ReadStringA(Address, Length) 47 | 48 | Reads a certain value from absolute **Address**. Returns the read value. If reading a String, length must also be declared. 49 | You generally only need this for absolute operations. Most of the time, you should not use this. 50 | The "**\[XXXX\]**" is a placeholder for the value type. 51 | 52 | List of types available: Byte, Short, Int, Long, Float, Boolean 53 | 54 | Example: 55 | ```lua 56 | local _tempInt = ReadIntA(0xB00BA) -- Read an integer from address 0xB00BA 57 | local _tempByte = ReadByteA(0xEEEEEE) -- Read a byte from address 0xEEEEEE 58 | ``` 59 | 60 | ### Write\[XXXX\]A(Address, Value) 61 | 62 | Writes **Value** to absolute **Address**. 63 | You generally only need this for absolute operations. Most of the time, you should not use this. 64 | The "**\[XXXX\]**" is a placeholder for the value type. 65 | 66 | List of types available: Byte, Short, Int, Long, Float, String, Boolean 67 | 68 | Example: 69 | ```lua 70 | WriteShortA(0xBABEEEE, 0xFFFF) -- Write 0xFFFF to 0xBABEEEE 71 | WriteBooleanA(0x5355355, true) -- Write true to 0x5355355 72 | ``` 73 | 74 | ### ReadArray(Address, Length, Absolute = false) 75 | 76 | Reads **Length** amount of bytes from memory, starting at **Address**. Returns the read bytes as an array. 77 | If **Absolute** is true, the address is taken as written and base address is not added into it. 78 | 79 | Example: 80 | ```lua 81 | local _tempArray = ReadArray(0xBEEFDED, 0x10) -- Reads 16 bytes starting at GameModule+0xBEEFDED 82 | ``` 83 | 84 | ### WriteArray(Address, Array, Absolute = false) 85 | 86 | Writes **Array** to the memory, starting at **Address**. The array must be made of bytes (8-bit integers). 87 | If **Absolute** is true, the address is taken as written and base address is not added into it. 88 | 89 | Example: 90 | ```lua 91 | local _tempArray = { 0xFE, 0xA5, 0x70 } 92 | WriteArray(0x6660420, _tempArray) -- Writes _tempArray to memory, starting at GameModule+0x6660420 93 | ``` 94 | 95 | ### ReadArrayA(Address, Length) 96 | 97 | Reads **Length** amount of bytes from memory, starting at absolute **Address**. Returns the read bytes as an array. 98 | You generally only need this for absolute operations. Most of the time, you should not use this. 99 | 100 | Example: 101 | ```lua 102 | local _tempArray = ReadArrayA(0xBEEFDED, 0x10) -- Reads 16 bytes starting at 0xBEEFDED 103 | ``` 104 | 105 | ### WriteArrayA(Address, Array) 106 | 107 | Writes **Array** to the memory, starting at absolute **Address**. The array must be made of bytes (8-bit integers). 108 | You generally only need this for absolute operations. Most of the time, you should not use this. 109 | 110 | Example: 111 | ```lua 112 | local _tempArray = { 0xFE, 0xA5, 0x70 } 113 | WriteArrayA(0x6660420, _tempArray) -- Writes _tempArray to memory, starting at 0x6660420 114 | ``` 115 | 116 | ### GetPointer(Address, Offset, Absolute = false) 117 | 118 | Calculates a pointer with the given values. 119 | Basically, reads the value at **Address** and adds **Offset** to it. Returns the resulting value. 120 | 121 | If **Absolute** is true, the address is taken as written and base address is not added into it. 122 | 123 | Example: 124 | ```lua 125 | local _tempPointer = GetPointer(0xBEEFDAD, 0x15) -- Reads the value at GameModule+0xBEEFDAD and adds 0x15 to it. 126 | ``` 127 | 128 | ### GetPointerA(Address, Offset) 129 | 130 | Calculates a pointer with the given values. 131 | Basically, reads the value at absolute **Address** and adds **Offset** to it. Returns the resulting value. 132 | You generally only need this for absolute operations. Most of the time, you should not use this. 133 | 134 | Example: 135 | ```lua 136 | local _tempPointer = GetPointerA(0xBEEFDAD, 0x15) -- Reads the value at 0xBEEFDAD and adds 0x15 to it. 137 | ``` 138 | 139 | ## General I/O Functions 140 | 141 | ### GetHertz() 142 | 143 | Gets the frequency of which LuaBackend scripts execute. 144 | 145 | ### SetHertz(Frequency) 146 | 147 | Sets the Backend execution cycle to **Frequency**. The accepted values are **60**, **120**, and **240**. 148 | 149 | ### ULShift32(Base, Shift) 150 | 151 | Shifts **Base** left by **Shift** abont of bytes. Only exists for 32-bit applications. 152 | 153 | Example: 154 | ```lua 155 | ULShift32(4294967295, 8) -- Shifts 4294967295 left by 8 bytes without an overflow to 64-bits. 156 | ``` 157 | 158 | ### ConsolePrint(Text, Type = NULL) 159 | 160 | Prints **Text** to the console, in the format given below. 161 | Unless **Type** is declared, nothing will prefix the message. 162 | 163 | **Type** can be the following: 164 | - 0 = MESSAGE 165 | - 1 = SUCCESS 166 | - 2 = WARNING 167 | - 3 = ERROR 168 | 169 | Format: 170 | ``` 171 | [LUA_NAME] TYPE: Text 172 | ``` 173 | 174 | Example: 175 | ```lua 176 | LUA_NAME = "SomeDudeScript" 177 | ConsolePrint("GET UP ON THE HYDRA'S BACK!") -- Prints the following: [SomeDudeScript] GET UP ON THE HYDRA'S BACK! 178 | ConsolePrint("NICE VIEW FROM UP HERE!", 0) -- Prints the following: [SomeDudeScript] MESSAGE: NICE VIEW FROM UP HERE! 179 | ``` 180 | 181 | ## Discord RPC Functions 182 | 183 | ### InitializeRPC(ApplicationID) 184 | 185 | Initializes and hooks a Discord Application with **ApplicationID**, for Rich Presence control. 186 | 187 | Example: 188 | ```lua 189 | InitializeRPC("833511404274974740") -- Initiaizes Discord Application "833511404274974740". 190 | ``` 191 | 192 | ### UpdateDetails(Text) 193 | 194 | Updates the details of the rich presence application initialized with InitializeRPC to say **Text**. 195 | 196 | Example: 197 | ```lua 198 | UpdateDetails("Hello World!") -- Updates the details section of the RPC to say "Hello World!". 199 | ``` 200 | 201 | ### UpdateState(Text) 202 | 203 | Updates the state of the rich presence application initialized with InitializeRPC to say **Text**. 204 | 205 | Example: 206 | ```lua 207 | UpdateState("Hello World!") -- Updates the state section of the RPC to say "Hello World!". 208 | ``` 209 | 210 | ### UpdateLImage(Key, Text) 211 | 212 | Updates the large image of the rich presence to be the image with **Key**. And it's text is updates to say **Text**. 213 | 214 | Example: 215 | ```lua 216 | UpdateLImage("image", "This is Image!") -- Updates the large image to "image" and it's text to "This is Image!" 217 | ``` 218 | 219 | ### UpdateSImage(Key, Text) 220 | 221 | Updates the small image of the rich presence to be the image with **Key**. And it's text is updates to say **Text**. 222 | 223 | Example: 224 | ```lua 225 | UpdateSImage("imagetwo", "This too, is Image!") -- Updates the small image to "imagetwo" and it's text to "This too, is Image!" 226 | ``` 227 | 228 | ### WriteExec(Address, Value) - [LuaBackend Only] 229 | 230 | Writes the given byte array **Value** to **Address** relative to the current EXE's address, NOT the provided base address. 231 | 232 | Example: 233 | ```lua 234 | WriteExec(0x00FBAAD, 0x15) -- Writes 0x15 to EXE_NAME.exe+0x00FBAAD. 235 | 236 | ``` 237 | 238 | #### * Any functions present in this document signify compatibility with the latest version. Any function absent in this document is no longer supported and should be considered obsolete. 239 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | ## Installing LuaBackend Hook 2 | 3 | ### Internal LuaBackend Hook [DLL] 4 | - Download ``DBGHELP.zip`` from the Releases tab. 5 | - For Kingdom Hearts 1.5+2.5 6 | - Extract the contents of ``DBGHELP.zip`` to the directory Kingdom Hearts 1.5+2.5 is installed which is named `KH_1.5_2.5`. 7 | - Place your scripts in a folder named `scripts/[gameid]` in the `KINGDOM HEARTS HD 1.5+2.5 ReMIX` folder in your Documents folder. 8 | - For Kingdom Hearts Final Mix the default folder will be `scripts/kh1`. 9 | - For Kingdom Hearts Re: Chain of Memories the default folder will be `scripts/recom`. 10 | - For Kingdom Hearts II Final Mix the default folder will be `scripts/kh2`. 11 | - For Kingdom Hearts Birth by Sleep Final Mix the default folder will be `scripts/bbs`. 12 | - The installation is now finished. LuaBackend will be automatically started with the game and can be easily uninstalled 13 | by removing the ``DBGHELP.dll``. To verify it is installed correctly, you can open the LuaBackend console using 14 | the F2 key on the keyboard in game. 15 | - For Kingdom Hearts 2.8 16 | - The steps for 2.8 are the similar, but the game's install directory is named `KH_2.8` and the default script path 17 | will be in the `KINGDOM HEARTS HD 2.8 Final Chapter Prologue` folder. 18 | - For Kingdom Hearts Dream Drop Distance HD the default scripts folder will be `scripts/kh3d`. 19 | 20 | ### Custom script locations 21 | 22 | The configuration file can be modified to customize the script location(s). 23 | 24 | - Edit the file called `LuaBackend.toml` in the same folder as `DBGHELP.dll` (the game install folder). 25 | - To edit the script paths, modify the `scripts` value, which is the list of script paths that will be used. 26 | - `path` is the scripts path for an entry. 27 | - `relative`, when true, make the `path` relative to the game's documents folder specified 28 | by `game_docs` and will be an absolute path otherwise. 29 | 30 | Sample configuration: 31 | 32 | ``` 33 | [kh1] 34 | scripts = [{ path = "D:\\kh1-scripts", relative = false }] 35 | exe = "KINGDOM HEARTS FINAL MIX.exe" 36 | game_docs = "KINGDOM HEARTS HD 1.5+2.5 ReMIX" 37 | 38 | [kh2] 39 | scripts = [ 40 | { path = "scripts\\kh2", relative = true }, 41 | { path = "C:\\Users\\johndoe\\bin\\KH\\PC\\openkh\\mod\\luascript", relative = false }, 42 | ] 43 | exe = "KINGDOM HEARTS II FINAL MIX.exe" 44 | game_docs = "KINGDOM HEARTS HD 1.5+2.5 ReMIX" 45 | ``` 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LuaBackend Hook 2 | 3 | ![Windows Build](https://github.com/Sirius902/LuaBackend/workflows/CI/badge.svg) 4 | 5 | ## What is this? 6 | 7 | This is a fork of TopazTK's [LuaBackend](https://github.com/TopazTK/LuaBackend) which focuses on 8 | consistency and reliability for timing-critical scripts. 9 | 10 | ## Why use this over LuaBackend or LuaFrontend? 11 | 12 | For most scripts there's no issue using LuaBackend or LuaFrontend but for scripts such as the 13 | Garden of Assemblage (GoA) Randomizer, which relies on running once before every frame in-game, it's 14 | important this requirement is met. LuaBackend and LuaFrontend currently aren't syncronized with 15 | the game's main loop, leading to unintended behavior in scripts like GoA which can range from 16 | crashes to warps to incorrect locations. This fork however syncronizes the Lua scripts with the game 17 | loop effectively eliminating these issues. However, scripts that rely on new features from LuaFrontend 18 | are not supported and it is recommended to use LuaFrontend concurrently with LuaBackend Hook to achieve this. 19 | 20 | ## Support 21 | 22 | Supports the PC Global and Japanese versions of: 23 | 24 | - Kingdom Hearts Final Mix 25 | - Kingdom Hearts Re: Chain of Memories 26 | - Kingdom Hearts II Final Mix 27 | - Kingdom Hearts Birth by Sleep Final Mix 28 | - Kingdom Hearts Dream Drop Distance HD 29 | 30 | Installation instructions are in [INSTALL.md](INSTALL.md). 31 | 32 | ## Why is the dll file named DBGHELP? 33 | 34 | This is so that LuaBackend Hook can hook into the game without requiring an EXE patch, but still 35 | be able to launch automatically with the game. 36 | 37 | To support platforms where hooking as DBGHELP does not work such as Linux using Wine, 38 | hooking as DINPUT8 is also supported. To hook as DINPUT8, rename the `DBGHELP.dll` to 39 | `DINPUT8.dll`. 40 | 41 | ## Building 42 | 43 | - Install Visual Studio Community 2022 (or just the build tools) and ensure the `Desktop development with C++` workflow is installed. 44 | - Install CMake: `winget install Kitware.CMake` 45 | - Install vcpkg by following steps 1 and 2.1 from 46 | [here](https://learn.microsoft.com/en-us/vcpkg/get_started/get-started?pivots=shell-powershell). 47 | - Install the required vcpkg dependencies by running the following in PowerShell. 48 | 49 | ```powershell 50 | $env:VCPKG_DEFAULT_TRIPLET="x64-windows-static" 51 | vcpkg install pkgconf ztd-text wil tomlplusplus sol2 lua discord-rpc 52 | ``` 53 | 54 | - Inside the repository run `cmake --preset=default` to configure the project. 55 | - Run `cmake --build build` to build the project. To build for release mode add `--config Release`. 56 | - The artifacts can now be found somewhere in the `build` directory. If building for MSVC in debug mode this will be `build/Debug`. 57 | -------------------------------------------------------------------------------- /build_info.h.in: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define HOOK_VERSION "@PROGRAM_VERSION@" 4 | -------------------------------------------------------------------------------- /config/LuaBackend.toml: -------------------------------------------------------------------------------- 1 | [kh1] 2 | scripts = [{ path = "scripts/kh1/", relative = true }] 3 | exe = "KINGDOM HEARTS FINAL MIX.exe" 4 | game_docs = "KINGDOM HEARTS HD 1.5+2.5 ReMIX" 5 | # For Steam Version replace with below line 6 | # game_docs = "My Games/KINGDOM HEARTS HD 1.5+2.5 ReMIX" 7 | 8 | [kh2] 9 | scripts = [{ path = "scripts/kh2/", relative = true }] 10 | exe = "KINGDOM HEARTS II FINAL MIX.exe" 11 | game_docs = "KINGDOM HEARTS HD 1.5+2.5 ReMIX" 12 | # For Steam Version replace with below line 13 | # game_docs = "My Games/KINGDOM HEARTS HD 1.5+2.5 ReMIX" 14 | 15 | [bbs] 16 | scripts = [{ path = "scripts/bbs/", relative = true }] 17 | exe = "KINGDOM HEARTS Birth by Sleep FINAL MIX.exe" 18 | game_docs = "KINGDOM HEARTS HD 1.5+2.5 ReMIX" 19 | # For Steam Version replace with below line 20 | # game_docs = "My Games/KINGDOM HEARTS HD 1.5+2.5 ReMIX" 21 | 22 | [recom] 23 | scripts = [{ path = "scripts/recom/", relative = true }] 24 | exe = "KINGDOM HEARTS Re_Chain of Memories.exe" 25 | game_docs = "KINGDOM HEARTS HD 1.5+2.5 ReMIX" 26 | # For Steam Version replace with below line 27 | # game_docs = "My Games/KINGDOM HEARTS HD 1.5+2.5 ReMIX" 28 | 29 | [kh3d] 30 | scripts = [{ path = "scripts/kh3d/", relative = true }] 31 | exe = "KINGDOM HEARTS Dream Drop Distance.exe" 32 | game_docs = "KINGDOM HEARTS HD 2.8 Final Chapter Prologue" 33 | # For Steam Version replace with below line 34 | # game_docs = "My Games/KINGDOM HEARTS HD 2.8 Final Chapter Prologue" 35 | -------------------------------------------------------------------------------- /external/include/crcpp/CRC.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file CRC.h 3 | @author Daniel Bahr 4 | @version 1.2.0.0 5 | @copyright 6 | @parblock 7 | CRC++ 8 | Copyright (c) 2022, Daniel Bahr 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | 14 | * Redistributions of source code must retain the above copyright notice, this 15 | list of conditions and the following disclaimer. 16 | 17 | * Redistributions in binary form must reproduce the above copyright notice, 18 | this list of conditions and the following disclaimer in the documentation 19 | and/or other materials provided with the distribution. 20 | 21 | * Neither the name of CRC++ nor the names of its 22 | contributors may be used to endorse or promote products derived from 23 | this software without specific prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | @endparblock 36 | */ 37 | 38 | /* 39 | CRC++ can be configured by setting various #defines before #including this header file: 40 | 41 | #define crcpp_uint8 - Specifies the type used to store CRCs that have a width of 8 bits or less. 42 | This type is not used in CRC calculations. Defaults to ::std::uint8_t. 43 | #define crcpp_uint16 - Specifies the type used to store CRCs that have a width between 9 and 16 bits (inclusive). 44 | This type is not used in CRC calculations. Defaults to ::std::uint16_t. 45 | #define crcpp_uint32 - Specifies the type used to store CRCs that have a width between 17 and 32 bits (inclusive). 46 | This type is not used in CRC calculations. Defaults to ::std::uint32_t. 47 | #define crcpp_uint64 - Specifies the type used to store CRCs that have a width between 33 and 64 bits (inclusive). 48 | This type is not used in CRC calculations. Defaults to ::std::uint64_t. 49 | #define crcpp_size - This type is used for loop iteration and function signatures only. Defaults to ::std::size_t. 50 | #define CRCPP_USE_NAMESPACE - Define to place all CRC++ code within the ::CRCPP namespace. 51 | #define CRCPP_BRANCHLESS - Define to enable a branchless CRC implementation. The branchless implementation uses a single integer 52 | multiplication in the bit-by-bit calculation instead of a small conditional. The branchless implementation 53 | may be faster on processor architectures which support single-instruction integer multiplication. 54 | #define CRCPP_USE_CPP11 - Define to enables C++11 features (move semantics, constexpr, static_assert, etc.). 55 | #define CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS - Define to include definitions for little-used CRCs. 56 | */ 57 | 58 | #ifndef CRCPP_CRC_H_ 59 | #define CRCPP_CRC_H_ 60 | 61 | #include // Includes CHAR_BIT 62 | #ifdef CRCPP_USE_CPP11 63 | #include // Includes ::std::size_t 64 | #include // Includes ::std::uint8_t, ::std::uint16_t, ::std::uint32_t, ::std::uint64_t 65 | #else 66 | #include // Includes size_t 67 | #include // Includes uint8_t, uint16_t, uint32_t, uint64_t 68 | #endif 69 | #include // Includes ::std::numeric_limits 70 | #include // Includes ::std::move 71 | 72 | #ifndef crcpp_uint8 73 | # ifdef CRCPP_USE_CPP11 74 | /// @brief Unsigned 8-bit integer definition, used primarily for parameter definitions. 75 | # define crcpp_uint8 ::std::uint8_t 76 | # else 77 | /// @brief Unsigned 8-bit integer definition, used primarily for parameter definitions. 78 | # define crcpp_uint8 uint8_t 79 | # endif 80 | #endif 81 | 82 | #ifndef crcpp_uint16 83 | # ifdef CRCPP_USE_CPP11 84 | /// @brief Unsigned 16-bit integer definition, used primarily for parameter definitions. 85 | # define crcpp_uint16 ::std::uint16_t 86 | # else 87 | /// @brief Unsigned 16-bit integer definition, used primarily for parameter definitions. 88 | # define crcpp_uint16 uint16_t 89 | # endif 90 | #endif 91 | 92 | #ifndef crcpp_uint32 93 | # ifdef CRCPP_USE_CPP11 94 | /// @brief Unsigned 32-bit integer definition, used primarily for parameter definitions. 95 | # define crcpp_uint32 ::std::uint32_t 96 | # else 97 | /// @brief Unsigned 32-bit integer definition, used primarily for parameter definitions. 98 | # define crcpp_uint32 uint32_t 99 | # endif 100 | #endif 101 | 102 | #ifndef crcpp_uint64 103 | # ifdef CRCPP_USE_CPP11 104 | /// @brief Unsigned 64-bit integer definition, used primarily for parameter definitions. 105 | # define crcpp_uint64 ::std::uint64_t 106 | # else 107 | /// @brief Unsigned 64-bit integer definition, used primarily for parameter definitions. 108 | # define crcpp_uint64 uint64_t 109 | # endif 110 | #endif 111 | 112 | #ifndef crcpp_size 113 | # ifdef CRCPP_USE_CPP11 114 | /// @brief Unsigned size definition, used for specifying data sizes. 115 | # define crcpp_size ::std::size_t 116 | # else 117 | /// @brief Unsigned size definition, used for specifying data sizes. 118 | # define crcpp_size size_t 119 | # endif 120 | #endif 121 | 122 | #ifdef CRCPP_USE_CPP11 123 | /// @brief Compile-time expression definition. 124 | # define crcpp_constexpr constexpr 125 | #else 126 | /// @brief Compile-time expression definition. 127 | # define crcpp_constexpr const 128 | #endif 129 | 130 | #ifdef CRCPP_USE_NAMESPACE 131 | namespace CRCPP 132 | { 133 | #endif 134 | 135 | /** 136 | @brief Static class for computing CRCs. 137 | @note This class supports computation of full and multi-part CRCs, using a bit-by-bit algorithm or a 138 | byte-by-byte lookup table. The CRCs are calculated using as many optimizations as is reasonable. 139 | If compiling with C++11, the constexpr keyword is used liberally so that many calculations are 140 | performed at compile-time instead of at runtime. 141 | */ 142 | class CRC 143 | { 144 | public: 145 | // Forward declaration 146 | template 147 | struct Table; 148 | 149 | /** 150 | @brief CRC parameters. 151 | */ 152 | template 153 | struct Parameters 154 | { 155 | CRCType polynomial; ///< CRC polynomial 156 | CRCType initialValue; ///< Initial CRC value 157 | CRCType finalXOR; ///< Value to XOR with the final CRC 158 | bool reflectInput; ///< true to reflect all input bytes 159 | bool reflectOutput; ///< true to reflect the output CRC (reflection occurs before the final XOR) 160 | 161 | Table MakeTable() const; 162 | }; 163 | 164 | /** 165 | @brief CRC lookup table. After construction, the CRC parameters are fixed. 166 | @note A CRC table can be used for multiple CRC calculations. 167 | */ 168 | template 169 | struct Table 170 | { 171 | // Constructors are intentionally NOT marked explicit. 172 | Table(const Parameters & parameters); 173 | 174 | #ifdef CRCPP_USE_CPP11 175 | Table(Parameters && parameters); 176 | #endif 177 | 178 | const Parameters & GetParameters() const; 179 | 180 | const CRCType * GetTable() const; 181 | 182 | CRCType operator[](unsigned char index) const; 183 | 184 | private: 185 | void InitTable(); 186 | 187 | Parameters parameters; ///< CRC parameters used to construct the table 188 | CRCType table[1 << CHAR_BIT]; ///< CRC lookup table 189 | }; 190 | 191 | // The number of bits in CRCType must be at least as large as CRCWidth. 192 | // CRCType must be an unsigned integer type or a custom type with operator overloads. 193 | template 194 | static CRCType Calculate(const void * data, crcpp_size size, const Parameters & parameters); 195 | 196 | template 197 | static CRCType Calculate(const void * data, crcpp_size size, const Parameters & parameters, CRCType crc); 198 | 199 | template 200 | static CRCType Calculate(const void * data, crcpp_size size, const Table & lookupTable); 201 | 202 | template 203 | static CRCType Calculate(const void * data, crcpp_size size, const Table & lookupTable, CRCType crc); 204 | 205 | template 206 | static CRCType CalculateBits(const void * data, crcpp_size size, const Parameters & parameters); 207 | 208 | template 209 | static CRCType CalculateBits(const void * data, crcpp_size size, const Parameters & parameters, CRCType crc); 210 | 211 | template 212 | static CRCType CalculateBits(const void * data, crcpp_size size, const Table & lookupTable); 213 | 214 | template 215 | static CRCType CalculateBits(const void * data, crcpp_size size, const Table & lookupTable, CRCType crc); 216 | 217 | // Common CRCs up to 64 bits. 218 | // Note: Check values are the computed CRCs when given an ASCII input of "123456789" (without null terminator) 219 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 220 | static const Parameters< crcpp_uint8, 4> & CRC_4_ITU(); 221 | static const Parameters< crcpp_uint8, 5> & CRC_5_EPC(); 222 | static const Parameters< crcpp_uint8, 5> & CRC_5_ITU(); 223 | static const Parameters< crcpp_uint8, 5> & CRC_5_USB(); 224 | static const Parameters< crcpp_uint8, 6> & CRC_6_CDMA2000A(); 225 | static const Parameters< crcpp_uint8, 6> & CRC_6_CDMA2000B(); 226 | static const Parameters< crcpp_uint8, 6> & CRC_6_ITU(); 227 | static const Parameters< crcpp_uint8, 6> & CRC_6_NR(); 228 | static const Parameters< crcpp_uint8, 7> & CRC_7(); 229 | #endif 230 | static const Parameters< crcpp_uint8, 8> & CRC_8(); 231 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 232 | static const Parameters< crcpp_uint8, 8> & CRC_8_EBU(); 233 | static const Parameters< crcpp_uint8, 8> & CRC_8_MAXIM(); 234 | static const Parameters< crcpp_uint8, 8> & CRC_8_WCDMA(); 235 | static const Parameters< crcpp_uint8, 8> & CRC_8_LTE(); 236 | static const Parameters & CRC_10(); 237 | static const Parameters & CRC_10_CDMA2000(); 238 | static const Parameters & CRC_11(); 239 | static const Parameters & CRC_11_NR(); 240 | static const Parameters & CRC_12_CDMA2000(); 241 | static const Parameters & CRC_12_DECT(); 242 | static const Parameters & CRC_12_UMTS(); 243 | static const Parameters & CRC_13_BBC(); 244 | static const Parameters & CRC_15(); 245 | static const Parameters & CRC_15_MPT1327(); 246 | #endif 247 | static const Parameters & CRC_16_ARC(); 248 | static const Parameters & CRC_16_BUYPASS(); 249 | static const Parameters & CRC_16_CCITTFALSE(); 250 | static const Parameters & CRC_16_MCRF4XX(); 251 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 252 | static const Parameters & CRC_16_CDMA2000(); 253 | static const Parameters & CRC_16_CMS(); 254 | static const Parameters & CRC_16_DECTR(); 255 | static const Parameters & CRC_16_DECTX(); 256 | static const Parameters & CRC_16_DNP(); 257 | #endif 258 | static const Parameters & CRC_16_GENIBUS(); 259 | static const Parameters & CRC_16_KERMIT(); 260 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 261 | static const Parameters & CRC_16_MAXIM(); 262 | static const Parameters & CRC_16_MODBUS(); 263 | static const Parameters & CRC_16_T10DIF(); 264 | static const Parameters & CRC_16_USB(); 265 | #endif 266 | static const Parameters & CRC_16_X25(); 267 | static const Parameters & CRC_16_XMODEM(); 268 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 269 | static const Parameters & CRC_17_CAN(); 270 | static const Parameters & CRC_21_CAN(); 271 | static const Parameters & CRC_24(); 272 | static const Parameters & CRC_24_FLEXRAYA(); 273 | static const Parameters & CRC_24_FLEXRAYB(); 274 | static const Parameters & CRC_24_LTEA(); 275 | static const Parameters & CRC_24_LTEB(); 276 | static const Parameters & CRC_24_NRC(); 277 | static const Parameters & CRC_30(); 278 | #endif 279 | static const Parameters & CRC_32(); 280 | static const Parameters & CRC_32_BZIP2(); 281 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 282 | static const Parameters & CRC_32_C(); 283 | #endif 284 | static const Parameters & CRC_32_MPEG2(); 285 | static const Parameters & CRC_32_POSIX(); 286 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 287 | static const Parameters & CRC_32_Q(); 288 | static const Parameters & CRC_40_GSM(); 289 | static const Parameters & CRC_64(); 290 | #endif 291 | 292 | #ifdef CRCPP_USE_CPP11 293 | CRC() = delete; 294 | CRC(const CRC & other) = delete; 295 | CRC & operator=(const CRC & other) = delete; 296 | CRC(CRC && other) = delete; 297 | CRC & operator=(CRC && other) = delete; 298 | #endif 299 | 300 | private: 301 | #ifndef CRCPP_USE_CPP11 302 | CRC(); 303 | CRC(const CRC & other); 304 | CRC & operator=(const CRC & other); 305 | #endif 306 | 307 | template 308 | static IntegerType Reflect(IntegerType value, crcpp_uint16 numBits); 309 | 310 | template 311 | static CRCType Finalize(CRCType remainder, CRCType finalXOR, bool reflectOutput); 312 | 313 | template 314 | static CRCType UndoFinalize(CRCType remainder, CRCType finalXOR, bool reflectOutput); 315 | 316 | template 317 | static CRCType CalculateRemainder(const void * data, crcpp_size size, const Parameters & parameters, CRCType remainder); 318 | 319 | template 320 | static CRCType CalculateRemainder(const void * data, crcpp_size size, const Table & lookupTable, CRCType remainder); 321 | 322 | template 323 | static CRCType CalculateRemainderBits(unsigned char byte, crcpp_size numBits, const Parameters & parameters, CRCType remainder); 324 | }; 325 | 326 | /** 327 | @brief Returns a CRC lookup table construct using these CRC parameters. 328 | @note This function primarily exists to allow use of the auto keyword instead of instantiating 329 | a table directly, since template parameters are not inferred in constructors. 330 | @tparam CRCType Integer type for storing the CRC result 331 | @tparam CRCWidth Number of bits in the CRC 332 | @return CRC lookup table 333 | */ 334 | template 335 | inline CRC::Table CRC::Parameters::MakeTable() const 336 | { 337 | // This should take advantage of RVO and optimize out the copy. 338 | return CRC::Table(*this); 339 | } 340 | 341 | /** 342 | @brief Constructs a CRC table from a set of CRC parameters 343 | @param[in] params CRC parameters 344 | @tparam CRCType Integer type for storing the CRC result 345 | @tparam CRCWidth Number of bits in the CRC 346 | */ 347 | template 348 | inline CRC::Table::Table(const Parameters & params) : 349 | parameters(params) 350 | { 351 | InitTable(); 352 | } 353 | 354 | #ifdef CRCPP_USE_CPP11 355 | /** 356 | @brief Constructs a CRC table from a set of CRC parameters 357 | @param[in] params CRC parameters 358 | @tparam CRCType Integer type for storing the CRC result 359 | @tparam CRCWidth Number of bits in the CRC 360 | */ 361 | template 362 | inline CRC::Table::Table(Parameters && params) : 363 | parameters(::std::move(params)) 364 | { 365 | InitTable(); 366 | } 367 | #endif 368 | 369 | /** 370 | @brief Gets the CRC parameters used to construct the CRC table 371 | @tparam CRCType Integer type for storing the CRC result 372 | @tparam CRCWidth Number of bits in the CRC 373 | @return CRC parameters 374 | */ 375 | template 376 | inline const CRC::Parameters & CRC::Table::GetParameters() const 377 | { 378 | return parameters; 379 | } 380 | 381 | /** 382 | @brief Gets the CRC table 383 | @tparam CRCType Integer type for storing the CRC result 384 | @tparam CRCWidth Number of bits in the CRC 385 | @return CRC table 386 | */ 387 | template 388 | inline const CRCType * CRC::Table::GetTable() const 389 | { 390 | return table; 391 | } 392 | 393 | /** 394 | @brief Gets an entry in the CRC table 395 | @param[in] index Index into the CRC table 396 | @tparam CRCType Integer type for storing the CRC result 397 | @tparam CRCWidth Number of bits in the CRC 398 | @return CRC table entry 399 | */ 400 | template 401 | inline CRCType CRC::Table::operator[](unsigned char index) const 402 | { 403 | return table[index]; 404 | } 405 | 406 | /** 407 | @brief Initializes a CRC table. 408 | @tparam CRCType Integer type for storing the CRC result 409 | @tparam CRCWidth Number of bits in the CRC 410 | */ 411 | template 412 | inline void CRC::Table::InitTable() 413 | { 414 | // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth) 415 | static crcpp_constexpr CRCType BIT_MASK((CRCType(1) << (CRCWidth - CRCType(1))) | 416 | ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1))); 417 | 418 | // The conditional expression is used to avoid a -Wshift-count-overflow warning. 419 | static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast(CHAR_BIT - CRCWidth) : 0); 420 | 421 | CRCType crc; 422 | unsigned char byte = 0; 423 | 424 | // Loop over each dividend (each possible number storable in an unsigned char) 425 | do 426 | { 427 | crc = CRC::CalculateRemainder(&byte, sizeof(byte), parameters, CRCType(0)); 428 | 429 | // This mask might not be necessary; all unit tests pass with this line commented out, 430 | // but that might just be a coincidence based on the CRC parameters used for testing. 431 | // In any case, this is harmless to leave in and only adds a single machine instruction per loop iteration. 432 | crc &= BIT_MASK; 433 | 434 | if (!parameters.reflectInput && CRCWidth < CHAR_BIT) 435 | { 436 | // Undo the special operation at the end of the CalculateRemainder() 437 | // function for non-reflected CRCs < CHAR_BIT. 438 | crc = static_cast(crc << SHIFT); 439 | } 440 | 441 | table[byte] = crc; 442 | } 443 | while (++byte); 444 | } 445 | 446 | /** 447 | @brief Computes a CRC. 448 | @param[in] data Data over which CRC will be computed 449 | @param[in] size Size of the data, in bytes 450 | @param[in] parameters CRC parameters 451 | @tparam CRCType Integer type for storing the CRC result 452 | @tparam CRCWidth Number of bits in the CRC 453 | @return CRC 454 | */ 455 | template 456 | inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Parameters & parameters) 457 | { 458 | CRCType remainder = CalculateRemainder(data, size, parameters, parameters.initialValue); 459 | 460 | // No need to mask the remainder here; the mask will be applied in the Finalize() function. 461 | 462 | return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 463 | } 464 | /** 465 | @brief Appends additional data to a previous CRC calculation. 466 | @note This function can be used to compute multi-part CRCs. 467 | @param[in] data Data over which CRC will be computed 468 | @param[in] size Size of the data, in bytes 469 | @param[in] parameters CRC parameters 470 | @param[in] crc CRC from a previous calculation 471 | @tparam CRCType Integer type for storing the CRC result 472 | @tparam CRCWidth Number of bits in the CRC 473 | @return CRC 474 | */ 475 | template 476 | inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Parameters & parameters, CRCType crc) 477 | { 478 | CRCType remainder = UndoFinalize(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 479 | 480 | remainder = CalculateRemainder(data, size, parameters, remainder); 481 | 482 | // No need to mask the remainder here; the mask will be applied in the Finalize() function. 483 | 484 | return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 485 | } 486 | 487 | /** 488 | @brief Computes a CRC via a lookup table. 489 | @param[in] data Data over which CRC will be computed 490 | @param[in] size Size of the data, in bytes 491 | @param[in] lookupTable CRC lookup table 492 | @tparam CRCType Integer type for storing the CRC result 493 | @tparam CRCWidth Number of bits in the CRC 494 | @return CRC 495 | */ 496 | template 497 | inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Table & lookupTable) 498 | { 499 | const Parameters & parameters = lookupTable.GetParameters(); 500 | 501 | CRCType remainder = CalculateRemainder(data, size, lookupTable, parameters.initialValue); 502 | 503 | // No need to mask the remainder here; the mask will be applied in the Finalize() function. 504 | 505 | return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 506 | } 507 | 508 | /** 509 | @brief Appends additional data to a previous CRC calculation using a lookup table. 510 | @note This function can be used to compute multi-part CRCs. 511 | @param[in] data Data over which CRC will be computed 512 | @param[in] size Size of the data, in bytes 513 | @param[in] lookupTable CRC lookup table 514 | @param[in] crc CRC from a previous calculation 515 | @tparam CRCType Integer type for storing the CRC result 516 | @tparam CRCWidth Number of bits in the CRC 517 | @return CRC 518 | */ 519 | template 520 | inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Table & lookupTable, CRCType crc) 521 | { 522 | const Parameters & parameters = lookupTable.GetParameters(); 523 | 524 | CRCType remainder = UndoFinalize(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 525 | 526 | remainder = CalculateRemainder(data, size, lookupTable, remainder); 527 | 528 | // No need to mask the remainder here; the mask will be applied in the Finalize() function. 529 | 530 | return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 531 | } 532 | 533 | /** 534 | @brief Computes a CRC. 535 | @param[in] data Data over which CRC will be computed 536 | @param[in] size Size of the data, in bits 537 | @param[in] parameters CRC parameters 538 | @tparam CRCType Integer type for storing the CRC result 539 | @tparam CRCWidth Number of bits in the CRC 540 | @return CRC 541 | */ 542 | template 543 | inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Parameters & parameters) 544 | { 545 | CRCType remainder = parameters.initialValue; 546 | 547 | // Calculate the remainder on a whole number of bytes first, then call 548 | // a special-case function for the remaining bits. 549 | crcpp_size wholeNumberOfBytes = size / CHAR_BIT; 550 | if (wholeNumberOfBytes > 0) 551 | { 552 | remainder = CalculateRemainder(data, wholeNumberOfBytes, parameters, remainder); 553 | } 554 | 555 | crcpp_size remainingNumberOfBits = size % CHAR_BIT; 556 | if (remainingNumberOfBits != 0) 557 | { 558 | unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); 559 | remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); 560 | } 561 | 562 | // No need to mask the remainder here; the mask will be applied in the Finalize() function. 563 | 564 | return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 565 | } 566 | /** 567 | @brief Appends additional data to a previous CRC calculation. 568 | @note This function can be used to compute multi-part CRCs. 569 | @param[in] data Data over which CRC will be computed 570 | @param[in] size Size of the data, in bits 571 | @param[in] parameters CRC parameters 572 | @param[in] crc CRC from a previous calculation 573 | @tparam CRCType Integer type for storing the CRC result 574 | @tparam CRCWidth Number of bits in the CRC 575 | @return CRC 576 | */ 577 | template 578 | inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Parameters & parameters, CRCType crc) 579 | { 580 | CRCType remainder = UndoFinalize(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 581 | 582 | // Calculate the remainder on a whole number of bytes first, then call 583 | // a special-case function for the remaining bits. 584 | crcpp_size wholeNumberOfBytes = size / CHAR_BIT; 585 | if (wholeNumberOfBytes > 0) 586 | { 587 | remainder = CalculateRemainder(data, wholeNumberOfBytes, parameters, parameters.initialValue); 588 | } 589 | 590 | crcpp_size remainingNumberOfBits = size % CHAR_BIT; 591 | if (remainingNumberOfBits != 0) 592 | { 593 | unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); 594 | remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); 595 | } 596 | 597 | // No need to mask the remainder here; the mask will be applied in the Finalize() function. 598 | 599 | return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 600 | } 601 | 602 | /** 603 | @brief Computes a CRC via a lookup table. 604 | @param[in] data Data over which CRC will be computed 605 | @param[in] size Size of the data, in bits 606 | @param[in] lookupTable CRC lookup table 607 | @tparam CRCType Integer type for storing the CRC result 608 | @tparam CRCWidth Number of bits in the CRC 609 | @return CRC 610 | */ 611 | template 612 | inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Table & lookupTable) 613 | { 614 | const Parameters & parameters = lookupTable.GetParameters(); 615 | 616 | CRCType remainder = parameters.initialValue; 617 | 618 | // Calculate the remainder on a whole number of bytes first, then call 619 | // a special-case function for the remaining bits. 620 | crcpp_size wholeNumberOfBytes = size / CHAR_BIT; 621 | if (wholeNumberOfBytes > 0) 622 | { 623 | remainder = CalculateRemainder(data, wholeNumberOfBytes, lookupTable, remainder); 624 | } 625 | 626 | crcpp_size remainingNumberOfBits = size % CHAR_BIT; 627 | if (remainingNumberOfBits != 0) 628 | { 629 | unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); 630 | remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); 631 | } 632 | 633 | // No need to mask the remainder here; the mask will be applied in the Finalize() function. 634 | 635 | return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 636 | } 637 | 638 | /** 639 | @brief Appends additional data to a previous CRC calculation using a lookup table. 640 | @note This function can be used to compute multi-part CRCs. 641 | @param[in] data Data over which CRC will be computed 642 | @param[in] size Size of the data, in bits 643 | @param[in] lookupTable CRC lookup table 644 | @param[in] crc CRC from a previous calculation 645 | @tparam CRCType Integer type for storing the CRC result 646 | @tparam CRCWidth Number of bits in the CRC 647 | @return CRC 648 | */ 649 | template 650 | inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Table & lookupTable, CRCType crc) 651 | { 652 | const Parameters & parameters = lookupTable.GetParameters(); 653 | 654 | CRCType remainder = UndoFinalize(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 655 | 656 | // Calculate the remainder on a whole number of bytes first, then call 657 | // a special-case function for the remaining bits. 658 | crcpp_size wholeNumberOfBytes = size / CHAR_BIT; 659 | if (wholeNumberOfBytes > 0) 660 | { 661 | remainder = CalculateRemainder(data, wholeNumberOfBytes, lookupTable, parameters.initialValue); 662 | } 663 | 664 | crcpp_size remainingNumberOfBits = size % CHAR_BIT; 665 | if (remainingNumberOfBits > 0) 666 | { 667 | unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); 668 | remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); 669 | } 670 | 671 | // No need to mask the remainder here; the mask will be applied in the Finalize() function. 672 | 673 | return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); 674 | } 675 | 676 | /** 677 | @brief Reflects (i.e. reverses the bits within) an integer value. 678 | @param[in] value Value to reflect 679 | @param[in] numBits Number of bits in the integer which will be reflected 680 | @tparam IntegerType Integer type of the value being reflected 681 | @return Reflected value 682 | */ 683 | template 684 | inline IntegerType CRC::Reflect(IntegerType value, crcpp_uint16 numBits) 685 | { 686 | IntegerType reversedValue(0); 687 | 688 | for (crcpp_uint16 i = 0; i < numBits; ++i) 689 | { 690 | reversedValue = static_cast((reversedValue << 1) | (value & 1)); 691 | value = static_cast(value >> 1); 692 | } 693 | 694 | return reversedValue; 695 | } 696 | 697 | /** 698 | @brief Computes the final reflection and XOR of a CRC remainder. 699 | @param[in] remainder CRC remainder to reflect and XOR 700 | @param[in] finalXOR Final value to XOR with the remainder 701 | @param[in] reflectOutput true to reflect each byte of the remainder before the XOR 702 | @tparam CRCType Integer type for storing the CRC result 703 | @tparam CRCWidth Number of bits in the CRC 704 | @return Final CRC 705 | */ 706 | template 707 | inline CRCType CRC::Finalize(CRCType remainder, CRCType finalXOR, bool reflectOutput) 708 | { 709 | // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth) 710 | static crcpp_constexpr CRCType BIT_MASK = (CRCType(1) << (CRCWidth - CRCType(1))) | 711 | ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1)); 712 | 713 | if (reflectOutput) 714 | { 715 | remainder = Reflect(remainder, CRCWidth); 716 | } 717 | 718 | return (remainder ^ finalXOR) & BIT_MASK; 719 | } 720 | 721 | /** 722 | @brief Undoes the process of computing the final reflection and XOR of a CRC remainder. 723 | @note This function allows for computation of multi-part CRCs 724 | @note Calling UndoFinalize() followed by Finalize() (or vice versa) will always return the original remainder value: 725 | 726 | CRCType x = ...; 727 | CRCType y = Finalize(x, finalXOR, reflectOutput); 728 | CRCType z = UndoFinalize(y, finalXOR, reflectOutput); 729 | assert(x == z); 730 | 731 | @param[in] crc Reflected and XORed CRC 732 | @param[in] finalXOR Final value XORed with the remainder 733 | @param[in] reflectOutput true if the remainder is to be reflected 734 | @tparam CRCType Integer type for storing the CRC result 735 | @tparam CRCWidth Number of bits in the CRC 736 | @return Un-finalized CRC remainder 737 | */ 738 | template 739 | inline CRCType CRC::UndoFinalize(CRCType crc, CRCType finalXOR, bool reflectOutput) 740 | { 741 | // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth) 742 | static crcpp_constexpr CRCType BIT_MASK = (CRCType(1) << (CRCWidth - CRCType(1))) | 743 | ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1)); 744 | 745 | crc = (crc & BIT_MASK) ^ finalXOR; 746 | 747 | if (reflectOutput) 748 | { 749 | crc = Reflect(crc, CRCWidth); 750 | } 751 | 752 | return crc; 753 | } 754 | 755 | /** 756 | @brief Computes a CRC remainder. 757 | @param[in] data Data over which the remainder will be computed 758 | @param[in] size Size of the data, in bytes 759 | @param[in] parameters CRC parameters 760 | @param[in] remainder Running CRC remainder. Can be an initial value or the result of a previous CRC remainder calculation. 761 | @tparam CRCType Integer type for storing the CRC result 762 | @tparam CRCWidth Number of bits in the CRC 763 | @return CRC remainder 764 | */ 765 | template 766 | inline CRCType CRC::CalculateRemainder(const void * data, crcpp_size size, const Parameters & parameters, CRCType remainder) 767 | { 768 | #ifdef CRCPP_USE_CPP11 769 | // This static_assert is put here because this function will always be compiled in no matter what 770 | // the template parameters are and whether or not a table lookup or bit-by-bit algorithm is used. 771 | static_assert(::std::numeric_limits::digits >= CRCWidth, "CRCType is too small to contain a CRC of width CRCWidth."); 772 | #else 773 | // Catching this compile-time error is very important. Sadly, the compiler error will be very cryptic, but it's 774 | // better than nothing. 775 | enum { static_assert_failed_CRCType_is_too_small_to_contain_a_CRC_of_width_CRCWidth = 1 / (::std::numeric_limits::digits >= CRCWidth ? 1 : 0) }; 776 | #endif 777 | 778 | const unsigned char * current = reinterpret_cast(data); 779 | 780 | // Slightly different implementations based on the parameters. The current implementations try to eliminate as much 781 | // computation from the inner loop (looping over each bit) as possible. 782 | if (parameters.reflectInput) 783 | { 784 | CRCType polynomial = CRC::Reflect(parameters.polynomial, CRCWidth); 785 | while (size--) 786 | { 787 | remainder = static_cast(remainder ^ *current++); 788 | 789 | // An optimizing compiler might choose to unroll this loop. 790 | for (crcpp_size i = 0; i < CHAR_BIT; ++i) 791 | { 792 | #ifdef CRCPP_BRANCHLESS 793 | // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: 794 | // if (remainder & 1) 795 | // remainder = (remainder >> 1) ^ polynomial; 796 | // else 797 | // remainder >>= 1; 798 | remainder = static_cast((remainder >> 1) ^ ((remainder & 1) * polynomial)); 799 | #else 800 | remainder = static_cast((remainder & 1) ? ((remainder >> 1) ^ polynomial) : (remainder >> 1)); 801 | #endif 802 | } 803 | } 804 | } 805 | else if constexpr (CRCWidth >= CHAR_BIT) 806 | { 807 | static crcpp_constexpr CRCType CRC_WIDTH_MINUS_ONE(CRCWidth - CRCType(1)); 808 | #ifndef CRCPP_BRANCHLESS 809 | static crcpp_constexpr CRCType CRC_HIGHEST_BIT_MASK(CRCType(1) << CRC_WIDTH_MINUS_ONE); 810 | #endif 811 | // The conditional expression is used to avoid a -Wshift-count-overflow warning. 812 | static crcpp_constexpr CRCType SHIFT((CRCWidth >= CHAR_BIT) ? static_cast(CRCWidth - CHAR_BIT) : 0); 813 | 814 | while (size--) 815 | { 816 | remainder = static_cast(remainder ^ (static_cast(*current++) << SHIFT)); 817 | 818 | // An optimizing compiler might choose to unroll this loop. 819 | for (crcpp_size i = 0; i < CHAR_BIT; ++i) 820 | { 821 | #ifdef CRCPP_BRANCHLESS 822 | // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: 823 | // if (remainder & CRC_HIGHEST_BIT_MASK) 824 | // remainder = (remainder << 1) ^ parameters.polynomial; 825 | // else 826 | // remainder <<= 1; 827 | remainder = static_cast((remainder << 1) ^ (((remainder >> CRC_WIDTH_MINUS_ONE) & 1) * parameters.polynomial)); 828 | #else 829 | remainder = static_cast((remainder & CRC_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ parameters.polynomial) : (remainder << 1)); 830 | #endif 831 | } 832 | } 833 | } 834 | else 835 | { 836 | static crcpp_constexpr CRCType CHAR_BIT_MINUS_ONE(CHAR_BIT - 1); 837 | #ifndef CRCPP_BRANCHLESS 838 | static crcpp_constexpr CRCType CHAR_BIT_HIGHEST_BIT_MASK(CRCType(1) << CHAR_BIT_MINUS_ONE); 839 | #endif 840 | // The conditional expression is used to avoid a -Wshift-count-overflow warning. 841 | static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast(CHAR_BIT - CRCWidth) : 0); 842 | 843 | CRCType polynomial = static_cast(parameters.polynomial << SHIFT); 844 | remainder = static_cast(remainder << SHIFT); 845 | 846 | while (size--) 847 | { 848 | remainder = static_cast(remainder ^ *current++); 849 | 850 | // An optimizing compiler might choose to unroll this loop. 851 | for (crcpp_size i = 0; i < CHAR_BIT; ++i) 852 | { 853 | #ifdef CRCPP_BRANCHLESS 854 | // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: 855 | // if (remainder & CHAR_BIT_HIGHEST_BIT_MASK) 856 | // remainder = (remainder << 1) ^ polynomial; 857 | // else 858 | // remainder <<= 1; 859 | remainder = static_cast((remainder << 1) ^ (((remainder >> CHAR_BIT_MINUS_ONE) & 1) * polynomial)); 860 | #else 861 | remainder = static_cast((remainder & CHAR_BIT_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ polynomial) : (remainder << 1)); 862 | #endif 863 | } 864 | } 865 | 866 | remainder = static_cast(remainder >> SHIFT); 867 | } 868 | 869 | return remainder; 870 | } 871 | 872 | /** 873 | @brief Computes a CRC remainder using lookup table. 874 | @param[in] data Data over which the remainder will be computed 875 | @param[in] size Size of the data, in bytes 876 | @param[in] lookupTable CRC lookup table 877 | @param[in] remainder Running CRC remainder. Can be an initial value or the result of a previous CRC remainder calculation. 878 | @tparam CRCType Integer type for storing the CRC result 879 | @tparam CRCWidth Number of bits in the CRC 880 | @return CRC remainder 881 | */ 882 | template 883 | inline CRCType CRC::CalculateRemainder(const void * data, crcpp_size size, const Table & lookupTable, CRCType remainder) 884 | { 885 | const unsigned char * current = reinterpret_cast(data); 886 | 887 | if (lookupTable.GetParameters().reflectInput) 888 | { 889 | while (size--) 890 | { 891 | #if defined(WIN32) || defined(_WIN32) || defined(WINCE) 892 | // Disable warning about data loss when doing (remainder >> CHAR_BIT) when 893 | // remainder is one byte long. The algorithm is still correct in this case, 894 | // though it's possible that one additional machine instruction will be executed. 895 | # pragma warning (push) 896 | # pragma warning (disable : 4333) 897 | #endif 898 | remainder = static_cast((remainder >> CHAR_BIT) ^ lookupTable[static_cast(remainder ^ *current++)]); 899 | #if defined(WIN32) || defined(_WIN32) || defined(WINCE) 900 | # pragma warning (pop) 901 | #endif 902 | } 903 | } 904 | else if (CRCWidth >= CHAR_BIT) 905 | { 906 | // The conditional expression is used to avoid a -Wshift-count-overflow warning. 907 | static crcpp_constexpr CRCType SHIFT((CRCWidth >= CHAR_BIT) ? static_cast(CRCWidth - CHAR_BIT) : 0); 908 | 909 | while (size--) 910 | { 911 | remainder = static_cast((remainder << CHAR_BIT) ^ lookupTable[static_cast((remainder >> SHIFT) ^ *current++)]); 912 | } 913 | } 914 | else 915 | { 916 | // The conditional expression is used to avoid a -Wshift-count-overflow warning. 917 | static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast(CHAR_BIT - CRCWidth) : 0); 918 | 919 | remainder = static_cast(remainder << SHIFT); 920 | 921 | while (size--) 922 | { 923 | // Note: no need to mask here since remainder is guaranteed to fit in a single byte. 924 | remainder = lookupTable[static_cast(remainder ^ *current++)]; 925 | } 926 | 927 | remainder = static_cast(remainder >> SHIFT); 928 | } 929 | 930 | return remainder; 931 | } 932 | 933 | template 934 | inline CRCType CRC::CalculateRemainderBits(unsigned char byte, crcpp_size numBits, const Parameters & parameters, CRCType remainder) 935 | { 936 | // Slightly different implementations based on the parameters. The current implementations try to eliminate as much 937 | // computation from the inner loop (looping over each bit) as possible. 938 | if (parameters.reflectInput) 939 | { 940 | CRCType polynomial = CRC::Reflect(parameters.polynomial, CRCWidth); 941 | remainder = static_cast(remainder ^ byte); 942 | 943 | // An optimizing compiler might choose to unroll this loop. 944 | for (crcpp_size i = 0; i < numBits; ++i) 945 | { 946 | #ifdef CRCPP_BRANCHLESS 947 | // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: 948 | // if (remainder & 1) 949 | // remainder = (remainder >> 1) ^ polynomial; 950 | // else 951 | // remainder >>= 1; 952 | remainder = static_cast((remainder >> 1) ^ ((remainder & 1) * polynomial)); 953 | #else 954 | remainder = static_cast((remainder & 1) ? ((remainder >> 1) ^ polynomial) : (remainder >> 1)); 955 | #endif 956 | } 957 | } 958 | else if (CRCWidth >= CHAR_BIT) 959 | { 960 | static crcpp_constexpr CRCType CRC_WIDTH_MINUS_ONE(CRCWidth - CRCType(1)); 961 | #ifndef CRCPP_BRANCHLESS 962 | static crcpp_constexpr CRCType CRC_HIGHEST_BIT_MASK(CRCType(1) << CRC_WIDTH_MINUS_ONE); 963 | #endif 964 | // The conditional expression is used to avoid a -Wshift-count-overflow warning. 965 | static crcpp_constexpr CRCType SHIFT((CRCWidth >= CHAR_BIT) ? static_cast(CRCWidth - CHAR_BIT) : 0); 966 | 967 | remainder = static_cast(remainder ^ (static_cast(byte) << SHIFT)); 968 | 969 | // An optimizing compiler might choose to unroll this loop. 970 | for (crcpp_size i = 0; i < numBits; ++i) 971 | { 972 | #ifdef CRCPP_BRANCHLESS 973 | // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: 974 | // if (remainder & CRC_HIGHEST_BIT_MASK) 975 | // remainder = (remainder << 1) ^ parameters.polynomial; 976 | // else 977 | // remainder <<= 1; 978 | remainder = static_cast((remainder << 1) ^ (((remainder >> CRC_WIDTH_MINUS_ONE) & 1) * parameters.polynomial)); 979 | #else 980 | remainder = static_cast((remainder & CRC_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ parameters.polynomial) : (remainder << 1)); 981 | #endif 982 | } 983 | } 984 | else 985 | { 986 | static crcpp_constexpr CRCType CHAR_BIT_MINUS_ONE(CHAR_BIT - 1); 987 | #ifndef CRCPP_BRANCHLESS 988 | static crcpp_constexpr CRCType CHAR_BIT_HIGHEST_BIT_MASK(CRCType(1) << CHAR_BIT_MINUS_ONE); 989 | #endif 990 | // The conditional expression is used to avoid a -Wshift-count-overflow warning. 991 | static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast(CHAR_BIT - CRCWidth) : 0); 992 | 993 | CRCType polynomial = static_cast(parameters.polynomial << SHIFT); 994 | remainder = static_cast((remainder << SHIFT) ^ byte); 995 | 996 | // An optimizing compiler might choose to unroll this loop. 997 | for (crcpp_size i = 0; i < numBits; ++i) 998 | { 999 | #ifdef CRCPP_BRANCHLESS 1000 | // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: 1001 | // if (remainder & CHAR_BIT_HIGHEST_BIT_MASK) 1002 | // remainder = (remainder << 1) ^ polynomial; 1003 | // else 1004 | // remainder <<= 1; 1005 | remainder = static_cast((remainder << 1) ^ (((remainder >> CHAR_BIT_MINUS_ONE) & 1) * polynomial)); 1006 | #else 1007 | remainder = static_cast((remainder & CHAR_BIT_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ polynomial) : (remainder << 1)); 1008 | #endif 1009 | } 1010 | 1011 | remainder = static_cast(remainder >> SHIFT); 1012 | } 1013 | 1014 | return remainder; 1015 | } 1016 | 1017 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 1018 | /** 1019 | @brief Returns a set of parameters for CRC-4 ITU. 1020 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1021 | @note CRC-4 ITU has the following parameters and check value: 1022 | - polynomial = 0x3 1023 | - initial value = 0x0 1024 | - final XOR = 0x0 1025 | - reflect input = true 1026 | - reflect output = true 1027 | - check value = 0x7 1028 | @return CRC-4 ITU parameters 1029 | */ 1030 | inline const CRC::Parameters & CRC::CRC_4_ITU() 1031 | { 1032 | static const Parameters parameters = { 0x3, 0x0, 0x0, true, true }; 1033 | return parameters; 1034 | } 1035 | 1036 | /** 1037 | @brief Returns a set of parameters for CRC-5 EPC. 1038 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1039 | @note CRC-5 EPC has the following parameters and check value: 1040 | - polynomial = 0x09 1041 | - initial value = 0x09 1042 | - final XOR = 0x00 1043 | - reflect input = false 1044 | - reflect output = false 1045 | - check value = 0x00 1046 | @return CRC-5 EPC parameters 1047 | */ 1048 | inline const CRC::Parameters & CRC::CRC_5_EPC() 1049 | { 1050 | static const Parameters parameters = { 0x09, 0x09, 0x00, false, false }; 1051 | return parameters; 1052 | } 1053 | 1054 | /** 1055 | @brief Returns a set of parameters for CRC-5 ITU. 1056 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1057 | @note CRC-5 ITU has the following parameters and check value: 1058 | - polynomial = 0x15 1059 | - initial value = 0x00 1060 | - final XOR = 0x00 1061 | - reflect input = true 1062 | - reflect output = true 1063 | - check value = 0x07 1064 | @return CRC-5 ITU parameters 1065 | */ 1066 | inline const CRC::Parameters & CRC::CRC_5_ITU() 1067 | { 1068 | static const Parameters parameters = { 0x15, 0x00, 0x00, true, true }; 1069 | return parameters; 1070 | } 1071 | 1072 | /** 1073 | @brief Returns a set of parameters for CRC-5 USB. 1074 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1075 | @note CRC-5 USB has the following parameters and check value: 1076 | - polynomial = 0x05 1077 | - initial value = 0x1F 1078 | - final XOR = 0x1F 1079 | - reflect input = true 1080 | - reflect output = true 1081 | - check value = 0x19 1082 | @return CRC-5 USB parameters 1083 | */ 1084 | inline const CRC::Parameters & CRC::CRC_5_USB() 1085 | { 1086 | static const Parameters parameters = { 0x05, 0x1F, 0x1F, true, true }; 1087 | return parameters; 1088 | } 1089 | 1090 | /** 1091 | @brief Returns a set of parameters for CRC-6 CDMA2000-A. 1092 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1093 | @note CRC-6 CDMA2000-A has the following parameters and check value: 1094 | - polynomial = 0x27 1095 | - initial value = 0x3F 1096 | - final XOR = 0x00 1097 | - reflect input = false 1098 | - reflect output = false 1099 | - check value = 0x0D 1100 | @return CRC-6 CDMA2000-A parameters 1101 | */ 1102 | inline const CRC::Parameters & CRC::CRC_6_CDMA2000A() 1103 | { 1104 | static const Parameters parameters = { 0x27, 0x3F, 0x00, false, false }; 1105 | return parameters; 1106 | } 1107 | 1108 | /** 1109 | @brief Returns a set of parameters for CRC-6 CDMA2000-B. 1110 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1111 | @note CRC-6 CDMA2000-A has the following parameters and check value: 1112 | - polynomial = 0x07 1113 | - initial value = 0x3F 1114 | - final XOR = 0x00 1115 | - reflect input = false 1116 | - reflect output = false 1117 | - check value = 0x3B 1118 | @return CRC-6 CDMA2000-B parameters 1119 | */ 1120 | inline const CRC::Parameters & CRC::CRC_6_CDMA2000B() 1121 | { 1122 | static const Parameters parameters = { 0x07, 0x3F, 0x00, false, false }; 1123 | return parameters; 1124 | } 1125 | 1126 | /** 1127 | @brief Returns a set of parameters for CRC-6 ITU. 1128 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1129 | @note CRC-6 ITU has the following parameters and check value: 1130 | - polynomial = 0x03 1131 | - initial value = 0x00 1132 | - final XOR = 0x00 1133 | - reflect input = true 1134 | - reflect output = true 1135 | - check value = 0x06 1136 | @return CRC-6 ITU parameters 1137 | */ 1138 | inline const CRC::Parameters & CRC::CRC_6_ITU() 1139 | { 1140 | static const Parameters parameters = { 0x03, 0x00, 0x00, true, true }; 1141 | return parameters; 1142 | } 1143 | 1144 | /** 1145 | @brief Returns a set of parameters for CRC-6 NR. 1146 | @note The parameters are static and are delayed-constructed to reduce memory 1147 | footprint. 1148 | @note CRC-6 NR has the following parameters and check value: 1149 | - polynomial = 0x21 1150 | - initial value = 0x00 1151 | - final XOR = 0x00 1152 | - reflect input = false 1153 | - reflect output = false 1154 | - check value = 0x15 1155 | @return CRC-6 NR parameters 1156 | */ 1157 | inline const CRC::Parameters & CRC::CRC_6_NR() 1158 | { 1159 | static const Parameters parameters = { 0x21, 0x00, 0x00, false, false }; 1160 | return parameters; 1161 | } 1162 | 1163 | /** 1164 | @brief Returns a set of parameters for CRC-7 JEDEC. 1165 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1166 | @note CRC-7 JEDEC has the following parameters and check value: 1167 | - polynomial = 0x09 1168 | - initial value = 0x00 1169 | - final XOR = 0x00 1170 | - reflect input = false 1171 | - reflect output = false 1172 | - check value = 0x75 1173 | @return CRC-7 JEDEC parameters 1174 | */ 1175 | inline const CRC::Parameters & CRC::CRC_7() 1176 | { 1177 | static const Parameters parameters = { 0x09, 0x00, 0x00, false, false }; 1178 | return parameters; 1179 | } 1180 | #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 1181 | 1182 | /** 1183 | @brief Returns a set of parameters for CRC-8 SMBus. 1184 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1185 | @note CRC-8 SMBus has the following parameters and check value: 1186 | - polynomial = 0x07 1187 | - initial value = 0x00 1188 | - final XOR = 0x00 1189 | - reflect input = false 1190 | - reflect output = false 1191 | - check value = 0xF4 1192 | @return CRC-8 SMBus parameters 1193 | */ 1194 | inline const CRC::Parameters & CRC::CRC_8() 1195 | { 1196 | static const Parameters parameters = { 0x07, 0x00, 0x00, false, false }; 1197 | return parameters; 1198 | } 1199 | 1200 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 1201 | /** 1202 | @brief Returns a set of parameters for CRC-8 EBU (aka CRC-8 AES). 1203 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1204 | @note CRC-8 EBU has the following parameters and check value: 1205 | - polynomial = 0x1D 1206 | - initial value = 0xFF 1207 | - final XOR = 0x00 1208 | - reflect input = true 1209 | - reflect output = true 1210 | - check value = 0x97 1211 | @return CRC-8 EBU parameters 1212 | */ 1213 | inline const CRC::Parameters & CRC::CRC_8_EBU() 1214 | { 1215 | static const Parameters parameters = { 0x1D, 0xFF, 0x00, true, true }; 1216 | return parameters; 1217 | } 1218 | 1219 | /** 1220 | @brief Returns a set of parameters for CRC-8 MAXIM (aka CRC-8 DOW-CRC). 1221 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1222 | @note CRC-8 MAXIM has the following parameters and check value: 1223 | - polynomial = 0x31 1224 | - initial value = 0x00 1225 | - final XOR = 0x00 1226 | - reflect input = true 1227 | - reflect output = true 1228 | - check value = 0xA1 1229 | @return CRC-8 MAXIM parameters 1230 | */ 1231 | inline const CRC::Parameters & CRC::CRC_8_MAXIM() 1232 | { 1233 | static const Parameters parameters = { 0x31, 0x00, 0x00, true, true }; 1234 | return parameters; 1235 | } 1236 | 1237 | /** 1238 | @brief Returns a set of parameters for CRC-8 WCDMA. 1239 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1240 | @note CRC-8 WCDMA has the following parameters and check value: 1241 | - polynomial = 0x9B 1242 | - initial value = 0x00 1243 | - final XOR = 0x00 1244 | - reflect input = true 1245 | - reflect output = true 1246 | - check value = 0x25 1247 | @return CRC-8 WCDMA parameters 1248 | */ 1249 | inline const CRC::Parameters & CRC::CRC_8_WCDMA() 1250 | { 1251 | static const Parameters parameters = { 0x9B, 0x00, 0x00, true, true }; 1252 | return parameters; 1253 | } 1254 | 1255 | /** 1256 | @brief Returns a set of parameters for CRC-8 LTE. 1257 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1258 | @note CRC-8 LTE has the following parameters and check value: 1259 | - polynomial = 0x9B 1260 | - initial value = 0x00 1261 | - final XOR = 0x00 1262 | - reflect input = false 1263 | - reflect output = false 1264 | - check value = 0xEA 1265 | @return CRC-8 LTE parameters 1266 | */ 1267 | inline const CRC::Parameters & CRC::CRC_8_LTE() 1268 | { 1269 | static const Parameters parameters = { 0x9B, 0x00, 0x00, false, false }; 1270 | return parameters; 1271 | } 1272 | 1273 | /** 1274 | @brief Returns a set of parameters for CRC-10 ITU. 1275 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1276 | @note CRC-10 ITU has the following parameters and check value: 1277 | - polynomial = 0x233 1278 | - initial value = 0x000 1279 | - final XOR = 0x000 1280 | - reflect input = false 1281 | - reflect output = false 1282 | - check value = 0x199 1283 | @return CRC-10 ITU parameters 1284 | */ 1285 | inline const CRC::Parameters & CRC::CRC_10() 1286 | { 1287 | static const Parameters parameters = { 0x233, 0x000, 0x000, false, false }; 1288 | return parameters; 1289 | } 1290 | 1291 | /** 1292 | @brief Returns a set of parameters for CRC-10 CDMA2000. 1293 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1294 | @note CRC-10 CDMA2000 has the following parameters and check value: 1295 | - polynomial = 0x3D9 1296 | - initial value = 0x3FF 1297 | - final XOR = 0x000 1298 | - reflect input = false 1299 | - reflect output = false 1300 | - check value = 0x233 1301 | @return CRC-10 CDMA2000 parameters 1302 | */ 1303 | inline const CRC::Parameters & CRC::CRC_10_CDMA2000() 1304 | { 1305 | static const Parameters parameters = { 0x3D9, 0x3FF, 0x000, false, false }; 1306 | return parameters; 1307 | } 1308 | 1309 | /** 1310 | @brief Returns a set of parameters for CRC-11 FlexRay. 1311 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1312 | @note CRC-11 FlexRay has the following parameters and check value: 1313 | - polynomial = 0x385 1314 | - initial value = 0x01A 1315 | - final XOR = 0x000 1316 | - reflect input = false 1317 | - reflect output = false 1318 | - check value = 0x5A3 1319 | @return CRC-11 FlexRay parameters 1320 | */ 1321 | inline const CRC::Parameters & CRC::CRC_11() 1322 | { 1323 | static const Parameters parameters = { 0x385, 0x01A, 0x000, false, false }; 1324 | return parameters; 1325 | } 1326 | 1327 | /** 1328 | @brief Returns a set of parameters for CRC-11 NR. 1329 | @note The parameters are static and are delayed-constructed to reduce memory 1330 | footprint. 1331 | @note CRC-11 NR has the following parameters and check value: 1332 | - polynomial = 0x621 1333 | - initial value = 0x000 1334 | - final XOR = 0x000 1335 | - reflect input = false 1336 | - reflect output = false 1337 | - check value = 0x5CA 1338 | @return CRC-11 NR parameters 1339 | */ 1340 | inline const CRC::Parameters & CRC::CRC_11_NR() 1341 | { 1342 | static const Parameters parameters = { 0x621, 0x000, 0x000, false, false }; 1343 | return parameters; 1344 | } 1345 | 1346 | /** 1347 | @brief Returns a set of parameters for CRC-12 CDMA2000. 1348 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1349 | @note CRC-12 CDMA2000 has the following parameters and check value: 1350 | - polynomial = 0xF13 1351 | - initial value = 0xFFF 1352 | - final XOR = 0x000 1353 | - reflect input = false 1354 | - reflect output = false 1355 | - check value = 0xD4D 1356 | @return CRC-12 CDMA2000 parameters 1357 | */ 1358 | inline const CRC::Parameters & CRC::CRC_12_CDMA2000() 1359 | { 1360 | static const Parameters parameters = { 0xF13, 0xFFF, 0x000, false, false }; 1361 | return parameters; 1362 | } 1363 | 1364 | /** 1365 | @brief Returns a set of parameters for CRC-12 DECT (aka CRC-12 X-CRC). 1366 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1367 | @note CRC-12 DECT has the following parameters and check value: 1368 | - polynomial = 0x80F 1369 | - initial value = 0x000 1370 | - final XOR = 0x000 1371 | - reflect input = false 1372 | - reflect output = false 1373 | - check value = 0xF5B 1374 | @return CRC-12 DECT parameters 1375 | */ 1376 | inline const CRC::Parameters & CRC::CRC_12_DECT() 1377 | { 1378 | static const Parameters parameters = { 0x80F, 0x000, 0x000, false, false }; 1379 | return parameters; 1380 | } 1381 | 1382 | /** 1383 | @brief Returns a set of parameters for CRC-12 UMTS (aka CRC-12 3GPP). 1384 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1385 | @note CRC-12 UMTS has the following parameters and check value: 1386 | - polynomial = 0x80F 1387 | - initial value = 0x000 1388 | - final XOR = 0x000 1389 | - reflect input = false 1390 | - reflect output = true 1391 | - check value = 0xDAF 1392 | @return CRC-12 UMTS parameters 1393 | */ 1394 | inline const CRC::Parameters & CRC::CRC_12_UMTS() 1395 | { 1396 | static const Parameters parameters = { 0x80F, 0x000, 0x000, false, true }; 1397 | return parameters; 1398 | } 1399 | 1400 | /** 1401 | @brief Returns a set of parameters for CRC-13 BBC. 1402 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1403 | @note CRC-13 BBC has the following parameters and check value: 1404 | - polynomial = 0x1CF5 1405 | - initial value = 0x0000 1406 | - final XOR = 0x0000 1407 | - reflect input = false 1408 | - reflect output = false 1409 | - check value = 0x04FA 1410 | @return CRC-13 BBC parameters 1411 | */ 1412 | inline const CRC::Parameters & CRC::CRC_13_BBC() 1413 | { 1414 | static const Parameters parameters = { 0x1CF5, 0x0000, 0x0000, false, false }; 1415 | return parameters; 1416 | } 1417 | 1418 | /** 1419 | @brief Returns a set of parameters for CRC-15 CAN. 1420 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1421 | @note CRC-15 CAN has the following parameters and check value: 1422 | - polynomial = 0x4599 1423 | - initial value = 0x0000 1424 | - final XOR = 0x0000 1425 | - reflect input = false 1426 | - reflect output = false 1427 | - check value = 0x059E 1428 | @return CRC-15 CAN parameters 1429 | */ 1430 | inline const CRC::Parameters & CRC::CRC_15() 1431 | { 1432 | static const Parameters parameters = { 0x4599, 0x0000, 0x0000, false, false }; 1433 | return parameters; 1434 | } 1435 | 1436 | /** 1437 | @brief Returns a set of parameters for CRC-15 MPT1327. 1438 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1439 | @note CRC-15 MPT1327 has the following parameters and check value: 1440 | - polynomial = 0x6815 1441 | - initial value = 0x0000 1442 | - final XOR = 0x0001 1443 | - reflect input = false 1444 | - reflect output = false 1445 | - check value = 0x2566 1446 | @return CRC-15 MPT1327 parameters 1447 | */ 1448 | inline const CRC::Parameters & CRC::CRC_15_MPT1327() 1449 | { 1450 | static const Parameters parameters = { 0x6815, 0x0000, 0x0001, false, false }; 1451 | return parameters; 1452 | } 1453 | #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 1454 | 1455 | /** 1456 | @brief Returns a set of parameters for CRC-16 ARC (aka CRC-16 IBM, CRC-16 LHA). 1457 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1458 | @note CRC-16 ARC has the following parameters and check value: 1459 | - polynomial = 0x8005 1460 | - initial value = 0x0000 1461 | - final XOR = 0x0000 1462 | - reflect input = true 1463 | - reflect output = true 1464 | - check value = 0xBB3D 1465 | @return CRC-16 ARC parameters 1466 | */ 1467 | inline const CRC::Parameters & CRC::CRC_16_ARC() 1468 | { 1469 | static const Parameters parameters = { 0x8005, 0x0000, 0x0000, true, true }; 1470 | return parameters; 1471 | } 1472 | 1473 | /** 1474 | @brief Returns a set of parameters for CRC-16 BUYPASS (aka CRC-16 VERIFONE, CRC-16 UMTS). 1475 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1476 | @note CRC-16 BUYPASS has the following parameters and check value: 1477 | - polynomial = 0x8005 1478 | - initial value = 0x0000 1479 | - final XOR = 0x0000 1480 | - reflect input = false 1481 | - reflect output = false 1482 | - check value = 0xFEE8 1483 | @return CRC-16 BUYPASS parameters 1484 | */ 1485 | inline const CRC::Parameters & CRC::CRC_16_BUYPASS() 1486 | { 1487 | static const Parameters parameters = { 0x8005, 0x0000, 0x0000, false, false }; 1488 | return parameters; 1489 | } 1490 | 1491 | /** 1492 | @brief Returns a set of parameters for CRC-16 CCITT FALSE. 1493 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1494 | @note CRC-16 CCITT FALSE has the following parameters and check value: 1495 | - polynomial = 0x1021 1496 | - initial value = 0xFFFF 1497 | - final XOR = 0x0000 1498 | - reflect input = false 1499 | - reflect output = false 1500 | - check value = 0x29B1 1501 | @return CRC-16 CCITT FALSE parameters 1502 | */ 1503 | inline const CRC::Parameters & CRC::CRC_16_CCITTFALSE() 1504 | { 1505 | static const Parameters parameters = { 0x1021, 0xFFFF, 0x0000, false, false }; 1506 | return parameters; 1507 | } 1508 | 1509 | /** 1510 | @brief Returns a set of parameters for CRC-16 MCRF4XX. 1511 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1512 | @note CRC-16 MCRF4XX has the following parameters and check value: 1513 | - polynomial = 0x1021 1514 | - initial value = 0xFFFF 1515 | - final XOR = 0x0000 1516 | - reflect input = true 1517 | - reflect output = true 1518 | - check value = 0x6F91 1519 | @return CRC-16 MCRF4XX parameters 1520 | */ 1521 | inline const CRC::Parameters & CRC::CRC_16_MCRF4XX() 1522 | { 1523 | static const Parameters parameters = { 0x1021, 0xFFFF, 0x0000, true, true}; 1524 | return parameters; 1525 | } 1526 | 1527 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 1528 | /** 1529 | @brief Returns a set of parameters for CRC-16 CDMA2000. 1530 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1531 | @note CRC-16 CDMA2000 has the following parameters and check value: 1532 | - polynomial = 0xC867 1533 | - initial value = 0xFFFF 1534 | - final XOR = 0x0000 1535 | - reflect input = false 1536 | - reflect output = false 1537 | - check value = 0x4C06 1538 | @return CRC-16 CDMA2000 parameters 1539 | */ 1540 | inline const CRC::Parameters & CRC::CRC_16_CDMA2000() 1541 | { 1542 | static const Parameters parameters = { 0xC867, 0xFFFF, 0x0000, false, false }; 1543 | return parameters; 1544 | } 1545 | 1546 | /** 1547 | @brief Returns a set of parameters for CRC-16 CMS. 1548 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1549 | @note CRC-16 CMS has the following parameters and check value: 1550 | - polynomial = 0x8005 1551 | - initial value = 0xFFFF 1552 | - final XOR = 0x0000 1553 | - reflect input = false 1554 | - reflect output = false 1555 | - check value = 0xAEE7 1556 | @return CRC-16 CMS parameters 1557 | */ 1558 | inline const CRC::Parameters & CRC::CRC_16_CMS() 1559 | { 1560 | static const Parameters parameters = { 0x8005, 0xFFFF, 0x0000, false, false }; 1561 | return parameters; 1562 | } 1563 | 1564 | /** 1565 | @brief Returns a set of parameters for CRC-16 DECT-R (aka CRC-16 R-CRC). 1566 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1567 | @note CRC-16 DECT-R has the following parameters and check value: 1568 | - polynomial = 0x0589 1569 | - initial value = 0x0000 1570 | - final XOR = 0x0001 1571 | - reflect input = false 1572 | - reflect output = false 1573 | - check value = 0x007E 1574 | @return CRC-16 DECT-R parameters 1575 | */ 1576 | inline const CRC::Parameters & CRC::CRC_16_DECTR() 1577 | { 1578 | static const Parameters parameters = { 0x0589, 0x0000, 0x0001, false, false }; 1579 | return parameters; 1580 | } 1581 | 1582 | /** 1583 | @brief Returns a set of parameters for CRC-16 DECT-X (aka CRC-16 X-CRC). 1584 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1585 | @note CRC-16 DECT-X has the following parameters and check value: 1586 | - polynomial = 0x0589 1587 | - initial value = 0x0000 1588 | - final XOR = 0x0000 1589 | - reflect input = false 1590 | - reflect output = false 1591 | - check value = 0x007F 1592 | @return CRC-16 DECT-X parameters 1593 | */ 1594 | inline const CRC::Parameters & CRC::CRC_16_DECTX() 1595 | { 1596 | static const Parameters parameters = { 0x0589, 0x0000, 0x0000, false, false }; 1597 | return parameters; 1598 | } 1599 | 1600 | /** 1601 | @brief Returns a set of parameters for CRC-16 DNP. 1602 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1603 | @note CRC-16 DNP has the following parameters and check value: 1604 | - polynomial = 0x3D65 1605 | - initial value = 0x0000 1606 | - final XOR = 0xFFFF 1607 | - reflect input = true 1608 | - reflect output = true 1609 | - check value = 0xEA82 1610 | @return CRC-16 DNP parameters 1611 | */ 1612 | inline const CRC::Parameters & CRC::CRC_16_DNP() 1613 | { 1614 | static const Parameters parameters = { 0x3D65, 0x0000, 0xFFFF, true, true }; 1615 | return parameters; 1616 | } 1617 | #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 1618 | 1619 | /** 1620 | @brief Returns a set of parameters for CRC-16 GENIBUS (aka CRC-16 EPC, CRC-16 I-CODE, CRC-16 DARC). 1621 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1622 | @note CRC-16 GENIBUS has the following parameters and check value: 1623 | - polynomial = 0x1021 1624 | - initial value = 0xFFFF 1625 | - final XOR = 0xFFFF 1626 | - reflect input = false 1627 | - reflect output = false 1628 | - check value = 0xD64E 1629 | @return CRC-16 GENIBUS parameters 1630 | */ 1631 | inline const CRC::Parameters & CRC::CRC_16_GENIBUS() 1632 | { 1633 | static const Parameters parameters = { 0x1021, 0xFFFF, 0xFFFF, false, false }; 1634 | return parameters; 1635 | } 1636 | 1637 | /** 1638 | @brief Returns a set of parameters for CRC-16 KERMIT (aka CRC-16 CCITT, CRC-16 CCITT-TRUE). 1639 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1640 | @note CRC-16 KERMIT has the following parameters and check value: 1641 | - polynomial = 0x1021 1642 | - initial value = 0x0000 1643 | - final XOR = 0x0000 1644 | - reflect input = true 1645 | - reflect output = true 1646 | - check value = 0x2189 1647 | @return CRC-16 KERMIT parameters 1648 | */ 1649 | inline const CRC::Parameters & CRC::CRC_16_KERMIT() 1650 | { 1651 | static const Parameters parameters = { 0x1021, 0x0000, 0x0000, true, true }; 1652 | return parameters; 1653 | } 1654 | 1655 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 1656 | /** 1657 | @brief Returns a set of parameters for CRC-16 MAXIM. 1658 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1659 | @note CRC-16 MAXIM has the following parameters and check value: 1660 | - polynomial = 0x8005 1661 | - initial value = 0x0000 1662 | - final XOR = 0xFFFF 1663 | - reflect input = true 1664 | - reflect output = true 1665 | - check value = 0x44C2 1666 | @return CRC-16 MAXIM parameters 1667 | */ 1668 | inline const CRC::Parameters & CRC::CRC_16_MAXIM() 1669 | { 1670 | static const Parameters parameters = { 0x8005, 0x0000, 0xFFFF, true, true }; 1671 | return parameters; 1672 | } 1673 | 1674 | /** 1675 | @brief Returns a set of parameters for CRC-16 MODBUS. 1676 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1677 | @note CRC-16 MODBUS has the following parameters and check value: 1678 | - polynomial = 0x8005 1679 | - initial value = 0xFFFF 1680 | - final XOR = 0x0000 1681 | - reflect input = true 1682 | - reflect output = true 1683 | - check value = 0x4B37 1684 | @return CRC-16 MODBUS parameters 1685 | */ 1686 | inline const CRC::Parameters & CRC::CRC_16_MODBUS() 1687 | { 1688 | static const Parameters parameters = { 0x8005, 0xFFFF, 0x0000, true, true }; 1689 | return parameters; 1690 | } 1691 | 1692 | /** 1693 | @brief Returns a set of parameters for CRC-16 T10-DIF. 1694 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1695 | @note CRC-16 T10-DIF has the following parameters and check value: 1696 | - polynomial = 0x8BB7 1697 | - initial value = 0x0000 1698 | - final XOR = 0x0000 1699 | - reflect input = false 1700 | - reflect output = false 1701 | - check value = 0xD0DB 1702 | @return CRC-16 T10-DIF parameters 1703 | */ 1704 | inline const CRC::Parameters & CRC::CRC_16_T10DIF() 1705 | { 1706 | static const Parameters parameters = { 0x8BB7, 0x0000, 0x0000, false, false }; 1707 | return parameters; 1708 | } 1709 | 1710 | /** 1711 | @brief Returns a set of parameters for CRC-16 USB. 1712 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1713 | @note CRC-16 USB has the following parameters and check value: 1714 | - polynomial = 0x8005 1715 | - initial value = 0xFFFF 1716 | - final XOR = 0xFFFF 1717 | - reflect input = true 1718 | - reflect output = true 1719 | - check value = 0xB4C8 1720 | @return CRC-16 USB parameters 1721 | */ 1722 | inline const CRC::Parameters & CRC::CRC_16_USB() 1723 | { 1724 | static const Parameters parameters = { 0x8005, 0xFFFF, 0xFFFF, true, true }; 1725 | return parameters; 1726 | } 1727 | 1728 | #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 1729 | 1730 | /** 1731 | @brief Returns a set of parameters for CRC-16 X-25 (aka CRC-16 IBM-SDLC, CRC-16 ISO-HDLC, CRC-16 B). 1732 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1733 | @note CRC-16 X-25 has the following parameters and check value: 1734 | - polynomial = 0x1021 1735 | - initial value = 0xFFFF 1736 | - final XOR = 0xFFFF 1737 | - reflect input = true 1738 | - reflect output = true 1739 | - check value = 0x906E 1740 | @return CRC-16 X-25 parameters 1741 | */ 1742 | inline const CRC::Parameters & CRC::CRC_16_X25() 1743 | { 1744 | static const Parameters parameters = { 0x1021, 0xFFFF, 0xFFFF, true, true }; 1745 | return parameters; 1746 | } 1747 | 1748 | /** 1749 | @brief Returns a set of parameters for CRC-16 XMODEM (aka CRC-16 ZMODEM, CRC-16 ACORN, CRC-16 LTE). 1750 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1751 | @note CRC-16 XMODEM has the following parameters and check value: 1752 | - polynomial = 0x1021 1753 | - initial value = 0x0000 1754 | - final XOR = 0x0000 1755 | - reflect input = false 1756 | - reflect output = false 1757 | - check value = 0x31C3 1758 | @return CRC-16 XMODEM parameters 1759 | */ 1760 | inline const CRC::Parameters & CRC::CRC_16_XMODEM() 1761 | { 1762 | static const Parameters parameters = { 0x1021, 0x0000, 0x0000, false, false }; 1763 | return parameters; 1764 | } 1765 | 1766 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 1767 | /** 1768 | @brief Returns a set of parameters for CRC-17 CAN. 1769 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1770 | @note CRC-17 CAN has the following parameters and check value: 1771 | - polynomial = 0x1685B 1772 | - initial value = 0x00000 1773 | - final XOR = 0x00000 1774 | - reflect input = false 1775 | - reflect output = false 1776 | - check value = 0x04F03 1777 | @return CRC-17 CAN parameters 1778 | */ 1779 | inline const CRC::Parameters & CRC::CRC_17_CAN() 1780 | { 1781 | static const Parameters parameters = { 0x1685B, 0x00000, 0x00000, false, false }; 1782 | return parameters; 1783 | } 1784 | 1785 | /** 1786 | @brief Returns a set of parameters for CRC-21 CAN. 1787 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1788 | @note CRC-21 CAN has the following parameters and check value: 1789 | - polynomial = 0x102899 1790 | - initial value = 0x000000 1791 | - final XOR = 0x000000 1792 | - reflect input = false 1793 | - reflect output = false 1794 | - check value = 0x0ED841 1795 | @return CRC-21 CAN parameters 1796 | */ 1797 | inline const CRC::Parameters & CRC::CRC_21_CAN() 1798 | { 1799 | static const Parameters parameters = { 0x102899, 0x000000, 0x000000, false, false }; 1800 | return parameters; 1801 | } 1802 | 1803 | /** 1804 | @brief Returns a set of parameters for CRC-24 OPENPGP. 1805 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1806 | @note CRC-24 OPENPGP has the following parameters and check value: 1807 | - polynomial = 0x864CFB 1808 | - initial value = 0xB704CE 1809 | - final XOR = 0x000000 1810 | - reflect input = false 1811 | - reflect output = false 1812 | - check value = 0x21CF02 1813 | @return CRC-24 OPENPGP parameters 1814 | */ 1815 | inline const CRC::Parameters & CRC::CRC_24() 1816 | { 1817 | static const Parameters parameters = { 0x864CFB, 0xB704CE, 0x000000, false, false }; 1818 | return parameters; 1819 | } 1820 | 1821 | /** 1822 | @brief Returns a set of parameters for CRC-24 FlexRay-A. 1823 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1824 | @note CRC-24 FlexRay-A has the following parameters and check value: 1825 | - polynomial = 0x5D6DCB 1826 | - initial value = 0xFEDCBA 1827 | - final XOR = 0x000000 1828 | - reflect input = false 1829 | - reflect output = false 1830 | - check value = 0x7979BD 1831 | @return CRC-24 FlexRay-A parameters 1832 | */ 1833 | inline const CRC::Parameters & CRC::CRC_24_FLEXRAYA() 1834 | { 1835 | static const Parameters parameters = { 0x5D6DCB, 0xFEDCBA, 0x000000, false, false }; 1836 | return parameters; 1837 | } 1838 | 1839 | /** 1840 | @brief Returns a set of parameters for CRC-24 FlexRay-B. 1841 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1842 | @note CRC-24 FlexRay-B has the following parameters and check value: 1843 | - polynomial = 0x5D6DCB 1844 | - initial value = 0xABCDEF 1845 | - final XOR = 0x000000 1846 | - reflect input = false 1847 | - reflect output = false 1848 | - check value = 0x1F23B8 1849 | @return CRC-24 FlexRay-B parameters 1850 | */ 1851 | inline const CRC::Parameters & CRC::CRC_24_FLEXRAYB() 1852 | { 1853 | static const Parameters parameters = { 0x5D6DCB, 0xABCDEF, 0x000000, false, false }; 1854 | return parameters; 1855 | } 1856 | 1857 | /** 1858 | @brief Returns a set of parameters for CRC-24 LTE-A/NR-A. 1859 | @note The parameters are static and are delayed-constructed to reduce memory 1860 | footprint. 1861 | @note CRC-24 LTE-A has the following parameters and check value: 1862 | - polynomial = 0x864CFB 1863 | - initial value = 0x000000 1864 | - final XOR = 0x000000 1865 | - reflect input = false 1866 | - reflect output = false 1867 | - check value = 0xCDE703 1868 | @return CRC-24 LTE-A parameters 1869 | */ 1870 | inline const CRC::Parameters & CRC::CRC_24_LTEA() 1871 | { 1872 | static const Parameters parameters = { 0x864CFB, 0x000000, 0x000000, false, false }; 1873 | return parameters; 1874 | } 1875 | 1876 | /** 1877 | @brief Returns a set of parameters for CRC-24 LTE-B/NR-B. 1878 | @note The parameters are static and are delayed-constructed to reduce memory 1879 | footprint. 1880 | @note CRC-24 LTE-B has the following parameters and check value: 1881 | - polynomial = 0x800063 1882 | - initial value = 0x000000 1883 | - final XOR = 0x000000 1884 | - reflect input = false 1885 | - reflect output = false 1886 | - check value = 0x23EF52 1887 | @return CRC-24 LTE-B parameters 1888 | */ 1889 | inline const CRC::Parameters & CRC::CRC_24_LTEB() 1890 | { 1891 | static const Parameters parameters = { 0x800063, 0x000000, 0x000000, false, false }; 1892 | return parameters; 1893 | } 1894 | 1895 | /** 1896 | @brief Returns a set of parameters for CRC-24 NR-C. 1897 | @note The parameters are static and are delayed-constructed to reduce memory 1898 | footprint. 1899 | @note CRC-24 NR-C has the following parameters and check value: 1900 | - polynomial = 0xB2B117 1901 | - initial value = 0x000000 1902 | - final XOR = 0x000000 1903 | - reflect input = false 1904 | - reflect output = false 1905 | - check value = 0xF48279 1906 | @return CRC-24 NR-C parameters 1907 | */ 1908 | inline const CRC::Parameters & CRC::CRC_24_NRC() 1909 | { 1910 | static const Parameters parameters = { 0xB2B117, 0x000000, 0x000000, false, false }; 1911 | return parameters; 1912 | } 1913 | 1914 | /** 1915 | @brief Returns a set of parameters for CRC-30 CDMA. 1916 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1917 | @note CRC-30 CDMA has the following parameters and check value: 1918 | - polynomial = 0x2030B9C7 1919 | - initial value = 0x3FFFFFFF 1920 | - final XOR = 0x00000000 1921 | - reflect input = false 1922 | - reflect output = false 1923 | - check value = 0x3B3CB540 1924 | @return CRC-30 CDMA parameters 1925 | */ 1926 | inline const CRC::Parameters & CRC::CRC_30() 1927 | { 1928 | static const Parameters parameters = { 0x2030B9C7, 0x3FFFFFFF, 0x00000000, false, false }; 1929 | return parameters; 1930 | } 1931 | #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 1932 | 1933 | /** 1934 | @brief Returns a set of parameters for CRC-32 (aka CRC-32 ADCCP, CRC-32 PKZip). 1935 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1936 | @note CRC-32 has the following parameters and check value: 1937 | - polynomial = 0x04C11DB7 1938 | - initial value = 0xFFFFFFFF 1939 | - final XOR = 0xFFFFFFFF 1940 | - reflect input = true 1941 | - reflect output = true 1942 | - check value = 0xCBF43926 1943 | @return CRC-32 parameters 1944 | */ 1945 | inline const CRC::Parameters & CRC::CRC_32() 1946 | { 1947 | static const Parameters parameters = { 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true }; 1948 | return parameters; 1949 | } 1950 | 1951 | /** 1952 | @brief Returns a set of parameters for CRC-32 BZIP2 (aka CRC-32 AAL5, CRC-32 DECT-B, CRC-32 B-CRC). 1953 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1954 | @note CRC-32 BZIP2 has the following parameters and check value: 1955 | - polynomial = 0x04C11DB7 1956 | - initial value = 0xFFFFFFFF 1957 | - final XOR = 0xFFFFFFFF 1958 | - reflect input = false 1959 | - reflect output = false 1960 | - check value = 0xFC891918 1961 | @return CRC-32 BZIP2 parameters 1962 | */ 1963 | inline const CRC::Parameters & CRC::CRC_32_BZIP2() 1964 | { 1965 | static const Parameters parameters = { 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, false, false }; 1966 | return parameters; 1967 | } 1968 | 1969 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 1970 | /** 1971 | @brief Returns a set of parameters for CRC-32 C (aka CRC-32 ISCSI, CRC-32 Castagnoli, CRC-32 Interlaken). 1972 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1973 | @note CRC-32 C has the following parameters and check value: 1974 | - polynomial = 0x1EDC6F41 1975 | - initial value = 0xFFFFFFFF 1976 | - final XOR = 0xFFFFFFFF 1977 | - reflect input = true 1978 | - reflect output = true 1979 | - check value = 0xE3069283 1980 | @return CRC-32 C parameters 1981 | */ 1982 | inline const CRC::Parameters & CRC::CRC_32_C() 1983 | { 1984 | static const Parameters parameters = { 0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true, true }; 1985 | return parameters; 1986 | } 1987 | #endif 1988 | 1989 | /** 1990 | @brief Returns a set of parameters for CRC-32 MPEG-2. 1991 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 1992 | @note CRC-32 MPEG-2 has the following parameters and check value: 1993 | - polynomial = 0x04C11DB7 1994 | - initial value = 0xFFFFFFFF 1995 | - final XOR = 0x00000000 1996 | - reflect input = false 1997 | - reflect output = false 1998 | - check value = 0x0376E6E7 1999 | @return CRC-32 MPEG-2 parameters 2000 | */ 2001 | inline const CRC::Parameters & CRC::CRC_32_MPEG2() 2002 | { 2003 | static const Parameters parameters = { 0x04C11DB7, 0xFFFFFFFF, 0x00000000, false, false }; 2004 | return parameters; 2005 | } 2006 | 2007 | /** 2008 | @brief Returns a set of parameters for CRC-32 POSIX. 2009 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 2010 | @note CRC-32 POSIX has the following parameters and check value: 2011 | - polynomial = 0x04C11DB7 2012 | - initial value = 0x00000000 2013 | - final XOR = 0xFFFFFFFF 2014 | - reflect input = false 2015 | - reflect output = false 2016 | - check value = 0x765E7680 2017 | @return CRC-32 POSIX parameters 2018 | */ 2019 | inline const CRC::Parameters & CRC::CRC_32_POSIX() 2020 | { 2021 | static const Parameters parameters = { 0x04C11DB7, 0x00000000, 0xFFFFFFFF, false, false }; 2022 | return parameters; 2023 | } 2024 | 2025 | #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 2026 | /** 2027 | @brief Returns a set of parameters for CRC-32 Q. 2028 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 2029 | @note CRC-32 Q has the following parameters and check value: 2030 | - polynomial = 0x814141AB 2031 | - initial value = 0x00000000 2032 | - final XOR = 0x00000000 2033 | - reflect input = false 2034 | - reflect output = false 2035 | - check value = 0x3010BF7F 2036 | @return CRC-32 Q parameters 2037 | */ 2038 | inline const CRC::Parameters & CRC::CRC_32_Q() 2039 | { 2040 | static const Parameters parameters = { 0x814141AB, 0x00000000, 0x00000000, false, false }; 2041 | return parameters; 2042 | } 2043 | 2044 | /** 2045 | @brief Returns a set of parameters for CRC-40 GSM. 2046 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 2047 | @note CRC-40 GSM has the following parameters and check value: 2048 | - polynomial = 0x0004820009 2049 | - initial value = 0x0000000000 2050 | - final XOR = 0xFFFFFFFFFF 2051 | - reflect input = false 2052 | - reflect output = false 2053 | - check value = 0xD4164FC646 2054 | @return CRC-40 GSM parameters 2055 | */ 2056 | inline const CRC::Parameters & CRC::CRC_40_GSM() 2057 | { 2058 | static const Parameters parameters = { 0x0004820009, 0x0000000000, 0xFFFFFFFFFF, false, false }; 2059 | return parameters; 2060 | } 2061 | 2062 | /** 2063 | @brief Returns a set of parameters for CRC-64 ECMA. 2064 | @note The parameters are static and are delayed-constructed to reduce memory footprint. 2065 | @note CRC-64 ECMA has the following parameters and check value: 2066 | - polynomial = 0x42F0E1EBA9EA3693 2067 | - initial value = 0x0000000000000000 2068 | - final XOR = 0x0000000000000000 2069 | - reflect input = false 2070 | - reflect output = false 2071 | - check value = 0x6C40DF5F0B497347 2072 | @return CRC-64 ECMA parameters 2073 | */ 2074 | inline const CRC::Parameters & CRC::CRC_64() 2075 | { 2076 | static const Parameters parameters = { 0x42F0E1EBA9EA3693, 0x0000000000000000, 0x0000000000000000, false, false }; 2077 | return parameters; 2078 | } 2079 | #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 2080 | 2081 | #ifdef CRCPP_USE_NAMESPACE 2082 | } 2083 | #endif 2084 | 2085 | #endif // CRCPP_CRC_H_ 2086 | -------------------------------------------------------------------------------- /src/ConsoleLib.cpp: -------------------------------------------------------------------------------- 1 | #include "ConsoleLib.h" 2 | 3 | void ConsoleLib::MessageOutput(const std::string& Text, int MessageType) { 4 | HANDLE _hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 5 | 6 | switch (MessageType) { 7 | case 0: 8 | SetConsoleTextAttribute(_hConsole, 11); 9 | std::cout << "MESSAGE: "; 10 | break; 11 | case 1: 12 | SetConsoleTextAttribute(_hConsole, 10); 13 | std::cout << "SUCCESS: "; 14 | break; 15 | case 2: 16 | SetConsoleTextAttribute(_hConsole, 14); 17 | std::cout << "WARNING: "; 18 | break; 19 | case 3: 20 | SetConsoleTextAttribute(_hConsole, 12); 21 | std::cout << "ERROR: "; 22 | break; 23 | } 24 | 25 | SetConsoleTextAttribute(_hConsole, 7); 26 | std::cout << Text; 27 | } 28 | -------------------------------------------------------------------------------- /src/ConsoleLib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define WIN32_LEAN_AND_MEAN 7 | #include 8 | 9 | namespace ConsoleLib { 10 | void MessageOutput(const std::string& Text, int MessageType); 11 | }; // namespace ConsoleLib 12 | -------------------------------------------------------------------------------- /src/DCInstance.cpp: -------------------------------------------------------------------------------- 1 | #include "DCInstance.h" 2 | 3 | void DCInstance::InitializeRPC(const char* applicationID) { 4 | Discord_Initialize(applicationID, NULL, 1, NULL); 5 | 6 | std::memset(&DCInstance::Presence, 0, sizeof(DCInstance::Presence)); 7 | 8 | auto _currTime = std::chrono::system_clock::now().time_since_epoch(); 9 | auto _secondCast = 10 | std::chrono::duration_cast(_currTime); 11 | 12 | DCInstance::Presence.startTimestamp = _secondCast.count(); 13 | Discord_UpdatePresence(&DCInstance::Presence); 14 | } 15 | 16 | void DCInstance::UpdateDetails(const char* input) { 17 | DCInstance::Presence.details = input; 18 | Discord_UpdatePresence(&DCInstance::Presence); 19 | } 20 | 21 | void DCInstance::UpdateState(const char* input) { 22 | DCInstance::Presence.state = input; 23 | Discord_UpdatePresence(&DCInstance::Presence); 24 | } 25 | 26 | void DCInstance::UpdateLImage(const char* key, const char* text) { 27 | DCInstance::Presence.largeImageKey = key; 28 | DCInstance::Presence.largeImageText = text; 29 | Discord_UpdatePresence(&DCInstance::Presence); 30 | } 31 | 32 | void DCInstance::UpdateSImage(const char* key, const char* text) { 33 | DCInstance::Presence.smallImageKey = key; 34 | DCInstance::Presence.smallImageText = text; 35 | Discord_UpdatePresence(&DCInstance::Presence); 36 | } 37 | -------------------------------------------------------------------------------- /src/DCInstance.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | class DCInstance { 11 | public: 12 | static inline DiscordRichPresence Presence; 13 | 14 | static void InitializeRPC(const char* applicationID); 15 | 16 | static void UpdateDetails(const char* input); 17 | static void UpdateState(const char* input); 18 | static void UpdateLImage(const char* key, const char* text); 19 | static void UpdateSImage(const char* key, const char* text); 20 | }; 21 | -------------------------------------------------------------------------------- /src/LuaBackend.cpp: -------------------------------------------------------------------------------- 1 | #include "LuaBackend.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace fs = std::filesystem; 9 | 10 | LuaBackend::LuaBackend(const std::vector& ScriptPaths, 11 | std::uint64_t BaseInput) { 12 | frameLimit = 16; 13 | LoadScripts(ScriptPaths, BaseInput); 14 | } 15 | 16 | int LuaBackend::ExceptionHandle( 17 | lua_State* luaState, sol::optional thrownException, 18 | sol::string_view description) { 19 | (void)description; 20 | 21 | const std::exception _ex = *thrownException; 22 | ConsoleLib::MessageOutput(std::string{_ex.what()} + "\n", 3); 23 | 24 | return sol::stack::push(luaState, _ex.what()); 25 | } 26 | 27 | void LuaBackend::LoadScripts(const std::vector& ScriptPaths, 28 | std::uint64_t BaseInput) { 29 | loadedScripts.clear(); 30 | 31 | for (auto scriptsDir : ScriptPaths) { 32 | if (!fs::is_directory(scriptsDir)) { 33 | continue; 34 | } 35 | 36 | for (auto _path : fs::directory_iterator(scriptsDir)) { 37 | auto _script = std::make_unique(); 38 | 39 | // clang-format off 40 | _script->luaState.open_libraries( 41 | sol::lib::base, 42 | sol::lib::package, 43 | sol::lib::coroutine, 44 | sol::lib::string, 45 | sol::lib::os, 46 | sol::lib::math, 47 | sol::lib::table, 48 | sol::lib::io, 49 | sol::lib::bit32, 50 | sol::lib::utf8 51 | ); 52 | // clang-format on 53 | 54 | _script->luaState.set_exception_handler(&ExceptionHandle); 55 | 56 | SetFunctions(&_script->luaState); 57 | 58 | fs::path _luaPath = scriptsDir / L"io_packages" / L"?.lua"; 59 | fs::path _dllPath = scriptsDir / L"io_packages" / L"?.dll"; 60 | 61 | _script->luaState["package"]["path"] = _luaPath.string(); 62 | _script->luaState["package"]["cpath"] = _dllPath.string(); 63 | 64 | fs::path _loadPath = scriptsDir / L"io_load"; 65 | 66 | _script->luaState["LOAD_PATH"] = _loadPath.string(); 67 | _script->luaState["SCRIPT_PATH"] = scriptsDir.string(); 68 | _script->luaState["CHEATS_PATH"] = "NOT_AVAILABLE"; 69 | 70 | fs::path _pathFull = MemoryLib::PName; 71 | auto _pathExe = _pathFull.filename().string(); 72 | 73 | _script->luaState["ENGINE_VERSION"] = 5; 74 | _script->luaState["ENGINE_TYPE"] = "BACKEND"; 75 | _script->luaState["GAME_ID"] = 76 | CRC::Calculate(_pathExe.c_str(), _pathExe.length(), CRC::CRC_32()); 77 | _script->luaState["BASE_ADDR"] = BaseInput; 78 | 79 | const auto _filePath = _path.path(); 80 | const auto _filePathStr = _filePath.string(); 81 | 82 | if (_filePath.extension() == ".lua") { 83 | _script->luaState["LUA_NAME"] = _filePath.filename().string(); 84 | 85 | ConsoleLib::MessageOutput( 86 | "Found script: \"" + _filePathStr + "\" Initializing...\n", 0); 87 | 88 | auto _result = _script->luaState.script_file( 89 | _filePathStr, &sol::script_pass_on_error); 90 | 91 | _script->initFunction = _script->luaState["_OnInit"]; 92 | _script->frameFunction = _script->luaState["_OnFrame"]; 93 | 94 | if (_result.valid()) { 95 | if (!_script->initFunction && !_script->frameFunction) { 96 | ConsoleLib::MessageOutput( 97 | "No event handlers exist or all of them have " 98 | "errors.\n", 99 | 3); 100 | ConsoleLib::MessageOutput("Initialization of this script cannot " 101 | "continue...\n", 102 | 3); 103 | return; 104 | } 105 | 106 | if (!_script->initFunction) 107 | ConsoleLib::MessageOutput( 108 | "The event handler for initialization either has " 109 | "errors or " 110 | "does not exist.\n", 111 | 2); 112 | 113 | if (!_script->frameFunction) 114 | ConsoleLib::MessageOutput( 115 | "The event handler for framedraw either has errors " 116 | "or does not " 117 | "exist.\n", 118 | 2); 119 | 120 | ConsoleLib::MessageOutput( 121 | "Initialization of this script was successful!\n\n", 1); 122 | 123 | loadedScripts.push_back(std::move(_script)); 124 | } else { 125 | sol::error err = _result; 126 | ConsoleLib::MessageOutput(std::string{err.what()} + "\n", 3); 127 | ConsoleLib::MessageOutput( 128 | "Initialization of this script was aborted.\n", 3); 129 | } 130 | } 131 | } 132 | } 133 | } 134 | 135 | void LuaBackend::SetFunctions(LuaState* _state) { 136 | _state->set_function("ReadByte", MemoryLib::ReadByte); 137 | _state->set_function("ReadShort", MemoryLib::ReadShort); 138 | _state->set_function("ReadInt", MemoryLib::ReadInt); 139 | _state->set_function("ReadLong", MemoryLib::ReadLong); 140 | _state->set_function("ReadFloat", MemoryLib::ReadFloat); 141 | _state->set_function("ReadBoolean", MemoryLib::ReadBool); 142 | _state->set_function("ReadArray", MemoryLib::ReadBytes); 143 | _state->set_function("ReadString", MemoryLib::ReadString); 144 | 145 | _state->set_function("WriteByte", MemoryLib::WriteByte); 146 | _state->set_function("WriteShort", MemoryLib::WriteShort); 147 | _state->set_function("WriteInt", MemoryLib::WriteInt); 148 | _state->set_function("WriteLong", MemoryLib::WriteLong); 149 | _state->set_function("WriteFloat", MemoryLib::WriteFloat); 150 | _state->set_function("WriteBoolean", MemoryLib::WriteBool); 151 | _state->set_function("WriteArray", MemoryLib::WriteBytes); 152 | _state->set_function("WriteString", MemoryLib::WriteString); 153 | _state->set_function("WriteExec", MemoryLib::WriteExec); 154 | _state->set_function("GetPointer", MemoryLib::GetPointer); 155 | 156 | _state->set_function("ReadByteA", MemoryLib::ReadByteAbsolute); 157 | _state->set_function("ReadShortA", MemoryLib::ReadShortAbsolute); 158 | _state->set_function("ReadIntA", MemoryLib::ReadIntAbsolute); 159 | _state->set_function("ReadLongA", MemoryLib::ReadLongAbsolute); 160 | _state->set_function("ReadFloatA", MemoryLib::ReadFloatAbsolute); 161 | _state->set_function("ReadBooleanA", MemoryLib::ReadBoolAbsolute); 162 | _state->set_function("ReadArrayA", MemoryLib::ReadBytesAbsolute); 163 | _state->set_function("ReadStringA", MemoryLib::ReadStringAbsolute); 164 | 165 | _state->set_function("WriteByteA", MemoryLib::WriteByteAbsolute); 166 | _state->set_function("WriteShortA", MemoryLib::WriteShortAbsolute); 167 | _state->set_function("WriteIntA", MemoryLib::WriteIntAbsolute); 168 | _state->set_function("WriteLongA", MemoryLib::WriteLongAbsolute); 169 | _state->set_function("WriteFloatA", MemoryLib::WriteFloatAbsolute); 170 | _state->set_function("WriteBooleanA", MemoryLib::WriteBoolAbsolute); 171 | _state->set_function("WriteArrayA", MemoryLib::WriteBytesAbsolute); 172 | _state->set_function("WriteStringA", MemoryLib::WriteStringAbsolute); 173 | _state->set_function("GetPointerA", MemoryLib::GetPointerAbsolute); 174 | 175 | _state->set_function("InitializeRPC", DCInstance::InitializeRPC); 176 | _state->set_function("UpdateDetails", DCInstance::UpdateDetails); 177 | _state->set_function("UpdateState", DCInstance::UpdateState); 178 | _state->set_function("UpdateLImage", DCInstance::UpdateLImage); 179 | _state->set_function("UpdateSImage", DCInstance::UpdateSImage); 180 | 181 | _state->set_function( 182 | "ULShift32", 183 | [](std::uint32_t base, std::uint32_t shift) { return base << shift; }); 184 | 185 | _state->set_function( 186 | "ConsolePrint", 187 | sol::overload( 188 | [_state](sol::object Text) { 189 | HANDLE _hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 190 | 191 | SetConsoleTextAttribute(_hConsole, 14); 192 | std::cout << "[" + 193 | _state->globals()["LUA_NAME"].get() + 194 | "] "; 195 | 196 | SetConsoleTextAttribute(_hConsole, 7); 197 | std::cout << Text.as() << '\n'; 198 | }, 199 | 200 | [_state](sol::object Text, int MessageType) { 201 | HANDLE _hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 202 | 203 | SetConsoleTextAttribute(_hConsole, 14); 204 | std::cout << "[" + 205 | _state->globals()["LUA_NAME"].get() + 206 | "] "; 207 | 208 | switch (MessageType) { 209 | case 0: 210 | SetConsoleTextAttribute(_hConsole, 11); 211 | std::cout << "MESSAGE: "; 212 | break; 213 | case 1: 214 | SetConsoleTextAttribute(_hConsole, 10); 215 | std::cout << "SUCCESS: "; 216 | break; 217 | case 2: 218 | SetConsoleTextAttribute(_hConsole, 14); 219 | std::cout << "WARNING: "; 220 | break; 221 | case 3: 222 | SetConsoleTextAttribute(_hConsole, 12); 223 | std::cout << "ERROR: "; 224 | break; 225 | } 226 | 227 | SetConsoleTextAttribute(_hConsole, 7); 228 | std::cout << Text.as() << '\n'; 229 | })); 230 | 231 | _state->set_function("GetHertz", [this]() { 232 | switch (frameLimit) { 233 | default: 234 | return 60; 235 | case 8: 236 | return 120; 237 | case 4: 238 | return 240; 239 | } 240 | }); 241 | 242 | _state->set_function("SetHertz", [this](int Input) { 243 | switch (Input) { 244 | default: 245 | frameLimit = 16; 246 | break; 247 | case 120: 248 | frameLimit = 8; 249 | break; 250 | case 240: 251 | frameLimit = 4; 252 | break; 253 | } 254 | }); 255 | } 256 | -------------------------------------------------------------------------------- /src/LuaBackend.h: -------------------------------------------------------------------------------- 1 | #ifndef LUABACKEND 2 | #define LUABACKEND 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "ConsoleLib.h" 10 | #include "DCInstance.h" 11 | #include "MemoryLib.h" 12 | 13 | using LuaState = sol::state; 14 | using LuaFunction = sol::safe_function; 15 | 16 | class LuaBackend { 17 | public: 18 | struct LuaScript { 19 | LuaState luaState; 20 | LuaFunction initFunction; 21 | LuaFunction frameFunction; 22 | }; 23 | 24 | std::vector> loadedScripts; 25 | int frameLimit; 26 | 27 | LuaBackend(const std::vector& ScriptPaths, 28 | std::uint64_t BaseInput); 29 | 30 | static int 31 | ExceptionHandle(lua_State* luaState, 32 | sol::optional thrownException, 33 | sol::string_view description); 34 | 35 | void LoadScripts(const std::vector& ScriptPaths, 36 | std::uint64_t BaseInput); 37 | void SetFunctions(LuaState* _state); 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/MemoryLib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define WIN32_LEAN_AND_MEAN 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "wil_extra.h" 18 | 19 | class MemoryLib { 20 | private: 21 | static inline STARTUPINFOW _sInfo; 22 | static inline PROCESS_INFORMATION _pInfo; 23 | static inline bool _bigEndian = false; 24 | 25 | class protect_lock { 26 | private: 27 | std::uintptr_t address; 28 | std::size_t size; 29 | DWORD protection; 30 | bool is_acquired; 31 | 32 | public: 33 | protect_lock(std::uintptr_t address, std::size_t size) 34 | : address(address), size(size), protection(0), is_acquired(false) { 35 | if (VirtualProtect((void*)address, size, PAGE_READWRITE, &protection) != 36 | 0) 37 | is_acquired = true; 38 | } 39 | 40 | ~protect_lock() { 41 | if (good()) 42 | VirtualProtect((void*)address, size, protection, &protection); 43 | } 44 | 45 | bool good() const noexcept { return is_acquired; } 46 | }; 47 | 48 | public: 49 | static inline std::uint64_t ExecAddress; 50 | static inline std::uint64_t BaseAddress; 51 | static inline DWORD PIdentifier = 0; 52 | static inline HANDLE PHandle = NULL; 53 | static inline std::wstring PName; 54 | 55 | static HMODULE FindBaseAddr(HANDLE InputHandle, std::wstring InputName) { 56 | HMODULE hMods[1024]; 57 | DWORD cbNeeded; 58 | unsigned int i; 59 | 60 | if (EnumProcessModules(InputHandle, hMods, sizeof(hMods), &cbNeeded)) { 61 | for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) { 62 | std::wstring szModName; 63 | if (wil::GetModuleFileNameExW(InputHandle, hMods[i], szModName)) { 64 | if (szModName.find(InputName) != std::wstring::npos) 65 | return hMods[i]; 66 | } 67 | } 68 | } 69 | 70 | return nullptr; 71 | } 72 | 73 | static DWORD FindProcessId(const std::wstring& processName) { 74 | PROCESSENTRY32 processInfo; 75 | processInfo.dwSize = sizeof(processInfo); 76 | 77 | HANDLE processesSnapshot = 78 | CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 79 | if (processesSnapshot == INVALID_HANDLE_VALUE) 80 | return 0; 81 | 82 | Process32First(processesSnapshot, &processInfo); 83 | if (!processName.compare(processInfo.szExeFile)) { 84 | CloseHandle(processesSnapshot); 85 | return processInfo.th32ProcessID; 86 | } 87 | 88 | while (Process32Next(processesSnapshot, &processInfo)) { 89 | if (!processName.compare(processInfo.szExeFile)) { 90 | CloseHandle(processesSnapshot); 91 | return processInfo.th32ProcessID; 92 | } 93 | } 94 | 95 | CloseHandle(processesSnapshot); 96 | return 0; 97 | } 98 | 99 | static void SetBaseAddr(std::uint64_t InputAddress) { 100 | BaseAddress = InputAddress; 101 | } 102 | 103 | static int ExecuteProcess(std::wstring InputName, std::uint64_t InputAddress, 104 | bool InputEndian) { 105 | ZeroMemory(&_sInfo, sizeof(_sInfo)); 106 | _sInfo.cb = sizeof(_sInfo); 107 | ZeroMemory(&_pInfo, sizeof(_pInfo)); 108 | 109 | if (CreateProcessW(InputName.c_str(), NULL, NULL, NULL, TRUE, 0, NULL, NULL, 110 | &_sInfo, &_pInfo) == 0) 111 | return -1; 112 | 113 | BaseAddress = InputAddress; 114 | _bigEndian = InputEndian; 115 | 116 | return 0; 117 | }; 118 | 119 | static bool LatchProcess(std::wstring InputName, std::uint64_t InputAddress, 120 | bool InputEndian) { 121 | ZeroMemory(&_sInfo, sizeof(_sInfo)); 122 | _sInfo.cb = sizeof(_sInfo); 123 | ZeroMemory(&_pInfo, sizeof(_pInfo)); 124 | 125 | PIdentifier = 126 | FindProcessId(std::wstring(InputName.begin(), InputName.end())); 127 | PHandle = OpenProcess(PROCESS_ALL_ACCESS, false, PIdentifier); 128 | 129 | wil_extra::GetProcessImageFileNameW(MemoryLib::PHandle, PName); 130 | BaseAddress = InputAddress; 131 | 132 | ExecAddress = (std::uint64_t)FindBaseAddr(PHandle, PName); 133 | _bigEndian = InputEndian; 134 | 135 | if (PHandle == NULL) 136 | return false; 137 | 138 | return true; 139 | }; 140 | 141 | static void ExternProcess(DWORD InputID, HANDLE InputH, 142 | std::uint64_t InputAddress) { 143 | PIdentifier = InputID; 144 | PHandle = InputH; 145 | 146 | wil_extra::GetProcessImageFileNameW(MemoryLib::PHandle, PName); 147 | 148 | BaseAddress = InputAddress; 149 | ExecAddress = (std::uint64_t)FindBaseAddr(PHandle, PName); 150 | }; 151 | 152 | template , int> = 0> 154 | static T readScalarAbsolute(std::uint64_t Address) { 155 | protect_lock lock(Address, sizeof(T)); 156 | if (!lock.good()) 157 | return 0; 158 | 159 | return *reinterpret_cast(Address); 160 | } 161 | 162 | static inline std::uint8_t ReadByteAbsolute(std::uint64_t Address) { 163 | return readScalarAbsolute(Address); 164 | } 165 | 166 | static inline std::uint16_t ReadShortAbsolute(std::uint64_t Address) { 167 | return readScalarAbsolute(Address); 168 | } 169 | 170 | static inline std::uint32_t ReadIntAbsolute(std::uint64_t Address) { 171 | return readScalarAbsolute(Address); 172 | } 173 | 174 | static inline std::uint64_t ReadLongAbsolute(std::uint64_t Address) { 175 | return readScalarAbsolute(Address); 176 | } 177 | 178 | static inline float ReadFloatAbsolute(std::uint64_t Address) { 179 | return readScalarAbsolute(Address); 180 | } 181 | 182 | static inline bool ReadBoolAbsolute(std::uint64_t Address) { 183 | return ReadByteAbsolute(Address) != 0; 184 | } 185 | 186 | static std::vector ReadBytesAbsolute(std::uint64_t Address, 187 | int Length) { 188 | std::vector _buffer; 189 | 190 | protect_lock lock(Address, static_cast(Length)); 191 | if (lock.good()) { 192 | _buffer.resize(Length); 193 | std::memcpy(_buffer.data(), (void*)Address, Length); 194 | } 195 | 196 | return _buffer; 197 | } 198 | 199 | static std::string ReadStringAbsolute(std::uint64_t Address, int Length) { 200 | std::string _output; 201 | 202 | protect_lock lock(Address, static_cast(Length)); 203 | if (lock.good()) { 204 | _output.resize(Length); 205 | std::memcpy(_output.data(), (void*)Address, Length); 206 | } 207 | 208 | return _output; 209 | } 210 | 211 | template 212 | static T readScalar(std::uint64_t Address, bool absolute = false) { 213 | if (absolute) { 214 | return readScalarAbsolute(Address); 215 | } else { 216 | return readScalarAbsolute(Address + BaseAddress); 217 | } 218 | } 219 | 220 | static inline std::uint8_t ReadByte(std::uint64_t Address, 221 | bool absolute = false) { 222 | return readScalar(Address, absolute); 223 | } 224 | 225 | static inline std::uint16_t ReadShort(std::uint64_t Address, 226 | bool absolute = false) { 227 | return readScalar(Address, absolute); 228 | } 229 | 230 | static inline std::uint32_t ReadInt(std::uint64_t Address, 231 | bool absolute = false) { 232 | return readScalar(Address, absolute); 233 | } 234 | 235 | static inline std::uint64_t ReadLong(std::uint64_t Address, 236 | bool absolute = false) { 237 | return readScalar(Address, absolute); 238 | } 239 | 240 | static inline float ReadFloat(std::uint64_t Address, bool absolute = false) { 241 | return readScalar(Address, absolute); 242 | } 243 | 244 | static inline bool ReadBool(std::uint64_t Address, bool absolute = false) { 245 | return ReadByte(Address, absolute) != 0; 246 | } 247 | 248 | static std::vector ReadBytes(std::uint64_t Address, int Length, 249 | bool absolute = false) { 250 | if (absolute) { 251 | return ReadBytesAbsolute(Address, Length); 252 | } else { 253 | return ReadBytesAbsolute(Address + BaseAddress, Length); 254 | } 255 | } 256 | 257 | static std::string ReadString(std::uint64_t Address, int Length, 258 | bool absolute = false) { 259 | if (absolute) { 260 | return ReadStringAbsolute(Address, Length); 261 | } else { 262 | return ReadStringAbsolute(Address + BaseAddress, Length); 263 | } 264 | } 265 | 266 | template , int> = 0> 268 | static void writeScalarAbsolute(std::uint64_t Address, T t) { 269 | protect_lock lock(Address, sizeof(T)); 270 | if (!lock.good()) 271 | return; 272 | 273 | *reinterpret_cast(Address) = t; 274 | } 275 | 276 | static inline void WriteByteAbsolute(std::uint64_t Address, 277 | std::uint8_t Input) { 278 | writeScalarAbsolute(Address, Input); 279 | } 280 | 281 | static inline void WriteShortAbsolute(std::uint64_t Address, 282 | std::uint16_t Input) { 283 | writeScalarAbsolute(Address, Input); 284 | } 285 | 286 | static inline void WriteIntAbsolute(std::uint64_t Address, 287 | std::uint32_t Input) { 288 | writeScalarAbsolute(Address, Input); 289 | } 290 | 291 | static inline void WriteLongAbsolute(std::uint64_t Address, 292 | std::uint64_t Input) { 293 | writeScalarAbsolute(Address, Input); 294 | } 295 | 296 | static inline void WriteFloatAbsolute(std::uint64_t Address, float Input) { 297 | writeScalarAbsolute(Address, Input); 298 | } 299 | 300 | static inline void WriteBoolAbsolute(std::uint64_t Address, bool Input) { 301 | WriteByteAbsolute(Address, Input ? 1 : 0); 302 | } 303 | 304 | static void WriteBytesAbsolute(std::uint64_t Address, 305 | std::vector Input) { 306 | protect_lock lock(Address, Input.size()); 307 | if (lock.good()) 308 | std::memcpy((void*)Address, Input.data(), Input.size()); 309 | } 310 | 311 | static void WriteStringAbsolute(std::uint64_t Address, std::string Input) { 312 | protect_lock lock(Address, Input.size()); 313 | if (lock.good()) 314 | std::memcpy((void*)Address, Input.data(), Input.size()); 315 | } 316 | 317 | template 318 | static void writeScalar(std::uint64_t Address, T const& t, 319 | bool absolute = false) { 320 | if (absolute) { 321 | writeScalarAbsolute(Address, t); 322 | } else { 323 | writeScalarAbsolute(Address + BaseAddress, t); 324 | } 325 | } 326 | 327 | static inline void WriteByte(std::uint64_t Address, std::uint8_t Input, 328 | bool absolute = false) { 329 | writeScalar(Address, Input, absolute); 330 | } 331 | 332 | static inline void WriteShort(std::uint64_t Address, std::uint16_t Input, 333 | bool absolute = false) { 334 | writeScalar(Address, Input, absolute); 335 | } 336 | 337 | static inline void WriteInt(std::uint64_t Address, std::uint32_t Input, 338 | bool absolute = false) { 339 | writeScalar(Address, Input, absolute); 340 | } 341 | 342 | static inline void WriteLong(std::uint64_t Address, std::uint64_t Input, 343 | bool absolute = false) { 344 | writeScalar(Address, Input, absolute); 345 | } 346 | 347 | static inline void WriteFloat(std::uint64_t Address, float Input, 348 | bool absolute = false) { 349 | writeScalar(Address, Input, absolute); 350 | } 351 | 352 | static inline void WriteBool(std::uint64_t Address, bool Input, 353 | bool absolute = false) { 354 | WriteByte(Address, Input ? 1 : 0, absolute); 355 | } 356 | 357 | static void WriteBytes(std::uint64_t Address, std::vector Input, 358 | bool absolute = false) { 359 | if (absolute) { 360 | WriteBytesAbsolute(Address, std::move(Input)); 361 | } else { 362 | WriteBytesAbsolute(Address + BaseAddress, std::move(Input)); 363 | } 364 | } 365 | 366 | static void WriteString(std::uint64_t Address, std::string Input, 367 | bool absolute = false) { 368 | if (absolute) { 369 | WriteStringAbsolute(Address, std::move(Input)); 370 | } else { 371 | WriteStringAbsolute(Address + BaseAddress, std::move(Input)); 372 | } 373 | } 374 | 375 | static void WriteExec(std::uint64_t Address, 376 | std::vector Input) { 377 | protect_lock lock(Address, Input.size()); 378 | if (lock.good()) 379 | std::memcpy((void*)(Address + ExecAddress), Input.data(), Input.size()); 380 | } 381 | 382 | static inline std::uint64_t GetPointer(std::uint64_t Address, 383 | std::uint64_t Offset, 384 | bool absolute = false) { 385 | std::uint64_t _temp = ReadLong(Address, absolute); 386 | return _temp + Offset; 387 | } 388 | 389 | static inline std::uint64_t GetPointerAbsolute(std::uint64_t Address, 390 | std::uint64_t Offset) { 391 | std::uint64_t _temp = ReadLongAbsolute(Address); 392 | return _temp + Offset; 393 | } 394 | }; 395 | -------------------------------------------------------------------------------- /src/config.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace fs = std::filesystem; 13 | 14 | Config Config::load(const fs::path& path) { 15 | Config config; 16 | auto data = toml::parse_file(path.u8string()); 17 | 18 | for (const auto& [k, _] : data) { 19 | const auto& entry = data[k]; 20 | 21 | const auto scripts = entry["scripts"].as_array(); 22 | const auto base = entry["base"].value(); 23 | const auto exe = entry["exe"].value(); 24 | const auto game_docs = entry["game_docs"].value(); 25 | 26 | if (!scripts) { 27 | throw std::runtime_error{std::string{k} + ": scripts failed to parse"}; 28 | } 29 | if (!exe) { 30 | throw std::runtime_error{std::string{k} + ": exe failed to parse"}; 31 | } 32 | if (!game_docs) { 33 | throw std::runtime_error{std::string{k} + ": game_docs failed to parse"}; 34 | } 35 | 36 | std::vector paths; 37 | for (std::size_t i = 0; i < scripts->size(); i++) { 38 | const auto& v = *scripts->get_as(i); 39 | const auto str = v["path"].value(); 40 | const auto relative = v["relative"].value(); 41 | 42 | if (!str) { 43 | throw std::runtime_error{std::string{k} + ": at index " + 44 | std::to_string(i) + 45 | ": script entry path failed to parse"}; 46 | } 47 | if (!relative) { 48 | throw std::runtime_error{std::string{k} + ": at index " + 49 | std::to_string(i) + 50 | ": script entry relative failed to parse"}; 51 | } 52 | 53 | paths.emplace_back(*str, *relative); 54 | } 55 | 56 | config.infos.emplace(*exe, GameInfo{.baseAddress = base.value_or(0), 57 | .scriptPaths = std::move(paths), 58 | .gameDocsPathStr = *game_docs}); 59 | } 60 | 61 | return config; 62 | } 63 | 64 | std::optional> 65 | Config::gameInfo(const std::u8string& exe) const { 66 | if (auto info = infos.find(exe); info != infos.end()) { 67 | return std::cref(info->second); 68 | } else { 69 | return {}; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "game_info.h" 11 | 12 | class Config { 13 | private: 14 | std::unordered_map infos; 15 | 16 | public: 17 | static Config load(const std::filesystem::path& path); 18 | std::optional> 19 | gameInfo(const std::u8string& exe) const; 20 | }; 21 | -------------------------------------------------------------------------------- /src/game_info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct ScriptPath { 8 | std::u8string str; 9 | bool relative; 10 | }; 11 | 12 | struct GameInfo { 13 | std::uintptr_t baseAddress; 14 | std::vector scriptPaths; 15 | std::u8string gameDocsPathStr; 16 | }; 17 | -------------------------------------------------------------------------------- /src/header_text.cpp: -------------------------------------------------------------------------------- 1 | #include "header_text.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | template 10 | [[nodiscard]] constexpr static auto 11 | generateBlockText(const char (&... lines)[Len]) { 12 | constexpr std::string_view separator = " "; 13 | constexpr std::string_view padding = "="; 14 | constexpr std::size_t edge_pad_amount = 3; 15 | 16 | constexpr std::size_t max_line_length = std::max({Len...}) - 1; 17 | constexpr std::size_t num_lines = sizeof...(Len); 18 | 19 | constexpr std::size_t formatted_line_size = 20 | max_line_length + (2 * separator.size()) + (edge_pad_amount * 2); 21 | 22 | constexpr std::size_t text_size = (formatted_line_size + 1) * num_lines + 1; 23 | std::array text; 24 | text[text.size() - 1] = '\0'; 25 | 26 | char* dst = text.data(); 27 | for (const auto src : {(std::string_view{lines, Len - 1})...}) { 28 | std::size_t sep_size = src.empty() ? 0 : separator.size(); 29 | std::size_t total_pad = formatted_line_size - src.size() - (2 * sep_size); 30 | std::size_t right_pad = total_pad / 2; 31 | std::size_t left_pad = total_pad - right_pad; 32 | 33 | const auto copy = [](auto& dst, const auto& src) { 34 | std::copy(src.begin(), src.end(), dst); 35 | dst += src.size(); 36 | }; 37 | 38 | const auto cylic_copy_n = [](auto& dst, const auto& src, std::size_t n) { 39 | for (std::size_t i = 0; i < n;) { 40 | std::size_t copy_len = std::min(src.size(), n - i); 41 | std::copy(src.begin(), src.begin() + copy_len, dst); 42 | dst += copy_len; 43 | i += copy_len; 44 | } 45 | }; 46 | 47 | cylic_copy_n(dst, padding, left_pad); 48 | cylic_copy_n(dst, separator, sep_size); 49 | copy(dst, src); 50 | cylic_copy_n(dst, separator, sep_size); 51 | cylic_copy_n(dst, padding, right_pad); 52 | *dst++ = '\n'; 53 | } 54 | 55 | return text; 56 | } 57 | 58 | std::string_view getHeaderText() { 59 | // clang-format off 60 | constexpr static auto headerText = generateBlockText( 61 | "", 62 | "LuaBackendHook " HOOK_VERSION, 63 | "Copyright 2022 - TopazTK | Sirius902", 64 | "", 65 | "Compatible with LuaEngine v5.0", 66 | "Embedded Version", 67 | "" 68 | ); 69 | // clang-format on 70 | constexpr static auto headerTextView = 71 | std::string_view{headerText.begin(), headerText.end()}; 72 | return headerTextView; 73 | } 74 | -------------------------------------------------------------------------------- /src/header_text.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | std::string_view getHeaderText(); 6 | -------------------------------------------------------------------------------- /src/lua_exec.cpp: -------------------------------------------------------------------------------- 1 | #include "lua_exec.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "ConsoleLib.h" 7 | #include "LuaBackend.h" 8 | #include "header_text.h" 9 | 10 | namespace fs = std::filesystem; 11 | 12 | static bool _funcOneState = true; 13 | static bool _funcTwoState = true; 14 | static bool _funcThreeState = true; 15 | 16 | static std::vector _scriptPaths; 17 | 18 | static bool _showConsole = false; 19 | static bool _requestedReset = false; 20 | 21 | static std::unique_ptr _backend; 22 | 23 | static std::chrono::high_resolution_clock::time_point _sClock; 24 | static std::chrono::high_resolution_clock::time_point _msClock; 25 | 26 | void ResetLUA() { 27 | std::printf("\n"); 28 | ConsoleLib::MessageOutput("Reloading...\n\n", 0); 29 | _backend = std::make_unique( 30 | _scriptPaths, MemoryLib::ExecAddress + MemoryLib::BaseAddress); 31 | 32 | if (_backend->loadedScripts.size() == 0) 33 | ConsoleLib::MessageOutput("No scripts found! Reload halted!\n\n", 3); 34 | 35 | ConsoleLib::MessageOutput("Executing initialization event handlers...\n\n", 36 | 0); 37 | 38 | for (auto& _script : _backend->loadedScripts) 39 | if (_script->initFunction) { 40 | auto _result = _script->initFunction(); 41 | 42 | if (!_result.valid()) { 43 | sol::error _err = _result; 44 | ConsoleLib::MessageOutput(_err.what(), 3); 45 | std::printf("\n\n"); 46 | } 47 | } 48 | 49 | ConsoleLib::MessageOutput("Reload complete!\n\n", 1); 50 | 51 | _msClock = std::chrono::high_resolution_clock::now(); 52 | _sClock = std::chrono::high_resolution_clock::now(); 53 | 54 | _requestedReset = false; 55 | } 56 | 57 | int EntryLUA(int ProcessID, HANDLE ProcessH, std::uint64_t TargetAddress, 58 | std::vector ScriptPaths) { 59 | ShowWindow(GetConsoleWindow(), SW_HIDE); 60 | 61 | std::cout << getHeaderText() << '\n'; 62 | 63 | ConsoleLib::MessageOutput("Initializing LuaEngine v5.0...\n\n", 0); 64 | _scriptPaths = std::move(ScriptPaths); 65 | 66 | MemoryLib::ExternProcess(ProcessID, ProcessH, TargetAddress); 67 | 68 | _backend = std::make_unique(_scriptPaths, MemoryLib::ExecAddress + 69 | TargetAddress); 70 | _backend->frameLimit = 16; 71 | 72 | if (_backend->loadedScripts.size() == 0) { 73 | ConsoleLib::MessageOutput( 74 | "No scripts were found! Initialization halted!\n\n", 3); 75 | return -1; 76 | } 77 | 78 | ConsoleLib::MessageOutput("Executing initialization event handlers...\n\n", 79 | 0); 80 | 81 | for (auto& _script : _backend->loadedScripts) 82 | if (_script->initFunction) { 83 | auto _result = _script->initFunction(); 84 | 85 | if (!_result.valid()) { 86 | sol::error _err = _result; 87 | ConsoleLib::MessageOutput(_err.what(), 3); 88 | std::printf("\n\n"); 89 | } 90 | } 91 | 92 | ConsoleLib::MessageOutput("Initialization complete!\n", 1); 93 | ConsoleLib::MessageOutput( 94 | "Press 'F1' to reload all scripts, press 'F2' to toggle the console, " 95 | "press 'F3' to set " 96 | "execution frequency.\n\n", 97 | 0); 98 | 99 | _msClock = std::chrono::high_resolution_clock::now(); 100 | _sClock = std::chrono::high_resolution_clock::now(); 101 | 102 | return 0; 103 | } 104 | 105 | void ExecuteLUA() { 106 | if (_requestedReset == false) { 107 | auto _currTime = std::chrono::high_resolution_clock::now(); 108 | auto _sTime = std::chrono::duration_cast( 109 | _currTime - _sClock) 110 | .count(); 111 | 112 | if (GetKeyState(VK_F3) & 0x8000 && _funcThreeState) { 113 | switch (_backend->frameLimit) { 114 | case 16: 115 | _backend->frameLimit = 8; 116 | ConsoleLib::MessageOutput("Frequency set to 120Hz.\n", 0); 117 | break; 118 | case 8: 119 | _backend->frameLimit = 4; 120 | ConsoleLib::MessageOutput("Frequency set to 240Hz.\n", 0); 121 | break; 122 | case 4: 123 | _backend->frameLimit = 16; 124 | ConsoleLib::MessageOutput("Frequency set to 60Hz.\n", 0); 125 | break; 126 | } 127 | 128 | _sTime = 0; 129 | _funcThreeState = false; 130 | _sClock = std::chrono::high_resolution_clock::now(); 131 | } 132 | if (GetKeyState(VK_F2) & 0x8000 && _funcTwoState) { 133 | if (_showConsole) { 134 | ShowWindow(GetConsoleWindow(), SW_HIDE); 135 | _showConsole = false; 136 | } 137 | 138 | else { 139 | ShowWindow(GetConsoleWindow(), SW_RESTORE); 140 | _showConsole = true; 141 | } 142 | 143 | _sTime = 0; 144 | _funcTwoState = false; 145 | _sClock = std::chrono::high_resolution_clock::now(); 146 | } 147 | if (GetKeyState(VK_F1) & 0x8000 && _funcOneState) { 148 | _requestedReset = true; 149 | 150 | _sTime = 0; 151 | _funcOneState = false; 152 | _sClock = std::chrono::high_resolution_clock::now(); 153 | } 154 | 155 | for (std::size_t i = 0; i < _backend->loadedScripts.size(); i++) { 156 | auto& _script = _backend->loadedScripts[i]; 157 | 158 | if (_script->frameFunction) { 159 | auto _result = _script->frameFunction(); 160 | 161 | if (!_result.valid()) { 162 | sol::error _err = _result; 163 | ConsoleLib::MessageOutput(_err.what(), 3); 164 | std::printf("\n\n"); 165 | 166 | _backend->loadedScripts.erase(_backend->loadedScripts.begin() + i); 167 | } 168 | } 169 | } 170 | 171 | _msClock = std::chrono::high_resolution_clock::now(); 172 | 173 | if (_sTime > 250) { 174 | _funcOneState = true; 175 | _funcTwoState = true; 176 | _funcThreeState = true; 177 | _sClock = std::chrono::high_resolution_clock::now(); 178 | } 179 | } 180 | 181 | else 182 | ResetLUA(); 183 | } 184 | 185 | bool CheckLUA() { 186 | auto _int = MemoryLib::ReadInt(0); 187 | 188 | if (_int == 0) 189 | return false; 190 | 191 | return true; 192 | } 193 | 194 | int VersionLUA() { return 128; } 195 | -------------------------------------------------------------------------------- /src/lua_exec.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define WIN32_LEAN_AND_MEAN 10 | #include 11 | 12 | #include "LuaBackend.h" 13 | #include "MemoryLib.h" 14 | 15 | void EnterWait(); 16 | void ResetLUA(); 17 | int EntryLUA(int ProcessID, HANDLE ProcessH, std::uint64_t TargetAddress, 18 | std::vector ScriptPaths); 19 | void ExecuteLUA(); 20 | bool CheckLUA(); 21 | int VersionLUA(); 22 | -------------------------------------------------------------------------------- /src/main_dll.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define WIN32_LEAN_AND_MEAN 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define MiniDumpWriteDump MiniDumpWriteDump_ 21 | #include 22 | #undef MiniDumpWriteDump 23 | 24 | #include "config.h" 25 | #include "game_info.h" 26 | #include "lua_exec.h" 27 | #include "wil_extra.h" 28 | 29 | // TODO: Remove after init fix. 30 | #include 31 | 32 | namespace fs = std::filesystem; 33 | namespace ranges = std::ranges; 34 | 35 | using MiniDumpWriteDumpProc = decltype(&MiniDumpWriteDump_); 36 | 37 | using DirectInput8CreateProc = HRESULT(WINAPI*)(HINSTANCE hinst, 38 | DWORD dwVersion, 39 | LPCVOID riidltf, LPVOID* ppvOut, 40 | LPVOID punkOuter); 41 | 42 | using GameFrameProc = std::uint64_t(__cdecl*)(void* rcx); 43 | 44 | MiniDumpWriteDumpProc writeDumpProc = nullptr; 45 | DirectInput8CreateProc createProc = nullptr; 46 | 47 | GameFrameProc* frameProcPtr = nullptr; 48 | GameFrameProc frameProc = nullptr; 49 | 50 | std::optional config; 51 | std::optional gameInfo; 52 | 53 | std::uint64_t moduleAddress = 0; 54 | 55 | template 56 | requires std::same_as, std::uintptr_t> 57 | std::optional followPointerChain(std::uintptr_t start, 58 | const R& offsets) { 59 | std::uintptr_t current = start; 60 | 61 | for (auto it = ranges::begin(offsets); it != ranges::end(offsets); ++it) { 62 | if (current == 0) 63 | return {}; 64 | 65 | if (it != ranges::end(offsets) - 1) { 66 | current = *reinterpret_cast(current + *it); 67 | } else { 68 | current += *it; 69 | } 70 | } 71 | 72 | return current; 73 | } 74 | 75 | std::uint64_t __cdecl frameHook(void* rcx) { 76 | ExecuteLUA(); 77 | return frameProc(rcx); 78 | } 79 | 80 | LONG WINAPI crashDumpHandler(PEXCEPTION_POINTERS exceptionPointers) { 81 | HANDLE file = CreateFileW(L"CrashDump.dmp", GENERIC_READ | GENERIC_WRITE, 0, 82 | NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 83 | 84 | if (file != INVALID_HANDLE_VALUE) { 85 | MINIDUMP_EXCEPTION_INFORMATION mdei; 86 | 87 | mdei.ThreadId = GetCurrentThreadId(); 88 | mdei.ExceptionPointers = exceptionPointers; 89 | mdei.ClientPointers = TRUE; 90 | 91 | (*writeDumpProc)(GetCurrentProcess(), GetCurrentProcessId(), file, 92 | MiniDumpNormal, &mdei, 0, 0); 93 | 94 | CloseHandle(file); 95 | } 96 | 97 | return EXCEPTION_EXECUTE_HANDLER; 98 | } 99 | 100 | struct SectionInfo { 101 | std::uintptr_t offset; 102 | std::size_t size; 103 | }; 104 | 105 | SectionInfo findTextSectionInfo() { 106 | const auto basePtr = std::bit_cast(moduleAddress); 107 | const auto dosHeader = reinterpret_cast(basePtr); 108 | if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { 109 | throw std::runtime_error{"DOS header is corrupt"}; 110 | } 111 | 112 | const auto ntHeaderPtr = basePtr + dosHeader->e_lfanew; 113 | const auto ntHeader = reinterpret_cast(ntHeaderPtr); 114 | if (ntHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) { 115 | throw new std::runtime_error{"NT64 header is invalid"}; 116 | } 117 | 118 | std::optional textSection; 119 | 120 | for (WORD i = 0; i < ntHeader->FileHeader.NumberOfSections; i++) { 121 | const auto sectionHeader = reinterpret_cast( 122 | ntHeaderPtr + sizeof(IMAGE_NT_HEADERS64) + 123 | (i * sizeof(IMAGE_SECTION_HEADER))); 124 | 125 | constexpr char textSectionName[] = ".text"; 126 | if (std::memcmp(reinterpret_cast(sectionHeader->Name), 127 | textSectionName, sizeof(textSectionName) - 1) == 0) { 128 | textSection = SectionInfo{ 129 | .offset = sectionHeader->VirtualAddress, 130 | .size = sectionHeader->SizeOfRawData, 131 | }; 132 | break; 133 | } 134 | } 135 | 136 | return textSection.value(); 137 | } 138 | 139 | std::optional findFrameProc(const SectionInfo& textInfo) { 140 | constexpr char sig[] = "\x48\x89\x35\xA7\xB6\x69\x00\x48\x8B\xC6"; 141 | constexpr char mask[] = "\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF"; 142 | static_assert(sizeof(sig) == sizeof(mask)); 143 | 144 | const char* textStart = 145 | std::bit_cast(moduleAddress + textInfo.offset); 146 | const char* textEnd = textStart + textInfo.size; 147 | 148 | for (const char* p = textStart; p != textEnd - (sizeof(sig) - 1); p++) { 149 | bool isMatch = true; 150 | for (std::size_t i = 0; i < sizeof(sig) - 1; i++) { 151 | if ((p[i] & mask[i]) != (sig[i] & mask[i])) { 152 | isMatch = false; 153 | break; 154 | } 155 | } 156 | 157 | if (!isMatch) 158 | continue; 159 | 160 | const auto scanRes = std::bit_cast(p); 161 | const auto appPtrAddress = 162 | scanRes + 0x7 + *reinterpret_cast(scanRes + 0x3); 163 | const auto appPtr = *std::bit_cast(appPtrAddress); 164 | 165 | if (appPtr == nullptr) 166 | return std::nullopt; 167 | 168 | const auto vtableAddress = *static_cast(appPtr); 169 | const auto onFrameEntry = vtableAddress + 4 * sizeof(std::uintptr_t); 170 | return std::bit_cast(onFrameEntry); 171 | } 172 | 173 | return std::nullopt; 174 | } 175 | 176 | bool hookGame() { 177 | static_assert(sizeof(std::uint64_t) == sizeof(std::uintptr_t)); 178 | 179 | const auto textInfo = findTextSectionInfo(); 180 | const auto frameProcPtrOpt = findFrameProc(textInfo); 181 | 182 | if (!frameProcPtrOpt.has_value()) { 183 | return false; 184 | } 185 | 186 | frameProcPtr = frameProcPtrOpt.value(); 187 | if (*frameProcPtr == nullptr) 188 | return false; 189 | 190 | DWORD originalProt = 0; 191 | VirtualProtect(frameProcPtr, sizeof(frameProcPtr), PAGE_READWRITE, 192 | &originalProt); 193 | frameProc = *frameProcPtr; 194 | *frameProcPtr = frameHook; 195 | VirtualProtect(frameProcPtr, sizeof(frameProcPtr), originalProt, 196 | &originalProt); 197 | 198 | SetUnhandledExceptionFilter(crashDumpHandler); 199 | 200 | return true; 201 | } 202 | 203 | DWORD WINAPI entry([[maybe_unused]] LPVOID lpParameter) { 204 | std::wstring modulePathStr; 205 | wil::GetModuleFileNameW(nullptr, modulePathStr); 206 | 207 | fs::path modulePath = fs::path{modulePathStr}; 208 | fs::path moduleDir = modulePath.parent_path(); 209 | std::wstring moduleNameW = modulePath.filename(); 210 | 211 | std::u8string moduleName = 212 | ztd::text::transcode(moduleNameW, ztd::text::wide_utf16, ztd::text::utf8, 213 | ztd::text::replacement_handler); 214 | 215 | try { 216 | config = Config::load("LuaBackend.toml"); 217 | auto entry = config->gameInfo(moduleName); 218 | if (entry) { 219 | gameInfo = *entry; 220 | } else { 221 | return 0; 222 | } 223 | 224 | moduleAddress = (std::uint64_t)GetModuleHandleW(nullptr); 225 | std::uint64_t baseAddress = moduleAddress + gameInfo->baseAddress; 226 | 227 | fs::path gameDocsRoot = [&]() { 228 | PWSTR docsRootStr; 229 | SHGetKnownFolderPath(FOLDERID_Documents, 0, nullptr, &docsRootStr); 230 | 231 | return fs::path{docsRootStr} / gameInfo->gameDocsPathStr; 232 | }(); 233 | 234 | std::vector scriptPaths; 235 | for (const auto& path : gameInfo->scriptPaths) { 236 | if (path.relative) { 237 | fs::path gameScriptsPath = gameDocsRoot / path.str; 238 | if (fs::exists(gameScriptsPath)) { 239 | scriptPaths.push_back(gameScriptsPath); 240 | } 241 | } else { 242 | fs::path gameScriptsPath = fs::path{path.str}; 243 | if (fs::exists(gameScriptsPath)) { 244 | scriptPaths.push_back(gameScriptsPath); 245 | } 246 | } 247 | } 248 | 249 | if (!scriptPaths.empty()) { 250 | AllocConsole(); 251 | SetConsoleOutputCP(CP_UTF8); 252 | FILE* f; 253 | freopen_s(&f, "CONOUT$", "w", stdout); 254 | 255 | if (EntryLUA(GetCurrentProcessId(), GetCurrentProcess(), baseAddress, 256 | std::move(scriptPaths)) == 0) { 257 | // TODO: Hook after game initialization is done. 258 | while (!hookGame()) { 259 | std::this_thread::sleep_for(std::chrono::milliseconds(16)); 260 | } 261 | } else { 262 | std::cout << "Failed to initialize internal LuaBackend!" << std::endl; 263 | } 264 | } 265 | } catch (std::exception& e) { 266 | std::string msg = "entry exception: " + std::string(e.what()) + 267 | "\n\nScripts failed to load."; 268 | std::wstring wmsg = 269 | ztd::text::transcode(msg, ztd::text::compat_utf8, ztd::text::wide_utf16, 270 | ztd::text::replacement_handler); 271 | MessageBoxW(NULL, wmsg.c_str(), L"LuaBackendHook", MB_ICONERROR | MB_OK); 272 | } 273 | 274 | return 0; 275 | } 276 | 277 | BOOL WINAPI DllMain([[maybe_unused]] HINSTANCE hinstDLL, DWORD fdwReason, 278 | [[maybe_unused]] LPVOID lpReserved) { 279 | static HMODULE dbgHelp = nullptr; 280 | static HMODULE dinput8 = nullptr; 281 | 282 | switch (fdwReason) { 283 | case DLL_PROCESS_ATTACH: { 284 | std::wstring systemDirectoryStr; 285 | wil::GetSystemDirectoryW(systemDirectoryStr); 286 | fs::path dllPath = fs::path{systemDirectoryStr} / L"DBGHELP.dll"; 287 | 288 | dbgHelp = LoadLibraryW(dllPath.wstring().c_str()); 289 | writeDumpProc = 290 | (MiniDumpWriteDumpProc)GetProcAddress(dbgHelp, "MiniDumpWriteDump"); 291 | 292 | fs::path dinput8Path = fs::path{systemDirectoryStr} / L"DINPUT8.dll"; 293 | 294 | dinput8 = LoadLibraryW(dinput8Path.wstring().c_str()); 295 | createProc = 296 | (DirectInput8CreateProc)GetProcAddress(dinput8, "DirectInput8Create"); 297 | 298 | if (CreateThread(nullptr, 0, entry, nullptr, 0, nullptr) == nullptr) { 299 | return FALSE; 300 | } 301 | 302 | break; 303 | } 304 | case DLL_PROCESS_DETACH: { 305 | FreeLibrary(dbgHelp); 306 | FreeLibrary(dinput8); 307 | break; 308 | } 309 | default: 310 | break; 311 | } 312 | 313 | return TRUE; 314 | } 315 | 316 | extern "C" __declspec(dllexport) HRESULT WINAPI 317 | DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, LPCVOID riidltf, 318 | LPVOID* ppvOut, LPVOID punkOuter) { 319 | return createProc(hinst, dwVersion, riidltf, ppvOut, punkOuter); 320 | } 321 | 322 | extern "C" __declspec(dllexport) BOOL WINAPI MiniDumpWriteDump( 323 | HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, 324 | PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, 325 | PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, 326 | PMINIDUMP_CALLBACK_INFORMATION CallbackParam) { 327 | return writeDumpProc(hProcess, ProcessId, hFile, DumpType, ExceptionParam, 328 | UserStreamParam, CallbackParam); 329 | } 330 | -------------------------------------------------------------------------------- /src/wil_extra.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN 4 | #include 5 | #include 6 | #include 7 | 8 | namespace wil_extra { 9 | template 10 | HRESULT GetProcessImageFileNameW(HANDLE hProcess, 11 | string_type& result) WI_NOEXCEPT { 12 | return wil::AdaptFixedSizeToAllocatedResult( 13 | result, 14 | [&](_Out_writes_(valueLength) PWSTR value, std::size_t valueLength, 15 | _Out_ std::size_t* valueLengthNeededWithNul) -> HRESULT { 16 | *valueLengthNeededWithNul = ::GetProcessImageFileNameW( 17 | hProcess, value, static_cast(valueLength)); 18 | RETURN_LAST_ERROR_IF(*valueLengthNeededWithNul == 0); 19 | if (*valueLengthNeededWithNul < valueLength) { 20 | (*valueLengthNeededWithNul)++; // it fit, account for the null 21 | } 22 | return S_OK; 23 | }); 24 | } 25 | } // namespace wil_extra 26 | --------------------------------------------------------------------------------