├── .gitattributes ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .vscode ├── c_cpp_properties.json ├── launch.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── examples ├── cleo5 │ ├── example.jpg │ ├── imgui_test.cs │ └── imgui_test.txt └── redux │ └── imgui_test │ ├── example.jpg │ └── index.js ├── include ├── cleo │ ├── CLEO.h │ ├── CLEO_Utils.h │ └── cleo_redux_sdk.h ├── imgui │ ├── imconfig.h │ ├── imgui.cpp │ ├── imgui.h │ ├── imgui_demo.cpp │ ├── imgui_draw.cpp │ ├── imgui_impl_dx11.cpp │ ├── imgui_impl_dx11.h │ ├── imgui_impl_dx9.cpp │ ├── imgui_impl_dx9.h │ ├── imgui_impl_opengl3.cpp │ ├── imgui_impl_opengl3.h │ ├── imgui_impl_opengl3_loader.h │ ├── imgui_impl_win32.cpp │ ├── imgui_impl_win32.h │ ├── imgui_internal.h │ ├── imgui_stdlib.cpp │ ├── imgui_stdlib.h │ ├── imgui_tables.cpp │ ├── imgui_widgets.cpp │ ├── imstb_rectpack.h │ ├── imstb_textedit.h │ └── imstb_truetype.h ├── injector │ ├── assembly.hpp │ ├── calling.hpp │ ├── gvm │ │ ├── gvm.hpp │ │ └── translator.hpp │ ├── hooking.hpp │ ├── injector.hpp │ └── utility.hpp ├── kiero │ ├── MinHook.h │ ├── kiero.cpp │ └── kiero.h └── misc │ └── stb_image.h ├── lib ├── CLEO.lib ├── cleo_redux.lib ├── cleo_redux64.lib ├── d3dx9.lib ├── d3dx9x64.lib ├── libMinHook-x64.lib └── libMinHook-x86.lib ├── src ├── dllmain.cpp ├── font.h ├── hook.cpp ├── hook.h ├── imguiframe.hpp ├── notifypopup.cpp ├── notifypopup.h ├── opcodemgr.cpp ├── opcodemgr.h ├── pch.cpp ├── pch.h ├── scriptextender.hpp ├── table.hpp ├── texturemgr.cpp ├── texturemgr.h └── wrapper.hpp └── tools ├── AStyle.exe ├── Debug.bat ├── Debug64.bat ├── DebugCleo.bat ├── FormatCode.bat ├── Release.bat ├── Release64.bat ├── ReleaseCleo.bat ├── Setup.bat ├── out.json ├── premake5.exe ├── premake5.lua ├── tes.py └── test.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build ImGuiRedux 2 | on: push 3 | jobs: 4 | ImGuiRedux: 5 | runs-on: windows-latest 6 | strategy: 7 | matrix: 8 | platform: [Win32, Win64] 9 | buildtype: [Release] 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v3.0.0 13 | - name: Setup premake 14 | uses: abel0b/setup-premake@v2 15 | with: 16 | version: "5.0.0-beta1" 17 | - name: Configure build 18 | uses: ilammy/msvc-dev-cmd@v1 19 | with: 20 | arch: ${{matrix.platform}} 21 | - name: Build plugin 22 | run: | 23 | cd tools 24 | premake5 vs2022 25 | cd ../build 26 | MsBuild ImGuiRedux.sln /property:Configuration=${{matrix.buildtype}} /p:Platform=${{matrix.platform}} /t:ImGuiRedux 27 | - name: Upload plugin 28 | uses: actions/upload-artifact@v3 29 | with: 30 | name: ImGuiRedux${{matrix.platform}} 31 | path: build\bin\ImGuiRedux${{matrix.platform}}.cleo 32 | - name: Archive plugin 33 | uses: papeloto/action-zip@v1 34 | with: 35 | files: build\bin\ImGuiRedux${{matrix.platform}}.cleo 36 | dest: ImGuiRedux${{matrix.platform}}.zip 37 | - name: Add build to release tag 38 | uses: ncipollo/release-action@v1 39 | with: 40 | artifacts: ImGuiRedux${{matrix.platform}}.zip 41 | name: "${{matrix.platform}} Builds" 42 | body: "This release is updated frequently with newer builds.\n\n- ImGuiReduxWin64 -> For CLEORedux (Supports 64 bit games)" 43 | allowUpdates: true 44 | tag: "${{matrix.platform}}-latest" 45 | ImGuiCleo: 46 | runs-on: windows-latest 47 | steps: 48 | - name: Checkout 49 | uses: actions/checkout@v3.0.0 50 | - name: Setup premake 51 | uses: abel0b/setup-premake@v2 52 | with: 53 | version: "5.0.0-beta1" 54 | - name: Configure build 55 | uses: ilammy/msvc-dev-cmd@v1 56 | with: 57 | arch: Win32 58 | - name: Build plugin 59 | run: | 60 | cd tools 61 | premake5 vs2022 62 | cd ../build 63 | MsBuild ImGuiRedux.sln /property:Configuration=ReleaseCleo /p:Platform=Win32 /t:ImGuiRedux 64 | - name: Upload plugin 65 | uses: actions/upload-artifact@v3 66 | with: 67 | name: ImGuiCleoWin32 68 | path: build\bin\ImGuiCleoWin32.cleo 69 | - name: Archive plugin 70 | uses: papeloto/action-zip@v1 71 | with: 72 | files: build\bin\ImGuiCleoWin32.cleo 73 | dest: ImGuiCleoWin32.zip 74 | - name: Add build to release tag 75 | uses: ncipollo/release-action@v1 76 | with: 77 | artifacts: ImGuiCleoWin32.zip 78 | name: "Win32 Builds" 79 | body: "This release is updated frequently with newer builds.\n\n- ImGuiCleoWin32 -> For CLEO5 (Supports GTA SA). Only required if you use ImGui in .cs scripts. \n- ImGuiReduxWin32 -> For CLEORedux (Supports 32 bit games). GTA SA Support is also included." 80 | allowUpdates: true 81 | tag: "Win32-latest" 82 | 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | archives/ 2 | build/ 3 | tools/pack/ 4 | .gitignore 5 | CheatMenuVC.7z 6 | CheatMenuIII.7z 7 | CheatMenuSA.7z 8 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "GTASA", 5 | "includePath": [ 6 | "${workspaceFolder}/**", 7 | "${DXSDK_DIR}/Include/*", 8 | "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\ucrt\\*" 9 | ], 10 | "defines": [ 11 | "_DEBUG", 12 | "_DX9_SDK_INSTALLED", 13 | "RUNTIME_CLEO", 14 | ], 15 | "windowsSdkVersion": "10.0.19041.0", 16 | "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.29.30037/bin/Hostx64/x64/cl.exe", 17 | "cStandard": "c17", 18 | "cppStandard": "c++20", 19 | "intelliSenseMode": "windows-msvc-x86" 20 | } 21 | ], 22 | "version": 4 23 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch SS", 9 | "type": "cppvsdbg", 10 | "request": "launch", 11 | "program": "${env:GTA_SS_DIR}/gta_sa.exe", 12 | "args": [], 13 | "stopAtEntry": false, 14 | "cwd": "${env:GTA_SS_DIR}", 15 | "environment": [], 16 | "console": "internalConsole" 17 | }, 18 | { 19 | "name": "Launch SA", 20 | "type": "cppvsdbg", 21 | "request": "launch", 22 | "program": "${env:GTA_SA_DIR}/gta_sa.exe", 23 | "args": [], 24 | "stopAtEntry": false, 25 | "cwd": "${env:GTA_SA_DIR}", 26 | "environment": [], 27 | "console": "internalConsole" 28 | }, 29 | { 30 | "name": "Launch VC", 31 | "type": "cppvsdbg", 32 | "request": "launch", 33 | "program": "${env:GTA_VC_DIR}/gta-vc.exe", 34 | "args": [], 35 | "stopAtEntry": false, 36 | "cwd": "${env:GTA_VC_DIR}", 37 | "environment": [], 38 | "console": "internalConsole" 39 | }, 40 | { 41 | "name": "Launch III", 42 | "type": "cppvsdbg", 43 | "request": "launch", 44 | "program": "${env:GTA_III_DIR}/Gta3.exe", 45 | "args": [], 46 | "stopAtEntry": false, 47 | "cwd": "${env:GTA_III_DIR}", 48 | "environment": [], 49 | "console": "internalConsole" 50 | }, 51 | { 52 | "name": "Attach", 53 | "type": "cppvsdbg", 54 | "request": "attach", 55 | "processId": "${command:pickProcess}" 56 | } 57 | ] 58 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "algorithm": "cpp", 4 | "chrono": "cpp", 5 | "functional": "cpp", 6 | "memory": "cpp", 7 | "thread": "cpp", 8 | "xmemory": "cpp", 9 | "iosfwd": "cpp", 10 | "array": "cpp", 11 | "atomic": "cpp", 12 | "bit": "cpp", 13 | "cctype": "cpp", 14 | "charconv": "cpp", 15 | "clocale": "cpp", 16 | "cmath": "cpp", 17 | "compare": "cpp", 18 | "concepts": "cpp", 19 | "condition_variable": "cpp", 20 | "cstddef": "cpp", 21 | "cstdint": "cpp", 22 | "cstdio": "cpp", 23 | "cstdlib": "cpp", 24 | "cstring": "cpp", 25 | "ctime": "cpp", 26 | "cwchar": "cpp", 27 | "exception": "cpp", 28 | "filesystem": "cpp", 29 | "format": "cpp", 30 | "forward_list": "cpp", 31 | "fstream": "cpp", 32 | "initializer_list": "cpp", 33 | "iomanip": "cpp", 34 | "ios": "cpp", 35 | "iostream": "cpp", 36 | "istream": "cpp", 37 | "iterator": "cpp", 38 | "limits": "cpp", 39 | "list": "cpp", 40 | "locale": "cpp", 41 | "map": "cpp", 42 | "mutex": "cpp", 43 | "new": "cpp", 44 | "numeric": "cpp", 45 | "optional": "cpp", 46 | "ostream": "cpp", 47 | "ratio": "cpp", 48 | "shared_mutex": "cpp", 49 | "sstream": "cpp", 50 | "stdexcept": "cpp", 51 | "stop_token": "cpp", 52 | "streambuf": "cpp", 53 | "string": "cpp", 54 | "system_error": "cpp", 55 | "tuple": "cpp", 56 | "type_traits": "cpp", 57 | "typeinfo": "cpp", 58 | "unordered_map": "cpp", 59 | "utility": "cpp", 60 | "valarray": "cpp", 61 | "vector": "cpp", 62 | "xfacet": "cpp", 63 | "xhash": "cpp", 64 | "xiosbase": "cpp", 65 | "xlocale": "cpp", 66 | "xlocbuf": "cpp", 67 | "xlocinfo": "cpp", 68 | "xlocmes": "cpp", 69 | "xlocmon": "cpp", 70 | "xlocnum": "cpp", 71 | "xloctime": "cpp", 72 | "xstddef": "cpp", 73 | "xstring": "cpp", 74 | "xtr1common": "cpp", 75 | "xtree": "cpp", 76 | "xutility": "cpp", 77 | "*.rh": "cpp", 78 | "any": "cpp", 79 | "deque": "cpp", 80 | "stack": "cpp" 81 | } 82 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Build Debug", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/tools/Debug.bat", 10 | "presentation": { 11 | "echo": true, 12 | "reveal": "always", 13 | "focus": false, 14 | "panel": "shared", 15 | "showReuseMessage": false, 16 | "clear": true 17 | }, 18 | "group": { 19 | "kind": "build", 20 | "isDefault": true 21 | }, 22 | "windows": { 23 | "options": { 24 | "shell": { 25 | "executable": "cmd.exe", 26 | "args": [ 27 | "/d", "/c" 28 | ] 29 | } 30 | } 31 | }, 32 | }, 33 | { 34 | "label": "Build Release", 35 | "type": "shell", 36 | "command": "${workspaceFolder}/tools/Release.bat", 37 | "presentation": { 38 | "echo": true, 39 | "reveal": "always", 40 | "focus": false, 41 | "panel": "shared", 42 | "showReuseMessage": false, 43 | "clear": true 44 | }, 45 | "group": { 46 | "kind": "build", 47 | "isDefault": true 48 | }, 49 | "windows": { 50 | "options": { 51 | "shell": { 52 | "executable": "cmd.exe", 53 | "args": [ 54 | "/d", "/c" 55 | ] 56 | } 57 | } 58 | }, 59 | }, 60 | { 61 | "label": "Build Debug CLEO", 62 | "type": "shell", 63 | "command": "${workspaceFolder}/tools/DebugCleo.bat", 64 | "presentation": { 65 | "echo": true, 66 | "reveal": "always", 67 | "focus": false, 68 | "panel": "shared", 69 | "showReuseMessage": false, 70 | "clear": true 71 | }, 72 | "group": { 73 | "kind": "build", 74 | "isDefault": true 75 | }, 76 | "windows": { 77 | "options": { 78 | "shell": { 79 | "executable": "cmd.exe", 80 | "args": [ 81 | "/d", "/c" 82 | ] 83 | } 84 | } 85 | }, 86 | }, 87 | { 88 | "label": "Build Release CLEO", 89 | "type": "shell", 90 | "command": "${workspaceFolder}/tools/ReleaseCleo.bat", 91 | "presentation": { 92 | "echo": true, 93 | "reveal": "always", 94 | "focus": false, 95 | "panel": "shared", 96 | "showReuseMessage": false, 97 | "clear": true 98 | }, 99 | "group": { 100 | "kind": "build", 101 | "isDefault": true 102 | }, 103 | "windows": { 104 | "options": { 105 | "shell": { 106 | "executable": "cmd.exe", 107 | "args": [ 108 | "/d", "/c" 109 | ] 110 | } 111 | } 112 | }, 113 | }, 114 | { 115 | "label": "Build Debug64", 116 | "type": "shell", 117 | "command": "${workspaceFolder}/tools/Debug64.bat", 118 | "presentation": { 119 | "echo": true, 120 | "reveal": "always", 121 | "focus": false, 122 | "panel": "shared", 123 | "showReuseMessage": false, 124 | "clear": true 125 | }, 126 | "group": { 127 | "kind": "build", 128 | "isDefault": true 129 | }, 130 | "windows": { 131 | "options": { 132 | "shell": { 133 | "executable": "cmd.exe", 134 | "args": [ 135 | "/d", "/c" 136 | ] 137 | } 138 | } 139 | }, 140 | }, 141 | { 142 | "label": "Build Release64", 143 | "type": "shell", 144 | "command": "${workspaceFolder}/tools/Release64.bat", 145 | "presentation": { 146 | "echo": true, 147 | "reveal": "always", 148 | "focus": false, 149 | "panel": "shared", 150 | "showReuseMessage": false, 151 | "clear": true 152 | }, 153 | "group": { 154 | "kind": "build", 155 | "isDefault": true 156 | }, 157 | "windows": { 158 | "options": { 159 | "shell": { 160 | "executable": "cmd.exe", 161 | "args": [ 162 | "/d", "/c" 163 | ] 164 | } 165 | } 166 | }, 167 | }, 168 | { 169 | "label": "Format Code", 170 | "type": "shell", 171 | "command": "${workspaceFolder}/tools/FormatCode.bat", 172 | "presentation": { 173 | "echo": true, 174 | "reveal": "always", 175 | "focus": false, 176 | "panel": "shared", 177 | "showReuseMessage": false, 178 | "clear": true 179 | }, 180 | "group": { 181 | "kind": "build", 182 | "isDefault": true 183 | }, 184 | "windows": { 185 | "options": { 186 | "shell": { 187 | "executable": "cmd.exe", 188 | "args": [ 189 | "/d", "/c" 190 | ] 191 | } 192 | } 193 | }, 194 | }, 195 | ] 196 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ImGuiRedux 2 | [Dear ImGui](https://github.com/ocornut/imgui) bindings for [CLEORedux](https://re.cleo.li/). Check out the example script [here](https://github.com/user-grinch/ImGuiRedux/blob/master/resource/imgui_test.js) & download binaries from [here](https://github.com/user-grinch/ImGuiRedux/releases) 3 | 4 | ## Supported Games 5 | - GTA III 6 | - GTA III DE 7 | - GTA Vice City 8 | - GTA Vice City DE 9 | - GTA San Andreas 10 | - GTA San Andreas DE 11 | - GTA 4 Complete Edition 12 | - Bully Scholarship Edition 13 | 14 | ## Versions 15 | - ImGuiCleoWin32 -> For CLEO5 (Supports GTA SA). Only required if you use ImGui in .cs scripts. 16 | - ImGuiReduxWin32 -> For CLEORedux (Supports 32 bit games). GTA SA Support is also included. 17 | - ImGuiReduxWin64 -> For CLEORedux (Supports 64 bit games) 18 | 19 | 20 | ### Installation 21 | 1. Install [ASI Loader](https://github.com/ThirteenAG/Ultimate-ASI-Loader/releases) & [ImGuiRedux x86](https://github.com/user-grinch/ImGuiRedux/releases/tag/Win32-latest) 22 | 3. For GTAs install [SilentPatch](https://gtaforums.com/topic/669045-silentpatch/) 23 | 4. For GTA III & VC install [d3d8to9 Wrapper](https://github.com/crosire/d3d8to9/releases) 24 | 25 | ## Unknown hosts 26 | Unknown hosts are basically untested games. They may or may not work on per game basis. Use it at your own risk!
27 | **PS: Let me know if your X game works. I'll add it in the list above.** 28 | 29 | Below version of DirectX games are supported, 30 | 1. D3D8 (with [wrapper](https://github.com/user-grinch/ImGuiRedux/blob/master/resource/d3d8.dll)) 31 | 2. D3D9 32 | 3. D3D11 33 | 4. OpenGL3 (Soon) 34 | 35 | ### Installation 36 | 1. Install your required version of [ASI Loader](https://github.com/ThirteenAG/Ultimate-ASI-Loader/releases) & [ImGuiRedux](https://github.com/user-grinch/ImGuiRedux/releases/) (x86 or x64) 37 | 2. Cross your fingers and try it in game! 38 | 39 | More info [here](https://re.cleo.li/docs/en/embedding.html) 40 | 41 | -------------------------------------------------------------------------------- /examples/cleo5/example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/examples/cleo5/example.jpg -------------------------------------------------------------------------------- /examples/cleo5/imgui_test.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/examples/cleo5/imgui_test.cs -------------------------------------------------------------------------------- /examples/cleo5/imgui_test.txt: -------------------------------------------------------------------------------- 1 | // 2 | // ImGuiCleo Example Script 3 | // 4 | {$CLEO} 5 | {$USE CLEO} 6 | {$USE imgui} 7 | 8 | const TOGGLE_KEY = 116 // F5 9 | int $gShowWindow = 0 10 | int $gVersionInfo = 0 11 | int $gRadioBtn = 1 12 | int $gTimerExample = 0 13 | int $gPrevTimer = 0 14 | int $gComboSelection = 1 15 | int $gImage = ImGui.LoadImage("cleo\example.jpg") 16 | 17 | while true 18 | /* 19 | This must always be 0 to render ImGui each frame 20 | If you need to wait for something use timers instead, 21 | example below 22 | */ 23 | wait 0 24 | 25 | 26 | /* 27 | All ImGui code must be wrapped inside the BeginFrame() .. EndFrame() 28 | You need to pass a "UNIQUE ID" for the frame name. 29 | Use something that's unlikely to be used by any other scripts 30 | */ 31 | ImGui.BeginFrame("IMGUI_CLEO_DEMO") 32 | ImGui.SetCursorVisible($gShowWindow) 33 | 34 | if $gShowWindow == 1 35 | then 36 | ImGui.SetNextWindowSize(350.0, 600.0, ImGuiCond.Once) 37 | $gShowWindow = ImGui.Begin("ImGuiCleo Demo Window", $gShowWindow, 0, 0, 0, 0) 38 | 39 | float $reduxVer = ImGui.GetPluginVersion() 40 | s$imguiVer = ImGui.GetVersion() 41 | int $fps = Game.GetFramerate() 42 | 43 | ImGui.Spacing() 44 | 45 | if $gVersionInfo == 1 46 | then 47 | ImGui.Columns(2) 48 | Text.StringFormat(s$temp, "ImGui: %s", s$imguiVer) 49 | ImGui.Text(s$temp) 50 | Text.StringFormat(s$temp, "Framerate: %d", $fps) 51 | ImGui.Text(s$temp) 52 | ImGui.NextColumn() 53 | Text.StringFormat(s$temp, "CLEO: %f", $reduxVer) 54 | ImGui.Text(s$temp) 55 | ImGui.Columns(1) 56 | ImGui.Spacing() 57 | end 58 | 59 | ImGui.BeginChild("WindowChild") 60 | 61 | int $tab = ImGui.Tabs("TabBar", "Checkbox,Button,Input,Text,Styles") 62 | 63 | if $tab == 0 64 | then 65 | ImGui.Spacing() 66 | ImGui.Columns(2) 67 | $gVersionInfo = ImGui.Checkbox("Show version info", $gVersionInfo) 68 | ImGui.NextColumn() 69 | $gTimerExample = ImGui.Checkbox("Show timer example", $gTimerExample) 70 | ImGui.Columns(1) 71 | ImGui.Spacing() 72 | end 73 | 74 | 75 | if $tab == 1 76 | then 77 | ImGui.Spacing() 78 | if ImGui.CollapsingHeader("Arrow buttons") 79 | then 80 | ImGui.ButtonArrow("Left", 0) 81 | ImGui.SameLine() 82 | ImGui.ButtonArrow("Right", 1) 83 | ImGui.SameLine() 84 | ImGui.ButtonArrow("Up", 2) 85 | ImGui.SameLine() 86 | ImGui.ButtonArrow("Down", 3) 87 | 88 | ImGui.Separator() 89 | ImGui.Spacing() 90 | end 91 | 92 | if ImGui.CollapsingHeader("Radio buttons") 93 | then 94 | $gRadioBtn = ImGui.RadioButton("RB1", $gRadioBtn, 1) 95 | ImGui.SameLine() 96 | $gRadioBtn = ImGui.RadioButton("RB2", $gRadioBtn, 2) 97 | ImGui.SameLine() 98 | $gRadioBtn = ImGui.RadioButton("RB3", $gRadioBtn, 3) 99 | ImGui.Spacing() 100 | end 101 | 102 | if ImGui.CollapsingHeader("Regular buttons") 103 | then 104 | ImGui.GetScalingSize("S0", 2, 0, $szX, $szY) 105 | if ImGui.Button("Normal button", $szX, $szY) 106 | then 107 | Text.PrintString("Normal button was pressed", 1000) 108 | end 109 | ImGui.SameLine() 110 | if ImGui.ButtonImage("Image Button", $gImage, $szX, $szY) 111 | then 112 | Text.PrintString("Image Button was pressed", 1000) 113 | end 114 | 115 | ImGui.Spacing() 116 | 117 | float $szX = 0 118 | float $szY = 0 119 | $szX, $szY = ImGui.GetScalingSize("S1", 3, 0) 120 | if ImGui.ButtonColored("CB 1", 1.0, 0.0, 0.0, 1.0, $szX, $szY) 121 | then 122 | Text.PrintString("Color button 1 was pressed", 1000) 123 | end 124 | ImGui.SameLine() 125 | if ImGui.ButtonColored("CB 2", 0.0, 1.0, 0.0, 1.0, $szX, $szY) 126 | then 127 | Text.PrintString("Color button 2 was pressed", 1000) 128 | end 129 | ImGui.SameLine() 130 | if ImGui.ButtonColored("CB 3", 0.0, 0.0, 1.0, 1.0, $szX, $szY) 131 | then 132 | Text.PrintString("Color button 3 was pressed", 1000) 133 | end 134 | 135 | ImGui.GetScalingSize("S2", 1, 0, $szX, $szY) 136 | ImGui.Text("Tip:\n\tClick the below area") 137 | if ImGui.ButtonInvisible("Invis button", $szX, $szY) 138 | then 139 | Text.PrintString("Invisible button was pressed", 1000) 140 | end 141 | 142 | if ImGui.IsItemHovered("HOver") 143 | then 144 | ImGui.Text("Hovering invisible button") 145 | end 146 | 147 | ImGui.Spacing() 148 | ImGui.Separator() 149 | end 150 | end 151 | 152 | ImGui.Spacing() 153 | 154 | // Input and Slider example 155 | if $tab == 2 156 | then 157 | ImGui.Spacing() 158 | 1@ = ImGui.InputInt("Int input", 420, 0, 1000) 159 | 1@ = ImGui.InputFloat("Float input", 69.9, 0.0, 100.0) 160 | ImGui.Spacing() 161 | 1@ = ImGui.SliderInt("Int slider", 5, 0, 10) 162 | 1@ = ImGui.SliderFloat("Float slider", 5.0, 0.0, 10.0) 163 | ImGui.Spacing() 164 | s$text = ImGui.InputText("Text input widget") 165 | ImGui.Spacing() 166 | 167 | float $szX = 0 168 | float $szY = 0 169 | $szX, $szY = ImGui.GetScalingSize("S012", 2, 0) 170 | if ImGui.Button("Rest Inputs", $szX, $szY) 171 | then 172 | ImGui.SetItemValueInt("Int input", 420) 173 | ImGui.SetItemValueInt("Int slider", 5) 174 | end 175 | ImGui.SameLine() 176 | if ImGui.Button("Rest Sliders", $szX, $szY) 177 | then 178 | ImGui.SetItemValueFloat("Float input", 69.9) 179 | ImGui.SetItemValueFloat("Float slider", 5.0) 180 | end 181 | 182 | ImGui.Dummy(0.0, 20.0) 183 | 184 | float $r = 0 185 | float $g = 0 186 | float $b = 0 187 | float $a = 0 188 | $r, $g, $b, $a = ImGui.ColorPicker("Color Picker") 189 | ImGui.ButtonColored("COLORBTN", $r, $g, $b, $a, 70.0, 30.0) 190 | 191 | ImGui.Dummy(0.0, 10.0) 192 | ImGui.Text("Text input: " + text) 193 | 194 | $gComboSelection = ImGui.ComboBox("Combo", "Option1,Option2,Option3", $gComboSelection) 195 | end 196 | 197 | if $tab == 3 198 | then 199 | ImGui.Spacing() 200 | ImGui.Text("A little brown fox jumps over the lazy dog") 201 | ImGui.TextDisabled("A little brown fox jumps over the lazy dog") 202 | ImGui.TextColored("A little brown fox jumps over the lazy dog", 1.0, 0.0, 0.0, 1.0) 203 | ImGui.TextWithBullet("A little brown fox jumps over the lazy dog") 204 | ImGui.Spacing() 205 | ImGui.TextWrapped("A little brown fox jumps over the lazy dog. A little brown fox jumps over the lazy dog. A little brown fox jumps over the lazy dog") 206 | end 207 | 208 | if $tab == 4 209 | then 210 | ImGui.Spacing() 211 | ImGui.Text("Red checkbox") 212 | ImGui.Spacing() 213 | ImGui.PushStyleColor(ImGuiCol.FrameBg, 200, 0, 0, 255) 214 | ImGui.PushStyleColor(ImGuiCol.FrameBgActive, 90, 0, 0, 255) 215 | ImGui.PushStyleColor(ImGuiCol.FrameBgHovered, 120, 0, 0, 255) 216 | $gVersionInfo = ImGui.Checkbox("Show version info", $gVersionInfo) 217 | ImGui.PopStyleColor(3) 218 | ImGui.Spacing() 219 | ImGui.Text("Button with custom style") 220 | ImGui.Spacing() 221 | 222 | ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 10.0) 223 | 224 | float $szX = 0 225 | float $szY = 0 226 | $szX, $szY = ImGui.GetScalingSize("S012", 2, 0) 227 | if ImGui.Button("Rounded button", $szX, $szY) 228 | then 229 | Text.PrintString("Rounded button was pressed", 1000) 230 | end 231 | ImGui.PopStyleVar(1) 232 | 233 | ImGui.SameLine() 234 | if ImGui.Button("Regular button", $szX, $szY) 235 | then 236 | Text.PrintString("Regular button was pressed", 1000) 237 | end 238 | end 239 | 240 | ImGui.EndChild() 241 | 242 | ImGui.End() 243 | end 244 | ImGui.EndFrame() 245 | 246 | 247 | // Timer example 248 | // This code has 5 second delay 249 | float $delta = TIMERA - $gPrevTimer 250 | if and 251 | $gTimerExample > 0 252 | $delta > 5000 253 | then 254 | Text.PrintString("Timer test message", 1000) 255 | $gPrevTimer = TIMERA 256 | end 257 | 258 | if Pad.IsKeyPressed(TOGGLE_KEY) 259 | then 260 | while Pad.IsKeyPressed(TOGGLE_KEY) 261 | wait 0 262 | end 263 | 264 | if $gShowWindow == 1 265 | then 266 | $gShowWindow = 0 267 | else 268 | $gShowWindow = 1 269 | end 270 | end 271 | end 272 | 273 | 274 | -------------------------------------------------------------------------------- /examples/redux/imgui_test/example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/examples/redux/imgui_test/example.jpg -------------------------------------------------------------------------------- /examples/redux/imgui_test/index.js: -------------------------------------------------------------------------------- 1 | /// 2 | // 3 | // ImGuiRedux Example Script 4 | // 5 | import { ImGuiCol, ImGuiStyleVar } from "../.config/enums"; 6 | 7 | const TOGGLE_KEY = 116 // F5 8 | var gShowWindow = 0 9 | var gVersionInfo = 0 10 | var gRadioBtn = 1 11 | var gTimerExample = 0 12 | var gPrevTimer = 0 13 | var gComboSelection = 1 14 | var gImage = ImGui.LoadImage("cleo/imgui_test/example.jpg") 15 | 16 | function textBox(text) 17 | { 18 | if (["gta3", "vc", "sa", "gta3_unreal", "vc_unreal", "sa_unreal"].includes(HOST)) 19 | { 20 | showTextBox(text) 21 | } 22 | else 23 | { 24 | ImGui.SetMessage(text) 25 | } 26 | } 27 | 28 | while (true) 29 | { 30 | /* 31 | This must always be 0 to render ImGui each frame 32 | If you need to wait for something use timers instead, 33 | example below 34 | */ 35 | wait(0) 36 | 37 | 38 | /* 39 | All ImGui code must be wrapped inside the BeginFrame() .. EndFrame() 40 | You need to pass a "UNIQUE ID" for the frame name. 41 | Use something that's unlikely to be used by any other scripts 42 | */ 43 | ImGui.BeginFrame("IMGUI_DEMO") 44 | ImGui.SetCursorVisible(gShowWindow) 45 | 46 | if (gShowWindow) 47 | { 48 | ImGui.SetNextWindowSize(350.0, 600.0, 2) // 2 = ImGuiCond_Once 49 | gShowWindow = ImGui.Begin("ImGuiRedux Demo Window", gShowWindow, 0, 0, 0, 0) 50 | 51 | let reduxVer = ImGui.GetPluginVersion() 52 | let imguiVer = ImGui.GetVersion() 53 | let fps = Game.GetFramerate() 54 | 55 | ImGui.Spacing() 56 | 57 | if (gVersionInfo) 58 | { 59 | ImGui.Columns(2) 60 | ImGui.Text("ImGui: " + imguiVer) 61 | ImGui.Text("Framerate: " + fps) 62 | ImGui.NextColumn() 63 | ImGui.Text("Redux: " + reduxVer.toFixed(2)) 64 | ImGui.Columns(1) 65 | ImGui.Spacing() 66 | } 67 | 68 | ImGui.BeginChild("WindowChild") 69 | 70 | let tab = ImGui.Tabs("TabBar", "Checkbox,Button,Input,Text,Styles") 71 | 72 | if (tab == 0) 73 | { 74 | ImGui.Spacing() 75 | ImGui.Columns(2) 76 | gVersionInfo = ImGui.Checkbox("Show version info", gVersionInfo) 77 | ImGui.NextColumn() 78 | gTimerExample = ImGui.Checkbox("Show timer example", gTimerExample) 79 | ImGui.Columns(1) 80 | ImGui.Spacing() 81 | } 82 | 83 | 84 | if (tab == 1) 85 | { 86 | ImGui.Spacing() 87 | if (ImGui.CollapsingHeader("Arrow buttons")) 88 | { 89 | ImGui.ButtonArrow("Left", 0) 90 | ImGui.SameLine() 91 | ImGui.ButtonArrow("Right", 1) 92 | ImGui.SameLine() 93 | ImGui.ButtonArrow("Up", 2) 94 | ImGui.SameLine() 95 | ImGui.ButtonArrow("Down", 3) 96 | 97 | ImGui.Separator() 98 | ImGui.Spacing() 99 | } 100 | if (ImGui.CollapsingHeader("Radio buttons")) 101 | { 102 | gRadioBtn = ImGui.RadioButton("RB1", gRadioBtn, 1) 103 | ImGui.SameLine() 104 | gRadioBtn = ImGui.RadioButton("RB2", gRadioBtn, 2) 105 | ImGui.SameLine() 106 | gRadioBtn = ImGui.RadioButton("RB3", gRadioBtn, 3) 107 | ImGui.Spacing() 108 | let str = "Current Button: " + gRadioBtn 109 | ImGui.Text(str) 110 | 111 | ImGui.Separator() 112 | ImGui.Spacing() 113 | } 114 | if (ImGui.CollapsingHeader("Regular buttons")) 115 | { 116 | let size = ImGui.GetScalingSize("S0", 2, 0) 117 | if (ImGui.Button("Normal button", size.x, size.y*2)) 118 | { 119 | textBox("Normal button was pressed") 120 | } 121 | ImGui.SameLine() 122 | if (ImGui.ButtonImage("Image Button", gImage, size.x, size.y*2)) 123 | { 124 | textBox("Image Button was pressed") 125 | } 126 | 127 | ImGui.Spacing() 128 | 129 | size = ImGui.GetScalingSize("S1", 3, 0) 130 | if (ImGui.ButtonColored("CB 1", 1.0, 0.0, 0.0, 1.0, size.x, size.y)) 131 | { 132 | textBox("Color button 1 was pressed") 133 | } 134 | ImGui.SameLine() 135 | if (ImGui.ButtonColored("CB 2", 0.0, 1.0, 0.0, 1.0, size.x, size.y)) 136 | { 137 | textBox("Color button 2 was pressed") 138 | } 139 | ImGui.SameLine() 140 | if (ImGui.ButtonColored("CB 3", 0.0, 0.0, 1.0, 1.0, size.x, size.y)) 141 | { 142 | textBox("Color button 3 was pressed") 143 | } 144 | 145 | size = ImGui.GetScalingSize("S2", 1, 0) 146 | ImGui.Text("Tip:\n\tClick the below area") 147 | if (ImGui.ButtonInvisible("Invis button", size.x, size.y)) 148 | { 149 | textBox("Invisible button was pressed") 150 | } 151 | if (ImGui.IsItemHovered("HOver")) 152 | { 153 | ImGui.Text("Hovering invisible button") 154 | } 155 | 156 | ImGui.Spacing() 157 | ImGui.Separator() 158 | } 159 | } 160 | 161 | ImGui.Spacing() 162 | 163 | // Input and Slider example 164 | if (tab == 2) 165 | { 166 | ImGui.Spacing() 167 | ImGui.InputInt("Int input", 420, 0, 1000) 168 | ImGui.InputFloat("Float input", 69.9, 0.0, 100.0) 169 | ImGui.Spacing() 170 | ImGui.SliderInt("Int slider", 5, 0, 10) 171 | ImGui.SliderFloat("Float slider", 5.0, 0.0, 10.0) 172 | ImGui.Spacing() 173 | let text = ImGui.InputText("Text input widget") 174 | ImGui.Spacing() 175 | 176 | let size = ImGui.GetScalingSize("S012", 2, 0) 177 | if (ImGui.Button("Rest Inputs", size.x, size.y)) 178 | { 179 | ImGui.SetItemValueInt("Int input", 420) 180 | ImGui.SetItemValueInt("Int slider", 5) 181 | } 182 | ImGui.SameLine() 183 | if (ImGui.Button("Rest Sliders", size.x, size.y)) 184 | { 185 | ImGui.SetItemValueFloat("Float input", 69.9) 186 | ImGui.SetItemValueFloat("Float slider", 5.0) 187 | } 188 | 189 | ImGui.Dummy(0, 20) 190 | var col = ImGui.ColorPicker("Color Picker", 0) 191 | ImGui.ButtonColored("COLORBTN", col.red, col.green, col.blue, col.alpha, 70.0, 30.0) 192 | 193 | ImGui.Dummy(0, 10) 194 | ImGui.Text("Text input: " + text) 195 | 196 | gComboSelection = ImGui.ComboBox("Combo", "Option1,Option2,Option3", gComboSelection) 197 | let str = "Selection: " + gComboSelection 198 | ImGui.Text(str) 199 | } 200 | 201 | if (tab == 3) 202 | { 203 | ImGui.Spacing() 204 | ImGui.Text("A little brown fox jumps over the lazy dog") 205 | ImGui.TextDisabled("A little brown fox jumps over the lazy dog") 206 | ImGui.TextColored("A little brown fox jumps over the lazy dog", 1.0, 0.0, 0.0, 1.0) 207 | ImGui.TextWithBullet("A little brown fox jumps over the lazy dog") 208 | ImGui.Spacing() 209 | ImGui.TextWrapped("A little brown fox jumps over the lazy dog. A little brown fox jumps over the lazy dog. A little brown fox jumps over the lazy dog") 210 | } 211 | 212 | if (tab == 4) 213 | { 214 | ImGui.Spacing() 215 | ImGui.Text("Red checkbox") 216 | ImGui.Spacing() 217 | ImGui.PushStyleColor(ImGuiCol.FrameBg, 200, 0, 0, 255) 218 | ImGui.PushStyleColor(ImGuiCol.FrameBgActive, 90, 0, 0, 255) 219 | ImGui.PushStyleColor(ImGuiCol.FrameBgHovered, 120, 0, 0, 255) 220 | gVersionInfo = ImGui.Checkbox("Show version info", gVersionInfo) 221 | ImGui.PopStyleColor(3) 222 | ImGui.Spacing() 223 | ImGui.Text("Button with custom style") 224 | ImGui.Spacing() 225 | 226 | ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 10) 227 | let size = ImGui.GetScalingSize("S012", 2, 0) 228 | if (ImGui.Button("Rounded button", size.x, size.y*2)) 229 | { 230 | textBox("Rounded button was pressed") 231 | } 232 | ImGui.PopStyleVar(1) 233 | 234 | ImGui.SameLine() 235 | if (ImGui.Button("Regular button", size.x, size.y*2)) 236 | { 237 | textBox("Regular button was pressed") 238 | } 239 | } 240 | 241 | ImGui.EndChild() 242 | 243 | ImGui.End() 244 | } 245 | ImGui.EndFrame() 246 | 247 | 248 | // Timer example 249 | // This code has 5 second delay 250 | if (gTimerExample && (TIMERA - gPrevTimer > 5000)) 251 | { 252 | textBox("Timer test message") 253 | gPrevTimer = TIMERA 254 | } 255 | 256 | if (Pad.IsKeyDown(TOGGLE_KEY)) 257 | { 258 | gShowWindow = !gShowWindow 259 | } 260 | } 261 | 262 | 263 | -------------------------------------------------------------------------------- /include/cleo/CLEO.h: -------------------------------------------------------------------------------- 1 | /* 2 | CLEO 5 header file 3 | Copyright (c) 2023 Alien, Deji, Junior_Djjr, Miran, Seemann 4 | */ 5 | #pragma once 6 | 7 | #ifdef __cplusplus 8 | #include 9 | #endif 10 | #include 11 | 12 | #define CLEO_VERSION_MAIN 5 13 | #define CLEO_VERSION_MAJOR 0 14 | #define CLEO_VERSION_MINOR 0 15 | 16 | #define CLEO_VERSION ((CLEO_VERSION_MAIN << 24)|(CLEO_VERSION_MAJOR << 16)|(CLEO_VERSION_MINOR << 8)) // 0x0v0v0v00 17 | 18 | #define __TO_STR(x) #x 19 | #define TO_STR(x) __TO_STR(x) 20 | #define CLEO_VERSION_STR "5.0.0-alpha.63" 21 | 22 | namespace CLEO 23 | { 24 | // result of CLEO_GetScriptVersion 25 | enum eCLEO_Version : DWORD 26 | { 27 | CLEO_VER_3 = 0x03000000, 28 | CLEO_VER_4_MIN = 0x04000000, 29 | CLEO_VER_4_2 = 0x04020000, 30 | CLEO_VER_4_3 = 0x04030000, 31 | CLEO_VER_4_4 = 0x04040000, 32 | CLEO_VER_4 = CLEO_VER_4_4, 33 | CLEO_VER_5 = 0x05000000, 34 | CLEO_VER_CUR = CLEO_VERSION 35 | }; 36 | 37 | // result of CLEO_GetGameVersion 38 | enum eGameVersion : int 39 | { 40 | GV_US10 = 0, // 1.0 us 41 | GV_US11 = 1, // 1.01 us - not supported 42 | GV_EU10 = 2, // 1.0 eu 43 | GV_EU11 = 3, // 1.01 eu 44 | GV_STEAM, 45 | GV_TOTAL, 46 | GV_UNK = -1 // any other 47 | }; 48 | 49 | // operand types 50 | enum eDataType : BYTE 51 | { 52 | DT_END, // variable args end marker 53 | DT_DWORD, // literal int 32 54 | DT_VAR, // globalVar $ 55 | DT_LVAR, // localVar @ 56 | DT_BYTE, // literal int 8 57 | DT_WORD, // literal int 16 58 | DT_FLOAT, // literal float 32 59 | DT_VAR_ARRAY, // globalArr $(,) 60 | DT_LVAR_ARRAY, // localArr @(,) 61 | DT_TEXTLABEL, // literal string up to 7 chars 62 | DT_VAR_TEXTLABEL, // globalVarSString s$ 63 | DT_LVAR_TEXTLABEL, // localVarSString @s 64 | DT_VAR_TEXTLABEL_ARRAY, // globalVarSStringArr s$(,) 65 | DT_LVAR_TEXTLABEL_ARRAY, // localVarSStringArr @s(,) 66 | DT_VARLEN_STRING, // literal vstring "" 67 | DT_STRING, // literal string up to 15 chars 68 | DT_VAR_STRING, // globalVarVString v$ 69 | DT_LVAR_STRING, // localVarVString @v 70 | DT_VAR_STRING_ARRAY, // globalVarStringArr v$(,) 71 | DT_LVAR_STRING_ARRAY, // localVarStringArr @v(,) 72 | DT_INVALID = 0xFF // CLEO internal 73 | }; 74 | 75 | enum eArrayDataType : BYTE 76 | { 77 | ADT_INT, // variable with integer 78 | ADT_FLOAT, // variable with integer 79 | ADT_TEXTLABEL, // variable with short string (8 char) 80 | ADT_STRING, // variable with long string (16 char) 81 | ADT_NONE = 0xFF // CLEO internal 82 | }; 83 | static const BYTE ArrayDataTypeMask = ADT_INT | ADT_FLOAT | ADT_TEXTLABEL | ADT_STRING; // array flags byte contains other info too. Type needs to be masked when read 84 | 85 | static const char* ToStr(eDataType type) 86 | { 87 | switch (type) 88 | { 89 | case DT_END: return "VArgEnd"; break; 90 | case DT_DWORD: return "Int32"; break; 91 | case DT_VAR: return "GlobVar"; break; 92 | case DT_LVAR: return "LocVar"; break; 93 | case DT_BYTE: return "Int8"; break; 94 | case DT_WORD: return "Int16"; break; 95 | case DT_FLOAT: return "Float32"; break; 96 | case DT_VAR_ARRAY: return "GlobVarArr"; break; 97 | case DT_LVAR_ARRAY: return "LocVarArr"; break; 98 | case DT_TEXTLABEL: return "STxt"; break; 99 | case DT_VAR_TEXTLABEL: return "GlobVarSTxt"; break; 100 | case DT_LVAR_TEXTLABEL: return "LocVarSTxt"; break; 101 | case DT_VAR_TEXTLABEL_ARRAY: return "GlobVarSTxtArr"; break; 102 | case DT_LVAR_TEXTLABEL_ARRAY: return "LocVarSTxtArr"; break; 103 | case DT_VARLEN_STRING: return "Txt"; break; 104 | case DT_STRING: return "LTxt"; break; 105 | case DT_VAR_STRING: return "GlobVarLTxt"; break; 106 | case DT_LVAR_STRING: return "LocVarLTxt"; break; 107 | case DT_VAR_STRING_ARRAY: return "GlobVarLTxtArr"; break; 108 | case DT_LVAR_STRING_ARRAY: return "LocVarLTxtArr"; break; 109 | default: return "corrupted"; 110 | } 111 | } 112 | static bool IsImmInteger(eDataType type) // immediate/literal integer in code like 42 113 | { 114 | switch (type) 115 | { 116 | case DT_BYTE: 117 | case DT_WORD: 118 | case DT_DWORD: 119 | return true; 120 | } 121 | return false; 122 | } 123 | static bool IsImmFloat(eDataType type) // immediate/literal float in code like 42.0 124 | { 125 | return type == DT_FLOAT; 126 | } 127 | static bool IsImmString(eDataType type) // immediate/literal string in code like "text" 128 | { 129 | switch (type) 130 | { 131 | case DT_STRING: 132 | case DT_TEXTLABEL: 133 | case DT_VARLEN_STRING: 134 | return true; 135 | } 136 | return false; 137 | } 138 | static bool IsVarString(eDataType type) // string variable 139 | { 140 | switch (type) 141 | { 142 | case DT_LVAR_TEXTLABEL: 143 | case DT_LVAR_TEXTLABEL_ARRAY: 144 | case DT_LVAR_STRING: 145 | case DT_LVAR_STRING_ARRAY: 146 | case DT_VAR_TEXTLABEL: 147 | case DT_VAR_TEXTLABEL_ARRAY: 148 | case DT_VAR_STRING: 149 | case DT_VAR_STRING_ARRAY: 150 | return true; 151 | } 152 | return false; 153 | } 154 | static bool IsVariable(eDataType type) // can carry int, float, pointer to text 155 | { 156 | switch (type) 157 | { 158 | case DT_VAR: 159 | case DT_VAR_ARRAY: 160 | case DT_LVAR: 161 | case DT_LVAR_ARRAY: 162 | return true; 163 | } 164 | return false; 165 | } 166 | static bool IsArray(eDataType type) 167 | { 168 | switch (type) 169 | { 170 | case DT_LVAR_TEXTLABEL_ARRAY: 171 | case DT_LVAR_STRING_ARRAY: 172 | case DT_VAR_TEXTLABEL_ARRAY: 173 | case DT_VAR_STRING_ARRAY: 174 | case DT_VAR_ARRAY: 175 | case DT_LVAR_ARRAY: 176 | return true; 177 | } 178 | return false; 179 | } 180 | static const char* ToKindStr(eDataType type, eArrayDataType arrType = ADT_NONE) 181 | { 182 | switch (type) 183 | { 184 | case DT_BYTE: 185 | case DT_WORD: 186 | case DT_DWORD: 187 | return "int"; break; 188 | 189 | case DT_FLOAT: 190 | return "float"; break; 191 | 192 | case DT_STRING: 193 | case DT_TEXTLABEL: 194 | case DT_LVAR_TEXTLABEL: 195 | case DT_LVAR_TEXTLABEL_ARRAY: 196 | case DT_LVAR_STRING: 197 | case DT_LVAR_STRING_ARRAY: 198 | case DT_VAR_TEXTLABEL: 199 | case DT_VAR_TEXTLABEL_ARRAY: 200 | case DT_VAR_STRING: 201 | case DT_VAR_STRING_ARRAY: 202 | case DT_VARLEN_STRING: 203 | return "string"; break; 204 | 205 | case DT_VAR: 206 | case DT_LVAR: 207 | return "variable"; break; 208 | 209 | case DT_VAR_ARRAY: 210 | case DT_LVAR_ARRAY: 211 | switch(arrType) 212 | { 213 | case ADT_INT: 214 | return "int"; break; 215 | 216 | case ADT_FLOAT: 217 | return "float"; break; 218 | 219 | case ADT_TEXTLABEL: 220 | case ADT_STRING: 221 | return "string"; break; 222 | 223 | default: return "variable"; 224 | } 225 | 226 | case DT_END: 227 | return "varArgEnd"; break; 228 | 229 | default: 230 | return "corrupted"; break; 231 | } 232 | } 233 | 234 | const size_t MAX_STR_LEN = 0xff; // max length of string type parameter 235 | 236 | union SCRIPT_VAR 237 | { 238 | DWORD dwParam; 239 | short wParam; 240 | WORD usParam; 241 | BYTE ucParam; 242 | char cParam; 243 | bool bParam; 244 | int nParam; 245 | float fParam; 246 | void* pParam; 247 | char* pcParam; 248 | }; 249 | 250 | enum eLogicalOperation : WORD 251 | { 252 | NONE = 0, // just replace 253 | 254 | AND_2 = 1, // AND operation on results of next two conditional opcodes 255 | AND_3, 256 | AND_4, 257 | AND_5, 258 | AND_6, 259 | AND_7, 260 | AND_END, 261 | 262 | OR_2 = 21, // OR operation on results of next two conditional opcodes 263 | OR_3, 264 | OR_4, 265 | OR_5, 266 | OR_6, 267 | OR_7, 268 | OR_END, 269 | }; 270 | static eLogicalOperation& operator--(eLogicalOperation& o) 271 | { 272 | if (o == eLogicalOperation::NONE) return o; // can not be decremented anymore 273 | if (o == eLogicalOperation::OR_2) return o = eLogicalOperation::NONE; 274 | 275 | auto val = static_cast(o); // to number 276 | val--; 277 | return o = static_cast(val); 278 | } 279 | 280 | // CLEO virtual path prefixes. Expandable with CLEO_ResolvePath 281 | const char DIR_GAME[] = "root:"; // game root directory 282 | const char DIR_USER[] = "userfiles:"; // game save directory 283 | const char DIR_SCRIPT[] = "."; // current script directory 284 | const char DIR_CLEO[] = "cleo:"; // game\cleo directory 285 | const char DIR_MODULES[] = "modules:"; // game\cleo\modules directory 286 | 287 | // argument of CLEO_RegisterCallback 288 | enum class eCallbackId : DWORD 289 | { 290 | GameBegin, // void WINAPI OnGameBegin(DWORD saveSlot); // -1 if not started from save 291 | GameProcess, // void WINAPI OnGameProcess(); // called once every frame during gameplay 292 | GameEnd, // void WINAPI OnGameEnd(); 293 | ScriptsLoaded, // void WINAPI OnScriptsLoaded(); 294 | ScriptsFinalize, // void WINAPI OnScriptsFinalize(); 295 | ScriptRegister, // void WINAPI OnScriptRegister(CRunningScript* pScript); // called after script creation 296 | ScriptUnregister, // void WINAPI OnScriptUnregister(CRunningScript* pScript); // called before script deletion 297 | ScriptProcess, // bool WINAPI OnScriptProcess(CRunningScript* pScript); // return false to skip this script processing 298 | ScriptOpcodeProcess, // OpcodeResult WINAPI OnScriptOpcodeProcess(CRunningScript* pScript, DWORD opcode); // return other than OR_NONE to signal that opcode was handled in the callback 299 | ScriptOpcodeProcessFinished, // OpcodeResult WINAPI OnScriptOpcodeProcessFinished(CRunningScript* pScript, DWORD opcode, OpcodeResult result); // return other than OR_NONE to overwrite original result 300 | ScriptDraw, // void WINAPI OnScriptDraw(bool beforeFade); 301 | DrawingFinished, // void WINAPI OnDrawingFinished(); // called after game rendered everything and before presenting screen buffer 302 | Log, // void OnLog(eLogLevel level, const char* msg); 303 | MainWindowFocus, // void WINAPI OnMainWindowFocus(bool active); // called when game main window focus changes 304 | }; 305 | 306 | // used by CLEO_Log and Log callback 307 | enum class eLogLevel : DWORD 308 | { 309 | None, 310 | Error, // errors and warnings 311 | Debug, // debug mode / user traces 312 | Default // all log messages 313 | }; 314 | 315 | enum OpcodeResult : char 316 | { 317 | OR_NONE = -2, 318 | OR_ERROR = -1, 319 | OR_CONTINUE = 0, 320 | OR_INTERRUPT = 1, 321 | }; 322 | 323 | typedef int SCRIPT_HANDLE; 324 | typedef SCRIPT_HANDLE HANDLE_ACTOR, ACTOR, HACTOR, PED, HPED, HANDLE_PED; 325 | typedef SCRIPT_HANDLE HANDLE_CAR, CAR, HCAR, VEHICLE, HVEHICLE, HANDLE_VEHICLE; 326 | typedef SCRIPT_HANDLE HANDLE_OBJECT, OBJECT, HOBJECT; 327 | 328 | #pragma pack(push,1) 329 | #ifdef __cplusplus 330 | class CRunningScript 331 | { 332 | public: 333 | #else 334 | struct CRunningScript 335 | { 336 | #endif 337 | CRunningScript* Next; // 0x00 next script in queue 338 | CRunningScript* Previous; // 0x04 previous script in queue 339 | char Name[8]; // 0x08 name of script, given by 03A4 opcode 340 | void* BaseIP; // 0x10 pointer to begin of script in memory 341 | BYTE* CurrentIP; // 0x14 current instruction pointer 342 | BYTE* Stack[8]; // 0x18 return stack for 0050, 0051 343 | WORD SP; // 0x38 current item in stack 344 | BYTE _pad3A[2]; // 0x3A padding 345 | SCRIPT_VAR LocalVar[32]; // 0x3C script's local variables 346 | DWORD Timers[2]; // 0xBC script's timers 347 | bool bIsActive; // 0xC4 is script active 348 | bool bCondResult; // 0xC5 condition result 349 | bool bUseMissionCleanup; // 0xC6 clean mission 350 | bool bIsExternal; // 0xC7 is thread external (from script.img) 351 | bool bTextBlockOverride; // 0xC8 352 | BYTE bExternalType; // 0xC9 353 | BYTE _padCA[2]; // 0xCA padding 354 | DWORD WakeTime; // 0xCC time, when script starts again after 0001 opcode 355 | eLogicalOperation LogicalOp;// 0xD0 opcode 00D6 parameter 356 | bool NotFlag; // 0xD2 opcode & 0x8000 != 0 357 | bool bWastedBustedCheck; // 0xD3 wasted_or_busted check flag 358 | bool bWastedOrBusted; // 0xD4 is player wasted or busted 359 | char _padD5[3]; // 0xD5 padding 360 | void* SceneSkipIP; // 0xD8 scene skip label ptr 361 | bool bIsMission; // 0xDC is this script mission 362 | WORD ScmFunction; // 0xDD CLEO's previous scmFunction id 363 | bool bIsCustom; // 0xDF is this CLEO script 364 | 365 | #ifdef __cplusplus 366 | public: 367 | CRunningScript() 368 | { 369 | strcpy(Name, "noname"); 370 | BaseIP = 0; 371 | Previous = 0; 372 | Next = 0; 373 | CurrentIP = 0; 374 | memset(Stack, 0, sizeof(Stack)); 375 | SP = 0; 376 | WakeTime = 0; 377 | bIsActive = 0; 378 | bCondResult = 0; 379 | bUseMissionCleanup = 0; 380 | bIsExternal = 0; 381 | bTextBlockOverride = 0; 382 | bExternalType = -1; 383 | memset(LocalVar, 0, sizeof(LocalVar)); 384 | LogicalOp = eLogicalOperation::NONE; 385 | NotFlag = 0; 386 | bWastedBustedCheck = 1; 387 | bWastedOrBusted = 0; 388 | SceneSkipIP = 0; 389 | bIsMission = 0; 390 | ScmFunction = 0; 391 | bIsCustom = 0; 392 | } 393 | 394 | bool IsActive() const { return bIsActive; } 395 | bool IsExternal() const { return bIsExternal; } 396 | bool IsMission() const { return bIsMission; } 397 | bool IsCustom() const { return bIsCustom; } // is this CLEO Script? 398 | std::string GetName() const { auto str = std::string(Name, Name + 8); str.resize(strlen(str.c_str())); return str; } // make sure it is always null terminated 399 | BYTE* GetBasePointer() const { return (BYTE*)BaseIP; } 400 | BYTE* GetBytePointer() const { return CurrentIP; } 401 | void SetIp(void* ip) { CurrentIP = (BYTE*)ip; } 402 | void SetBaseIp(void* ip) { BaseIP = ip; } 403 | CRunningScript* GetNext() const { return Next; } 404 | CRunningScript* GetPrev() const { return Previous; } 405 | void SetIsExternal(bool b) { bIsExternal = b; } 406 | void SetActive(bool b) { bIsActive = b; } 407 | OpcodeResult Suspend() { WakeTime = 0xFFFFFFFF; return OpcodeResult::OR_INTERRUPT; } // suspend script execution forever 408 | void SetNext(CRunningScript* v) { Next = v; } 409 | void SetPrev(CRunningScript* v) { Previous = v; } 410 | SCRIPT_VAR* GetVarPtr() { return LocalVar; } 411 | SCRIPT_VAR* GetVarPtr(int i) { return &LocalVar[i]; } 412 | int* GetIntVarPtr(int i) { return (int*)&LocalVar[i].dwParam; } 413 | int GetIntVar(int i) const { return LocalVar[i].dwParam; } 414 | void SetIntVar(int i, int v) { LocalVar[i].dwParam = v; } 415 | void SetFloatVar(int i, float v) { LocalVar[i].fParam = v; } 416 | char GetByteVar(int i) const { return LocalVar[i].bParam; } 417 | bool GetConditionResult() const { return bCondResult != 0; } 418 | bool GetNotFlag() const { return NotFlag; } 419 | void SetNotFlag(bool state) { NotFlag = state; } 420 | 421 | eDataType PeekDataType() const { return *(eDataType*)CurrentIP; } 422 | eArrayDataType PeekArrayDataType() const { BYTE t = *(CurrentIP + 1 + 2 + 2 + 1); t &= ArrayDataTypeMask; return (eArrayDataType) t; } // result valid only for array type params 423 | 424 | eDataType ReadDataType() { return (eDataType)ReadDataByte(); } 425 | short ReadDataVarIndex() { return ReadDataWord(); } 426 | short ReadDataArrayOffset() { return ReadDataWord(); } 427 | short ReadDataArrayIndex() { return ReadDataWord(); } 428 | short ReadDataArraySize() { return ReadDataByte(); } 429 | short ReadDataArrayFlags() { return ReadDataByte(); } 430 | 431 | void IncPtr(int n = 1) { CurrentIP += n; } 432 | int ReadDataByte() { char b = *CurrentIP; ++CurrentIP; return b; } 433 | short ReadDataWord() { short v = *(short*)CurrentIP; CurrentIP += 2; return v; } 434 | int ReadDataInt() { int i = *(int*)CurrentIP; CurrentIP += 4; return i; } 435 | 436 | void PushStack(BYTE* ptr) { Stack[SP++] = ptr; } 437 | BYTE* PopStack() { return Stack[--SP]; } 438 | 439 | WORD GetScmFunction() const { return ScmFunction; } 440 | void SetScmFunction(WORD id) { ScmFunction = id; } 441 | 442 | #endif // __cplusplus 443 | }; 444 | #pragma pack(pop) 445 | static_assert(sizeof(CRunningScript) == 0xE0, "Invalid size of CRunningScript!"); 446 | 447 | // alias for legacy use 448 | #ifdef __cplusplus 449 | typedef class CRunningScript CScriptThread; 450 | #else 451 | typedef struct CRunningScript CScriptThread; 452 | #endif 453 | 454 | typedef OpcodeResult (CALLBACK* _pOpcodeHandler)(CRunningScript*); 455 | typedef void(*FuncScriptDeleteDelegateT) (CRunningScript*); 456 | 457 | #ifdef __cplusplus 458 | extern "C" { 459 | #endif //__cplusplus 460 | 461 | DWORD WINAPI CLEO_GetVersion(); 462 | eGameVersion WINAPI CLEO_GetGameVersion(); 463 | 464 | BOOL WINAPI CLEO_RegisterOpcode(WORD opcode, _pOpcodeHandler callback); 465 | BOOL WINAPI CLEO_RegisterCommand(const char* commandName, _pOpcodeHandler callback); // uses cleo\.CONFIG\sa.json to obtain opcode number from name 466 | void WINAPI CLEO_RegisterCallback(eCallbackId id, void* func); 467 | 468 | 469 | // script utils 470 | void WINAPI CLEO_GetScriptInfoStr(CRunningScript* thread, bool currLineInfo, char* buf, DWORD bufSize); // short text for displaying in error\log messages 471 | void WINAPI CLEO_GetScriptParamInfoStr(int idexOffset, char* buf, DWORD bufSize); // short text with current+offset opcode parameter info (index and name if available) 472 | eCLEO_Version WINAPI CLEO_GetScriptVersion(const CRunningScript* thread); // compatibility mode 473 | LPCSTR WINAPI CLEO_GetScriptFilename(const CRunningScript* thread); // returns nullptr if provided script ptr is not valid 474 | 475 | LPCSTR WINAPI CLEO_GetScriptWorkDir(const CRunningScript* thread); 476 | void WINAPI CLEO_SetScriptWorkDir(CRunningScript* thread, const char* path); 477 | 478 | void WINAPI CLEO_SetThreadCondResult(CRunningScript* thread, BOOL result); 479 | void WINAPI CLEO_ThreadJumpAtLabelPtr(CRunningScript* thread, int labelPtr); 480 | 481 | int WINAPI CLEO_GetOperandType(const CRunningScript* thread); // peek parameter data type. Returns int for legacy reason, should be eDataType. 482 | DWORD WINAPI CLEO_GetVarArgCount(CRunningScript* thread); // peek remaining var-args count 483 | 484 | extern SCRIPT_VAR* opcodeParams; 485 | extern SCRIPT_VAR* missionLocals; 486 | 487 | SCRIPT_VAR* WINAPI CLEO_GetOpcodeParamsArray(); // get pointer to 'SCRIPT_VAR[32] opcodeParams'. Used by Retrieve/Record opcode params functions 488 | BYTE WINAPI CLEO_GetParamsHandledCount(); // number of already read/written opcode parameters since current opcode handler was called 489 | 490 | // param read 491 | SCRIPT_VAR* WINAPI CLEO_GetPointerToScriptVariable(CRunningScript* thread); // get pointer to the variable's data, nullptr if parameter is not variable. Advances script to next param 492 | void WINAPI CLEO_RetrieveOpcodeParams(CRunningScript* thread, int count); // read multiple params. Stored in opcodeParams array 493 | DWORD WINAPI CLEO_GetIntOpcodeParam(CRunningScript* thread); 494 | float WINAPI CLEO_GetFloatOpcodeParam(CRunningScript* thread); 495 | LPCSTR WINAPI CLEO_ReadStringOpcodeParam(CRunningScript* thread, char* buff = nullptr, int buffSize = 0); // read always null-terminated string into buffer, clamped to its size. If no buffer provided then internal, globally shared by all CLEO_ReadStringOpcodeParam calls, is used. Returns pointer to the result buffer or nullptr on fail 496 | LPCSTR WINAPI CLEO_ReadStringPointerOpcodeParam(CRunningScript* thread, char* buff = nullptr, int buffSize = 0); // read always null-terminated string into buffer, clamped to its size. If no buffer provided then internal, globally shared by all CLEO_ReadStringPointerOpcodeParam calls, is used. WARNING: returned pointer may differ from buff and contain string longer than buffSize (ptr to original data source) 497 | void WINAPI CLEO_ReadStringParamWriteBuffer(CRunningScript* thread, char** outBuf, int* outBufSize, BOOL* outNeedsTerminator); // get info about the string opcode param, so it can be written latter. If outNeedsTerminator is not 0 then whole bufSize can be used as text characters. Advances script to next param 498 | char* WINAPI CLEO_ReadParamsFormatted(CRunningScript* thread, const char* format, char* buf = nullptr, int bufSize = 0); // consumes all var-arg params and terminator 499 | // get param value without advancing the script 500 | DWORD WINAPI CLEO_PeekIntOpcodeParam(CRunningScript* thread); 501 | float WINAPI CLEO_PeekFloatOpcodeParam(CRunningScript* thread); 502 | SCRIPT_VAR* WINAPI CLEO_PeekPointerToScriptVariable(CRunningScript* thread); // get pointer to the variable's data, nullptr if parameter is not variable 503 | 504 | // param skip without reading 505 | void WINAPI CLEO_SkipOpcodeParams(CRunningScript* thread, int count); 506 | void WINAPI CLEO_SkipUnusedVarArgs(CRunningScript* thread); // for var-args opcodes. Should be called even when all params were read (to skip var-arg terminator) 507 | 508 | // param write 509 | void WINAPI CLEO_RecordOpcodeParams(CRunningScript* thread, int count); // write multiple params from opcodeParams array 510 | void WINAPI CLEO_SetIntOpcodeParam(CRunningScript* thread, DWORD value); 511 | void WINAPI CLEO_SetFloatOpcodeParam(CRunningScript* thread, float value); 512 | void WINAPI CLEO_WriteStringOpcodeParam(CRunningScript* thread, const char* str); 513 | 514 | 515 | BOOL WINAPI CLEO_GetScriptDebugMode(const CRunningScript* thread); // debug mode features enabled for this script? 516 | void WINAPI CLEO_SetScriptDebugMode(CRunningScript* thread, BOOL enabled); 517 | 518 | CRunningScript* WINAPI CLEO_CreateCustomScript(CRunningScript* fromThread, const char* script_name, int label); 519 | CRunningScript* WINAPI CLEO_GetLastCreatedCustomScript(); 520 | CRunningScript* WINAPI CLEO_GetScriptByName(const char* threadName, BOOL standardScripts, BOOL customScripts, DWORD resultIndex = 0); // can be called multiple times to find more scripts named threadName. resultIndex should be incremented until the method returns nullptr 521 | CRunningScript* WINAPI CLEO_GetScriptByFilename(const char* path, DWORD resultIndex = 0); // can be absolute, partial path or just filename 522 | 523 | // scripts deletion callback 524 | void WINAPI CLEO_AddScriptDeleteDelegate(FuncScriptDeleteDelegateT func); 525 | void WINAPI CLEO_RemoveScriptDeleteDelegate(FuncScriptDeleteDelegateT func); 526 | 527 | DWORD WINAPI CLEO_GetScriptTextureById(CRunningScript* thread, int id); // ret RwTexture * 528 | 529 | DWORD WINAPI CLEO_GetInternalAudioStream(CRunningScript* thread, DWORD stream); // arg CAudioStream * 530 | 531 | // Should be always used when working with files. Provides ModLoader compatibility 532 | void WINAPI CLEO_ResolvePath(CRunningScript* thread, char* inOutPath, DWORD pathMaxLen); // convert to absolute (file system) path 533 | struct DirectoryList{ DWORD count; char** paths; }; 534 | DirectoryList WINAPI CLEO_ListDirectory(CRunningScript* thread, const char* searchPath, BOOL listDirs, BOOL listFiles); // thread can be null, searchPath can contain wildcards. After use CLEO_ListDirectoryFree must be called on returned DirectoryList to free allocated resources 535 | void WINAPI CLEO_ListDirectoryFree(DirectoryList list); // releases resources allocated by CLEO_ListDirectory 536 | 537 | void WINAPI CLEO_Log(eLogLevel level, const char* msg); // add message to log 538 | 539 | #ifdef __cplusplus 540 | } 541 | #endif //__cplusplus 542 | 543 | } // CLEO namespace 544 | -------------------------------------------------------------------------------- /include/cleo/cleo_redux_sdk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #define STR_MAX_LEN 128 5 | 6 | enum class HandlerResult 7 | { 8 | // Proceed to the next command 9 | CONTINUE = 0, 10 | // Pause the script and continue on the next game loop iteration 11 | BREAK = 1, 12 | // End the script gracefully 13 | TERMINATE = 2, 14 | // End the script and throw an error 15 | ERR = -1 16 | }; 17 | 18 | enum class HostId 19 | { 20 | RE3 = 1, 21 | REVC = 2, 22 | GTA3 = 3, 23 | VC = 4, 24 | SA = 5, 25 | GTA3_UNREAL = 6, 26 | VC_UNREAL = 7, 27 | SA_UNREAL = 8, 28 | IV = 9, 29 | BULLY = 10, 30 | MANIFEST = 254, 31 | UNKNOWN = 255 32 | }; 33 | 34 | enum class Directory 35 | { 36 | // /CLEO directory 37 | CLEO = 0, 38 | // /CLEO/.config 39 | CONFIG = 1, 40 | // /CLEO/CLEO_TEXT 41 | TEXT = 2, 42 | // /CLEO/CLEO_PLUGINS 43 | PLUGINS = 3, 44 | // Current working directory 45 | CWD = 4, 46 | // Host root directory 47 | HOST = 5, 48 | }; 49 | 50 | typedef void* Context; 51 | typedef intptr_t isize; 52 | 53 | typedef HandlerResult (*CommandHandler)(Context); 54 | typedef void* (*CustomLoader)(const char*); 55 | typedef void (*OnTickCallback)(unsigned int current_time, int time_step); 56 | typedef void (*OnRuntimeInitCallback)(); 57 | typedef void (*OnShowTextBoxCallback)(const char*); 58 | 59 | extern "C" { 60 | // since v1 61 | // Returns the current SDK version as an integer number. 62 | long GetSDKVersion(); 63 | // since v1 64 | // Returns the current host (game) id 65 | HostId GetHostId(); 66 | // since v1 67 | // Resolves a path to the absolute path 68 | void ResolvePath(const char* src, char* dest); 69 | // since v1 70 | // Returns the absolute path to the CLEO directory 71 | // deprecated: use GetDirectoryPath 72 | void GetCLEOFolder(char* dest); 73 | // since v1 74 | // Returns the absolute path to the current working directory (normally the game directory) 75 | void GetCwd(char* dest); 76 | // since v1 77 | // Prints a new entry to the cleo_redux.log 78 | void Log(const char* text); 79 | // since v1 80 | // Registers a new callback handler for the command with the given name. Permission token is required for unsafe operations interacting with the user environment (e.g. mem, fs, net) 81 | void RegisterCommand(const char* name, CommandHandler handler, const char* permission = nullptr); 82 | // since v1 83 | // Reads an integer argument (either 32 or 64 bit depending on the target platform) from the script input 84 | isize GetIntParam(Context ctx); 85 | // since v1 86 | // Reads a floating-point argument from the script input 87 | float GetFloatParam(Context ctx); 88 | // since v1 89 | // Copies atmost {maxlen} bytes of a UTF-8 encoded character sequence in the script input to {dest} 90 | void GetStringParam(Context ctx, char* dest, unsigned char maxlen); 91 | // since v1 92 | // Writes the integer {value} (either 32 or 64 bit depending on the target platform) to the script output 93 | void SetIntParam(Context ctx, isize value); 94 | // since v1 95 | // Writes the floating-point {value} to the script output 96 | void SetFloatParam(Context ctx, float value); 97 | // since v1 98 | // Copies a null-terminated UTF-8 encoded character sequence from {src} to the script output 99 | void SetStringParam(Context ctx, const char* src); 100 | // since v1 101 | // Sets the status of the current condition 102 | void UpdateCompareFlag(Context ctx, bool result); 103 | // since v2 104 | // Copies atmost {maxlen} bytes of a UTF-8 encoded host name to {dest} 105 | void GetHostName(char* dest, unsigned char maxlen); 106 | // since v2 107 | // Sets the new host name (available in scripts as the HOST constant) 108 | void SetHostName(const char* src); 109 | // since v2 110 | // Initializes or reloads CLEO runtime 111 | void RuntimeInit(); 112 | // since v2 113 | // Iterates the main loop 114 | void RuntimeNextTick(unsigned int current_time, int time_step); 115 | // since v3 116 | // Registers a new loader for files matching a glob pattern 117 | void RegisterLoader(const char* glob, CustomLoader loader); 118 | // since v3 119 | // Allocates a memory chunk with size in bytes. Memory is guaranteed to be zero initialized 120 | void* AllocMem(size_t size); 121 | // since v3 122 | // Frees up the memory chunk allocated with AllocMem 123 | void FreeMem(void *ptr); 124 | // since v4 125 | // Registers a new callback invoked on each main loop iteration (before scripts are executed) 126 | void OnBeforeScripts(OnTickCallback callback); 127 | // since v4 128 | // Registers a new callback invoked on each main loop iteration (after scripts are executed) 129 | void OnAfterScripts(OnTickCallback callback); 130 | // since v4 131 | // Registers a new callback invoked on each runtime init event (new game, saved game load, or SDK's RuntimeInit) 132 | void OnRuntimeInit(OnRuntimeInitCallback callback); 133 | // since v5 134 | // Registers a new callback invoked on a ShowTextBox function call. Providing a callback shadows built-in ShowTextBox implementation. 135 | void OnShowTextBox(OnShowTextBoxCallback callback); 136 | /// since v6 137 | /// Returns the absolute path to the CLEO root directory or one of its sub-directories 138 | void GetDirectoryPath(Directory dir, char* dest); 139 | /// since v6 140 | /// Returns CLEO Redux version as a string 141 | void GetCLEOVersion(char* dest); 142 | /// since v6 143 | /// Returns a memory address for the given symbol, or 0 if not found 144 | void* GetSymbolAddress(const char* symbol); 145 | /// since v6 146 | /// Returns number of active CS scripts 147 | size_t GetNumberOfActiveCSScripts(); 148 | /// since v6 149 | /// Returns number of active JS scripts 150 | size_t GetNumberOfActiveJSScripts(); 151 | /// since v6 152 | /// Is end of arguments reached 153 | bool IsEndOfArguments(Context ctx); 154 | /// since v7 155 | /// Triggers an event with the given name and data 156 | void TriggerEvent(const char* name, const char* data); 157 | } 158 | 159 | -------------------------------------------------------------------------------- /include/imgui/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI 3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. 4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. 5 | //----------------------------------------------------------------------------- 6 | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) 7 | // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. 8 | //----------------------------------------------------------------------------- 9 | // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp 10 | // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. 11 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. 12 | // Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. 13 | //----------------------------------------------------------------------------- 14 | 15 | #pragma once 16 | 17 | //---- Define assertion handler. Defaults to calling assert(). 18 | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. 19 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 20 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts 21 | 22 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows 23 | // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. 24 | // DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() 25 | // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. 26 | //#define IMGUI_API __declspec( dllexport ) 27 | //#define IMGUI_API __declspec( dllimport ) 28 | 29 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. 30 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 31 | //#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions. 32 | 33 | //---- Disable all of Dear ImGui or don't implement standard windows/tools. 34 | // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp. 35 | //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. 36 | //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. 37 | //#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88). 38 | 39 | //---- Don't implement some functions to reduce linkage requirements. 40 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) 41 | //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW) 42 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) 43 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). 44 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). 45 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) 46 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. 47 | //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) 48 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. 49 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). 50 | //#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available 51 | 52 | //---- Include imgui_user.h at the end of imgui.h as a convenience 53 | //#define IMGUI_INCLUDE_IMGUI_USER_H 54 | 55 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) 56 | //#define IMGUI_USE_BGRA_PACKED_COLOR 57 | 58 | //---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) 59 | //#define IMGUI_USE_WCHAR32 60 | 61 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version 62 | // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. 63 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" 64 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" 65 | //#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if enabled 66 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 67 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 68 | 69 | //---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) 70 | // Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h. 71 | //#define IMGUI_USE_STB_SPRINTF 72 | 73 | //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) 74 | // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). 75 | // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. 76 | // #define IMGUI_ENABLE_FREETYPE 77 | 78 | //---- Use stb_truetype to build and rasterize the font atlas (default) 79 | // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. 80 | //#define IMGUI_ENABLE_STB_TRUETYPE 81 | 82 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. 83 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 84 | /* 85 | #define IM_VEC2_CLASS_EXTRA \ 86 | constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \ 87 | operator MyVec2() const { return MyVec2(x,y); } 88 | 89 | #define IM_VEC4_CLASS_EXTRA \ 90 | constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \ 91 | operator MyVec4() const { return MyVec4(x,y,z,w); } 92 | */ 93 | 94 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. 95 | // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). 96 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. 97 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. 98 | //#define ImDrawIdx unsigned int 99 | 100 | //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) 101 | //struct ImDrawList; 102 | //struct ImDrawCmd; 103 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); 104 | //#define ImDrawCallback MyImDrawCallback 105 | 106 | //---- Debug Tools: Macro to break in Debugger 107 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) 108 | //#define IM_DEBUG_BREAK IM_ASSERT(0) 109 | //#define IM_DEBUG_BREAK __debugbreak() 110 | 111 | //---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(), 112 | // (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.) 113 | // This adds a small runtime cost which is why it is not enabled by default. 114 | //#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX 115 | 116 | //---- Debug Tools: Enable slower asserts 117 | //#define IMGUI_DEBUG_PARANOID 118 | 119 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 120 | /* 121 | namespace ImGui 122 | { 123 | void MyFunction(const char* name, const MyMatrix44& v); 124 | } 125 | */ 126 | -------------------------------------------------------------------------------- /include/imgui/imgui_impl_dx11.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX11 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. 7 | 8 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 9 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 10 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 11 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 12 | 13 | #pragma once 14 | #include "imgui.h" // IMGUI_IMPL_API 15 | 16 | struct ID3D11Device; 17 | struct ID3D11DeviceContext; 18 | 19 | IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); 20 | IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); 21 | IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); 22 | IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); 23 | 24 | // Use if you want to reset your rendering device without losing Dear ImGui state. 25 | IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); 26 | IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); 27 | -------------------------------------------------------------------------------- /include/imgui/imgui_impl_dx9.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX9 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. 7 | 8 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 9 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 10 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 11 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 12 | 13 | // CHANGELOG 14 | // (minor and older changes stripped away, please see git history for details) 15 | // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). 16 | // 2021-06-25: DirectX9: Explicitly disable texture state stages after >= 1. 17 | // 2021-05-19: DirectX9: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) 18 | // 2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states. 19 | // 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857). 20 | // 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file. 21 | // 2021-02-18: DirectX9: Change blending equation to preserve alpha in output buffer. 22 | // 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. 23 | // 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. 24 | // 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects(). 25 | // 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288. 26 | // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. 27 | // 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example. 28 | // 2018-06-08: DirectX9: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. 29 | // 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud. 30 | // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself. 31 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. 32 | 33 | #include "imgui.h" 34 | #include "imgui_impl_dx9.h" 35 | 36 | // DirectX 37 | #include 38 | 39 | // DirectX data 40 | struct ImGui_ImplDX9_Data 41 | { 42 | LPDIRECT3DDEVICE9 pd3dDevice; 43 | LPDIRECT3DVERTEXBUFFER9 pVB; 44 | LPDIRECT3DINDEXBUFFER9 pIB; 45 | LPDIRECT3DTEXTURE9 FontTexture; 46 | int VertexBufferSize; 47 | int IndexBufferSize; 48 | 49 | ImGui_ImplDX9_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } 50 | }; 51 | 52 | struct CUSTOMVERTEX 53 | { 54 | float pos[3]; 55 | D3DCOLOR col; 56 | float uv[2]; 57 | }; 58 | #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) 59 | 60 | #ifdef IMGUI_USE_BGRA_PACKED_COLOR 61 | #define IMGUI_COL_TO_DX9_ARGB(_COL) (_COL) 62 | #else 63 | #define IMGUI_COL_TO_DX9_ARGB(_COL) (((_COL) & 0xFF00FF00) | (((_COL) & 0xFF0000) >> 16) | (((_COL) & 0xFF) << 16)) 64 | #endif 65 | 66 | // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts 67 | // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. 68 | static ImGui_ImplDX9_Data* ImGui_ImplDX9_GetBackendData() 69 | { 70 | return ImGui::GetCurrentContext() ? (ImGui_ImplDX9_Data*)ImGui::GetIO().BackendRendererUserData : NULL; 71 | } 72 | 73 | // Functions 74 | static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data) 75 | { 76 | ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); 77 | 78 | // Setup viewport 79 | D3DVIEWPORT9 vp; 80 | vp.X = vp.Y = 0; 81 | vp.Width = (DWORD)draw_data->DisplaySize.x; 82 | vp.Height = (DWORD)draw_data->DisplaySize.y; 83 | vp.MinZ = 0.0f; 84 | vp.MaxZ = 1.0f; 85 | bd->pd3dDevice->SetViewport(&vp); 86 | 87 | // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient), bilinear sampling. 88 | bd->pd3dDevice->SetPixelShader(NULL); 89 | bd->pd3dDevice->SetVertexShader(NULL); 90 | bd->pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); 91 | bd->pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); 92 | bd->pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); 93 | bd->pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 94 | bd->pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 95 | bd->pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE); 96 | bd->pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 97 | bd->pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); 98 | bd->pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 99 | bd->pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 100 | bd->pd3dDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); 101 | bd->pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE); 102 | bd->pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA); 103 | bd->pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); 104 | bd->pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); 105 | bd->pd3dDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE); 106 | bd->pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE); 107 | bd->pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); 108 | bd->pd3dDevice->SetRenderState(D3DRS_CLIPPING, TRUE); 109 | bd->pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); 110 | bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); 111 | bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); 112 | bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); 113 | bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); 114 | bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); 115 | bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); 116 | bd->pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); 117 | bd->pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); 118 | bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 119 | bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 120 | 121 | // Setup orthographic projection matrix 122 | // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. 123 | // Being agnostic of whether or can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH() 124 | { 125 | float L = draw_data->DisplayPos.x + 0.5f; 126 | float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f; 127 | float T = draw_data->DisplayPos.y + 0.5f; 128 | float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f; 129 | D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } }; 130 | D3DMATRIX mat_projection = 131 | { { { 132 | 2.0f/(R-L), 0.0f, 0.0f, 0.0f, 133 | 0.0f, 2.0f/(T-B), 0.0f, 0.0f, 134 | 0.0f, 0.0f, 0.5f, 0.0f, 135 | (L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f 136 | } } }; 137 | bd->pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity); 138 | bd->pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity); 139 | bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection); 140 | } 141 | } 142 | 143 | // Render function. 144 | void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) 145 | { 146 | // Avoid rendering when minimized 147 | if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) 148 | return; 149 | 150 | // Create and grow buffers if needed 151 | ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); 152 | if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount) 153 | { 154 | if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; } 155 | bd->VertexBufferSize = draw_data->TotalVtxCount + 5000; 156 | if (bd->pd3dDevice->CreateVertexBuffer(bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, NULL) < 0) 157 | return; 158 | } 159 | if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount) 160 | { 161 | if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; } 162 | bd->IndexBufferSize = draw_data->TotalIdxCount + 10000; 163 | if (bd->pd3dDevice->CreateIndexBuffer(bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, NULL) < 0) 164 | return; 165 | } 166 | 167 | // Backup the DX9 state 168 | IDirect3DStateBlock9* d3d9_state_block = NULL; 169 | if (bd->pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0) 170 | return; 171 | if (d3d9_state_block->Capture() < 0) 172 | { 173 | d3d9_state_block->Release(); 174 | return; 175 | } 176 | 177 | // Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to) 178 | D3DMATRIX last_world, last_view, last_projection; 179 | bd->pd3dDevice->GetTransform(D3DTS_WORLD, &last_world); 180 | bd->pd3dDevice->GetTransform(D3DTS_VIEW, &last_view); 181 | bd->pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection); 182 | 183 | // Allocate buffers 184 | CUSTOMVERTEX* vtx_dst; 185 | ImDrawIdx* idx_dst; 186 | if (bd->pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0) 187 | { 188 | d3d9_state_block->Release(); 189 | return; 190 | } 191 | if (bd->pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0) 192 | { 193 | bd->pVB->Unlock(); 194 | d3d9_state_block->Release(); 195 | return; 196 | } 197 | 198 | // Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format. 199 | // FIXME-OPT: This is a minor waste of resource, the ideal is to use imconfig.h and 200 | // 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR 201 | // 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; } 202 | for (int n = 0; n < draw_data->CmdListsCount; n++) 203 | { 204 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 205 | const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data; 206 | for (int i = 0; i < cmd_list->VtxBuffer.Size; i++) 207 | { 208 | vtx_dst->pos[0] = vtx_src->pos.x; 209 | vtx_dst->pos[1] = vtx_src->pos.y; 210 | vtx_dst->pos[2] = 0.0f; 211 | vtx_dst->col = IMGUI_COL_TO_DX9_ARGB(vtx_src->col); 212 | vtx_dst->uv[0] = vtx_src->uv.x; 213 | vtx_dst->uv[1] = vtx_src->uv.y; 214 | vtx_dst++; 215 | vtx_src++; 216 | } 217 | memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 218 | idx_dst += cmd_list->IdxBuffer.Size; 219 | } 220 | bd->pVB->Unlock(); 221 | bd->pIB->Unlock(); 222 | bd->pd3dDevice->SetStreamSource(0, bd->pVB, 0, sizeof(CUSTOMVERTEX)); 223 | bd->pd3dDevice->SetIndices(bd->pIB); 224 | bd->pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); 225 | 226 | // Setup desired DX state 227 | ImGui_ImplDX9_SetupRenderState(draw_data); 228 | 229 | // Render command lists 230 | // (Because we merged all buffers into a single one, we maintain our own offset into them) 231 | int global_vtx_offset = 0; 232 | int global_idx_offset = 0; 233 | ImVec2 clip_off = draw_data->DisplayPos; 234 | for (int n = 0; n < draw_data->CmdListsCount; n++) 235 | { 236 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 237 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 238 | { 239 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 240 | if (pcmd->UserCallback != NULL) 241 | { 242 | // User callback, registered via ImDrawList::AddCallback() 243 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) 244 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) 245 | ImGui_ImplDX9_SetupRenderState(draw_data); 246 | else 247 | pcmd->UserCallback(cmd_list, pcmd); 248 | } 249 | else 250 | { 251 | // Project scissor/clipping rectangles into framebuffer space 252 | ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y); 253 | ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y); 254 | if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) 255 | continue; 256 | 257 | // Apply Scissor/clipping rectangle, Bind texture, Draw 258 | const RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y }; 259 | const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID(); 260 | bd->pd3dDevice->SetTexture(0, texture); 261 | bd->pd3dDevice->SetScissorRect(&r); 262 | bd->pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3); 263 | } 264 | } 265 | global_idx_offset += cmd_list->IdxBuffer.Size; 266 | global_vtx_offset += cmd_list->VtxBuffer.Size; 267 | } 268 | 269 | // Restore the DX9 transform 270 | bd->pd3dDevice->SetTransform(D3DTS_WORLD, &last_world); 271 | bd->pd3dDevice->SetTransform(D3DTS_VIEW, &last_view); 272 | bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection); 273 | 274 | // Restore the DX9 state 275 | d3d9_state_block->Apply(); 276 | d3d9_state_block->Release(); 277 | } 278 | 279 | bool ImGui_ImplDX9_Init(IDirect3DDevice9* device) 280 | { 281 | ImGuiIO& io = ImGui::GetIO(); 282 | IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); 283 | 284 | // Setup backend capabilities flags 285 | ImGui_ImplDX9_Data* bd = IM_NEW(ImGui_ImplDX9_Data)(); 286 | io.BackendRendererUserData = (void*)bd; 287 | io.BackendRendererName = "imgui_impl_dx9"; 288 | io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. 289 | 290 | bd->pd3dDevice = device; 291 | bd->pd3dDevice->AddRef(); 292 | 293 | return true; 294 | } 295 | 296 | void ImGui_ImplDX9_Shutdown() 297 | { 298 | ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); 299 | IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?"); 300 | ImGuiIO& io = ImGui::GetIO(); 301 | 302 | ImGui_ImplDX9_InvalidateDeviceObjects(); 303 | if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } 304 | io.BackendRendererName = NULL; 305 | io.BackendRendererUserData = NULL; 306 | IM_DELETE(bd); 307 | } 308 | 309 | static bool ImGui_ImplDX9_CreateFontsTexture() 310 | { 311 | // Build texture atlas 312 | ImGuiIO& io = ImGui::GetIO(); 313 | ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); 314 | unsigned char* pixels; 315 | int width, height, bytes_per_pixel; 316 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel); 317 | 318 | // Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices) 319 | #ifndef IMGUI_USE_BGRA_PACKED_COLOR 320 | if (io.Fonts->TexPixelsUseColors) 321 | { 322 | ImU32* dst_start = (ImU32*)ImGui::MemAlloc((size_t)width * height * bytes_per_pixel); 323 | for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + (size_t)width * height; dst < dst_end; src++, dst++) 324 | *dst = IMGUI_COL_TO_DX9_ARGB(*src); 325 | pixels = (unsigned char*)dst_start; 326 | } 327 | #endif 328 | 329 | // Upload texture to graphics system 330 | bd->FontTexture = NULL; 331 | if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, NULL) < 0) 332 | return false; 333 | D3DLOCKED_RECT tex_locked_rect; 334 | if (bd->FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK) 335 | return false; 336 | for (int y = 0; y < height; y++) 337 | memcpy((unsigned char*)tex_locked_rect.pBits + (size_t)tex_locked_rect.Pitch * y, pixels + (size_t)width * bytes_per_pixel * y, (size_t)width * bytes_per_pixel); 338 | bd->FontTexture->UnlockRect(0); 339 | 340 | // Store our identifier 341 | io.Fonts->SetTexID((ImTextureID)bd->FontTexture); 342 | 343 | #ifndef IMGUI_USE_BGRA_PACKED_COLOR 344 | if (io.Fonts->TexPixelsUseColors) 345 | ImGui::MemFree(pixels); 346 | #endif 347 | 348 | return true; 349 | } 350 | 351 | bool ImGui_ImplDX9_CreateDeviceObjects() 352 | { 353 | ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); 354 | if (!bd || !bd->pd3dDevice) 355 | return false; 356 | if (!ImGui_ImplDX9_CreateFontsTexture()) 357 | return false; 358 | return true; 359 | } 360 | 361 | void ImGui_ImplDX9_InvalidateDeviceObjects() 362 | { 363 | ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); 364 | if (!bd || !bd->pd3dDevice) 365 | return; 366 | if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; } 367 | if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; } 368 | if (bd->FontTexture) { bd->FontTexture->Release(); bd->FontTexture = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well. 369 | } 370 | 371 | void ImGui_ImplDX9_NewFrame() 372 | { 373 | ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); 374 | IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX9_Init()?"); 375 | 376 | if (!bd->FontTexture) 377 | ImGui_ImplDX9_CreateDeviceObjects(); 378 | } 379 | -------------------------------------------------------------------------------- /include/imgui/imgui_impl_dx9.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX9 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. 7 | 8 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 9 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 10 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 11 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 12 | 13 | #pragma once 14 | #include "imgui.h" // IMGUI_IMPL_API 15 | 16 | struct IDirect3DDevice9; 17 | 18 | IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device); 19 | IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown(); 20 | IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame(); 21 | IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data); 22 | 23 | // Use if you want to reset your rendering device without losing Dear ImGui state. 24 | IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects(); 25 | IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects(); 26 | -------------------------------------------------------------------------------- /include/imgui/imgui_impl_opengl3.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline 2 | // - Desktop GL: 2.x 3.x 4.x 3 | // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) 4 | // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) 5 | 6 | // Implemented features: 7 | // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! 8 | // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices. 9 | 10 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 11 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 12 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 13 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 14 | 15 | // About GLSL version: 16 | // The 'glsl_version' initialization parameter should be NULL (default) or a "#version XXX" string. 17 | // On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es" 18 | // Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp. 19 | 20 | #pragma once 21 | #include "imgui.h" // IMGUI_IMPL_API 22 | 23 | // Backend API 24 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL); 25 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); 26 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); 27 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); 28 | 29 | // (Optional) Called by Init/NewFrame/Shutdown 30 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); 31 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); 32 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); 33 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); 34 | 35 | // Specific OpenGL ES versions 36 | //#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten 37 | //#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android 38 | 39 | // You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. 40 | #if !defined(IMGUI_IMPL_OPENGL_ES2) \ 41 | && !defined(IMGUI_IMPL_OPENGL_ES3) 42 | 43 | // Try to detect GLES on matching platforms 44 | #if defined(__APPLE__) 45 | #include 46 | #endif 47 | #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) 48 | #define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" 49 | #elif defined(__EMSCRIPTEN__) || defined(__amigaos4__) 50 | #define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" 51 | #else 52 | // Otherwise imgui_impl_opengl3_loader.h will be used. 53 | #endif 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /include/imgui/imgui_impl_win32.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications) 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | 4 | // Implemented features: 5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) 6 | // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] 7 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 8 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 9 | 10 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 11 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 12 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 13 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 14 | 15 | #pragma once 16 | #include "imgui.h" // IMGUI_IMPL_API 17 | 18 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); 19 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); 20 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); 21 | 22 | // Win32 message handler your application need to call. 23 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. 24 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. 25 | // - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE. 26 | 27 | #if 0 28 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 29 | #endif 30 | 31 | // DPI-related helpers (optional) 32 | // - Use to enable DPI awareness without having to create an application manifest. 33 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 34 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 35 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 36 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 37 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness(); 38 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd 39 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor 40 | 41 | // Transparency related helpers (optional) [experimental] 42 | // - Use to enable alpha compositing transparency with the desktop. 43 | // - Use together with e.g. clearing your framebuffer with zero-alpha. 44 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd 45 | -------------------------------------------------------------------------------- /include/imgui/imgui_stdlib.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) 2 | // This is also an example of how you may wrap your own similar types. 3 | 4 | // Changelog: 5 | // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string 6 | 7 | #include "imgui.h" 8 | #include "imgui_stdlib.h" 9 | 10 | struct InputTextCallback_UserData 11 | { 12 | std::string* Str; 13 | ImGuiInputTextCallback ChainCallback; 14 | void* ChainCallbackUserData; 15 | }; 16 | 17 | static int InputTextCallback(ImGuiInputTextCallbackData* data) 18 | { 19 | InputTextCallback_UserData* user_data = (InputTextCallback_UserData*)data->UserData; 20 | if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) 21 | { 22 | // Resize string callback 23 | // If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want. 24 | std::string* str = user_data->Str; 25 | IM_ASSERT(data->Buf == str->c_str()); 26 | str->resize(data->BufTextLen); 27 | data->Buf = (char*)str->c_str(); 28 | } 29 | else if (user_data->ChainCallback) 30 | { 31 | // Forward to user callback, if any 32 | data->UserData = user_data->ChainCallbackUserData; 33 | return user_data->ChainCallback(data); 34 | } 35 | return 0; 36 | } 37 | 38 | bool ImGui::InputText(const char* label, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) 39 | { 40 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); 41 | flags |= ImGuiInputTextFlags_CallbackResize; 42 | 43 | InputTextCallback_UserData cb_user_data; 44 | cb_user_data.Str = str; 45 | cb_user_data.ChainCallback = callback; 46 | cb_user_data.ChainCallbackUserData = user_data; 47 | return InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); 48 | } 49 | 50 | bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) 51 | { 52 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); 53 | flags |= ImGuiInputTextFlags_CallbackResize; 54 | 55 | InputTextCallback_UserData cb_user_data; 56 | cb_user_data.Str = str; 57 | cb_user_data.ChainCallback = callback; 58 | cb_user_data.ChainCallbackUserData = user_data; 59 | return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data); 60 | } 61 | 62 | bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) 63 | { 64 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); 65 | flags |= ImGuiInputTextFlags_CallbackResize; 66 | 67 | InputTextCallback_UserData cb_user_data; 68 | cb_user_data.Str = str; 69 | cb_user_data.ChainCallback = callback; 70 | cb_user_data.ChainCallbackUserData = user_data; 71 | return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); 72 | } 73 | -------------------------------------------------------------------------------- /include/imgui/imgui_stdlib.h: -------------------------------------------------------------------------------- 1 | // dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) 2 | // This is also an example of how you may wrap your own similar types. 3 | 4 | // Changelog: 5 | // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace ImGui 12 | { 13 | // ImGui::InputText() with std::string 14 | // Because text input needs dynamic resizing, we need to setup a callback to grow the capacity 15 | IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); 16 | IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); 17 | IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); 18 | } 19 | -------------------------------------------------------------------------------- /include/injector/assembly.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Injectors - Useful Assembly Stuff 3 | * 4 | * Copyright (C) 2012-2014 LINK/2012 5 | * 6 | * This software is provided 'as-is', without any express or implied 7 | * warranty. In no event will the authors be held liable for any damages 8 | * arising from the use of this software. 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. If you use this software 16 | * in a product, an acknowledgment in the product documentation would be 17 | * appreciated but is not required. 18 | * 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 22 | * 3. This notice may not be removed or altered from any source 23 | * distribution. 24 | * 25 | */ 26 | #pragma once 27 | 28 | // This header is very restrict about compiler and architecture 29 | #ifndef _MSC_VER // MSVC is much more flexible when we're talking about inline assembly 30 | #error Cannot use this header in another compiler other than MSVC 31 | #endif 32 | #ifndef _M_IX86 33 | #error Supported only in x86 34 | #endif 35 | 36 | // 37 | #include "injector.hpp" 38 | 39 | namespace injector 40 | { 41 | struct reg_pack 42 | { 43 | // The ordering is very important, don't change 44 | // The first field is the last to be pushed and first to be poped 45 | 46 | // PUSHFD / POPFD 47 | uint32_t ef; 48 | 49 | // PUSHAD/POPAD -- must be the lastest fields (because of esp) 50 | union 51 | { 52 | uint32_t arr[8]; 53 | struct { uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; }; 54 | }; 55 | 56 | enum reg_name { 57 | reg_edi, reg_esi, reg_ebp, reg_esp, reg_ebx, reg_edx, reg_ecx, reg_eax 58 | }; 59 | 60 | enum ef_flag { 61 | carry_flag = 0, parity_flag = 2, adjust_flag = 4, zero_flag = 6, sign_flag = 7, 62 | direction_flag = 10, overflow_flag = 11 63 | }; 64 | 65 | uint32_t& operator[](size_t i) 66 | { return this->arr[i]; } 67 | const uint32_t& operator[](size_t i) const 68 | { return this->arr[i]; } 69 | 70 | template // bit starts from 0, use ef_flag enum 71 | bool flag() 72 | { 73 | return (this->ef & (1 << bit)) != 0; 74 | } 75 | 76 | bool jnb() 77 | { 78 | return flag() == false; 79 | } 80 | }; 81 | 82 | // Lowest level stuff (actual assembly) goes on the following namespace 83 | // PRIVATE! Skip this, not interesting for you. 84 | namespace injector_asm 85 | { 86 | // Wrapper functor, so the assembly can use some templating 87 | template 88 | struct wrapper 89 | { 90 | static void call(reg_pack* regs) 91 | { 92 | T fun; fun(*regs); 93 | } 94 | }; 95 | 96 | // Constructs a reg_pack and calls the wrapper functor 97 | template // where W is of type wrapper 98 | inline void __declspec(naked) make_reg_pack_and_call() 99 | { 100 | _asm 101 | { 102 | // Construct the reg_pack structure on the stack 103 | pushad // Pushes general purposes registers to reg_pack 104 | add [esp+12], 4 // Add 4 to reg_pack::esp 'cuz of our return pointer, let it be as before this func is called 105 | pushfd // Pushes EFLAGS to reg_pack 106 | 107 | // Call wrapper sending reg_pack as parameter 108 | push esp 109 | call W::call 110 | add esp, 4 111 | 112 | // Destructs the reg_pack from the stack 113 | sub [esp+12+4], 4 // Fix reg_pack::esp before popping it (doesn't make a difference though) (+4 because eflags) 114 | popfd // Warning: Do not use any instruction that changes EFLAGS after this (-> sub affects EF!! <-) 115 | popad 116 | 117 | // Back to normal flow 118 | ret 119 | } 120 | } 121 | }; 122 | 123 | 124 | /* 125 | * MakeInline 126 | * Makes inline assembly (but not assembly, an actual functor of type FuncT) at address 127 | */ 128 | template 129 | void MakeInline(memory_pointer_tr at) 130 | { 131 | typedef injector_asm::wrapper functor; 132 | if(false) functor::call(nullptr); // To instantiate the template, if not done _asm will fail 133 | MakeCALL(at, injector_asm::make_reg_pack_and_call); 134 | } 135 | 136 | /* 137 | * MakeInline 138 | * Same as above, but it NOPs everything between at and end (exclusive), then performs MakeInline 139 | */ 140 | template 141 | void MakeInline(memory_pointer_tr at, memory_pointer_tr end) 142 | { 143 | MakeRangedNOP(at, end); 144 | MakeInline(at); 145 | } 146 | 147 | /* 148 | * MakeInline 149 | * Same as above, but (at,end) are template parameters. 150 | * On this case the functor can be passed as argument since there will be one func instance for each at,end not just for each FuncT 151 | */ 152 | template 153 | void MakeInline(FuncT func) 154 | { 155 | static std::unique_ptr static_func; 156 | static_func.reset(new FuncT(std::move(func))); 157 | 158 | // Encapsulates the call to static_func 159 | struct Caps 160 | { 161 | void operator()(reg_pack& regs) 162 | { (*static_func)(regs); } 163 | }; 164 | 165 | // Does the actual MakeInline 166 | return MakeInline(lazy_pointer::get(), lazy_pointer::get()); 167 | } 168 | 169 | /* 170 | * MakeInline 171 | * Same as above, but (end) is calculated by the length of a call instruction 172 | */ 173 | template 174 | void MakeInline(FuncT func) 175 | { 176 | return MakeInline(func); 177 | } 178 | }; 179 | -------------------------------------------------------------------------------- /include/injector/calling.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Injectors - Function Calls Using Variadic Templates 3 | * 4 | * Copyright (C) 2014 LINK/2012 5 | * 6 | * This software is provided 'as-is', without any express or implied 7 | * warranty. In no event will the authors be held liable for any damages 8 | * arising from the use of this software. 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. If you use this software 16 | * in a product, an acknowledgment in the product documentation would be 17 | * appreciated but is not required. 18 | * 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 22 | * 3. This notice may not be removed or altered from any source 23 | * distribution. 24 | * 25 | */ 26 | #pragma once 27 | #include "injector.hpp" 28 | #include 29 | #include 30 | 31 | #if __cplusplus >= 201103L || _MSC_VER >= 1800 // MSVC 2013 32 | #else 33 | #error "This feature is not supported on this compiler" 34 | #endif 35 | 36 | namespace injector 37 | { 38 | template 39 | struct cstd; 40 | 41 | template 42 | struct cstd 43 | { 44 | // Call function at @p returning @Ret with args @Args 45 | static Ret call(memory_pointer_tr p, Args... a) 46 | { 47 | auto fn = (Ret(*)(Args...)) p.get(); 48 | return fn(std::forward(a)...); 49 | } 50 | 51 | template // Uses lazy pointer 52 | static Ret call(Args... a) 53 | { 54 | return call(lazy_pointer::get(), std::forward(a)...); 55 | } 56 | }; 57 | 58 | template 59 | struct stdcall; 60 | 61 | template 62 | struct stdcall 63 | { 64 | // Call function at @p returning @Ret with args @Args 65 | static Ret call(memory_pointer_tr p, Args... a) 66 | { 67 | auto fn = (Ret(__stdcall *)(Args...)) p.get(); 68 | return fn(std::forward(a)...); 69 | } 70 | 71 | template // Uses lazy pointer 72 | static Ret call(Args... a) 73 | { 74 | return call(lazy_pointer::get(), std::forward(a)...); 75 | } 76 | }; 77 | 78 | template 79 | struct fastcall; 80 | 81 | template 82 | struct fastcall 83 | { 84 | // Call function at @p returning @Ret with args @Args 85 | static Ret call(memory_pointer_tr p, Args... a) 86 | { 87 | auto fn = (Ret(__fastcall *)(Args...)) p.get();; 88 | return fn(std::forward(a)...); 89 | } 90 | 91 | template // Uses lazy pointer 92 | static Ret call(Args... a) 93 | { 94 | return call(lazy_pointer::get(), std::forward(a)...); 95 | } 96 | }; 97 | 98 | template 99 | struct thiscall; 100 | 101 | template 102 | struct thiscall 103 | { 104 | // Call function at @p returning @Ret with args @Args 105 | static Ret call(memory_pointer_tr p, Args... a) 106 | { 107 | auto fn = (Ret(__thiscall *)(Args...)) p.get(); 108 | return fn(std::forward(a)...); 109 | } 110 | 111 | // Call function at the index @i from the vtable of the object @a[0] 112 | template 113 | static Ret vtbl(Args... a) 114 | { 115 | auto obj = raw_ptr(std::get<0>(std::forward_as_tuple(a...))); 116 | auto p = raw_ptr( (*obj.template get()) [i] ); 117 | return call(p, std::forward(a)...); 118 | } 119 | 120 | template // Uses lazy pointer 121 | static Ret call(Args... a) 122 | { 123 | return call(lazy_pointer::get(), std::forward(a)...); 124 | } 125 | }; 126 | } 127 | 128 | -------------------------------------------------------------------------------- /include/injector/gvm/gvm.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Injectors - Base Header 3 | * 4 | * Copyright (C) 2012-2014 LINK/2012 5 | * 6 | * This software is provided 'as-is', without any express or implied 7 | * warranty. In no event will the authors be held liable for any damages 8 | * arising from the use of this software. 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. If you use this software 16 | * in a product, an acknowledgment in the product documentation would be 17 | * appreciated but is not required. 18 | * 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 22 | * 3. This notice may not be removed or altered from any source 23 | * distribution. 24 | * 25 | */ 26 | #pragma once 27 | #include 28 | #include 29 | #include 30 | 31 | namespace injector 32 | { 33 | 34 | #if 1 // GVM and Address Translator, Not very interesting for the users, so skip reading those... 35 | 36 | /* 37 | * game_version_manager 38 | * Detects the game, the game version and the game region 39 | * This assumes the executable is decrypted, so, Silent's ASI Loader is recommended. 40 | */ 41 | #ifndef INJECTOR_OWN_GVM 42 | #ifndef INJECTOR_GVM_DUMMY 43 | class game_version_manager 44 | { 45 | public: 46 | // Set this if you would like that MessagesBox contain PluginName as caption 47 | const char* PluginName; 48 | 49 | private: 50 | char game, region, major, minor, majorRevision, minorRevision, cracker, steam; 51 | 52 | public: 53 | game_version_manager() 54 | { 55 | #ifdef INJECTOR_GVM_PLUGIN_NAME 56 | PluginName = INJECTOR_GVM_PLUGIN_NAME; 57 | #else 58 | PluginName = "Plugin-SDK Plugin"; 59 | #endif 60 | 61 | this->Clear(); 62 | } 63 | 64 | 65 | // Clear any information about game version 66 | void Clear() 67 | { 68 | game = region = major = minor = majorRevision = minorRevision = cracker = steam = 0; 69 | } 70 | 71 | // Checks if I don't know the game we are attached to 72 | bool IsUnknown() { return game == 0; } 73 | // Checks if this is the steam version 74 | bool IsSteam() { return steam != 0; } 75 | // Gets the game we are attached to (0, '3', 'V', 'S', 'I', 'E') 76 | char GetGame() { return game; } 77 | // Gets the region from the game we are attached to (0, 'U', 'E'); 78 | char GetRegion() { return region; } 79 | // Get major and minor version of the game (e.g. [major = 1, minor = 0] = 1.0) 80 | int GetMajorVersion() { return major; } 81 | int GetMinorVersion() { return minor; } 82 | int GetMajorRevisionVersion() { return majorRevision; } 83 | int GetMinorRevisionVersion() { return minorRevision; } 84 | 85 | bool IsHoodlum() { return cracker == 'H'; } 86 | 87 | // Region conditions 88 | bool IsUS() { return region == 'U'; } 89 | bool IsEU() { return region == 'E'; } 90 | 91 | // Game Conditions 92 | bool IsIII() { return game == '3'; } 93 | bool IsVC () { return game == 'V'; } 94 | bool IsSA () { return game == 'S'; } 95 | bool IsIV () { return game == 'I'; } 96 | bool IsEFLC(){ return game == 'E'; } 97 | 98 | // Detects game, region and version; returns false if could not detect it 99 | bool Detect(); 100 | 101 | // Gets the game version as text, the buffer must contain at least 32 bytes of space. 102 | char* GetVersionText(char* buffer) 103 | { 104 | if(this->IsUnknown()) 105 | { 106 | strcpy(buffer, "UNKNOWN GAME"); 107 | return buffer; 108 | } 109 | 110 | const char* g = this->IsIII() ? "III" : this->IsVC() ? "VC" : this->IsSA() ? "SA" : this->IsIV() ? "IV" : this->IsEFLC() ? "EFLC" : "UNK"; 111 | const char* r = this->IsUS()? "US" : this->IsEU()? "EURO" : "UNK_REGION"; 112 | const char* s = this->IsSteam()? "Steam" : ""; 113 | sprintf(buffer, "GTA %s %d.%d.%d.%d %s%s", g, major, minor, majorRevision, minorRevision, r, s); 114 | return buffer; 115 | } 116 | 117 | 118 | public: 119 | // Raises a error saying that you could not detect the game version 120 | void RaiseCouldNotDetect() 121 | { 122 | MessageBoxA(0, 123 | "Could not detect the game version\nContact the mod creator!", 124 | PluginName, MB_ICONERROR 125 | ); 126 | } 127 | 128 | // Raises a error saying that the exe version is incompatible (and output the exe name) 129 | void RaiseIncompatibleVersion() 130 | { 131 | char buf[128], v[32]; 132 | sprintf(buf, 133 | "An incompatible exe version has been detected! (%s)\nContact the mod creator!", 134 | GetVersionText(v) 135 | ); 136 | MessageBoxA(0, buf, PluginName, MB_ICONERROR); 137 | } 138 | }; 139 | #else // INJECTOR_GVM_DUMMY 140 | class game_version_manager 141 | { 142 | public: 143 | bool Detect() { return true; } 144 | }; 145 | #endif // INJECTOR_GVM_DUMMY 146 | #endif // INJECTOR_OWN_GVM 147 | 148 | 149 | /* 150 | * address_manager 151 | * Address translator from 1.0 executables to other executables offsets 152 | * Inherits from game_version_manager ;) 153 | */ 154 | class address_manager : public game_version_manager 155 | { 156 | private: 157 | address_manager() 158 | { 159 | this->Detect(); 160 | } 161 | 162 | // You could implement your translator for the address your plugin uses 163 | // If not implemented, the translator won't translate anything, just return the samething as before 164 | #ifdef INJECTOR_GVM_HAS_TRANSLATOR 165 | void* translator(void* p); 166 | #else 167 | void* translator(void* p) { return p; } 168 | #endif 169 | 170 | public: 171 | // Translates address p to the running executable pointer 172 | void* translate(void* p) 173 | { 174 | return translator(p); 175 | } 176 | 177 | 178 | public: 179 | // Address manager singleton 180 | static address_manager& singleton() 181 | { 182 | static address_manager m; 183 | return m; 184 | } 185 | 186 | // Static version of translate() 187 | static void* translate_address(void* p) 188 | { 189 | return singleton().translate(p); 190 | } 191 | 192 | // 193 | static void set_name(const char* modname) 194 | { 195 | singleton().PluginName = modname; 196 | } 197 | 198 | public: 199 | // Functors for memory translation: 200 | 201 | // Translates aslr translator 202 | struct fn_mem_translator_aslr 203 | { 204 | void* operator()(void* p) const 205 | { 206 | static uintptr_t module = (uintptr_t)GetModuleHandle(NULL); 207 | return (void*)((uintptr_t)(p)-(0x400000 - module)); 208 | } 209 | }; 210 | 211 | // Translates nothing translator 212 | struct fn_mem_translator_nop 213 | { 214 | void* operator()(void* p) const 215 | { return p; } 216 | }; 217 | 218 | // Real translator 219 | struct fn_mem_translator 220 | { 221 | void* operator()(void* p) const 222 | { return translate_address(p); } 223 | }; 224 | }; 225 | 226 | #endif // #if 1 227 | 228 | 229 | } -------------------------------------------------------------------------------- /include/injector/gvm/translator.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Injectors - Address Translation Management 3 | * 4 | * Copyright (C) 2014 LINK/2012 5 | * 6 | * This software is provided 'as-is', without any express or implied 7 | * warranty. In no event will the authors be held liable for any damages 8 | * arising from the use of this software. 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. If you use this software 16 | * in a product, an acknowledgment in the product documentation would be 17 | * appreciated but is not required. 18 | * 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 22 | * 3. This notice may not be removed or altered from any source 23 | * distribution. 24 | * 25 | */ 26 | #pragma once 27 | 28 | #if !defined(INJECTOR_GVM_HAS_TRANSLATOR) 29 | #error Missing INJECTOR_GVM_HAS_TRANSLATOR on compiler definitions 30 | #endif 31 | 32 | /* 33 | * This is a quick solution for address translations if you're too lazy to implement a proper address_manager::translator by yourself 34 | * So, just call address_translator_manager::singleton().translate(p) from your address_manager::translator and that's it. 35 | * It'll translate addresses based on 'address_translator' objects, when one gets constructed it turns into a possible translator. 36 | * At the constructor of your derived 'address_translator' make the map object to have [addr_to_translate] = translated_addr; 37 | * There's also the virtual method 'fallback' that will get called when the translation wasn't possible, you can do some fallback stuff here 38 | * (such as return the pointer as is or output a error message) 39 | */ 40 | 41 | #include "../injector.hpp" 42 | #include 43 | #include 44 | #include 45 | 46 | namespace injector 47 | { 48 | /* 49 | * address_translator 50 | * Base for an address translator 51 | */ 52 | class address_translator 53 | { 54 | private: 55 | bool enabled; 56 | void add(); 57 | void remove(); 58 | 59 | protected: 60 | friend class address_translator_manager; 61 | std::map map; 62 | 63 | public: 64 | address_translator() : enabled(true) 65 | { 66 | // Must have bounds filled with min ptr and max ptr to have search working properly 67 | map.insert(std::make_pair(raw_ptr(0x00000000u), raw_ptr(0x00000000u))); 68 | map.insert(std::make_pair(raw_ptr(0xffffffffu), raw_ptr(0xffffffffu))); 69 | add(); 70 | } 71 | 72 | ~address_translator() 73 | { 74 | remove(); 75 | } 76 | 77 | virtual void* fallback(void*) const 78 | { 79 | return nullptr; 80 | } 81 | 82 | 83 | // Enables or disables this translator 84 | void enable(bool enable_it) 85 | { 86 | if(enable_it) this->enable(); 87 | else this->disable(); 88 | } 89 | 90 | // Enables this translator 91 | void enable() 92 | { 93 | this->enabled = true; 94 | } 95 | 96 | // Disables this translator 97 | void disable() 98 | { 99 | this->enabled = false; 100 | } 101 | 102 | // Checks if this translator is enabled 103 | bool is_enabled() const 104 | { 105 | return enabled; 106 | } 107 | }; 108 | 109 | /* 110 | * address_translator_manager 111 | * Manages the address_translator objects 112 | */ 113 | class address_translator_manager 114 | { 115 | protected: 116 | friend class address_manager; 117 | friend class address_translator; 118 | 119 | std::list translators; 120 | 121 | void add(const address_translator& t) 122 | { 123 | translators.push_front(&t); 124 | } 125 | 126 | void remove(const address_translator& t) 127 | { 128 | translators.remove(&t); 129 | } 130 | 131 | public: 132 | // Translates the address p 133 | void* translator(void* p); 134 | 135 | // Singleton object 136 | static address_translator_manager& singleton() 137 | { 138 | static address_translator_manager mgr; 139 | return mgr; 140 | } 141 | }; 142 | 143 | 144 | 145 | inline void* address_translator_manager::translator(void* p_) 146 | { 147 | static const size_t max_ptr_dist = 7; 148 | 149 | // Tries to find an address in a translator map 150 | auto try_map = [](const std::map& map, memory_pointer_raw p) -> memory_pointer_raw 151 | { 152 | memory_pointer_raw result = nullptr; 153 | 154 | // Find first element in the map that is greater than or equal to p 155 | auto it = map.lower_bound(p); 156 | if(it != map.end()) 157 | { 158 | // If it's not exactly the address, get back one position on the table 159 | if(it->first != p) --it; 160 | 161 | auto diff = (p - it->first).as_int(); // What's the difference between p and that address? 162 | if(diff <= max_ptr_dist) // Could we live with this difference in hands? 163 | result = it->second + raw_ptr(diff); // Yes, we can! 164 | } 165 | 166 | return result; 167 | }; 168 | 169 | 170 | // 171 | memory_pointer_raw result = nullptr; 172 | 173 | // Try to find translation for this pointer 174 | auto& mgr = address_translator_manager::singleton().translators; 175 | for(auto it = mgr.begin(); result == nullptr && it != mgr.end(); ++it) 176 | { 177 | auto& t = **it; 178 | if(t.is_enabled()) result = try_map(t.map, p_); 179 | } 180 | 181 | // If we couldn't translate the address, notify and try to fallback 182 | if(result.is_null()) 183 | { 184 | for(auto it = mgr.begin(); result == nullptr && it != mgr.end(); ++it) 185 | { 186 | auto& t = **it; 187 | if(t.is_enabled()) result = t.fallback(p_); 188 | } 189 | } 190 | 191 | return result.get(); 192 | } 193 | 194 | inline void address_translator::add() 195 | { 196 | address_translator_manager::singleton().add(*this); 197 | } 198 | 199 | inline void address_translator::remove() 200 | { 201 | address_translator_manager::singleton().remove(*this); 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /include/injector/utility.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Injectors - Utility / Helpers 3 | * 4 | * Copyright (C) 2014 LINK/2012 5 | * 6 | * This software is provided 'as-is', without any express or implied 7 | * warranty. In no event will the authors be held liable for any damages 8 | * arising from the use of this software. 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. If you use this software 16 | * in a product, an acknowledgment in the product documentation would be 17 | * appreciated but is not required. 18 | * 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 22 | * 3. This notice may not be removed or altered from any source 23 | * distribution. 24 | * 25 | */ 26 | #pragma once 27 | 28 | namespace injector 29 | { 30 | template 31 | T return_value() 32 | { 33 | return value; 34 | } 35 | 36 | template 37 | void* force_ptr(const T& fun) 38 | { 39 | auto ptr = fun; 40 | return *(void**)&ptr; 41 | } 42 | 43 | 44 | // Helper structure to help calling back what was there before a hook 45 | // e.g. hb.fun = MakeCALL(0x0, raw_ptr(my_hook)); 46 | template 47 | struct hook_back 48 | { 49 | typedef FuncType func_type; 50 | 51 | func_type fun; 52 | 53 | hook_back() : fun(nullptr) 54 | {} 55 | }; 56 | }; 57 | -------------------------------------------------------------------------------- /include/kiero/MinHook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) 32 | #error MinHook supports only x86 and x64 systems. 33 | #endif 34 | 35 | #include 36 | 37 | // MinHook Error Codes. 38 | typedef enum MH_STATUS 39 | { 40 | // Unknown error. Should not be returned. 41 | MH_UNKNOWN = -1, 42 | 43 | // Successful. 44 | MH_OK = 0, 45 | 46 | // MinHook is already initialized. 47 | MH_ERROR_ALREADY_INITIALIZED, 48 | 49 | // MinHook is not initialized yet, or already uninitialized. 50 | MH_ERROR_NOT_INITIALIZED, 51 | 52 | // The hook for the specified target function is already created. 53 | MH_ERROR_ALREADY_CREATED, 54 | 55 | // The hook for the specified target function is not created yet. 56 | MH_ERROR_NOT_CREATED, 57 | 58 | // The hook for the specified target function is already enabled. 59 | MH_ERROR_ENABLED, 60 | 61 | // The hook for the specified target function is not enabled yet, or already 62 | // disabled. 63 | MH_ERROR_DISABLED, 64 | 65 | // The specified pointer is invalid. It points the address of non-allocated 66 | // and/or non-executable region. 67 | MH_ERROR_NOT_EXECUTABLE, 68 | 69 | // The specified target function cannot be hooked. 70 | MH_ERROR_UNSUPPORTED_FUNCTION, 71 | 72 | // Failed to allocate memory. 73 | MH_ERROR_MEMORY_ALLOC, 74 | 75 | // Failed to change the memory protection. 76 | MH_ERROR_MEMORY_PROTECT, 77 | 78 | // The specified module is not loaded. 79 | MH_ERROR_MODULE_NOT_FOUND, 80 | 81 | // The specified function is not found. 82 | MH_ERROR_FUNCTION_NOT_FOUND 83 | } 84 | MH_STATUS; 85 | 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, 87 | // MH_QueueEnableHook or MH_QueueDisableHook. 88 | #define MH_ALL_HOOKS NULL 89 | 90 | #ifdef __cplusplus 91 | extern "C" { 92 | #endif 93 | 94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE 95 | // at the beginning of your program. 96 | MH_STATUS WINAPI MH_Initialize(VOID); 97 | 98 | // Uninitialize the MinHook library. You must call this function EXACTLY 99 | // ONCE at the end of your program. 100 | MH_STATUS WINAPI MH_Uninitialize(VOID); 101 | 102 | // Creates a Hook for the specified target function, in disabled state. 103 | // Parameters: 104 | // pTarget [in] A pointer to the target function, which will be 105 | // overridden by the detour function. 106 | // pDetour [in] A pointer to the detour function, which will override 107 | // the target function. 108 | // ppOriginal [out] A pointer to the trampoline function, which will be 109 | // used to call the original target function. 110 | // This parameter can be NULL. 111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); 112 | 113 | // Creates a Hook for the specified API function, in disabled state. 114 | // Parameters: 115 | // pszModule [in] A pointer to the loaded module name which contains the 116 | // target function. 117 | // pszTarget [in] A pointer to the target function name, which will be 118 | // overridden by the detour function. 119 | // pDetour [in] A pointer to the detour function, which will override 120 | // the target function. 121 | // ppOriginal [out] A pointer to the trampoline function, which will be 122 | // used to call the original target function. 123 | // This parameter can be NULL. 124 | MH_STATUS WINAPI MH_CreateHookApi( 125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); 126 | 127 | // Creates a Hook for the specified API function, in disabled state. 128 | // Parameters: 129 | // pszModule [in] A pointer to the loaded module name which contains the 130 | // target function. 131 | // pszTarget [in] A pointer to the target function name, which will be 132 | // overridden by the detour function. 133 | // pDetour [in] A pointer to the detour function, which will override 134 | // the target function. 135 | // ppOriginal [out] A pointer to the trampoline function, which will be 136 | // used to call the original target function. 137 | // This parameter can be NULL. 138 | // ppTarget [out] A pointer to the target function, which will be used 139 | // with other functions. 140 | // This parameter can be NULL. 141 | MH_STATUS WINAPI MH_CreateHookApiEx( 142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); 143 | 144 | // Removes an already created hook. 145 | // Parameters: 146 | // pTarget [in] A pointer to the target function. 147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 148 | 149 | // Enables an already created hook. 150 | // Parameters: 151 | // pTarget [in] A pointer to the target function. 152 | // If this parameter is MH_ALL_HOOKS, all created hooks are 153 | // enabled in one go. 154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 155 | 156 | // Disables an already created hook. 157 | // Parameters: 158 | // pTarget [in] A pointer to the target function. 159 | // If this parameter is MH_ALL_HOOKS, all created hooks are 160 | // disabled in one go. 161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 162 | 163 | // Queues to enable an already created hook. 164 | // Parameters: 165 | // pTarget [in] A pointer to the target function. 166 | // If this parameter is MH_ALL_HOOKS, all created hooks are 167 | // queued to be enabled. 168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 169 | 170 | // Queues to disable an already created hook. 171 | // Parameters: 172 | // pTarget [in] A pointer to the target function. 173 | // If this parameter is MH_ALL_HOOKS, all created hooks are 174 | // queued to be disabled. 175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 176 | 177 | // Applies all queued changes in one go. 178 | MH_STATUS WINAPI MH_ApplyQueued(VOID); 179 | 180 | // Translates the MH_STATUS to its name as a string. 181 | const char * WINAPI MH_StatusToString(MH_STATUS status); 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | -------------------------------------------------------------------------------- /include/kiero/kiero.h: -------------------------------------------------------------------------------- 1 | #ifndef __KIERO_H__ 2 | #define __KIERO_H__ 3 | 4 | #include 5 | 6 | #define KIERO_VERSION "1.2.12" 7 | 8 | #define KIERO_INCLUDE_D3D9 1 // 1 if you need D3D9 hook 9 | #define KIERO_INCLUDE_D3D10 0 // 1 if you need D3D10 hook 10 | #define KIERO_INCLUDE_D3D11 1 // 1 if you need D3D11 hook 11 | #define KIERO_INCLUDE_D3D12 0 // 1 if you need D3D12 hook 12 | #define KIERO_INCLUDE_OPENGL 1 // 1 if you need OpenGL hook 13 | #define KIERO_INCLUDE_VULKAN 0 // 1 if you need Vulkan hook 14 | #define KIERO_USE_MINHOOK 1 // 1 if you will use kiero::bind function 15 | 16 | #define KIERO_ARCH_X64 0 17 | #define KIERO_ARCH_X86 0 18 | 19 | #if defined(_M_X64) 20 | # undef KIERO_ARCH_X64 21 | # define KIERO_ARCH_X64 1 22 | #else 23 | # undef KIERO_ARCH_X86 24 | # define KIERO_ARCH_X86 1 25 | #endif 26 | 27 | #if KIERO_ARCH_X64 28 | typedef uint64_t uint150_t; 29 | #else 30 | typedef uint32_t uint150_t; 31 | #endif 32 | 33 | namespace kiero 34 | { 35 | struct Status 36 | { 37 | enum Enum 38 | { 39 | UnknownError = -1, 40 | NotSupportedError = -2, 41 | ModuleNotFoundError = -3, 42 | 43 | AlreadyInitializedError = -4, 44 | NotInitializedError = -5, 45 | 46 | Success = 0, 47 | }; 48 | }; 49 | 50 | struct RenderType 51 | { 52 | enum Enum 53 | { 54 | None, 55 | 56 | D3D9, 57 | D3D10, 58 | D3D11, 59 | D3D12, 60 | 61 | OpenGL, 62 | Vulkan, 63 | 64 | Auto 65 | }; 66 | }; 67 | 68 | Status::Enum init(RenderType::Enum renderType); 69 | void shutdown(); 70 | 71 | Status::Enum bind(uint16_t index, void** original, void* function); 72 | void unbind(uint16_t index); 73 | 74 | RenderType::Enum getRenderType(); 75 | uint150_t* getMethodsTable(); 76 | } 77 | 78 | #endif // __KIERO_H__ -------------------------------------------------------------------------------- /lib/CLEO.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/lib/CLEO.lib -------------------------------------------------------------------------------- /lib/cleo_redux.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/lib/cleo_redux.lib -------------------------------------------------------------------------------- /lib/cleo_redux64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/lib/cleo_redux64.lib -------------------------------------------------------------------------------- /lib/d3dx9.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/lib/d3dx9.lib -------------------------------------------------------------------------------- /lib/d3dx9x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/lib/d3dx9x64.lib -------------------------------------------------------------------------------- /lib/libMinHook-x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/lib/libMinHook-x64.lib -------------------------------------------------------------------------------- /lib/libMinHook-x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/lib/libMinHook-x86.lib -------------------------------------------------------------------------------- /src/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "opcodemgr.h" 3 | #include "hook.h" 4 | #include "wrapper.hpp" 5 | 6 | #include 7 | #include 8 | 9 | HINSTANCE gDllHandle; 10 | 11 | DWORD GetProcessIdFromModule(HMODULE hModule) { 12 | DWORD processId = 0; 13 | HANDLE hProcess = NULL; 14 | MODULEINFO moduleInfo; 15 | 16 | hProcess = GetCurrentProcess(); 17 | if (hProcess != NULL) { 18 | if (GetModuleInformation(hProcess, hModule, &moduleInfo, sizeof(moduleInfo))) { 19 | processId = GetProcessId(hProcess); 20 | } 21 | CloseHandle(hProcess); 22 | } 23 | 24 | return processId; 25 | } 26 | 27 | BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { 28 | DWORD processId = 0; 29 | GetWindowThreadProcessId(hwnd, &processId); 30 | 31 | if (processId == static_cast(lParam)) { 32 | return FALSE; // Stop 33 | } 34 | return TRUE; // Continue 35 | } 36 | 37 | bool HasGameLaunched(HMODULE hModule, int maxRetries, int sleepDuration) { 38 | DWORD processId = GetProcessIdFromModule(hModule); 39 | if (processId == 0) { 40 | MessageBox(NULL, "Failed to get process ID", "ImGuiRedux", MB_ICONERROR); 41 | return false; 42 | } 43 | 44 | int retries = 0; 45 | while (retries < maxRetries) { 46 | Sleep(sleepDuration); 47 | if (!EnumWindows(EnumWindowsProc, static_cast(processId))) { 48 | return true; 49 | } 50 | retries++; 51 | } 52 | MessageBox(NULL, "Failed to detect game window.", "ImGuiRedux", MB_ICONERROR); 53 | return false; 54 | } 55 | 56 | void ImGuiThread(void* param) { 57 | if (!HasGameLaunched(gDllHandle, 30, 5000)) { 58 | return; 59 | } 60 | 61 | if (gGameVer <= eGameVer::SA) { 62 | std::string moduleName = "SilentPatchSA.asi"; 63 | if (gGameVer == eGameVer::VC) { 64 | moduleName = "SilentPatchVC.asi"; 65 | } else if (gGameVer == eGameVer::III) { 66 | moduleName = "SilentPatchIII.asi"; 67 | } 68 | 69 | if (!GetModuleHandle(moduleName.c_str())) { 70 | int msgID = MessageBox(NULL, "SilentPatch not found. Do you want to install Silent Patch? (Game restart required)", "ImGuiRedux", MB_OKCANCEL | MB_DEFBUTTON1); 71 | if (msgID == IDOK) { 72 | ShellExecute(nullptr, "open", "https://gtaforums.com/topic/669045-silentpatch/", nullptr, nullptr, SW_SHOWNORMAL); 73 | }; 74 | return; 75 | } 76 | } 77 | 78 | if (!Hook::Inject(&ScriptExData::RenderFrames)) { 79 | MessageBox(HWND_DESKTOP, "Failed to inject dxhook..", "ImGuiRedux", MB_ICONERROR); 80 | } 81 | 82 | while (true) { 83 | Sleep(5000); 84 | } 85 | } 86 | 87 | void __stdcall _wrapper(DWORD saveSlot) { 88 | ScriptExData::Clear(); 89 | } 90 | 91 | BOOL WINAPI DllMain(HINSTANCE hDllHandle, DWORD nReason, LPVOID Reserved) { 92 | if (nReason == DLL_PROCESS_ATTACH) { 93 | #ifdef RUNTIME_CLEO 94 | CLEO::eGameVersion ver = CLEO::CLEO_GetGameVersion(); 95 | if (ver != CLEO::eGameVersion::GV_US10) { 96 | MessageBox(HWND_DESKTOP, "Unknown game/ version detected. gta_sa.exe v1.0 US required!", "ImGuiRedux", MB_ICONERROR); 97 | } 98 | gGameVer = eGameVer::SA; 99 | #else 100 | if (GetModuleHandle("ImGuiCleoWin32.cleo")) { 101 | Log("ImGuiReduxWin32: ImGuiCleoWin32 detected. Closing..."); 102 | return TRUE; 103 | } 104 | 105 | auto id = GetHostId(); 106 | if (id == HostId::GTA3) gGameVer = eGameVer::III; 107 | if (id == HostId::VC) gGameVer = eGameVer::VC; 108 | if (id == HostId::SA) gGameVer = eGameVer::SA; 109 | if (id == HostId::IV) gGameVer = eGameVer::IV; 110 | if (id == HostId::GTA3_UNREAL) gGameVer = eGameVer::III_DE; 111 | if (id == HostId::VC_UNREAL) gGameVer = eGameVer::VC_DE; 112 | if (id == HostId::SA_UNREAL) gGameVer = eGameVer::SA_DE; 113 | if (id == HostId::BULLY) gGameVer = eGameVer::BullySE; 114 | #endif 115 | 116 | #ifdef RUNTIME_CLEO 117 | CLEO::CLEO_RegisterCallback(CLEO::eCallbackId::GameBegin, _wrapper); 118 | #else 119 | OnRuntimeInit((OnRuntimeInitCallback)ScriptExData::Clear); 120 | #endif 121 | 122 | OpcodeMgr::RegisterCommands(); 123 | CreateThread(nullptr, NULL, (LPTHREAD_START_ROUTINE)&ImGuiThread, nullptr, NULL, nullptr); 124 | } 125 | 126 | return TRUE; 127 | } 128 | -------------------------------------------------------------------------------- /src/hook.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "hook.h" 3 | #include "kiero.h" 4 | #include "MinHook.h" 5 | #include "imgui_impl_dx9.h" 6 | #include "imgui_impl_dx11.h" 7 | #include "imgui_impl_opengl3.h" 8 | #include "imgui_impl_win32.h" 9 | #include "injector.hpp" 10 | #include "font.h" 11 | #include "kiero.h" 12 | #include "scriptextender.hpp" 13 | 14 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 15 | 16 | static const ImWchar* GetGlyphRanges() { 17 | static const ImWchar ranges[] = { 18 | 0x0020, 0x00FF, // Basic Latin + Latin Supplement 19 | 0x0980, 0x09FF, // Bengali 20 | 0x2000, 0x206F, // General Punctuation 21 | 22 | // Chinease 23 | // 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana 24 | // 0x31F0, 0x31FF, // Katakana Phonetic Extensions 25 | // 0xFF00, 0xFFEF, // Half-width characters 26 | // 0xFFFD, 0xFFFD, // Invalid 27 | // 0x4E00, 0x9FAF, // CJK Ideograms 28 | 29 | // Cyrillic 30 | 0x0400, 0x052F, // Cyrillic + Cyrillic Supplement 31 | 0x2DE0, 0x2DFF, // Cyrillic Extended-A 32 | 0xA640, 0xA69F, // Cyrillic Extended-B 33 | 34 | //Turkish 35 | 0x011E, 0x011F, 36 | 0x015E, 0x015F, 37 | 0x0130, 0x0131, 38 | 0, 39 | }; 40 | return &ranges[0]; 41 | } 42 | 43 | bool Hook::GetMouseState() { 44 | return mouseVisible; 45 | } 46 | 47 | void Hook::SetMouseState(bool state) { 48 | mouseVisible = state; 49 | } 50 | 51 | LRESULT Hook::hkWndProc(const HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 52 | if (m_bInitialized) { 53 | ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam); 54 | 55 | if (ImGui::GetIO().WantTextInput || (gGameVer > eGameVer::SA && mouseVisible)) { 56 | #ifndef _WIN64 57 | if (gGameVer == eGameVer::SA) { 58 | reinterpret_cast(0x53F1E0)(); // CPad::ClearKeyboardHistory 59 | } 60 | #endif 61 | return 1; 62 | } 63 | } 64 | 65 | return CallWindowProc(oWndProc, hWnd, uMsg, wParam, lParam); 66 | } 67 | 68 | HRESULT Hook::hkReset(IDirect3DDevice9* pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters) { 69 | ImGui_ImplDX9_InvalidateDeviceObjects(); 70 | 71 | return oReset(pDevice, pPresentationParameters); 72 | } 73 | 74 | void Hook::ProcessFrame(void* ptr) { 75 | if (m_bInitialized) { 76 | ProcessMouse(); 77 | 78 | // Scale the menu if game resolution changed 79 | static int height, width, RsGlobal; 80 | 81 | #ifndef _WIN64 82 | if (gGameVer == eGameVer::III) { 83 | RsGlobal = 0x8F4360; 84 | width = injector::ReadMemory(RsGlobal + 4, 0); // width 85 | height = injector::ReadMemory(RsGlobal + 8, 0); // height 86 | } else if (gGameVer == eGameVer::VC) { 87 | RsGlobal = 0x9B48D8; 88 | width = injector::ReadMemory(RsGlobal + 4, 0); // width 89 | height = injector::ReadMemory(RsGlobal + 8, 0); // height 90 | } else if (gGameVer == eGameVer::SA) { 91 | RsGlobal = 0xC17040; 92 | width = injector::ReadMemory(RsGlobal + 4, 0); // width 93 | height = injector::ReadMemory(RsGlobal + 8, 0); // height 94 | } else { 95 | RECT rect; 96 | GetWindowRect(hwnd, &rect); 97 | width = rect.right - rect.left; 98 | height = rect.bottom - rect.top; 99 | } 100 | #else 101 | RECT rect; 102 | GetWindowRect(hwnd, &rect); 103 | width = rect.right - rect.left; 104 | height = rect.bottom - rect.top; 105 | #endif 106 | 107 | static ImVec2 fScreenSize = ImVec2(-1, -1); 108 | if (fScreenSize.x != width && fScreenSize.y != height) { 109 | if (gRenderer == eRenderer::Dx9) { 110 | ImGui_ImplDX9_InvalidateDeviceObjects(); 111 | } else if (gRenderer == eRenderer::Dx11) { 112 | ImGui_ImplDX11_InvalidateDeviceObjects(); 113 | } 114 | 115 | ImGuiIO& io = ImGui::GetIO(); 116 | io.Fonts->Clear(); 117 | float fontSize = height / 48.0f; 118 | io.FontDefault = io.Fonts->AddFontFromMemoryCompressedBase85TTF(fontData, fontSize, NULL, GetGlyphRanges()); 119 | io.Fonts->Build(); 120 | 121 | ImGuiStyle* style = &ImGui::GetStyle(); 122 | float scaleX = width / 1366.0f; 123 | float scaleY = height / 768.0f; 124 | 125 | style->TabRounding = 0.0f; 126 | style->ChildBorderSize = 0; 127 | style->WindowBorderSize = 0; 128 | style->FrameBorderSize = 0; 129 | style->TabBorderSize = 0; 130 | style->PopupBorderSize = 0; 131 | style->FramePadding = ImVec2(5 * scaleX, 3 * scaleY); 132 | style->ItemSpacing = ImVec2(4 * scaleY, 4 * scaleY); 133 | style->ScrollbarSize = 12 * scaleX; 134 | style->IndentSpacing = 20 * scaleX; 135 | style->ItemInnerSpacing = ImVec2(4 * scaleY, 4 * scaleY); 136 | style->Colors[ImGuiCol_Header] = ImVec4(0.0f, 0.0f, 0.0f, 0.00f); 137 | style->Colors[ImGuiCol_ResizeGrip] = ImVec4(0.0f, 0.0f, 0.0f, 0.00f); 138 | style->WindowTitleAlign = ImVec2(0.5f, 0.5f); 139 | fScreenSize = ImVec2((float)width, (float)height); 140 | ScriptExData::SetScaling({scaleX, scaleY}); 141 | } 142 | 143 | ScriptExData::InitRenderStates(); 144 | 145 | ImGui_ImplWin32_NewFrame(); 146 | if (gRenderer == eRenderer::Dx9) { 147 | ImGui_ImplDX9_NewFrame(); 148 | } else if (gRenderer == eRenderer::Dx11) { 149 | ImGui_ImplDX11_NewFrame(); 150 | } else { 151 | ImGui_ImplOpenGL3_NewFrame(); 152 | } 153 | 154 | ImGui::NewFrame(); 155 | 156 | if (pCallbackFunc != nullptr) { 157 | static_cast(pCallbackFunc)(); 158 | } 159 | 160 | ImGui::EndFrame(); 161 | ImGui::Render(); 162 | 163 | if (gRenderer == eRenderer::Dx9) { 164 | ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData()); 165 | } else if (gRenderer == eRenderer::Dx11) { 166 | pDeviceContext->OMSetRenderTargets(1, &pRenderTargetView, NULL); 167 | ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); 168 | } else { 169 | ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); 170 | } 171 | } else { 172 | if (!ImGui::GetCurrentContext()) { 173 | ImGui::CreateContext(); 174 | } 175 | 176 | if (gGameVer == eGameVer::SA) { 177 | injector::MakeNOP(0x531155, 5); // shift trigger fix 178 | } 179 | 180 | if (gRenderer == eRenderer::Dx9) { 181 | hwnd = GetForegroundWindow(); 182 | if (!ImGui_ImplWin32_Init(hwnd)) { 183 | return; 184 | } 185 | 186 | if (!ImGui_ImplDX9_Init(reinterpret_cast(ptr))) { 187 | return; 188 | } 189 | gD3DDevice = ptr; 190 | } else if (gRenderer == eRenderer::Dx11) { 191 | IDXGISwapChain* pSwapChain = reinterpret_cast(ptr); 192 | if (SUCCEEDED(pSwapChain->GetDevice(__uuidof(ID3D11Device), &ptr))) { 193 | ID3D11Device *pDevice = reinterpret_cast(ptr); 194 | pDevice->GetImmediateContext(&pDeviceContext); 195 | 196 | DXGI_SWAP_CHAIN_DESC Desc; 197 | pSwapChain->GetDesc(&Desc); 198 | hwnd = Desc.OutputWindow; 199 | 200 | ID3D11Texture2D* backBuffer; 201 | pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBuffer); 202 | pDevice->CreateRenderTargetView(backBuffer, NULL, &pRenderTargetView); 203 | backBuffer->Release(); 204 | 205 | if (!ImGui_ImplWin32_Init(hwnd)) { 206 | return; 207 | } 208 | ImGui_ImplDX11_Init(pDevice, pDeviceContext); 209 | ImGui_ImplDX11_CreateDeviceObjects(); 210 | ImGui::GetIO().ImeWindowHandle = hwnd; 211 | } 212 | 213 | gD3DDevice = ptr; 214 | } else { 215 | hwnd = GetForegroundWindow(); 216 | if (!ImGui_ImplWin32_Init(hwnd)) { 217 | return; 218 | } 219 | 220 | if(!ImGui_ImplOpenGL3_Init()) { 221 | return; 222 | } 223 | } 224 | 225 | ImGui_ImplWin32_EnableDpiAwareness(); 226 | 227 | ShowCursor(false); 228 | ImGuiIO& io = ImGui::GetIO(); 229 | io.IniFilename = nullptr; 230 | io.LogFilename = nullptr; 231 | io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_NoMouseCursorChange; 232 | 233 | oWndProc = (WNDPROC)SetWindowLongPtr(hwnd, -4, (LRESULT)hkWndProc); // GWL_WNDPROC = -4 234 | m_bInitialized = true; 235 | } 236 | } 237 | 238 | HRESULT Hook::hkEndScene(IDirect3DDevice9* pDevice) { 239 | ProcessFrame(pDevice); 240 | return oEndScene(pDevice); 241 | } 242 | 243 | HRESULT Hook::hkPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags) { 244 | ProcessFrame(pSwapChain); 245 | return oPresent(pSwapChain, SyncInterval, Flags); 246 | } 247 | 248 | HRESULT Hook::hkResizeBuffers(IDXGISwapChain* pSwapChain, UINT a, UINT b, UINT c, DXGI_FORMAT d, UINT e) { 249 | if (pRenderTargetView) { 250 | pRenderTargetView->Release(); 251 | pRenderTargetView = nullptr; 252 | pDeviceContext->Flush(); 253 | } 254 | 255 | HRESULT hr = oResizeBuffers(pSwapChain, a, b, c, d, e); 256 | ID3D11Texture2D* back_buffer{}; 257 | pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&back_buffer); 258 | reinterpret_cast(pSwapChain)->CreateRenderTargetView(back_buffer, nullptr, &pRenderTargetView); 259 | back_buffer->Release(); 260 | return hr; 261 | } 262 | 263 | bool Hook::hkGlSwapBuffer(HDC unnamedParam1, UINT unnamedParam2) { 264 | ProcessFrame(nullptr); 265 | return oGlSwapBuffer(unnamedParam1, unnamedParam2); 266 | } 267 | 268 | void Hook::ProcessMouse() { 269 | static bool curState = false; 270 | if (curState != mouseVisible) { 271 | ImGui::GetIO().MouseDrawCursor = mouseVisible; 272 | 273 | /* 274 | Skip mouse patches on unknown host 275 | ImGui menus should be interactive on game menu 276 | */ 277 | #ifndef _WIN64 278 | if (gGameVer == eGameVer::SA) { 279 | if (ImGui::GetIO().MouseDrawCursor) { 280 | injector::WriteMemory(0x6194A0, 0xC3, true); 281 | injector::MakeNOP(0x541DD7, 5, true); 282 | } else { 283 | injector::WriteMemory(0x6194A0, 0xE9, true); 284 | injector::WriteMemoryRaw(0x541DD7, (char*)"\xE8\xE4\xD5\xFF\xFF", 5, true); 285 | } 286 | 287 | // ClearMouseStates 288 | injector::WriteMemory(0xB73418 + 12, 0, true); // X 289 | injector::WriteMemory(0xB73418 + 16, 0, true); // Y 290 | 291 | reinterpret_cast(0x541BD0)(); // CPad::ClearMouseHistory(); 292 | reinterpret_cast(0x541DD0)(); // CPad::UpdatePads(); 293 | } else if (gGameVer == eGameVer::VC) { 294 | if (ImGui::GetIO().MouseDrawCursor) { 295 | injector::WriteMemory(0x6020A0, 0xC3, true); 296 | injector::MakeNOP(0x4AB6CA, 5, true); 297 | } else { 298 | injector::WriteMemory(0x6020A0, 0x53, true); 299 | injector::WriteMemoryRaw(0x4AB6CA, (char*)"\xE8\x51\x21\x00\x00", 5, true); 300 | } 301 | 302 | // ClearMouseStates 303 | injector::WriteMemory(0x94D788 + 8, 0, true); // X 304 | injector::WriteMemory(0x94D788 + 12, 0, true);// Y 305 | 306 | reinterpret_cast(0x4ADB30)(); // CPad::ClearMouseHistory(); 307 | reinterpret_cast(0x4AB6C0)(); // CPad::UpdatePads(); 308 | } else if (gGameVer == eGameVer::III) { 309 | if (ImGui::GetIO().MouseDrawCursor) { 310 | injector::WriteMemory(0x580D20, 0xC3, true); 311 | injector::MakeNOP(0x49272F, 5, true); 312 | } else { 313 | injector::WriteMemory(0x580D20, 0x53, true); 314 | injector::WriteMemoryRaw(0x49272F, (char*)"\xE8\x6C\xF5\xFF\xFF", 5, true); 315 | } 316 | 317 | // ClearMouseStates 318 | injector::WriteMemory(0x8809F0 + 8, 0, true); // X 319 | injector::WriteMemory(0x8809F0 + 12, 0, true);// Y 320 | 321 | int pad = reinterpret_cast(0x492F60)(NULL); // CPad::GetPads(); 322 | reinterpret_cast(0x491B50)(pad); // CPad::ClearMouseHistory(); 323 | reinterpret_cast(0x492720)(); // CPad::UpdatePads(); 324 | } 325 | #endif 326 | 327 | curState = mouseVisible; 328 | } 329 | } 330 | 331 | static bool IsKeyPressed(int i, LPVOID data) { 332 | return reinterpret_cast(data)[i] & 0x80; 333 | } 334 | 335 | HRESULT CALLBACK Hook::hkGetDeviceState(IDirectInputDevice8* pThis, DWORD cbData, LPVOID lpvData) { 336 | HRESULT result = oGetDeviceState(pThis, cbData, lpvData); 337 | 338 | /* 339 | * We're detecting it here since usual WndProc doesn't seem to work for bully 340 | * This probably should work for other games using dinput too..? 341 | */ 342 | ImGuiIO& io = ImGui::GetIO(); 343 | if (ImGui::GetIO().MouseDrawCursor) { 344 | int frameCount = ImGui::GetFrameCount(); 345 | if (cbData == 16) { // mouse 346 | LPDIMOUSESTATE2 mouseState = reinterpret_cast(lpvData); 347 | 348 | // Block camera rotation 349 | mouseState->lX = 0; 350 | mouseState->lY = 0; 351 | io.MouseWheel = mouseState->lZ / static_cast(WHEEL_DELTA); 352 | mouseState->lZ = 0; 353 | 354 | static int mouseCount = -1; 355 | if (frameCount != mouseCount) { 356 | io.MouseDown[0] = (mouseState->rgbButtons[0] != 0); 357 | io.MouseDown[1] = (mouseState->rgbButtons[1] != 0); 358 | mouseCount = frameCount; 359 | } 360 | 361 | // Block left & right clicks 362 | mouseState->rgbButtons[0] = 0; 363 | mouseState->rgbButtons[1] = 0; 364 | } else if (cbData == 256) { // keyboard 365 | /* 366 | * GetDeviceData doesn't work 367 | */ 368 | static int keyCount = -1; 369 | if (frameCount != keyCount) { 370 | io.KeyAlt = IsKeyPressed(DIK_LALT, lpvData) || IsKeyPressed(DIK_RALT, lpvData); 371 | io.KeyCtrl = IsKeyPressed(DIK_LCONTROL, lpvData) || IsKeyPressed(DIK_RCONTROL, lpvData); 372 | io.KeyShift = IsKeyPressed(DIK_LSHIFT, lpvData) || IsKeyPressed(DIK_RSHIFT, lpvData); 373 | 374 | for (size_t i = 0; i < cbData; ++i) { 375 | bool pressed = IsKeyPressed(i, lpvData); 376 | UINT vk = MapVirtualKeyEx(i, MAPVK_VSC_TO_VK, GetKeyboardLayout(NULL)); 377 | 378 | // ignore key holds 379 | if (io.KeysDown[vk] != pressed) { 380 | if (pressed) { 381 | WCHAR c; 382 | BYTE keystate[256]; 383 | ZeroMemory(keystate, 256); 384 | ToUnicode(vk, i, keystate, &c, 1, 0); 385 | 386 | // Capital letters on shift hold 387 | if (io.KeyShift && c >= 0x61 && c <= 0x7A) { 388 | c -= 0x20; 389 | } 390 | io.AddInputCharacterUTF16(c); 391 | } 392 | io.KeysDown[vk] = pressed; 393 | } 394 | } 395 | keyCount = frameCount; 396 | } 397 | } 398 | } 399 | 400 | if (io.WantTextInput) { 401 | ZeroMemory(lpvData, 256); 402 | result = oGetDeviceState(pThis, cbData, lpvData); 403 | } 404 | return result; 405 | } 406 | 407 | bool Hook::GetDinputDevice(void** pMouse, size_t size) { 408 | if (!pMouse) { 409 | return false; 410 | } 411 | 412 | IDirectInput8* pDirectInput = NULL; 413 | 414 | // Create dummy device 415 | if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&pDirectInput, NULL) != DI_OK) { 416 | return false; 417 | } 418 | 419 | LPDIRECTINPUTDEVICE8 lpdiInput; 420 | 421 | /* 422 | * We're creating a sysMouse but it still seems to receive keyboard messages? 423 | */ 424 | if (pDirectInput->CreateDevice(GUID_SysMouse, &lpdiInput, NULL) != DI_OK) { 425 | pDirectInput->Release(); 426 | return false; 427 | } 428 | 429 | lpdiInput->SetDataFormat(&c_dfDIKeyboard); 430 | lpdiInput->SetCooperativeLevel(GetActiveWindow(), DISCL_NONEXCLUSIVE); 431 | memcpy(pMouse, *reinterpret_cast(lpdiInput), size); 432 | lpdiInput->Release(); 433 | pDirectInput->Release(); 434 | return true; 435 | } 436 | 437 | BOOL CALLBACK Hook::hkSetCursorPos(int x, int y) { 438 | if (ImGui::GetIO().MouseDrawCursor) { 439 | return true; 440 | } 441 | return oSetCursorPos(x, y); 442 | } 443 | 444 | BOOL CALLBACK Hook::hkShowCursor(bool flag) { 445 | if (ImGui::GetIO().MouseDrawCursor) { 446 | return oShowCursor(TRUE); 447 | } 448 | return oShowCursor(flag); 449 | } 450 | 451 | void Hook::InputWatcher() 452 | { 453 | while (true) 454 | { 455 | ImGuiIO& io = ImGui::GetIO(); 456 | if (io.MouseDrawCursor) { 457 | io.MouseDown[0] = (GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0; 458 | io.MouseDown[1] = (GetAsyncKeyState(VK_RBUTTON) & 0x8000) != 0; 459 | io.MouseDown[2] = (GetAsyncKeyState(VK_MBUTTON) & 0x8000) != 0; 460 | } 461 | Sleep(1); 462 | } 463 | } 464 | 465 | bool Hook::Inject(void *pCallback) { 466 | static bool injected; 467 | if (injected) { 468 | return false; 469 | } 470 | 471 | ImGui::CreateContext(); 472 | MH_Initialize(); 473 | PVOID pSetCursorPos = GetProcAddress(GetModuleHandle("user32.dll"), "SetCursorPos"); 474 | PVOID pShowCursor = GetProcAddress(GetModuleHandle("user32.dll"), "ShowCursor"); 475 | MH_CreateHook(pSetCursorPos, hkSetCursorPos, reinterpret_cast(&oSetCursorPos)); 476 | MH_CreateHook(pShowCursor, hkShowCursor, reinterpret_cast(&oShowCursor)); 477 | MH_EnableHook(pSetCursorPos); 478 | MH_EnableHook(pShowCursor); 479 | 480 | /* 481 | Must check for d3d9 first! 482 | Seems to crash with nvidia geforce experience overlay 483 | if anything else is checked before d3d9 484 | */ 485 | if (GetModuleHandle("_gtaRenderHook.asi") 486 | || gGameVer == eGameVer::III_DE || gGameVer == eGameVer::VC_DE || gGameVer == eGameVer::SA_DE) { 487 | goto dx11; 488 | } 489 | 490 | if (init(kiero::RenderType::D3D9) == kiero::Status::Success) { 491 | gRenderer = eRenderer::Dx9; 492 | injected = true; 493 | kiero::bind(16, reinterpret_cast(&oReset), hkReset); 494 | kiero::bind(42, reinterpret_cast(&oEndScene), hkEndScene); 495 | pCallbackFunc = pCallback; 496 | } 497 | 498 | if (init(kiero::RenderType::OpenGL) == kiero::Status::Success) { 499 | gRenderer = eRenderer::OpenGL; 500 | injected = true; 501 | 502 | HMODULE hMod = GetModuleHandle("OPENGL32.dll"); 503 | if (!hMod) { 504 | return false; 505 | } 506 | FARPROC addr = GetProcAddress(hMod, "wglSwapBuffers"); 507 | MH_CreateHook(addr, hkGlSwapBuffer, reinterpret_cast(&oGlSwapBuffer)); 508 | MH_EnableHook(addr); 509 | pCallbackFunc = pCallback; 510 | } 511 | 512 | dx11: 513 | if (init(kiero::RenderType::D3D11) == kiero::Status::Success) { 514 | gRenderer = eRenderer::Dx11; 515 | kiero::bind(8, reinterpret_cast(&oPresent), hkPresent); 516 | kiero::bind(13, reinterpret_cast(&oResizeBuffers), hkResizeBuffers); 517 | pCallbackFunc = pCallback; 518 | injected = true; 519 | } 520 | 521 | if (gGameVer == eGameVer::BullySE) { 522 | static void *diMouse[32]; 523 | if (GetDinputDevice(diMouse, sizeof(diMouse))) { 524 | MH_CreateHook(diMouse[9], hkGetDeviceState, reinterpret_cast(&oGetDeviceState)); 525 | MH_EnableHook(diMouse[9]); 526 | } 527 | } 528 | 529 | if (gGameVer == eGameVer::IV) { 530 | CreateThread(nullptr, 0, reinterpret_cast(InputWatcher), nullptr, 0, nullptr); 531 | } 532 | 533 | return injected; 534 | } 535 | 536 | void Hook::Remove() { 537 | pCallbackFunc = nullptr; 538 | SetWindowLongPtr(hwnd, -4, (LRESULT)oWndProc); // GWL_WNDPROC = -4 539 | 540 | if (gRenderer == eRenderer::Dx9) { 541 | ImGui_ImplDX9_Shutdown(); 542 | } else if (gRenderer == eRenderer::Dx11) { 543 | ImGui_ImplDX11_Shutdown(); 544 | } else { 545 | ImGui_ImplOpenGL3_Shutdown(); 546 | } 547 | 548 | ImGui_ImplWin32_Shutdown(); 549 | ImGui::DestroyContext(); 550 | kiero::shutdown(); 551 | } 552 | -------------------------------------------------------------------------------- /src/hook.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma warning(push, 0) 3 | #include 4 | #include 5 | #include 6 | #include 7 | #pragma warning(pop) 8 | 9 | class Hook { 10 | private: 11 | using f_EndScene = HRESULT(CALLBACK*)(IDirect3DDevice9*); 12 | using f_Present = HRESULT(CALLBACK*)(IDXGISwapChain*, UINT, UINT); 13 | using f_Reset = HRESULT(CALLBACK*)(IDirect3DDevice9*, D3DPRESENT_PARAMETERS*); 14 | using f_ResizeBuffers = HRESULT(CALLBACK*)(IDXGISwapChain*, UINT, UINT, UINT, DXGI_FORMAT, UINT); 15 | using f_SetCursorPos = BOOL(CALLBACK*)(int, int); 16 | using f_ShowCursor = BOOL(CALLBACK*)(bool); 17 | using f_SwapBuffer = BOOL(CALLBACK*) (HDC, UINT); 18 | using f_GetDeviceState = HRESULT(CALLBACK*)(IDirectInputDevice8* pThis, DWORD cbData, LPVOID lpvData); 19 | 20 | static inline WNDPROC oWndProc; 21 | static inline f_Present oPresent; 22 | static inline f_EndScene oEndScene; 23 | static inline f_Reset oReset; 24 | static inline f_ResizeBuffers oResizeBuffers; 25 | static inline f_SetCursorPos oSetCursorPos; 26 | static inline f_ShowCursor oShowCursor; 27 | static inline f_SwapBuffer oGlSwapBuffer; 28 | static inline f_GetDeviceState oGetDeviceState; 29 | static inline ID3D11DeviceContext* pDeviceContext; 30 | static inline ID3D11RenderTargetView* pRenderTargetView; 31 | 32 | static inline bool mouseVisible; 33 | static inline void* pCallbackFunc = nullptr; 34 | static inline HWND hwnd = NULL; 35 | 36 | static void CALLBACK ProcessFrame(void* ptr); 37 | static LRESULT CALLBACK hkWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 38 | static void ProcessMouse(); 39 | 40 | static BOOL CALLBACK hkSetCursorPos(int, int); 41 | static BOOL CALLBACK hkShowCursor(bool); 42 | // DirectX9 43 | static HRESULT CALLBACK hkEndScene(IDirect3DDevice9* pDevice); 44 | static HRESULT CALLBACK hkReset(IDirect3DDevice9* pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters); 45 | 46 | // DirectX11, Renderhook 47 | static HRESULT CALLBACK hkPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags); 48 | static HRESULT CALLBACK hkResizeBuffers(IDXGISwapChain*, UINT, UINT, UINT, DXGI_FORMAT, UINT); 49 | 50 | // OpenGL 51 | static bool CALLBACK hkGlSwapBuffer(HDC unnamedParam1, UINT unnamedParam2); 52 | 53 | // Bully 54 | static bool GetDinputDevice(void** pMouse, size_t size); 55 | static HRESULT CALLBACK hkGetDeviceState(IDirectInputDevice8* pThis, DWORD cbData, LPVOID lpvData); 56 | 57 | // IV 58 | static void InputWatcher(); 59 | 60 | public: 61 | static inline bool m_bInitialized = false; 62 | 63 | Hook() = delete; 64 | Hook(Hook const&) = delete; 65 | void operator=(Hook const&) = delete; 66 | 67 | static bool GetMouseState(); 68 | static bool Inject(void *pCallback); 69 | static void Remove(); 70 | static void SetMouseState(bool state); 71 | }; 72 | -------------------------------------------------------------------------------- /src/imguiframe.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "imgui.h" 3 | #include 4 | #include 5 | #include 6 | 7 | extern enum class eGameVer; 8 | extern eGameVer gGameVer; 9 | 10 | struct FontInfo { 11 | bool m_bFontLoaded = false; 12 | ImFont *m_pFont = nullptr; 13 | std::string m_Path; 14 | float m_nSize = 14.0f; 15 | size_t m_nStart, m_nEnd; 16 | }; 17 | 18 | class ImGuiFrame { 19 | public: 20 | ImGuiContext *m_pContext = nullptr; 21 | 22 | // Scaling related 23 | ImVec2 m_vecScaling = ImVec2(1, 1); 24 | bool m_bWasScalingUpdatedThisFrame; 25 | bool m_bNeedToUpdateScaling; 26 | long long m_nLastScriptCallMS; 27 | 28 | // Render buffers 29 | bool m_bIsBackBufferReady; 30 | std::vector> m_RenderBuffer, m_BackBuffer; 31 | 32 | // for ImGui::ImageButton() 33 | ImVec4 m_vecImgTint = ImVec4(1, 1, 1, 1); 34 | ImVec4 m_vecImgBgCol = ImVec4(1, 1, 1, 1); 35 | 36 | // Fonts 37 | std::vector> m_FontGlyphRange; 38 | std::vector m_FontTable; 39 | 40 | ImGuiFrame() { 41 | // m_pContext = ImGui::CreateContext(); 42 | } 43 | 44 | ImGuiFrame& operator+=(std::function f) { 45 | if (!m_bIsBackBufferReady) { 46 | m_BackBuffer.push_back(f); 47 | } 48 | return *this; 49 | } 50 | 51 | void BeforeRender() { 52 | // bool buildRequired = false; 53 | // for (auto& e: m_FontTable) { 54 | // if (!e.m_bFontLoaded) { 55 | // ImWchar ranges[] = { 56 | // e.m_nStart, e.m_nEnd, 0 57 | // }; 58 | // ImGui::GetIO().Fonts->AddFontFromFileTTF(e.m_Path.c_str(), e.m_nSize, NULL, ranges); 59 | // buildRequired = true; 60 | // } 61 | // } 62 | 63 | // if (buildRequired) { 64 | // ImGui::GetIO().Fonts->Build(); 65 | // } 66 | } 67 | 68 | void OnRender() { 69 | for (auto func : m_RenderBuffer) { 70 | func(); 71 | } 72 | 73 | // if back buffer is render ready switch the buffer and reset render state 74 | if (m_bIsBackBufferReady) { 75 | m_RenderBuffer = std::move(m_BackBuffer); 76 | m_bIsBackBufferReady = false; 77 | } 78 | 79 | time_t curTime = time(NULL); 80 | // Clear buffer when script stops responding 81 | bool scriptsPaused = false; 82 | switch(static_cast(gGameVer)) { 83 | case 0: // III 84 | scriptsPaused = *(bool*)0x95CD7C; 85 | break; 86 | case 1: // VC 87 | scriptsPaused = *(bool*)0xA10B36; 88 | break; 89 | case 2: // SA 90 | scriptsPaused = *(bool*)0xB7CB49; 91 | break; 92 | default: 93 | break; 94 | } 95 | 96 | if (curTime-m_nLastScriptCallMS > 2 || scriptsPaused) { 97 | OnClear(); 98 | } 99 | 100 | if (m_bWasScalingUpdatedThisFrame) { 101 | m_bNeedToUpdateScaling = false; 102 | m_bWasScalingUpdatedThisFrame = false; 103 | } 104 | } 105 | 106 | void OnClear() { 107 | m_RenderBuffer.clear(); 108 | } 109 | }; -------------------------------------------------------------------------------- /src/notifypopup.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "notifypopup.h" 3 | 4 | void NotifiyPopup::AddToQueue(std::string&& message) { 5 | m_Messages.push_back({std::move(message), 0}); 6 | } 7 | 8 | bool NotifiyPopup::IsMessagesInQueue() { 9 | return m_Messages.size() != 0; 10 | } 11 | 12 | size_t NotifiyPopup::GetQueueSize() { 13 | return m_Messages.size(); 14 | } 15 | 16 | void NotifiyPopup::Draw() { 17 | static ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | 18 | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoMove; 19 | static ImVec2 pivot{ 0.0f, 0.0f }; 20 | 21 | ImGuiIO& io = ImGui::GetIO(); 22 | ImVec2 pos{ m_fOffset, m_fOffset }; 23 | ImGui::SetNextWindowPos(pos, ImGuiCond_Always, pivot); 24 | ImGui::SetNextWindowBgAlpha(0.75f); 25 | 26 | if (IsMessagesInQueue()) { 27 | if (ImGui::Begin("Notification", nullptr, window_flags)) { 28 | ImGui::Text("Notifications"); 29 | ImGui::Separator(); 30 | ImGui::Spacing(); 31 | double curTimer = ImGui::GetTime(); 32 | 33 | size_t popCount = 0; 34 | for (size_t i = 0; i < m_nMaxDisplayCount; ++i) { 35 | if (i >= m_Messages.size()) { 36 | break; 37 | } 38 | 39 | if (m_Messages[i].timer == 0) { 40 | m_Messages[i].timer = curTimer; 41 | } 42 | 43 | ImGui::TextUnformatted(m_Messages[i].message.c_str()); 44 | 45 | if ((curTimer - m_Messages[i].timer) > m_fDuration) { 46 | ++popCount; 47 | } 48 | } 49 | 50 | for (size_t i = 0; i != popCount; ++i) { 51 | m_Messages.pop_front(); 52 | } 53 | ImGui::End(); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/notifypopup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | /* 7 | A notification system for games 8 | Based on ImGui 9 | 10 | Displays a black box on the top left side of screen 11 | with messages 12 | */ 13 | class NotifiyPopup { 14 | private: 15 | struct Notification { 16 | std::string message; 17 | double timer; 18 | }; 19 | 20 | static inline const float m_fOffset = 10.0f; 21 | static inline const float m_fDuration = 1.5f; 22 | static inline const size_t m_nMaxDisplayCount = 3; 23 | static inline std::deque m_Messages; 24 | 25 | static bool IsMessagesInQueue(); 26 | static size_t GetQueueSize(); 27 | 28 | public: 29 | NotifiyPopup() = delete; 30 | NotifiyPopup(NotifiyPopup&) = delete; 31 | void operator=(NotifiyPopup const&) = delete; 32 | 33 | static void Draw(); 34 | static void AddToQueue(std::string&& message); 35 | }; 36 | -------------------------------------------------------------------------------- /src/opcodemgr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class OpcodeMgr { 4 | public: 5 | OpcodeMgr() = delete; 6 | OpcodeMgr(const OpcodeMgr&) = delete; 7 | void operator=(const OpcodeMgr&) = delete; 8 | 9 | static void RegisterCommands(); 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /src/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | eRenderer gRenderer = eRenderer::Unknown; 4 | eGameVer gGameVer = eGameVer::Unknown; 5 | void* gD3DDevice = nullptr; 6 | -------------------------------------------------------------------------------- /src/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define _CRT_SECURE_NO_WARNINGS 3 | #define IMGUI_REDUX_VERSION 3.0f 4 | #define IMGUI_REDUX_VERSION_NUM 30000 5 | #include "imgui.h" 6 | #include "imgui_stdlib.h" 7 | #include "scriptextender.hpp" 8 | 9 | enum class eRenderer { 10 | Dx9, 11 | Dx11, 12 | Dx12, 13 | OpenGL, 14 | Unknown 15 | }; 16 | 17 | enum class eGameVer { 18 | III, 19 | VC, 20 | SA, 21 | IV, 22 | V, 23 | III_DE, 24 | VC_DE, 25 | SA_DE, 26 | RE_III, 27 | RE_VC, 28 | RE_SA, 29 | BullySE, 30 | Unknown 31 | }; 32 | 33 | extern eRenderer gRenderer; 34 | extern eGameVer gGameVer; 35 | extern void* gD3DDevice; 36 | -------------------------------------------------------------------------------- /src/scriptextender.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "table.hpp" 5 | #include "hook.h" 6 | #include 7 | #include 8 | #include "opcodemgr.h" 9 | #include "imgui_internal.h" 10 | #include "imguiframe.hpp" 11 | #include "notifypopup.h" 12 | 13 | /* 14 | * Handles data exchange between ImGui & CLEO 15 | * Repalce with new data when previous is passed 16 | */ 17 | struct ImGui2ScriptCom { 18 | bool m_bPassed; 19 | std::any m_Val; 20 | }; 21 | 22 | class ScriptExData { 23 | private: 24 | static inline Table> m_FrameCache; 25 | static inline std::vector m_pScriptTable; 26 | static inline bool m_bShowCursorFlag; 27 | static inline std::string m_CurrentScriptID; 28 | static inline size_t m_nFramerate; 29 | 30 | std::string m_ScriptID; 31 | 32 | ScriptExData(std::string id): m_ScriptID(id) {} 33 | 34 | public: 35 | ImGuiFrame m_ImGuiData; 36 | 37 | static size_t GetGameFPS() { 38 | return m_nFramerate; 39 | } 40 | 41 | static void SetCurrentScript(std::string id) { 42 | m_CurrentScriptID = id; 43 | } 44 | 45 | static std::string GetCurrentScript() { 46 | return m_CurrentScriptID; 47 | } 48 | 49 | static ScriptExData* Get() { 50 | for (auto it = m_pScriptTable.begin(); it != m_pScriptTable.end(); ++it) { 51 | if ((*it)->m_ScriptID == m_CurrentScriptID) { 52 | return *it; 53 | } 54 | } 55 | 56 | ScriptExData* script = new ScriptExData(m_CurrentScriptID); 57 | m_pScriptTable.push_back(script); 58 | return script; 59 | } 60 | 61 | template 62 | T GetData(const char* label, int index, T defaultVal) { 63 | try { 64 | ImGui2ScriptCom *pData = &m_FrameCache[label].at(index); 65 | T val = std::any_cast(pData->m_Val); 66 | pData->m_bPassed = true; 67 | return val; 68 | } catch(...) { 69 | return defaultVal; 70 | } 71 | } 72 | 73 | template 74 | void SetData(const char* label,size_t index, T val) { 75 | // Set data when previous one is retrived 76 | if (m_FrameCache[label].size() < index+1) { 77 | m_FrameCache[label].push_back({false, val}); 78 | } else { 79 | if (m_FrameCache[label].at(index).m_bPassed) { 80 | m_FrameCache[label].at(index) = {false, val}; 81 | } 82 | } 83 | } 84 | 85 | static void SetCursorVisible(bool flag) { 86 | m_bShowCursorFlag = flag; 87 | } 88 | 89 | static void InitRenderStates() { 90 | for (auto it = m_pScriptTable.begin(); it != m_pScriptTable.end(); ++it) { 91 | (*it)->m_ImGuiData.BeforeRender(); 92 | } 93 | } 94 | 95 | static void RenderFrames() { 96 | m_bShowCursorFlag = false; 97 | 98 | for (auto it = m_pScriptTable.begin(); it != m_pScriptTable.end(); ++it) { 99 | (*it)->m_ImGuiData.OnRender(); 100 | } 101 | 102 | NotifiyPopup::Draw(); 103 | 104 | Hook::SetMouseState(m_bShowCursorFlag); 105 | m_nFramerate = (size_t)ImGui::GetIO().Framerate; 106 | } 107 | 108 | static void SetScaling(ImVec2 scaling) { 109 | for (auto it = m_pScriptTable.begin(); it != m_pScriptTable.end(); ++it) { 110 | (*it)->m_ImGuiData.m_vecScaling = scaling; 111 | (*it)->m_ImGuiData.m_bNeedToUpdateScaling = true; 112 | } 113 | } 114 | 115 | static void Clear() { 116 | m_pScriptTable.clear(); 117 | m_FrameCache.Clear(); 118 | } 119 | }; -------------------------------------------------------------------------------- /src/table.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | // Basic table implementation inspired by lua tables 5 | template 6 | class Table 7 | { 8 | private: 9 | std::vector> _data; 10 | public: 11 | 12 | void Clear() 13 | { 14 | _data.clear(); 15 | } 16 | 17 | T& operator[](S str) 18 | { 19 | for (auto it = _data.begin(); it != _data.end(); ++it) 20 | { 21 | // value exists, return ref 22 | if (it->first == str) 23 | { 24 | return it->second; 25 | } 26 | } 27 | 28 | // push the value into vector and return a ref 29 | _data.push_back({ str, T{}}); 30 | return _data.back().second; 31 | } 32 | }; -------------------------------------------------------------------------------- /src/texturemgr.cpp: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_IMPLEMENTATION 2 | #include "pch.h" 3 | #include "texturemgr.h" 4 | #include "stb_image.h" 5 | 6 | // d3dx9.h 7 | extern "C" 8 | { 9 | HRESULT WINAPI 10 | D3DXCreateTextureFromFileA( 11 | LPDIRECT3DDEVICE9 pDevice, 12 | LPCSTR pSrcFile, 13 | LPDIRECT3DTEXTURE9* ppTexture); 14 | 15 | HRESULT WINAPI 16 | D3DXCreateTextureFromFileW( 17 | LPDIRECT3DDEVICE9 pDevice, 18 | LPCWSTR pSrcFile, 19 | LPDIRECT3DTEXTURE9* ppTexture); 20 | 21 | #ifdef UNICODE 22 | #define D3DXCreateTextureFromFile D3DXCreateTextureFromFileW 23 | #else 24 | #define D3DXCreateTextureFromFile D3DXCreateTextureFromFileA 25 | #endif 26 | } 27 | 28 | static bool D3D11CreateTextureFromFile(ID3D11Device* pDevice, const char* filename, 29 | ID3D11ShaderResourceView** outSrc) { 30 | // Load from disk into a raw RGBA buffer 31 | int width = 0; 32 | int height = 0; 33 | unsigned char* data = stbi_load(filename, &width, &height, NULL, 4); 34 | if (data == NULL) { 35 | return false; 36 | } 37 | 38 | // Create texture 39 | D3D11_TEXTURE2D_DESC desc; 40 | ZeroMemory(&desc, sizeof(desc)); 41 | desc.Width = width; 42 | desc.Height = height; 43 | desc.MipLevels = 1; 44 | desc.ArraySize = 1; 45 | desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 46 | desc.SampleDesc.Count = 1; 47 | desc.Usage = D3D11_USAGE_DEFAULT; 48 | desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; 49 | desc.CPUAccessFlags = 0; 50 | 51 | ID3D11Texture2D *pTexture = NULL; 52 | D3D11_SUBRESOURCE_DATA subResource; 53 | subResource.pSysMem = data; 54 | subResource.SysMemPitch = desc.Width * 4; 55 | subResource.SysMemSlicePitch = 0; 56 | 57 | pDevice->CreateTexture2D(&desc, &subResource, &pTexture); 58 | 59 | // Create texture view 60 | D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 61 | ZeroMemory(&srvDesc, sizeof(srvDesc)); 62 | srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 63 | srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 64 | srvDesc.Texture2D.MipLevels = desc.MipLevels; 65 | srvDesc.Texture2D.MostDetailedMip = 0; 66 | pDevice->CreateShaderResourceView(pTexture, &srvDesc, outSrc); 67 | 68 | stbi_image_free(data); 69 | 70 | return true; 71 | } 72 | 73 | void TextureMgr::LoadTexture(TextureInfo &info) { 74 | if (!gD3DDevice) { 75 | return; 76 | } 77 | 78 | if (gRenderer == eRenderer::Dx9) { 79 | D3DXCreateTextureFromFile(reinterpret_cast(gD3DDevice), info.path.c_str(), 80 | reinterpret_cast(&info.pTexture)); 81 | } else if (gRenderer == eRenderer::Dx11) { 82 | D3D11CreateTextureFromFile(reinterpret_cast(gD3DDevice), info.path.c_str(), 83 | reinterpret_cast(&info.pTexture)); 84 | } 85 | } 86 | 87 | TextureInfo* TextureMgr::LoadTextureFromPath(const char *path) { 88 | TextureInfo info; 89 | info.path = std::string(path); 90 | info.pTexture = nullptr; 91 | // FIX ME 92 | // LoadTexture(info); 93 | textureList.push_back(std::move(info)); 94 | return &textureList.back(); 95 | } 96 | 97 | void TextureMgr::FreeTexture(TextureInfo *pInfo) { 98 | if (!pInfo) { 99 | return; 100 | } 101 | 102 | if (gRenderer == eRenderer::Dx9) { 103 | reinterpret_cast(pInfo->pTexture)->Release(); 104 | } else if (gRenderer == eRenderer::Dx11) { 105 | reinterpret_cast(pInfo->pTexture)->Release(); 106 | } 107 | 108 | std::remove(textureList.begin(), textureList.end(), *pInfo); 109 | } 110 | 111 | TextureInfo* TextureMgr::FindInfo(std::string &&path) { 112 | for (auto &item : textureList) { 113 | if (item.path == path) { 114 | return &item; 115 | } 116 | } 117 | 118 | return nullptr; 119 | } 120 | 121 | bool TextureMgr::Exists(TextureInfo *pInfo) { 122 | for (TextureInfo item : textureList) { 123 | if (item.path == pInfo->path) { 124 | return true; 125 | } 126 | } 127 | return false; 128 | } -------------------------------------------------------------------------------- /src/texturemgr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pch.h" 3 | 4 | struct TextureInfo { 5 | public: 6 | std::string path; 7 | void *pTexture; 8 | unsigned int lastAccessed; // last time when the texture was accessed (seconds) 9 | 10 | TextureInfo() {}; 11 | bool operator==(const TextureInfo &pInfo) { 12 | return (path == pInfo.path && pInfo.pTexture && pTexture == pInfo.pTexture); 13 | } 14 | }; 15 | 16 | /* 17 | Handles loading, unloading images 18 | */ 19 | class TextureMgr { 20 | private: 21 | // static inline constexpr unsigned int TIMEOUT = 30; // Unload unused textures 22 | static inline std::vector textureList; 23 | 24 | public: 25 | TextureMgr() = delete; 26 | TextureMgr(TextureMgr&) = delete; 27 | 28 | // Returns true if texture exsits in list 29 | static bool Exists(TextureInfo *pInfo); 30 | 31 | // Unloads a texture from memory, handles different backends 32 | static void FreeTexture(TextureInfo *pInfo); 33 | 34 | // Returns TextureInfo from file path 35 | static TextureInfo* FindInfo(std::string&& path); 36 | 37 | // Loads texture, returns nullptr on failure 38 | static void LoadTexture(TextureInfo &info); 39 | 40 | // Loads texture from given path, returns nullptr on failure 41 | static TextureInfo* LoadTextureFromPath(const char *path); 42 | 43 | // Frees memory by clearing up unused textures 44 | // static void RunCleanup(); 45 | }; -------------------------------------------------------------------------------- /src/wrapper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pch.h" 3 | #ifdef RUNTIME_CLEO 4 | #include "../include/cleo/CLEO.h" 5 | #define RTN_CONTINUE CLEO::OR_CONTINUE 6 | #define RTN_TYPE CLEO::OpcodeResult 7 | #define RUNTIME_API WINAPI 8 | #define RUNTIME_CONTEXT CLEO::CRunningScript* 9 | #define CMD_DEF CLEO::_pOpcodeHandler 10 | #define INT int 11 | #else 12 | #include "../include/cleo/cleo_redux_sdk.h" 13 | #define RTN_CONTINUE HandlerResult::CONTINUE 14 | #define RTN_TYPE HandlerResult 15 | #define RUNTIME_API 16 | #define RUNTIME_CONTEXT Context 17 | #define CMD_DEF CommandHandler 18 | #define INT isize 19 | #endif 20 | 21 | #define RUNTIME_STR_LEN 128 22 | 23 | static void wGetStringParam(RUNTIME_CONTEXT ctx, char* label, unsigned char length) { 24 | #ifdef RUNTIME_CLEO 25 | CLEO_ReadStringOpcodeParam(ctx, label, length); 26 | #else 27 | GetStringParam(ctx, label, length); 28 | #endif 29 | } 30 | 31 | /* 32 | Appending BeginFrame uniqueID to widget names 33 | This ensures scripts won't clash with each other 34 | */ 35 | static void wGetStringWithFrame(RUNTIME_CONTEXT ctx, char* label, unsigned char length) { 36 | wGetStringParam(ctx, label, length); 37 | strcat(label, "##"); 38 | strcat(label, ScriptExData::GetCurrentScript().c_str()); 39 | } 40 | 41 | static void wSetIntParam(RUNTIME_CONTEXT ctx, INT value) { 42 | #ifdef RUNTIME_CLEO 43 | CLEO_SetIntOpcodeParam(reinterpret_cast(ctx), value); 44 | #else 45 | SetIntParam(ctx, value); 46 | #endif 47 | } 48 | 49 | static void wSetFloatParam(RUNTIME_CONTEXT ctx, float value) { 50 | #ifdef RUNTIME_CLEO 51 | CLEO_SetFloatOpcodeParam(reinterpret_cast(ctx), value); 52 | #else 53 | SetFloatParam(ctx, value); 54 | #endif 55 | } 56 | 57 | static INT wGetIntParam(RUNTIME_CONTEXT ctx) { 58 | #ifdef RUNTIME_CLEO 59 | return CLEO_GetIntOpcodeParam(reinterpret_cast(ctx)); 60 | #else 61 | return GetIntParam(ctx); 62 | #endif 63 | } 64 | 65 | static bool wGetBoolParam(RUNTIME_CONTEXT ctx) { 66 | #ifdef RUNTIME_CLEO 67 | return static_cast(CLEO_GetIntOpcodeParam(reinterpret_cast(ctx))); 68 | #else 69 | return static_cast(GetIntParam(ctx)); 70 | #endif 71 | } 72 | 73 | static float wGetFloatParam(RUNTIME_CONTEXT ctx) { 74 | #ifdef RUNTIME_CLEO 75 | return CLEO_GetFloatOpcodeParam(reinterpret_cast(ctx)); 76 | #else 77 | return GetFloatParam(ctx); 78 | #endif 79 | return -1.0f; 80 | } 81 | 82 | static void wUpdateCompareFlag(RUNTIME_CONTEXT ctx, bool flag) { 83 | #ifdef RUNTIME_CLEO 84 | typedef unsigned __int16 (__thiscall* _type)(RUNTIME_CONTEXT, bool); 85 | ((_type)0x4859D0)(ctx, flag); // CRunningScript::UpdateCompareFlag(); 86 | #else 87 | UpdateCompareFlag(ctx, flag); 88 | #endif 89 | } 90 | 91 | static void wResolvePath(RUNTIME_CONTEXT ctx, const char* src, char* dest, size_t maxLength) { 92 | #ifdef RUNTIME_CLEO 93 | strcpy(dest, src); 94 | CLEO_ResolvePath(ctx, dest, maxLength); 95 | #else 96 | ResolvePath(src, dest); 97 | #endif 98 | } 99 | 100 | static void wRegisterCommand(const char *name, CMD_DEF handler) { 101 | #ifdef RUNTIME_CLEO 102 | static size_t opcode = 0x2200; 103 | CLEO_RegisterOpcode(opcode, handler); 104 | opcode++; 105 | #else 106 | RegisterCommand(name, handler); 107 | #endif 108 | } 109 | 110 | static void wSetStringParam(RUNTIME_CONTEXT ctx, const char* buf) { 111 | #ifdef RUNTIME_CLEO 112 | CLEO_WriteStringOpcodeParam(reinterpret_cast(ctx), buf); 113 | #else 114 | SetStringParam(ctx, buf); 115 | #endif 116 | } -------------------------------------------------------------------------------- /tools/AStyle.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/tools/AStyle.exe -------------------------------------------------------------------------------- /tools/Debug.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo -------------------------------------------------- 3 | echo Building Debug 4 | echo -------------------------------------------------- 5 | echo[ 6 | call "tools\Setup.bat" 7 | MsBuild ImGuiRedux.sln /property:Configuration=Debug /t:ImGuiRedux /property:Platform=Win32 8 | del "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\ImGuiReduxWin32.cleo" /Q 9 | del "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\ImGuiReduxWin32.pdb" /Q 10 | xcopy /s "bin\ImGuiReduxWin32.cleo" "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\" /K /D /H /Y 11 | xcopy /s "bin\ImGuiReduxWin32.pdb" "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\" /K /D /H /Y 12 | -------------------------------------------------------------------------------- /tools/Debug64.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo -------------------------------------------------- 3 | echo Building Debug 4 | echo -------------------------------------------------- 5 | echo[ 6 | call "tools\Setup.bat" 7 | MsBuild ImGuiRedux.sln /property:Configuration=Release /t:ImGuiRedux /property:Platform=Win64 8 | del "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\ImGuiReduxWin64.cleo" /Q 9 | del "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\ImGuiReduxWin64.pdb" /Q 10 | xcopy /s "bin\ImGuiReduxWin64.cleo" "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\" /K /D /H /Y 11 | xcopy /s "bin\ImGuiReduxWin64.pdb" "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\" /K /D /H /Y 12 | -------------------------------------------------------------------------------- /tools/DebugCleo.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo -------------------------------------------------- 3 | echo Building Debug 4 | echo -------------------------------------------------- 5 | echo[ 6 | call "tools\Setup.bat" 7 | MsBuild ImGuiRedux.sln /property:Configuration=DebugCleo /t:ImGuiRedux /property:Platform=Win32 8 | del "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\ImGuiCleoWin32.cleo" /Q 9 | del "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\ImGuiCleoWin32.pdb" /Q 10 | xcopy /s "bin\ImGuiCleoWin32.cleo" "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\" /K /D /H /Y 11 | xcopy /s "bin\ImGuiCleoWin32.pdb" "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\" /K /D /H /Y 12 | -------------------------------------------------------------------------------- /tools/FormatCode.bat: -------------------------------------------------------------------------------- 1 | tools\\AStyle.exe --style= -n --recursive ../src/*.cpp ../src/*.h 2 | -------------------------------------------------------------------------------- /tools/Release.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo -------------------------------------------------- 3 | echo Building Release 4 | echo -------------------------------------------------- 5 | echo[ 6 | call "tools\Setup.bat" 7 | MsBuild ImGuiRedux.sln /property:Configuration=Release /t:ImGuiRedux /property:Platform=Win32 8 | del "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\ImGuiReduxWin32.cleo" /Q 9 | xcopy /s "bin\ImGuiReduxWin32.cleo" "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\" /K /D /H /Y 10 | -------------------------------------------------------------------------------- /tools/Release64.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo -------------------------------------------------- 3 | echo Building Release 4 | echo -------------------------------------------------- 5 | echo[ 6 | call "tools\Setup.bat" 7 | MsBuild ImGuiRedux.sln /property:Configuration=Release /t:ImGuiRedux /property:Platform=Win64 8 | del "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\ImGuiReduxWin64.cleo" /Q 9 | xcopy /s "bin\ImGuiReduxWin64.cleo" "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\" /K /D /H /Y 10 | -------------------------------------------------------------------------------- /tools/ReleaseCleo.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo -------------------------------------------------- 3 | echo Building Release 4 | echo -------------------------------------------------- 5 | echo[ 6 | call "tools\Setup.bat" 7 | MsBuild ImGuiRedux.sln /property:Configuration=ReleaseCleo /t:ImGuiRedux /property:Platform=Win32 8 | del "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\ImGuiReduxWin32.cleo" /Q 9 | xcopy /s "bin\ImGuiReduxWin32.cleo" "%GTA_SA_DIR%\cleo\CLEO_PLUGINS\" /K /D /H /Y 10 | -------------------------------------------------------------------------------- /tools/Setup.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set "projectdir=%CD%" 3 | set "PLUGIN_NAME="GrinchTrainer"" 4 | 5 | :find_vs_path 6 | set "vs_path=" 7 | for %%d in (Community Preview Professional) do ( 8 | for /d %%e in ("C:\Program Files\Microsoft Visual Studio\2022\%%d") do ( 9 | if exist "%%e\Common7\Tools\VsDevCmd.bat" ( 10 | set "vs_path=%%e" 11 | goto :check_game_path 12 | ) 13 | ) 14 | ) 15 | goto :eof 16 | 17 | :check_game_path 18 | if "%GTA_SA_DIR%"=="" ( 19 | echo Error: GTA_SA_DIR environment variable is not set. 20 | ) 21 | 22 | if "%GTA_VC_DIR%"=="" ( 23 | echo Error: GTA_VC_DIR environment variable is not set. 24 | ) 25 | 26 | if "%GTA_III_DIR%"=="" ( 27 | echo Error: GTA_III_DIR environment variable is not set. 28 | ) 29 | 30 | if "%GTA_SS_DIR%"=="" ( 31 | echo Error: GTA_SS_DIR environment variable is not set. 32 | ) 33 | echo[ 34 | 35 | :vs_install_found 36 | if not defined vs_path ( 37 | echo Error: Visual Studio installation not found. 38 | exit /b 1 39 | ) 40 | 41 | :run_premake 42 | cd "%projectdir%\tools" 43 | premake5.exe vs2022 44 | 45 | :run_dev 46 | cd "%projectdir%\build" 47 | call %vs_path%"\Common7\Tools\VsDevCmd.bat" 48 | -------------------------------------------------------------------------------- /tools/premake5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/user-grinch/ImGuiRedux/11604d4dc061ba8a9f4c4a41f65a84174b5d1223/tools/premake5.exe -------------------------------------------------------------------------------- /tools/premake5.lua: -------------------------------------------------------------------------------- 1 | workspace "ImGuiRedux" 2 | configurations { 3 | "Debug", 4 | "Release", 5 | "DebugCleo", 6 | "ReleaseCleo" 7 | } 8 | platforms { 9 | "Win32", 10 | "Win64" 11 | } 12 | language "C++" 13 | cppdialect "C++latest" 14 | characterset "MBCS" 15 | staticruntime "On" 16 | location "../build" 17 | targetdir "../build/bin" 18 | kind "SharedLib" 19 | targetextension ".cleo" 20 | files { 21 | "../include/**", 22 | "../src/**" 23 | } 24 | includedirs { 25 | "../include/**" 26 | } 27 | libdirs { 28 | "../lib/" 29 | } 30 | 31 | project "ImGuiRedux" 32 | filter { "platforms:Win32" } 33 | architecture "x86" 34 | links { 35 | "d3d9", 36 | "d3dx9", 37 | "d3d11", 38 | "delayimp", 39 | "libMinHook-x86", 40 | "dinput8.lib", 41 | "dxguid.lib" 42 | } 43 | filter "configurations:DebugCleo" 44 | targetname "ImGuiCleoWin32" 45 | symbols "On" 46 | defines { 47 | "RUNTIME_CLEO" 48 | } 49 | links { 50 | "CLEO", 51 | } 52 | 53 | filter "configurations:ReleaseCleo" 54 | targetname "ImGuiCleoWin32" 55 | optimize "On" 56 | defines { 57 | "NDEBUG", 58 | "RUNTIME_CLEO" 59 | } 60 | links { 61 | "CLEO", 62 | } 63 | 64 | filter "configurations:Debug" 65 | targetname "ImGuiReduxWin32" 66 | symbols "On" 67 | defines { 68 | "RUNTIME_REDUX" 69 | } 70 | links { 71 | "cleo_redux", 72 | } 73 | 74 | filter "configurations:Release" 75 | targetname "ImGuiReduxWin32" 76 | optimize "On" 77 | defines { 78 | "NDEBUG", 79 | "RUNTIME_REDUX" 80 | } 81 | links { 82 | "cleo_redux", 83 | } 84 | 85 | filter { "platforms:Win64" } 86 | targetname "ImGuiReduxWin64" 87 | architecture "x64" 88 | links { 89 | "d3d9", 90 | "d3dx9x64", 91 | "d3d11", 92 | "delayimp", 93 | "cleo_redux64", 94 | "libMinHook-x64", 95 | "dinput8.lib", 96 | "dxguid.lib" 97 | } 98 | 99 | filter "configurations:Debug" 100 | symbols "On" 101 | defines { 102 | "RUNTIME_REDUX" 103 | } 104 | 105 | filter "configurations:Release" 106 | optimize "On" 107 | defines { 108 | "NDEBUG", 109 | "RUNTIME_REDUX" 110 | } 111 | -------------------------------------------------------------------------------- /tools/tes.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | lst = { 4 | "IMGUI_BEGIN_FRAME" : 0x2200, 5 | "IMGUI_END_FRAME" : 0x2201, 6 | "IMGUI_BEGIN" : 0x2202, 7 | "IMGUI_END" : 0x2203, 8 | "IMGUI_BEGIN_MAINMENUBAR" : 0x2204, 9 | "IMGUI_END_MAINMENUBAR" : 0x2205, 10 | "IMGUI_BEGIN_CHILD" : 0x2206, 11 | "IMGUI_END_CHILD" : 0x2207, 12 | "IMGUI_TABS" : 0x2208, 13 | "IMGUI_COLLAPSING_HEADER" : 0x2209, 14 | "IMGUI_SET_WINDOW_POS" : 0x220A, 15 | "IMGUI_SET_WINDOW_SIZE" : 0x220B, 16 | "IMGUI_SET_NEXT_WINDOW_POS" : 0x220C, 17 | "IMGUI_SET_NEXT_WINDOW_SIZE" : 0x220D, 18 | "IMGUI_TEXT" : 0x220E, 19 | "IMGUI_TEXT_CENTERED" : 0x220F, 20 | "IMGUI_TEXT_DISABLED" : 0x2210, 21 | "IMGUI_TEXT_WRAPPED" : 0x2211, 22 | "IMGUI_TEXT_COLORED" : 0x2212, 23 | "IMGUI_BULLET_TEXT" : 0x2213, 24 | "IMGUI_BULLET" : 0x2214, 25 | "IMGUI_CHECKBOX" : 0x2215, 26 | "IMGUI_COMBO" : 0x2216, 27 | "IMGUI_SET_TOOLTIP" : 0x2217, 28 | "IMGUI_BUTTON" : 0x2218, 29 | "IMGUI_IMAGE_BUTTON" : 0x2219, 30 | "IMGUI_INVISIBLE_BUTTON" : 0x221A, 31 | "IMGUI_COLOR_BUTTON" : 0x221B, 32 | "IMGUI_ARROW_BUTTON" : 0x221C, 33 | "IMGUI_SLIDER_INT" : 0x221D, 34 | "IMGUI_SLIDER_FLOAT" : 0x221E, 35 | "IMGUI_INPUT_INT" : 0x221F, 36 | "IMGUI_INPUT_FLOAT" : 0x2220, 37 | "IMGUI_INPUT_TEXT" : 0x2221, 38 | "IMGUI_RADIO_BUTTON" : 0x2222, 39 | "IMGUI_COLOR_PICKER" : 0x2223, 40 | "IMGUI_MENU_ITEM" : 0x2224, 41 | "IMGUI_SELECTABLE" : 0x2225, 42 | "IMGUI_DUMMY" : 0x2226, 43 | "IMGUI_SAMELINE" : 0x2227, 44 | "IMGUI_NEWLINE" : 0x2228, 45 | "IMGUI_COLUMNS" : 0x2229, 46 | "IMGUI_NEXT_COLUMN" : 0x222A, 47 | "IMGUI_SPACING" : 0x222B, 48 | "IMGUI_SEPARATOR" : 0x222C, 49 | "IMGUI_PUSH_ITEM_WIDTH" : 0x222D, 50 | "IMGUI_POP_ITEM_WIDTH" : 0x222E, 51 | "IMGUI_IS_ITEM_ACTIVE" : 0x222F, 52 | "IMGUI_IS_ITEM_CLICKED" : 0x2230, 53 | "IMGUI_IS_ITEM_FOCUSED" : 0x2231, 54 | "IMGUI_IS_ITEM_HOVERED" : 0x2232, 55 | "IMGUI_SET_ITEM_INT" : 0x2233, 56 | "IMGUI_SET_ITEM_FLOAT" : 0x2234, 57 | "IMGUI_SET_ITEM_TEXT" : 0x2235, 58 | "IMGUI_SET_IMAGE_BG_COLOR" : 0x2236, 59 | "IMGUI_SET_IMAGE_TINT_COLOR" : 0x2237, 60 | "IMGUI_LOAD_IMAGE" : 0x2238, 61 | "IMGUI_FREE_IMAGE" : 0x2239, 62 | "IMGUI_PUSH_STYLE_VAR" : 0x223A, 63 | "IMGUI_PUSH_STYLE_VAR2" : 0x223B, 64 | "IMGUI_PUSH_STYLE_COLOR" : 0x223C, 65 | "IMGUI_POP_STYLE_VAR" : 0x223D, 66 | "IMGUI_POP_STYLE_COLOR" : 0x223E, 67 | "IMGUI_GET_FOREGROUND_DRAWLIST" : 0x223F, 68 | "IMGUI_GET_BACKGROUND_DRAWLIST" : 0x2240, 69 | "IMGUI_GET_WINDOW_DRAWLIST" : 0x2241, 70 | "IMGUI_DRAWLIST_ADD_TEXT" : 0x2242, 71 | "IMGUI_DRAWLIST_ADD_LINE" : 0x2243, 72 | "GET_FRAMERATE" : 0x2244, 73 | "IMGUI_GET_VERSION" : 0x2245, 74 | "IMGUI_GET_PLUGIN_VERSION" : 0x2246, 75 | "IMGUI_SET_CURSOR_VISIBLE" : 0x2247, 76 | "IMGUI_GET_FRAME_HEIGHT" : 0x2248, 77 | "IMGUI_GET_WINDOW_POS" : 0x2249, 78 | "IMGUI_GET_WINDOW_SIZE" : 0x224A, 79 | "IMGUI_CALC_TEXT_SIZE" : 0x224B, 80 | "IMGUI_GET_WINDOW_CONTENT_REGION_WIDTH" : 0x224C, 81 | "IMGUI_GET_SCALING_SIZE" : 0x224D, 82 | "IMGUI_GET_DISPLAY_SIZE" : 0x224E, 83 | "IMGUI_SET_NEXT_WINDOW_TRANSPARENCY" : 0x224F, 84 | "IMGUI_SET_MESSAGE" : 0x2250 85 | } 86 | 87 | # Retrieve JSON data from the file 88 | with open("E:/ImGuiRedux/tools/test.json", "r") as f: 89 | data = json.load(f) 90 | 91 | outdata = [] 92 | with open("E:/ImGuiRedux/tools/out.json", "w") as w: 93 | for e in data["commands"]: 94 | e["id"] = str(hex(lst[e["name"]])).replace("0x", "").upper(); 95 | outdata.insert(-1, e); 96 | formatted_data = json.dumps(outdata, indent=2) 97 | 98 | w.write(formatted_data) --------------------------------------------------------------------------------