├── .gitattributes ├── .gitignore ├── README.md ├── detours ├── detours.h └── detours.lib ├── dll_loader.ini ├── dll_loader ├── Source.def ├── cpp.hint ├── dll_loader.vcxproj ├── dll_loader.vcxproj.filters ├── dllmain.cpp ├── framework.h ├── pch.cpp └── pch.h ├── hitbox overlay.sln ├── hitbox overlay ├── dllmain.cpp ├── framework.h ├── hitbox overlay.vcxproj ├── hitbox overlay.vcxproj.filters ├── pch.cpp └── pch.h └── mINI └── mINI.h /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MBTL-hitbox-viewer 2 | 3 | ## What it does 4 | * Draw the hitbox 5 | * Display frame data 6 | * Unlock the unused color slots for custom palettes (Off by default; Edit dll_loader.ini to turn it on) (You need the file patching dll to load custom palettes) 7 | 8 | ## How to use 9 | * Build the project / Download the files in the releases 10 | * Place the dlls and dll_loader.ini to the game folder 11 | * Press F5 to toggle the hitbox (default is on) 12 | * Press F6 to pause 13 | * Press F7 to step one frame 14 | -------------------------------------------------------------------------------- /detours/detours.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Core Detours Functionality (detours.h of detours.lib) 4 | // 5 | // Microsoft Research Detours Package, Version 4.0.1 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | 10 | #pragma once 11 | #ifndef _DETOURS_H_ 12 | #define _DETOURS_H_ 13 | 14 | #define DETOURS_VERSION 0x4c0c1 // 0xMAJORcMINORcPATCH 15 | 16 | ////////////////////////////////////////////////////////////////////////////// 17 | // 18 | 19 | #ifdef DETOURS_INTERNAL 20 | 21 | #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 22 | #define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1 23 | 24 | #pragma warning(disable:4068) // unknown pragma (suppress) 25 | 26 | #if _MSC_VER >= 1900 27 | #pragma warning(push) 28 | #pragma warning(disable:4091) // empty typedef 29 | #endif 30 | 31 | #include 32 | #if (_MSC_VER < 1310) 33 | #else 34 | #pragma warning(push) 35 | #if _MSC_VER > 1400 36 | #pragma warning(disable:6102 6103) // /analyze warnings 37 | #endif 38 | #include 39 | #pragma warning(pop) 40 | #endif 41 | 42 | #endif // DETOURS_INTERNAL 43 | 44 | ////////////////////////////////////////////////////////////////////////////// 45 | // 46 | 47 | #undef DETOURS_X64 48 | #undef DETOURS_X86 49 | #undef DETOURS_IA64 50 | #undef DETOURS_ARM 51 | #undef DETOURS_ARM64 52 | #undef DETOURS_BITS 53 | #undef DETOURS_32BIT 54 | #undef DETOURS_64BIT 55 | 56 | #if defined(_X86_) 57 | #define DETOURS_X86 58 | #define DETOURS_OPTION_BITS 64 59 | 60 | #elif defined(_AMD64_) 61 | #define DETOURS_X64 62 | #define DETOURS_OPTION_BITS 32 63 | 64 | #elif defined(_IA64_) 65 | #define DETOURS_IA64 66 | #define DETOURS_OPTION_BITS 32 67 | 68 | #elif defined(_ARM_) 69 | #define DETOURS_ARM 70 | 71 | #elif defined(_ARM64_) 72 | #define DETOURS_ARM64 73 | 74 | #else 75 | #error Unknown architecture (x86, amd64, ia64, arm, arm64) 76 | #endif 77 | 78 | #ifdef _WIN64 79 | #undef DETOURS_32BIT 80 | #define DETOURS_64BIT 1 81 | #define DETOURS_BITS 64 82 | // If all 64bit kernels can run one and only one 32bit architecture. 83 | //#define DETOURS_OPTION_BITS 32 84 | #else 85 | #define DETOURS_32BIT 1 86 | #undef DETOURS_64BIT 87 | #define DETOURS_BITS 32 88 | // If all 64bit kernels can run one and only one 32bit architecture. 89 | //#define DETOURS_OPTION_BITS 32 90 | #endif 91 | 92 | #define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) 93 | 94 | ////////////////////////////////////////////////////////////////////////////// 95 | // 96 | 97 | #if (_MSC_VER < 1299) 98 | typedef LONG LONG_PTR; 99 | typedef ULONG ULONG_PTR; 100 | #endif 101 | 102 | ///////////////////////////////////////////////// SAL 2.0 Annotations w/o SAL. 103 | // 104 | // These definitions are include so that Detours will build even if the 105 | // compiler doesn't have full SAL 2.0 support. 106 | // 107 | #ifndef DETOURS_DONT_REMOVE_SAL_20 108 | 109 | #ifdef DETOURS_TEST_REMOVE_SAL_20 110 | #undef _Analysis_assume_ 111 | #undef _Benign_race_begin_ 112 | #undef _Benign_race_end_ 113 | #undef _Field_range_ 114 | #undef _Field_size_ 115 | #undef _In_ 116 | #undef _In_bytecount_ 117 | #undef _In_count_ 118 | #undef _In_opt_ 119 | #undef _In_opt_bytecount_ 120 | #undef _In_opt_count_ 121 | #undef _In_opt_z_ 122 | #undef _In_range_ 123 | #undef _In_reads_ 124 | #undef _In_reads_bytes_ 125 | #undef _In_reads_opt_ 126 | #undef _In_reads_opt_bytes_ 127 | #undef _In_reads_or_z_ 128 | #undef _In_z_ 129 | #undef _Inout_ 130 | #undef _Inout_opt_ 131 | #undef _Inout_z_count_ 132 | #undef _Out_ 133 | #undef _Out_opt_ 134 | #undef _Out_writes_ 135 | #undef _Outptr_result_maybenull_ 136 | #undef _Readable_bytes_ 137 | #undef _Success_ 138 | #undef _Writable_bytes_ 139 | #undef _Pre_notnull_ 140 | #endif 141 | 142 | #if defined(_Deref_out_opt_z_) && !defined(_Outptr_result_maybenull_) 143 | #define _Outptr_result_maybenull_ _Deref_out_opt_z_ 144 | #endif 145 | 146 | #if defined(_In_count_) && !defined(_In_reads_) 147 | #define _In_reads_(x) _In_count_(x) 148 | #endif 149 | 150 | #if defined(_In_opt_count_) && !defined(_In_reads_opt_) 151 | #define _In_reads_opt_(x) _In_opt_count_(x) 152 | #endif 153 | 154 | #if defined(_In_opt_bytecount_) && !defined(_In_reads_opt_bytes_) 155 | #define _In_reads_opt_bytes_(x) _In_opt_bytecount_(x) 156 | #endif 157 | 158 | #if defined(_In_bytecount_) && !defined(_In_reads_bytes_) 159 | #define _In_reads_bytes_(x) _In_bytecount_(x) 160 | #endif 161 | 162 | #ifndef _In_ 163 | #define _In_ 164 | #endif 165 | 166 | #ifndef _In_bytecount_ 167 | #define _In_bytecount_(x) 168 | #endif 169 | 170 | #ifndef _In_count_ 171 | #define _In_count_(x) 172 | #endif 173 | 174 | #ifndef _In_opt_ 175 | #define _In_opt_ 176 | #endif 177 | 178 | #ifndef _In_opt_bytecount_ 179 | #define _In_opt_bytecount_(x) 180 | #endif 181 | 182 | #ifndef _In_opt_count_ 183 | #define _In_opt_count_(x) 184 | #endif 185 | 186 | #ifndef _In_opt_z_ 187 | #define _In_opt_z_ 188 | #endif 189 | 190 | #ifndef _In_range_ 191 | #define _In_range_(x,y) 192 | #endif 193 | 194 | #ifndef _In_reads_ 195 | #define _In_reads_(x) 196 | #endif 197 | 198 | #ifndef _In_reads_bytes_ 199 | #define _In_reads_bytes_(x) 200 | #endif 201 | 202 | #ifndef _In_reads_opt_ 203 | #define _In_reads_opt_(x) 204 | #endif 205 | 206 | #ifndef _In_reads_opt_bytes_ 207 | #define _In_reads_opt_bytes_(x) 208 | #endif 209 | 210 | #ifndef _In_reads_or_z_ 211 | #define _In_reads_or_z_ 212 | #endif 213 | 214 | #ifndef _In_z_ 215 | #define _In_z_ 216 | #endif 217 | 218 | #ifndef _Inout_ 219 | #define _Inout_ 220 | #endif 221 | 222 | #ifndef _Inout_opt_ 223 | #define _Inout_opt_ 224 | #endif 225 | 226 | #ifndef _Inout_z_count_ 227 | #define _Inout_z_count_(x) 228 | #endif 229 | 230 | #ifndef _Out_ 231 | #define _Out_ 232 | #endif 233 | 234 | #ifndef _Out_opt_ 235 | #define _Out_opt_ 236 | #endif 237 | 238 | #ifndef _Out_writes_ 239 | #define _Out_writes_(x) 240 | #endif 241 | 242 | #ifndef _Outptr_result_maybenull_ 243 | #define _Outptr_result_maybenull_ 244 | #endif 245 | 246 | #ifndef _Writable_bytes_ 247 | #define _Writable_bytes_(x) 248 | #endif 249 | 250 | #ifndef _Readable_bytes_ 251 | #define _Readable_bytes_(x) 252 | #endif 253 | 254 | #ifndef _Success_ 255 | #define _Success_(x) 256 | #endif 257 | 258 | #ifndef _Pre_notnull_ 259 | #define _Pre_notnull_ 260 | #endif 261 | 262 | #ifdef DETOURS_INTERNAL 263 | 264 | #pragma warning(disable:4615) // unknown warning type (suppress with older compilers) 265 | 266 | #ifndef _Benign_race_begin_ 267 | #define _Benign_race_begin_ 268 | #endif 269 | 270 | #ifndef _Benign_race_end_ 271 | #define _Benign_race_end_ 272 | #endif 273 | 274 | #ifndef _Field_size_ 275 | #define _Field_size_(x) 276 | #endif 277 | 278 | #ifndef _Field_range_ 279 | #define _Field_range_(x,y) 280 | #endif 281 | 282 | #ifndef _Analysis_assume_ 283 | #define _Analysis_assume_(x) 284 | #endif 285 | 286 | #endif // DETOURS_INTERNAL 287 | #endif // DETOURS_DONT_REMOVE_SAL_20 288 | 289 | ////////////////////////////////////////////////////////////////////////////// 290 | // 291 | #ifndef GUID_DEFINED 292 | #define GUID_DEFINED 293 | typedef struct _GUID 294 | { 295 | DWORD Data1; 296 | WORD Data2; 297 | WORD Data3; 298 | BYTE Data4[ 8 ]; 299 | } GUID; 300 | 301 | #ifdef INITGUID 302 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 303 | const GUID name \ 304 | = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } 305 | #else 306 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 307 | const GUID name 308 | #endif // INITGUID 309 | #endif // !GUID_DEFINED 310 | 311 | #if defined(__cplusplus) 312 | #ifndef _REFGUID_DEFINED 313 | #define _REFGUID_DEFINED 314 | #define REFGUID const GUID & 315 | #endif // !_REFGUID_DEFINED 316 | #else // !__cplusplus 317 | #ifndef _REFGUID_DEFINED 318 | #define _REFGUID_DEFINED 319 | #define REFGUID const GUID * const 320 | #endif // !_REFGUID_DEFINED 321 | #endif // !__cplusplus 322 | 323 | #ifndef ARRAYSIZE 324 | #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) 325 | #endif 326 | 327 | // 328 | ////////////////////////////////////////////////////////////////////////////// 329 | 330 | #ifdef __cplusplus 331 | extern "C" { 332 | #endif // __cplusplus 333 | 334 | /////////////////////////////////////////////////// Instruction Target Macros. 335 | // 336 | #define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0) 337 | #define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1) 338 | #define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0" 339 | 340 | extern const GUID DETOUR_EXE_RESTORE_GUID; 341 | extern const GUID DETOUR_EXE_HELPER_GUID; 342 | 343 | #define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! 344 | typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; 345 | 346 | /////////////////////////////////////////////////////////// Binary Structures. 347 | // 348 | #pragma pack(push, 8) 349 | typedef struct _DETOUR_SECTION_HEADER 350 | { 351 | DWORD cbHeaderSize; 352 | DWORD nSignature; 353 | DWORD nDataOffset; 354 | DWORD cbDataSize; 355 | 356 | DWORD nOriginalImportVirtualAddress; 357 | DWORD nOriginalImportSize; 358 | DWORD nOriginalBoundImportVirtualAddress; 359 | DWORD nOriginalBoundImportSize; 360 | 361 | DWORD nOriginalIatVirtualAddress; 362 | DWORD nOriginalIatSize; 363 | DWORD nOriginalSizeOfImage; 364 | DWORD cbPrePE; 365 | 366 | DWORD nOriginalClrFlags; 367 | DWORD reserved1; 368 | DWORD reserved2; 369 | DWORD reserved3; 370 | 371 | // Followed by cbPrePE bytes of data. 372 | } DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER; 373 | 374 | typedef struct _DETOUR_SECTION_RECORD 375 | { 376 | DWORD cbBytes; 377 | DWORD nReserved; 378 | GUID guid; 379 | } DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD; 380 | 381 | typedef struct _DETOUR_CLR_HEADER 382 | { 383 | // Header versioning 384 | ULONG cb; 385 | USHORT MajorRuntimeVersion; 386 | USHORT MinorRuntimeVersion; 387 | 388 | // Symbol table and startup information 389 | IMAGE_DATA_DIRECTORY MetaData; 390 | ULONG Flags; 391 | 392 | // Followed by the rest of the IMAGE_COR20_HEADER 393 | } DETOUR_CLR_HEADER, *PDETOUR_CLR_HEADER; 394 | 395 | typedef struct _DETOUR_EXE_RESTORE 396 | { 397 | DWORD cb; 398 | DWORD cbidh; 399 | DWORD cbinh; 400 | DWORD cbclr; 401 | 402 | PBYTE pidh; 403 | PBYTE pinh; 404 | PBYTE pclr; 405 | 406 | IMAGE_DOS_HEADER idh; 407 | union { 408 | IMAGE_NT_HEADERS inh; // all environments have this 409 | #ifdef IMAGE_NT_OPTIONAL_HDR32_MAGIC // some environments do not have this 410 | IMAGE_NT_HEADERS32 inh32; 411 | #endif 412 | #ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC // some environments do not have this 413 | IMAGE_NT_HEADERS64 inh64; 414 | #endif 415 | #ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC // some environments do not have this 416 | BYTE raw[sizeof(IMAGE_NT_HEADERS64) + 417 | sizeof(IMAGE_SECTION_HEADER) * 32]; 418 | #else 419 | BYTE raw[0x108 + sizeof(IMAGE_SECTION_HEADER) * 32]; 420 | #endif 421 | }; 422 | DETOUR_CLR_HEADER clr; 423 | 424 | } DETOUR_EXE_RESTORE, *PDETOUR_EXE_RESTORE; 425 | 426 | #ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC 427 | C_ASSERT(sizeof(IMAGE_NT_HEADERS64) == 0x108); 428 | #endif 429 | 430 | // The size can change, but assert for clarity due to the muddying #ifdefs. 431 | #ifdef _WIN64 432 | C_ASSERT(sizeof(DETOUR_EXE_RESTORE) == 0x688); 433 | #else 434 | C_ASSERT(sizeof(DETOUR_EXE_RESTORE) == 0x678); 435 | #endif 436 | 437 | typedef struct _DETOUR_EXE_HELPER 438 | { 439 | DWORD cb; 440 | DWORD pid; 441 | DWORD nDlls; 442 | CHAR rDlls[4]; 443 | } DETOUR_EXE_HELPER, *PDETOUR_EXE_HELPER; 444 | 445 | #pragma pack(pop) 446 | 447 | #define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \ 448 | { \ 449 | sizeof(DETOUR_SECTION_HEADER),\ 450 | DETOUR_SECTION_HEADER_SIGNATURE,\ 451 | sizeof(DETOUR_SECTION_HEADER),\ 452 | (cbSectionSize),\ 453 | \ 454 | 0,\ 455 | 0,\ 456 | 0,\ 457 | 0,\ 458 | \ 459 | 0,\ 460 | 0,\ 461 | 0,\ 462 | 0,\ 463 | } 464 | 465 | /////////////////////////////////////////////////////////////// Helper Macros. 466 | // 467 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) 468 | #define DETOURS_STRINGIFY_(x) #x 469 | 470 | ///////////////////////////////////////////////////////////// Binary Typedefs. 471 | // 472 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)( 473 | _In_opt_ PVOID pContext, 474 | _In_opt_ LPCSTR pszFile, 475 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile); 476 | 477 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)( 478 | _In_opt_ PVOID pContext, 479 | _In_ LPCSTR pszOrigFile, 480 | _In_ LPCSTR pszFile, 481 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile); 482 | 483 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)( 484 | _In_opt_ PVOID pContext, 485 | _In_ ULONG nOrigOrdinal, 486 | _In_ ULONG nOrdinal, 487 | _Out_ ULONG *pnOutOrdinal, 488 | _In_opt_ LPCSTR pszOrigSymbol, 489 | _In_opt_ LPCSTR pszSymbol, 490 | _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol); 491 | 492 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_COMMIT_CALLBACK)( 493 | _In_opt_ PVOID pContext); 494 | 495 | typedef BOOL (CALLBACK *PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(_In_opt_ PVOID pContext, 496 | _In_ ULONG nOrdinal, 497 | _In_opt_ LPCSTR pszName, 498 | _In_opt_ PVOID pCode); 499 | 500 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FILE_CALLBACK)(_In_opt_ PVOID pContext, 501 | _In_opt_ HMODULE hModule, 502 | _In_opt_ LPCSTR pszFile); 503 | 504 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK)(_In_opt_ PVOID pContext, 505 | _In_ DWORD nOrdinal, 506 | _In_opt_ LPCSTR pszFunc, 507 | _In_opt_ PVOID pvFunc); 508 | 509 | // Same as PF_DETOUR_IMPORT_FUNC_CALLBACK but extra indirection on last parameter. 510 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK_EX)(_In_opt_ PVOID pContext, 511 | _In_ DWORD nOrdinal, 512 | _In_opt_ LPCSTR pszFunc, 513 | _In_opt_ PVOID* ppvFunc); 514 | 515 | typedef VOID * PDETOUR_BINARY; 516 | typedef VOID * PDETOUR_LOADED_BINARY; 517 | 518 | //////////////////////////////////////////////////////////// Transaction APIs. 519 | // 520 | LONG WINAPI DetourTransactionBegin(VOID); 521 | LONG WINAPI DetourTransactionAbort(VOID); 522 | LONG WINAPI DetourTransactionCommit(VOID); 523 | LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer); 524 | 525 | LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread); 526 | 527 | LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer, 528 | _In_ PVOID pDetour); 529 | 530 | LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer, 531 | _In_ PVOID pDetour, 532 | _Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline, 533 | _Out_opt_ PVOID *ppRealTarget, 534 | _Out_opt_ PVOID *ppRealDetour); 535 | 536 | LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer, 537 | _In_ PVOID pDetour); 538 | 539 | BOOL WINAPI DetourSetIgnoreTooSmall(_In_ BOOL fIgnore); 540 | BOOL WINAPI DetourSetRetainRegions(_In_ BOOL fRetain); 541 | PVOID WINAPI DetourSetSystemRegionLowerBound(_In_ PVOID pSystemRegionLowerBound); 542 | PVOID WINAPI DetourSetSystemRegionUpperBound(_In_ PVOID pSystemRegionUpperBound); 543 | 544 | ////////////////////////////////////////////////////////////// Code Functions. 545 | // 546 | PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, 547 | _In_ LPCSTR pszFunction); 548 | PVOID WINAPI DetourCodeFromPointer(_In_ PVOID pPointer, 549 | _Out_opt_ PVOID *ppGlobals); 550 | PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst, 551 | _Inout_opt_ PVOID *ppDstPool, 552 | _In_ PVOID pSrc, 553 | _Out_opt_ PVOID *ppTarget, 554 | _Out_opt_ LONG *plExtra); 555 | BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule, 556 | _In_ BOOL fLimitReferencesToModule); 557 | PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget, 558 | _Out_ PDWORD pcbAllocatedSize); 559 | 560 | ///////////////////////////////////////////////////// Loaded Binary Functions. 561 | // 562 | HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr); 563 | HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast); 564 | PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule); 565 | ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule); 566 | BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule, 567 | _In_opt_ PVOID pContext, 568 | _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport); 569 | BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule, 570 | _In_opt_ PVOID pContext, 571 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, 572 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc); 573 | 574 | BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule, 575 | _In_opt_ PVOID pContext, 576 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, 577 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFuncEx); 578 | 579 | _Writable_bytes_(*pcbData) 580 | _Readable_bytes_(*pcbData) 581 | _Success_(return != NULL) 582 | PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule, 583 | _In_ REFGUID rguid, 584 | _Out_ DWORD *pcbData); 585 | 586 | _Writable_bytes_(*pcbData) 587 | _Readable_bytes_(*pcbData) 588 | _Success_(return != NULL) 589 | PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid, 590 | _Out_ DWORD * pcbData); 591 | 592 | DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule); 593 | 594 | ///////////////////////////////////////////////// Persistent Binary Functions. 595 | // 596 | 597 | PDETOUR_BINARY WINAPI DetourBinaryOpen(_In_ HANDLE hFile); 598 | 599 | _Writable_bytes_(*pcbData) 600 | _Readable_bytes_(*pcbData) 601 | _Success_(return != NULL) 602 | PVOID WINAPI DetourBinaryEnumeratePayloads(_In_ PDETOUR_BINARY pBinary, 603 | _Out_opt_ GUID *pGuid, 604 | _Out_ DWORD *pcbData, 605 | _Inout_ DWORD *pnIterator); 606 | 607 | _Writable_bytes_(*pcbData) 608 | _Readable_bytes_(*pcbData) 609 | _Success_(return != NULL) 610 | PVOID WINAPI DetourBinaryFindPayload(_In_ PDETOUR_BINARY pBinary, 611 | _In_ REFGUID rguid, 612 | _Out_ DWORD *pcbData); 613 | 614 | PVOID WINAPI DetourBinarySetPayload(_In_ PDETOUR_BINARY pBinary, 615 | _In_ REFGUID rguid, 616 | _In_reads_opt_(cbData) PVOID pData, 617 | _In_ DWORD cbData); 618 | BOOL WINAPI DetourBinaryDeletePayload(_In_ PDETOUR_BINARY pBinary, _In_ REFGUID rguid); 619 | BOOL WINAPI DetourBinaryPurgePayloads(_In_ PDETOUR_BINARY pBinary); 620 | BOOL WINAPI DetourBinaryResetImports(_In_ PDETOUR_BINARY pBinary); 621 | BOOL WINAPI DetourBinaryEditImports(_In_ PDETOUR_BINARY pBinary, 622 | _In_opt_ PVOID pContext, 623 | _In_opt_ PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway, 624 | _In_opt_ PF_DETOUR_BINARY_FILE_CALLBACK pfFile, 625 | _In_opt_ PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol, 626 | _In_opt_ PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit); 627 | BOOL WINAPI DetourBinaryWrite(_In_ PDETOUR_BINARY pBinary, _In_ HANDLE hFile); 628 | BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary); 629 | 630 | /////////////////////////////////////////////////// Create Process & Load Dll. 631 | // 632 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)( 633 | _In_opt_ LPCSTR lpApplicationName, 634 | _Inout_opt_ LPSTR lpCommandLine, 635 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 636 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 637 | _In_ BOOL bInheritHandles, 638 | _In_ DWORD dwCreationFlags, 639 | _In_opt_ LPVOID lpEnvironment, 640 | _In_opt_ LPCSTR lpCurrentDirectory, 641 | _In_ LPSTARTUPINFOA lpStartupInfo, 642 | _Out_ LPPROCESS_INFORMATION lpProcessInformation); 643 | 644 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEW)( 645 | _In_opt_ LPCWSTR lpApplicationName, 646 | _Inout_opt_ LPWSTR lpCommandLine, 647 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 648 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 649 | _In_ BOOL bInheritHandles, 650 | _In_ DWORD dwCreationFlags, 651 | _In_opt_ LPVOID lpEnvironment, 652 | _In_opt_ LPCWSTR lpCurrentDirectory, 653 | _In_ LPSTARTUPINFOW lpStartupInfo, 654 | _Out_ LPPROCESS_INFORMATION lpProcessInformation); 655 | 656 | BOOL WINAPI DetourCreateProcessWithDllA(_In_opt_ LPCSTR lpApplicationName, 657 | _Inout_opt_ LPSTR lpCommandLine, 658 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 659 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 660 | _In_ BOOL bInheritHandles, 661 | _In_ DWORD dwCreationFlags, 662 | _In_opt_ LPVOID lpEnvironment, 663 | _In_opt_ LPCSTR lpCurrentDirectory, 664 | _In_ LPSTARTUPINFOA lpStartupInfo, 665 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 666 | _In_ LPCSTR lpDllName, 667 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 668 | 669 | BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName, 670 | _Inout_opt_ LPWSTR lpCommandLine, 671 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 672 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 673 | _In_ BOOL bInheritHandles, 674 | _In_ DWORD dwCreationFlags, 675 | _In_opt_ LPVOID lpEnvironment, 676 | _In_opt_ LPCWSTR lpCurrentDirectory, 677 | _In_ LPSTARTUPINFOW lpStartupInfo, 678 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 679 | _In_ LPCSTR lpDllName, 680 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 681 | 682 | #ifdef UNICODE 683 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllW 684 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW 685 | #else 686 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllA 687 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA 688 | #endif // !UNICODE 689 | 690 | BOOL WINAPI DetourCreateProcessWithDllExA(_In_opt_ LPCSTR lpApplicationName, 691 | _Inout_opt_ LPSTR lpCommandLine, 692 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 693 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 694 | _In_ BOOL bInheritHandles, 695 | _In_ DWORD dwCreationFlags, 696 | _In_opt_ LPVOID lpEnvironment, 697 | _In_opt_ LPCSTR lpCurrentDirectory, 698 | _In_ LPSTARTUPINFOA lpStartupInfo, 699 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 700 | _In_ LPCSTR lpDllName, 701 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 702 | 703 | BOOL WINAPI DetourCreateProcessWithDllExW(_In_opt_ LPCWSTR lpApplicationName, 704 | _Inout_opt_ LPWSTR lpCommandLine, 705 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 706 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 707 | _In_ BOOL bInheritHandles, 708 | _In_ DWORD dwCreationFlags, 709 | _In_opt_ LPVOID lpEnvironment, 710 | _In_opt_ LPCWSTR lpCurrentDirectory, 711 | _In_ LPSTARTUPINFOW lpStartupInfo, 712 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 713 | _In_ LPCSTR lpDllName, 714 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 715 | 716 | #ifdef UNICODE 717 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExW 718 | #else 719 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExA 720 | #endif // !UNICODE 721 | 722 | BOOL WINAPI DetourCreateProcessWithDllsA(_In_opt_ LPCSTR lpApplicationName, 723 | _Inout_opt_ LPSTR lpCommandLine, 724 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 725 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 726 | _In_ BOOL bInheritHandles, 727 | _In_ DWORD dwCreationFlags, 728 | _In_opt_ LPVOID lpEnvironment, 729 | _In_opt_ LPCSTR lpCurrentDirectory, 730 | _In_ LPSTARTUPINFOA lpStartupInfo, 731 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 732 | _In_ DWORD nDlls, 733 | _In_reads_(nDlls) LPCSTR *rlpDlls, 734 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 735 | 736 | BOOL WINAPI DetourCreateProcessWithDllsW(_In_opt_ LPCWSTR lpApplicationName, 737 | _Inout_opt_ LPWSTR lpCommandLine, 738 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 739 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 740 | _In_ BOOL bInheritHandles, 741 | _In_ DWORD dwCreationFlags, 742 | _In_opt_ LPVOID lpEnvironment, 743 | _In_opt_ LPCWSTR lpCurrentDirectory, 744 | _In_ LPSTARTUPINFOW lpStartupInfo, 745 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 746 | _In_ DWORD nDlls, 747 | _In_reads_(nDlls) LPCSTR *rlpDlls, 748 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 749 | 750 | #ifdef UNICODE 751 | #define DetourCreateProcessWithDlls DetourCreateProcessWithDllsW 752 | #else 753 | #define DetourCreateProcessWithDlls DetourCreateProcessWithDllsA 754 | #endif // !UNICODE 755 | 756 | BOOL WINAPI DetourProcessViaHelperA(_In_ DWORD dwTargetPid, 757 | _In_ LPCSTR lpDllName, 758 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 759 | 760 | BOOL WINAPI DetourProcessViaHelperW(_In_ DWORD dwTargetPid, 761 | _In_ LPCSTR lpDllName, 762 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 763 | 764 | #ifdef UNICODE 765 | #define DetourProcessViaHelper DetourProcessViaHelperW 766 | #else 767 | #define DetourProcessViaHelper DetourProcessViaHelperA 768 | #endif // !UNICODE 769 | 770 | BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, 771 | _In_ DWORD nDlls, 772 | _In_reads_(nDlls) LPCSTR *rlpDlls, 773 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 774 | 775 | BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, 776 | _In_ DWORD nDlls, 777 | _In_reads_(nDlls) LPCSTR *rlpDlls, 778 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 779 | 780 | #ifdef UNICODE 781 | #define DetourProcessViaHelperDlls DetourProcessViaHelperDllsW 782 | #else 783 | #define DetourProcessViaHelperDlls DetourProcessViaHelperDllsA 784 | #endif // !UNICODE 785 | 786 | BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, 787 | _In_reads_(nDlls) LPCSTR *rlpDlls, 788 | _In_ DWORD nDlls); 789 | 790 | BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, 791 | _In_ HMODULE hImage, 792 | _In_ BOOL bIs32Bit, 793 | _In_reads_(nDlls) LPCSTR *rlpDlls, 794 | _In_ DWORD nDlls); 795 | 796 | BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, 797 | _In_ REFGUID rguid, 798 | _In_reads_bytes_(cbData) PVOID pvData, 799 | _In_ DWORD cbData); 800 | BOOL WINAPI DetourRestoreAfterWith(VOID); 801 | BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData, 802 | _In_ DWORD cbData); 803 | BOOL WINAPI DetourIsHelperProcess(VOID); 804 | VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, 805 | _In_ HINSTANCE, 806 | _In_ LPSTR, 807 | _In_ INT); 808 | 809 | // 810 | ////////////////////////////////////////////////////////////////////////////// 811 | #ifdef __cplusplus 812 | } 813 | #endif // __cplusplus 814 | 815 | //////////////////////////////////////////////// Detours Internal Definitions. 816 | // 817 | #ifdef __cplusplus 818 | #ifdef DETOURS_INTERNAL 819 | 820 | #define NOTHROW 821 | // #define NOTHROW (nothrow) 822 | 823 | ////////////////////////////////////////////////////////////////////////////// 824 | // 825 | #if (_MSC_VER < 1299) 826 | #include 827 | typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; 828 | typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; 829 | typedef IMAGEHLP_SYMBOL SYMBOL_INFO; 830 | typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO; 831 | 832 | static inline 833 | LONG InterlockedCompareExchange(_Inout_ LONG *ptr, _In_ LONG nval, _In_ LONG oval) 834 | { 835 | return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval); 836 | } 837 | #else 838 | #pragma warning(push) 839 | #pragma warning(disable:4091) // empty typedef 840 | #include 841 | #pragma warning(pop) 842 | #endif 843 | 844 | #ifdef IMAGEAPI // defined by DBGHELP.H 845 | typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(_In_ LPAPI_VERSION AppVersion); 846 | 847 | typedef BOOL (NTAPI *PF_SymInitialize)(_In_ HANDLE hProcess, 848 | _In_opt_ LPCSTR UserSearchPath, 849 | _In_ BOOL fInvadeProcess); 850 | typedef DWORD (NTAPI *PF_SymSetOptions)(_In_ DWORD SymOptions); 851 | typedef DWORD (NTAPI *PF_SymGetOptions)(VOID); 852 | typedef DWORD64 (NTAPI *PF_SymLoadModule64)(_In_ HANDLE hProcess, 853 | _In_opt_ HANDLE hFile, 854 | _In_ LPSTR ImageName, 855 | _In_opt_ LPSTR ModuleName, 856 | _In_ DWORD64 BaseOfDll, 857 | _In_opt_ DWORD SizeOfDll); 858 | typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(_In_ HANDLE hProcess, 859 | _In_ DWORD64 qwAddr, 860 | _Out_ PIMAGEHLP_MODULE64 ModuleInfo); 861 | typedef BOOL (NTAPI *PF_SymFromName)(_In_ HANDLE hProcess, 862 | _In_ LPSTR Name, 863 | _Out_ PSYMBOL_INFO Symbol); 864 | 865 | typedef struct _DETOUR_SYM_INFO 866 | { 867 | HANDLE hProcess; 868 | HMODULE hDbgHelp; 869 | PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx; 870 | PF_SymInitialize pfSymInitialize; 871 | PF_SymSetOptions pfSymSetOptions; 872 | PF_SymGetOptions pfSymGetOptions; 873 | PF_SymLoadModule64 pfSymLoadModule64; 874 | PF_SymGetModuleInfo64 pfSymGetModuleInfo64; 875 | PF_SymFromName pfSymFromName; 876 | } DETOUR_SYM_INFO, *PDETOUR_SYM_INFO; 877 | 878 | PDETOUR_SYM_INFO DetourLoadImageHlp(VOID); 879 | 880 | #endif // IMAGEAPI 881 | 882 | #if defined(_INC_STDIO) && !defined(_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS) 883 | #error detours.h must be included before stdio.h (or at least define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS earlier) 884 | #endif 885 | #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 886 | 887 | #ifndef DETOUR_TRACE 888 | #if DETOUR_DEBUG 889 | #define DETOUR_TRACE(x) printf x 890 | #define DETOUR_BREAK() __debugbreak() 891 | #include 892 | #include 893 | #else 894 | #define DETOUR_TRACE(x) 895 | #define DETOUR_BREAK() 896 | #endif 897 | #endif 898 | 899 | #if 1 || defined(DETOURS_IA64) 900 | 901 | // 902 | // IA64 instructions are 41 bits, 3 per bundle, plus 5 bit bundle template => 128 bits per bundle. 903 | // 904 | 905 | #define DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE (3) 906 | 907 | #define DETOUR_IA64_TEMPLATE_OFFSET (0) 908 | #define DETOUR_IA64_TEMPLATE_SIZE (5) 909 | 910 | #define DETOUR_IA64_INSTRUCTION_SIZE (41) 911 | #define DETOUR_IA64_INSTRUCTION0_OFFSET (DETOUR_IA64_TEMPLATE_SIZE) 912 | #define DETOUR_IA64_INSTRUCTION1_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) 913 | #define DETOUR_IA64_INSTRUCTION2_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) 914 | 915 | C_ASSERT(DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * DETOUR_IA64_INSTRUCTION_SIZE == 128); 916 | 917 | __declspec(align(16)) struct DETOUR_IA64_BUNDLE 918 | { 919 | public: 920 | union 921 | { 922 | BYTE data[16]; 923 | UINT64 wide[2]; 924 | }; 925 | 926 | enum { 927 | A_UNIT = 1u, 928 | I_UNIT = 2u, 929 | M_UNIT = 3u, 930 | B_UNIT = 4u, 931 | F_UNIT = 5u, 932 | L_UNIT = 6u, 933 | X_UNIT = 7u, 934 | }; 935 | struct DETOUR_IA64_METADATA 936 | { 937 | ULONG nTemplate : 8; // Instruction template. 938 | ULONG nUnit0 : 4; // Unit for slot 0 939 | ULONG nUnit1 : 4; // Unit for slot 1 940 | ULONG nUnit2 : 4; // Unit for slot 2 941 | }; 942 | 943 | protected: 944 | static const DETOUR_IA64_METADATA s_rceCopyTable[33]; 945 | 946 | UINT RelocateBundle(_Inout_ DETOUR_IA64_BUNDLE* pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; 947 | 948 | bool RelocateInstruction(_Inout_ DETOUR_IA64_BUNDLE* pDst, 949 | _In_ BYTE slot, 950 | _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; 951 | 952 | // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0 953 | // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0. 954 | 955 | // 00 956 | // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0. 957 | // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0] 958 | // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5] 959 | // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42] 960 | // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46] 961 | // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83] 962 | // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87] 963 | // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124] 964 | BYTE GetTemplate() const; 965 | // Get 4 bit opcodes. 966 | BYTE GetInst0() const; 967 | BYTE GetInst1() const; 968 | BYTE GetInst2() const; 969 | BYTE GetUnit(BYTE slot) const; 970 | BYTE GetUnit0() const; 971 | BYTE GetUnit1() const; 972 | BYTE GetUnit2() const; 973 | // Get 37 bit data. 974 | UINT64 GetData0() const; 975 | UINT64 GetData1() const; 976 | UINT64 GetData2() const; 977 | 978 | // Get/set the full 41 bit instructions. 979 | UINT64 GetInstruction(BYTE slot) const; 980 | UINT64 GetInstruction0() const; 981 | UINT64 GetInstruction1() const; 982 | UINT64 GetInstruction2() const; 983 | void SetInstruction(BYTE slot, UINT64 instruction); 984 | void SetInstruction0(UINT64 instruction); 985 | void SetInstruction1(UINT64 instruction); 986 | void SetInstruction2(UINT64 instruction); 987 | 988 | // Get/set bitfields. 989 | static UINT64 GetBits(UINT64 Value, UINT64 Offset, UINT64 Count); 990 | static UINT64 SetBits(UINT64 Value, UINT64 Offset, UINT64 Count, UINT64 Field); 991 | 992 | // Get specific read-only fields. 993 | static UINT64 GetOpcode(UINT64 instruction); // 4bit opcode 994 | static UINT64 GetX(UINT64 instruction); // 1bit opcode extension 995 | static UINT64 GetX3(UINT64 instruction); // 3bit opcode extension 996 | static UINT64 GetX6(UINT64 instruction); // 6bit opcode extension 997 | 998 | // Get/set specific fields. 999 | static UINT64 GetImm7a(UINT64 instruction); 1000 | static UINT64 SetImm7a(UINT64 instruction, UINT64 imm7a); 1001 | static UINT64 GetImm13c(UINT64 instruction); 1002 | static UINT64 SetImm13c(UINT64 instruction, UINT64 imm13c); 1003 | static UINT64 GetSignBit(UINT64 instruction); 1004 | static UINT64 SetSignBit(UINT64 instruction, UINT64 signBit); 1005 | static UINT64 GetImm20a(UINT64 instruction); 1006 | static UINT64 SetImm20a(UINT64 instruction, UINT64 imm20a); 1007 | static UINT64 GetImm20b(UINT64 instruction); 1008 | static UINT64 SetImm20b(UINT64 instruction, UINT64 imm20b); 1009 | 1010 | static UINT64 SignExtend(UINT64 Value, UINT64 Offset); 1011 | 1012 | BOOL IsMovlGp() const; 1013 | 1014 | VOID SetInst(BYTE Slot, BYTE nInst); 1015 | VOID SetInst0(BYTE nInst); 1016 | VOID SetInst1(BYTE nInst); 1017 | VOID SetInst2(BYTE nInst); 1018 | VOID SetData(BYTE Slot, UINT64 nData); 1019 | VOID SetData0(UINT64 nData); 1020 | VOID SetData1(UINT64 nData); 1021 | VOID SetData2(UINT64 nData); 1022 | BOOL SetNop(BYTE Slot); 1023 | BOOL SetNop0(); 1024 | BOOL SetNop1(); 1025 | BOOL SetNop2(); 1026 | 1027 | public: 1028 | BOOL IsBrl() const; 1029 | VOID SetBrl(); 1030 | VOID SetBrl(UINT64 target); 1031 | UINT64 GetBrlTarget() const; 1032 | VOID SetBrlTarget(UINT64 target); 1033 | VOID SetBrlImm(UINT64 imm); 1034 | UINT64 GetBrlImm() const; 1035 | 1036 | UINT64 GetMovlGp() const; 1037 | VOID SetMovlGp(UINT64 gp); 1038 | 1039 | VOID SetStop(); 1040 | 1041 | UINT Copy(_Out_ DETOUR_IA64_BUNDLE *pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra = NULL) const; 1042 | }; 1043 | #endif // DETOURS_IA64 1044 | 1045 | #ifdef DETOURS_ARM 1046 | 1047 | #define DETOURS_PFUNC_TO_PBYTE(p) ((PBYTE)(((ULONG_PTR)(p)) & ~(ULONG_PTR)1)) 1048 | #define DETOURS_PBYTE_TO_PFUNC(p) ((PBYTE)(((ULONG_PTR)(p)) | (ULONG_PTR)1)) 1049 | 1050 | #endif // DETOURS_ARM 1051 | 1052 | ////////////////////////////////////////////////////////////////////////////// 1053 | 1054 | #ifdef __cplusplus 1055 | extern "C" { 1056 | #endif // __cplusplus 1057 | 1058 | #define DETOUR_OFFLINE_LIBRARY(x) \ 1059 | PVOID WINAPI DetourCopyInstruction##x(_In_opt_ PVOID pDst, \ 1060 | _Inout_opt_ PVOID *ppDstPool, \ 1061 | _In_ PVOID pSrc, \ 1062 | _Out_opt_ PVOID *ppTarget, \ 1063 | _Out_opt_ LONG *plExtra); \ 1064 | \ 1065 | BOOL WINAPI DetourSetCodeModule##x(_In_ HMODULE hModule, \ 1066 | _In_ BOOL fLimitReferencesToModule); \ 1067 | 1068 | DETOUR_OFFLINE_LIBRARY(X86) 1069 | DETOUR_OFFLINE_LIBRARY(X64) 1070 | DETOUR_OFFLINE_LIBRARY(ARM) 1071 | DETOUR_OFFLINE_LIBRARY(ARM64) 1072 | DETOUR_OFFLINE_LIBRARY(IA64) 1073 | 1074 | #undef DETOUR_OFFLINE_LIBRARY 1075 | 1076 | ////////////////////////////////////////////////////////////////////////////// 1077 | // 1078 | // Helpers for manipulating page protection. 1079 | // 1080 | 1081 | _Success_(return != FALSE) 1082 | BOOL WINAPI DetourVirtualProtectSameExecuteEx(_In_ HANDLE hProcess, 1083 | _In_ PVOID pAddress, 1084 | _In_ SIZE_T nSize, 1085 | _In_ DWORD dwNewProtect, 1086 | _Out_ PDWORD pdwOldProtect); 1087 | 1088 | _Success_(return != FALSE) 1089 | BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress, 1090 | _In_ SIZE_T nSize, 1091 | _In_ DWORD dwNewProtect, 1092 | _Out_ PDWORD pdwOldProtect); 1093 | #ifdef __cplusplus 1094 | } 1095 | #endif // __cplusplus 1096 | 1097 | ////////////////////////////////////////////////////////////////////////////// 1098 | 1099 | #define MM_ALLOCATION_GRANULARITY 0x10000 1100 | 1101 | ////////////////////////////////////////////////////////////////////////////// 1102 | 1103 | #endif // DETOURS_INTERNAL 1104 | #endif // __cplusplus 1105 | 1106 | #endif // _DETOURS_H_ 1107 | // 1108 | //////////////////////////////////////////////////////////////// End of File. 1109 | -------------------------------------------------------------------------------- /detours/detours.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eiton/MBTL-Hitbox-Viewer/4d5539c3f685ee007eb4d36ac531d8bb427d26f8/detours/detours.lib -------------------------------------------------------------------------------- /dll_loader.ini: -------------------------------------------------------------------------------- 1 | [dll_list] 2 | d1=filepatch-tl.dll 3 | d2=MBTL_hitbox_overlay.dll 4 | #add other dlls you want to load 5 | 6 | 7 | 8 | [hitbox_viewer] 9 | #Config of the hitbox viewer 10 | #1=on, 0=off 11 | toggle_hitbox_on_launch=1 12 | unlock_additional_color_slots=0 -------------------------------------------------------------------------------- /dll_loader/Source.def: -------------------------------------------------------------------------------- 1 | LIBRARY d3d9 2 | EXPORTS 3 | Direct3DCreate9 -------------------------------------------------------------------------------- /dll_loader/cpp.hint: -------------------------------------------------------------------------------- 1 | #define D3D9H_API __declspec(dllexport) 2 | #define D3D9H_API __declspec(dllimport) 3 | -------------------------------------------------------------------------------- /dll_loader/dll_loader.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {b44ccb5a-ce43-41e6-9e38-854c8f32e97e} 25 | dll_loader 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | d3d9 76 | $(WindowsSDK_LibraryPath_x86);$(LibraryPath);$(DXSDK_DIR)Lib\x86 77 | $(SolutionDir)mINI;$(IncludePath) 78 | 79 | 80 | false 81 | d3d9 82 | $(WindowsSDK_LibraryPath_x86);E:\VisualStudio\VC\Tools\MSVC\14.28.29910\atlmfc\lib\x86;E:\VisualStudio\VC\Tools\MSVC\14.28.29910\lib\x86;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x86;E:\Windows Kits\10\lib\10.0.19041.0\ucrt\x86;$(DXSDK_DIR)Lib\x86 83 | $(SolutionDir)mINI;$(IncludePath) 84 | 85 | 86 | true 87 | dll_loader 88 | 89 | 90 | false 91 | dll_loader 92 | 93 | 94 | 95 | Level3 96 | true 97 | WIN32;_DEBUG;dll_loader_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 98 | true 99 | Use 100 | pch.h 101 | 102 | 103 | Windows 104 | true 105 | false 106 | Source.def 107 | 108 | 109 | 110 | 111 | Level3 112 | true 113 | true 114 | true 115 | WIN32;NDEBUG;dll_loader_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 116 | true 117 | Use 118 | pch.h 119 | 120 | 121 | Windows 122 | true 123 | true 124 | true 125 | false 126 | Source.def 127 | 128 | 129 | 130 | 131 | Level3 132 | true 133 | _DEBUG;dll_loader_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 134 | true 135 | Use 136 | pch.h 137 | 138 | 139 | Windows 140 | true 141 | false 142 | Source.def 143 | 144 | 145 | 146 | 147 | Level3 148 | true 149 | true 150 | true 151 | NDEBUG;dll_loader_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 152 | true 153 | Use 154 | pch.h 155 | 156 | 157 | Windows 158 | true 159 | true 160 | true 161 | false 162 | Source.def 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | Create 177 | Create 178 | Create 179 | Create 180 | 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /dll_loader/dll_loader.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | Source Files 21 | 22 | 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /dll_loader/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include 3 | #include 4 | #include 5 | #include "mINI.h" 6 | #include 7 | #pragma comment(lib, "d3d9.lib") 8 | //#pragma comment(lib, "d3dx9.lib") 9 | 10 | TCHAR szDllPath[MAX_PATH] = { 0 }; 11 | typedef IDirect3D9* (WINAPI* FAA)(UINT a); 12 | FAA Direct3DCreate9_out; 13 | 14 | IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion) { 15 | return Direct3DCreate9_out(SDKVersion); 16 | } 17 | 18 | 19 | 20 | DWORD WINAPI MainThread(LPVOID hModule) 21 | { 22 | 23 | Sleep(2000); 24 | mINI::INIFile file("dll_loader.ini"); 25 | mINI::INIStructure ini; 26 | 27 | file.read(ini); 28 | 29 | 30 | for (auto const& it2 : ini["dll_list"]) 31 | { 32 | std::string s = it2.second; 33 | std::wstring p(s.begin(), s.end()); 34 | HMODULE hDll2 = LoadLibrary(p.c_str()); 35 | if (hDll2 == NULL) 36 | { 37 | } 38 | } 39 | return TRUE; 40 | } 41 | 42 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID /* lpReserved */) 43 | { 44 | switch (ul_reason_for_call) 45 | { 46 | case DLL_PROCESS_ATTACH: 47 | CreateThread(0, 0, MainThread, hModule, 0, 0); 48 | case DLL_THREAD_ATTACH: 49 | case DLL_THREAD_DETACH: 50 | case DLL_PROCESS_DETACH: 51 | break; 52 | } 53 | GetSystemDirectory(szDllPath, MAX_PATH); 54 | 55 | 56 | std::wstring fPath = szDllPath; 57 | std::wstring tmp = L"\\d3d9.dll"; 58 | fPath = fPath + tmp; 59 | 60 | HMODULE hDll = LoadLibrary(fPath.c_str()); 61 | 62 | if (hDll == NULL) 63 | { 64 | MessageBoxA(NULL, "failed to load d3d9.dll from system directory", "Error", MB_OK); 65 | return FALSE; 66 | } 67 | 68 | // Pointer to the original function 69 | 70 | Direct3DCreate9_out = (FAA)GetProcAddress(hDll, "Direct3DCreate9"); 71 | if (Direct3DCreate9_out == NULL) 72 | { 73 | MessageBoxA(NULL, "failed to get Direct3DCreate9 address", "Error", MB_OK); 74 | FreeLibrary(hDll); 75 | return FALSE; 76 | } 77 | return TRUE; 78 | } 79 | -------------------------------------------------------------------------------- /dll_loader/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 4 | // Windows Header Files 5 | #include 6 | -------------------------------------------------------------------------------- /dll_loader/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /dll_loader/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: This is a precompiled header file. 2 | // Files listed below are compiled only once, improving build performance for future builds. 3 | // This also affects IntelliSense performance, including code completion and many code browsing features. 4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds. 5 | // Do not add files here that you will be updating frequently as this negates the performance advantage. 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // add headers that you want to pre-compile here 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /hitbox overlay.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29201.188 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hitbox overlay", "hitbox overlay\hitbox overlay.vcxproj", "{0F14E1BC-A90B-4C0A-BD15-D6690E35909C}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll_loader", "..\dll_loader\dll_loader\dll_loader.vcxproj", "{B44CCB5A-CE43-41E6-9E38-854C8F32E97E}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {0F14E1BC-A90B-4C0A-BD15-D6690E35909C}.Debug|x64.ActiveCfg = Debug|x64 19 | {0F14E1BC-A90B-4C0A-BD15-D6690E35909C}.Debug|x64.Build.0 = Debug|x64 20 | {0F14E1BC-A90B-4C0A-BD15-D6690E35909C}.Debug|x86.ActiveCfg = Debug|Win32 21 | {0F14E1BC-A90B-4C0A-BD15-D6690E35909C}.Debug|x86.Build.0 = Debug|Win32 22 | {0F14E1BC-A90B-4C0A-BD15-D6690E35909C}.Release|x64.ActiveCfg = Release|x64 23 | {0F14E1BC-A90B-4C0A-BD15-D6690E35909C}.Release|x64.Build.0 = Release|x64 24 | {0F14E1BC-A90B-4C0A-BD15-D6690E35909C}.Release|x86.ActiveCfg = Release|Win32 25 | {0F14E1BC-A90B-4C0A-BD15-D6690E35909C}.Release|x86.Build.0 = Release|Win32 26 | {B44CCB5A-CE43-41E6-9E38-854C8F32E97E}.Debug|x64.ActiveCfg = Debug|x64 27 | {B44CCB5A-CE43-41E6-9E38-854C8F32E97E}.Debug|x64.Build.0 = Debug|x64 28 | {B44CCB5A-CE43-41E6-9E38-854C8F32E97E}.Debug|x86.ActiveCfg = Debug|Win32 29 | {B44CCB5A-CE43-41E6-9E38-854C8F32E97E}.Debug|x86.Build.0 = Debug|Win32 30 | {B44CCB5A-CE43-41E6-9E38-854C8F32E97E}.Release|x64.ActiveCfg = Release|x64 31 | {B44CCB5A-CE43-41E6-9E38-854C8F32E97E}.Release|x64.Build.0 = Release|x64 32 | {B44CCB5A-CE43-41E6-9E38-854C8F32E97E}.Release|x86.ActiveCfg = Release|Win32 33 | {B44CCB5A-CE43-41E6-9E38-854C8F32E97E}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {EE84431C-F183-4368-8E27-9FAB3695D30F} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /hitbox overlay/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "detours.h" 7 | #include 8 | #include 9 | #include "mINI.h" 10 | 11 | #pragma comment(lib,"d3d9.lib") 12 | #pragma comment(lib,"d3dx9.lib") 13 | #pragma comment(lib, "detours.lib") 14 | 15 | // box color 16 | D3DCOLOR hurtbox_color1 = D3DCOLOR_ARGB(96, 30, 30, 255); 17 | D3DCOLOR hurtbox_color2 = D3DCOLOR_ARGB(255, 0, 0, 255); 18 | D3DCOLOR hurtbox_armored_color1 = D3DCOLOR_ARGB(96, 255, 255, 255); 19 | D3DCOLOR hurtbox_armored_color2 = D3DCOLOR_ARGB(255, 255, 255, 255); 20 | D3DCOLOR pushbox_color1 = D3DCOLOR_ARGB(96, 255, 255, 0); 21 | D3DCOLOR pushbox_color2 = D3DCOLOR_ARGB(255, 255, 255, 0); 22 | D3DCOLOR clashbox_color1 = D3DCOLOR_ARGB(96, 30, 255, 30); 23 | D3DCOLOR clashbox_color2 = D3DCOLOR_ARGB(255, 0, 255, 0); 24 | D3DCOLOR hitbox_color1 = D3DCOLOR_ARGB(96, 255, 30, 30); 25 | D3DCOLOR hitbox_color2 = D3DCOLOR_ARGB(255, 255, 0, 0); 26 | 27 | 28 | // handle, address and offset 29 | HANDLE phandle; 30 | DWORD base_address; 31 | DWORD p1_address; 32 | 33 | int* pause; 34 | DWORD pause_address2; 35 | 36 | DWORD objList_address; 37 | int* objCount; 38 | 39 | int* resolutionX; 40 | int* resolutionY; 41 | 42 | signed int* cameraPosX; 43 | signed int* cameraPosY; 44 | float* cameraZoom; 45 | 46 | 47 | // asm codes to patch the exe 48 | 49 | //pause 50 | const BYTE je[6] = { 0x0F,0x84,0xC3,0x06,0x00,0x00 }; 51 | const BYTE jmp[6] = { 0xE9,0xC4,0x06,0x00,0x00,0x90 }; 52 | 53 | int pal_num = 0x1e; 54 | 55 | 56 | 57 | 58 | // variables for d3d hook 59 | typedef HRESULT(_stdcall* f_Present)(IDirect3DDevice9* pDevice, const RECT* pSourceRect, const RECT* pDestRect, HWND hDestWindowOverride, const RGNDATA* pDirtyRegion); 60 | f_Present oPresent; 61 | void** vtable; 62 | 63 | 64 | // other global variables 65 | int keyPressed = 0; 66 | bool toggleHitbox = true; 67 | bool unlockColorSlots = false; 68 | bool frameStep = false; 69 | LPD3DXFONT m_font; 70 | 71 | void DrawRectangle(IDirect3DDevice9* pDevice, const float x1, const float x2, const float y1, const float y2, const float z, D3DCOLOR innerColor, D3DCOLOR outerColor) { 72 | struct vertex 73 | { 74 | float x, y, z, rhw; 75 | DWORD color; 76 | }; 77 | DWORD alphaBlendEnable; 78 | DWORD destBlend; 79 | DWORD srcBlend; 80 | DWORD destBlendAlpha; 81 | DWORD srcBlendAlpha; 82 | DWORD pFVF; 83 | IDirect3DPixelShader9* pixelShader; 84 | IDirect3DBaseTexture9* texture; 85 | pDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &alphaBlendEnable); 86 | pDevice->GetRenderState(D3DRS_DESTBLEND, &destBlend); 87 | pDevice->GetRenderState(D3DRS_SRCBLEND, &srcBlend); 88 | pDevice->GetRenderState(D3DRS_DESTBLENDALPHA, &destBlendAlpha); 89 | pDevice->GetRenderState(D3DRS_SRCBLENDALPHA, &srcBlendAlpha); 90 | pDevice->GetPixelShader(&pixelShader); 91 | pDevice->GetFVF(&pFVF); 92 | pDevice->GetTexture(0, &texture); 93 | 94 | pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); 95 | pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 96 | pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 97 | pDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ONE); 98 | pDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ZERO); 99 | pDevice->SetPixelShader(nullptr); 100 | pDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); 101 | pDevice->SetTexture(0, nullptr); 102 | 103 | vertex vertices[] = 104 | { 105 | { x1, y1, z, 1.F, innerColor }, 106 | { x1, y2, z, 1.F, innerColor }, 107 | { x2, y1, z, 1.F, innerColor }, 108 | { x2, y2, z, 1.F, innerColor }, 109 | }; 110 | pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(vertex)); 111 | 112 | vertex outline[] = 113 | { 114 | { x1, y1, z, 1.F, outerColor }, 115 | { x1, y2, z, 1.F, outerColor }, 116 | { x2, y2, z, 1.F, outerColor }, 117 | { x2, y1, z, 1.F, outerColor }, 118 | { x1, y1, z, 1.F, outerColor }, 119 | }; 120 | pDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, 4, outline, sizeof(vertex)); 121 | 122 | 123 | pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, alphaBlendEnable); 124 | pDevice->SetRenderState(D3DRS_DESTBLEND, destBlend); 125 | pDevice->SetRenderState(D3DRS_SRCBLEND, srcBlend); 126 | pDevice->SetRenderState(D3DRS_DESTBLENDALPHA, destBlendAlpha); 127 | pDevice->SetRenderState(D3DRS_SRCBLENDALPHA, srcBlendAlpha); 128 | pDevice->SetPixelShader(pixelShader); 129 | pDevice->SetFVF(pFVF); 130 | pDevice->SetTexture(0, texture); 131 | if (texture != nullptr) 132 | texture->Release(); 133 | } 134 | void drawBox(IDirect3DDevice9* pDevice, int start, int end, DWORD boxAddr, float rx, float ry, BYTE facing, D3DCOLOR innerColor, D3DCOLOR outerColor) { 135 | for (int i = start; i < end; i++) { 136 | DWORD clsnAddress = *(DWORD*)(boxAddr + i * 4); 137 | if (clsnAddress != 0) { 138 | signed short* x1, * x2, * y1, * y2; 139 | x1 = (signed short*)clsnAddress; 140 | y1 = (signed short*)(clsnAddress + 0x2); 141 | x2 = (signed short*)(clsnAddress + 0x4); 142 | y2 = (signed short*)(clsnAddress + 0x6); 143 | float fx1, fx2, fy1, fy2; 144 | fx1 = ((*x1 * (facing == 0 ? 1.0f : -1.0f) + rx) * (*cameraZoom) + 640.0f) * (*resolutionX) / 1280.0f; 145 | fx2 = ((*x2 * (facing == 0 ? 1.0f : -1.0f) + rx) * (*cameraZoom) + 640.0f) * (*resolutionX) / 1280.0f; 146 | fy1 = ((*y1 + ry) * (*cameraZoom) + 640.0f) * (*resolutionY) / 720.0f; 147 | fy2 = ((*y2 + ry) * (*cameraZoom) + 640.0f) * (*resolutionY) / 720.0f; 148 | DrawRectangle(pDevice, fx1, fx2, fy1, fy2, 0, innerColor, outerColor); 149 | } 150 | 151 | } 152 | } 153 | void drawFrameData(IDirect3DDevice9* pDevice, DWORD objData, float rx, float ry) { 154 | bool isHurt = *(DWORD*)(objData + 0x2d8); 155 | int frameNum = 0; 156 | int totalFrames = 0; 157 | if (isHurt) { 158 | totalFrames = *(DWORD*)(objData + 0x2e0); 159 | if (totalFrames == -1) { 160 | totalFrames = *(BYTE*)(objData + 0x2cc); 161 | frameNum = *(BYTE*)(objData + 0x2c2) + 1; 162 | } 163 | else { 164 | frameNum = 1 + totalFrames - *(DWORD*)(objData + 0x2dc); 165 | } 166 | } 167 | else { 168 | DWORD state = *(DWORD*)((*(DWORD*)(objData + 0x6f8)) + 0x30); 169 | DWORD elem = *(DWORD*)(objData + 0x20); 170 | DWORD elemTime = *(DWORD*)(objData + 0x30); 171 | int i = 0; 172 | bool end = false; 173 | while (end == false && (*(DWORD*)(state + i * 0x4) != 0)) { 174 | if (i == elem) { 175 | frameNum = totalFrames + elemTime; 176 | } 177 | DWORD fa = (*(DWORD*)(state + i * 0x4) + 0x96); 178 | totalFrames += *(BYTE*)fa; 179 | DWORD ea = (*(DWORD*)(state + i * 0x4) + 0x98); 180 | end = *(bool*)ea != 1; 181 | i++; 182 | if (end && i <= elem) { 183 | end = false; 184 | state += i * 0x4; 185 | elem -= i; 186 | totalFrames = 1; 187 | i = 0; 188 | } 189 | } 190 | } 191 | BYTE dInvTime = *(BYTE*)(objData + 0x2b8); 192 | BYTE tInvTime = *(BYTE*)(objData + 0x2b9); 193 | //84 c1 b8 01 00 00 194 | BYTE invFlag = *(BYTE*)(objData + 0x554); 195 | BYTE invFlagTime = *(BYTE*)(objData + 0x560); 196 | 197 | BYTE invFlag2 = *(BYTE*)(*(DWORD*)(*(DWORD*)(objData + 0x6fc) + 0xAC) + 0xD); 198 | 199 | BYTE invFlag3 = *(BYTE*)(objData + 0x2a5); 200 | BYTE invFlag3_2 = *(BYTE*)(objData + 0x2a7); 201 | 202 | if (m_font == NULL) { 203 | D3DXCreateFont(pDevice, 17, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &m_font); 204 | } 205 | D3DCOLOR fontColor = D3DCOLOR_ARGB(255, 255, 255, 255); 206 | RECT rct; 207 | rct.left = ((rx - 400.0f) * (*cameraZoom) + 640.0f) * (*resolutionX) / 1280.0f; 208 | rct.right = ((rx + 400.0f) * (*cameraZoom) + 640.0f) * (*resolutionX) / 1280.0f; 209 | rct.top = ((10.0f + ry) * (*cameraZoom) + 640.0f) * (*resolutionY) / 720.0f; 210 | rct.bottom = ((60.0f + ry) * (*cameraZoom) + 640.0f) * (*resolutionY) / 720.0f; 211 | int k = 1; 212 | 213 | std::string text = std::to_string(frameNum) + "/" + std::to_string(totalFrames) + '\n'; 214 | if (dInvTime || invFlag2 == 3 || invFlag2 == 5 || (invFlag3 >= 3 && invFlag3_2 == 0)) { 215 | text += "S";//invincible to strikes 216 | } 217 | else if (invFlag != 0) { 218 | if ((invFlag & 1) > 0) { 219 | text += "A";//invincible to air attacks 220 | } 221 | if ((invFlag & 2) > 0) { 222 | text += "G";//invincible to ground attacks 223 | } 224 | if ((invFlag & 8) > 0) { 225 | text += "P";//invincible to projectiles 226 | } 227 | } 228 | if (tInvTime || invFlag2 == 4 || invFlag2 == 5 || (invFlag3 >= 3 && invFlag3_2 == 0)) { 229 | text += "T";//invincible to throws 230 | } 231 | m_font->DrawTextA(NULL, text.c_str(), -1, &rct, DT_CENTER, fontColor); 232 | 233 | } 234 | void drawObj(IDirect3DDevice9* pDevice, DWORD objData, int drawBlue, DWORD state, bool drawFrame) { 235 | signed int* posX, * posX2, * posY, * posY2; 236 | BYTE* facing; 237 | posX = (signed int*)(objData + 0x64); 238 | posY = (signed int*)(objData + 0x68); 239 | posX2 = (signed int*)(objData + 0x70); 240 | posY2 = (signed int*)(objData + 0x74); 241 | facing = (BYTE*)(objData + 0x6ec); 242 | BYTE* numBox1; 243 | BYTE* numBox2; 244 | numBox1 = (BYTE*)(state + 0xb7); 245 | numBox2 = (BYTE*)(state + 0xb6); 246 | float rx, ry; 247 | rx = (*posX + *posX2 - (*cameraPosX)) / 128.0f; 248 | ry = (*posY + *posY2 - (*cameraPosY)) / 128.0f; 249 | if (*numBox2 > 0) { 250 | DWORD* boxAddress = (DWORD*)(state + 0xc0); 251 | if (drawBlue) { 252 | if (drawBlue == 2) { 253 | drawBox(pDevice, 1, (*numBox2 > 8 ? 8 : *numBox2), *boxAddress, rx, ry, *facing, hurtbox_armored_color1, hurtbox_armored_color2); 254 | } 255 | else { 256 | drawBox(pDevice, 1, (*numBox2 > 8 ? 8 : *numBox2), *boxAddress, rx, ry, *facing, hurtbox_color1, hurtbox_color2); 257 | } 258 | drawBox(pDevice, 0, 1, *boxAddress, rx, ry, *facing, pushbox_color1, pushbox_color2); 259 | if (*numBox2 >= 0xC) { 260 | drawBox(pDevice, 0, 1, *boxAddress + 0xB * 4, rx, ry, *facing, clashbox_color1, clashbox_color2); 261 | } 262 | } 263 | } 264 | if (*numBox1 > 0) { 265 | DWORD* boxAddress = (DWORD*)(state + 0xc4); 266 | drawBox(pDevice, 0, *numBox1, *boxAddress, rx, ry, *facing, hitbox_color1, hitbox_color2); 267 | } 268 | if (drawFrame) { 269 | drawFrameData(pDevice, objData, rx, ry); 270 | } 271 | } 272 | 273 | HRESULT _stdcall Hooked_Present(IDirect3DDevice9* pDevice, const RECT* pSourceRect, const RECT* pDestRect, HWND hDestWindowOverride, const RGNDATA* pDirtyRegion) { 274 | 275 | if (toggleHitbox) { 276 | pDevice->BeginScene(); 277 | DWORD state; 278 | DWORD obj_addrress = p1_address; 279 | state = *(DWORD*)(obj_addrress + 0x6fc); 280 | for (int i = 0; i < 4; i++) { 281 | if (state != 0) { 282 | DWORD c; 283 | int drawBlue = 1; 284 | int armor = 0; 285 | c = *(DWORD*)(obj_addrress + 0x5e0); 286 | if (c > 0) { 287 | c = *(DWORD*)(obj_addrress + 0x5d4); 288 | drawBlue = c != 0; 289 | } 290 | else { 291 | c = *(DWORD*)(obj_addrress + 0x2a4); 292 | drawBlue = c != 1; 293 | } 294 | if (drawBlue == 1) { 295 | c = *(DWORD*)(obj_addrress + 0x624); 296 | if (c > 0) { 297 | c = *(DWORD*)(obj_addrress + 0x618); 298 | if (c != 0) { 299 | c = *(DWORD*)(obj_addrress + 0x704); 300 | if (c != 0) { 301 | c = *(DWORD*)(obj_addrress + 0x9ac); 302 | armor = !c; 303 | } 304 | } 305 | } 306 | } 307 | 308 | 309 | drawObj(pDevice, obj_addrress, drawBlue + armor, state, true); 310 | } 311 | obj_addrress = obj_addrress + 0xc44; 312 | state = *(DWORD*)(obj_addrress + 0x6fc); 313 | } 314 | if (*objCount > 0) { 315 | for (int i = 0; i < *objCount; i++) { 316 | obj_addrress = *(DWORD*)(objList_address + i * 4); 317 | if (obj_addrress != 0) { 318 | state = *(DWORD*)(obj_addrress + 0x6fc); 319 | if (state != 0) { 320 | DWORD c; 321 | int drawBlue = 1; 322 | c = *(DWORD*)(obj_addrress + 0x5ec); 323 | if (c > 0) { 324 | c = *(DWORD*)(obj_addrress + 0x5e0); 325 | drawBlue = c != 0; 326 | } 327 | else { 328 | c = *(DWORD*)(obj_addrress + 0x2a2); 329 | drawBlue = c != 1; 330 | } 331 | c = *(DWORD*)(obj_addrress + 0x78); 332 | if (c != 0) { 333 | drawBlue = 0; 334 | } 335 | c = *(DWORD*)(obj_addrress + 0x84); 336 | if ((c & 0x100) != 0) { 337 | drawBlue = 0; 338 | } 339 | drawObj(pDevice, obj_addrress, drawBlue, state, false); 340 | } 341 | } 342 | } 343 | } 344 | pDevice->EndScene(); 345 | } 346 | 347 | if (!GetAsyncKeyState(VK_F5) && 348 | !GetAsyncKeyState(VK_F6) && 349 | !GetAsyncKeyState(VK_F7)) { 350 | keyPressed = 0; 351 | } 352 | else { 353 | keyPressed++; 354 | } 355 | if (frameStep == true) { 356 | if (*pause == 0) { 357 | *pause = 1; 358 | WriteProcessMemory(phandle, (LPVOID)pause_address2, !*pause ? &je : &jmp, 6, 0); 359 | frameStep = 0; 360 | } 361 | else { 362 | *pause = 0; 363 | WriteProcessMemory(phandle, (LPVOID)pause_address2, !*pause ? &je : &jmp, 6, 0); 364 | } 365 | 366 | } 367 | else { 368 | 369 | if (GetAsyncKeyState(VK_F5) && keyPressed == 1) { 370 | toggleHitbox = !toggleHitbox; 371 | } 372 | else 373 | if (GetAsyncKeyState(VK_F6) && keyPressed == 1) { 374 | *pause = !*pause; 375 | WriteProcessMemory(phandle, (LPVOID)pause_address2, !*pause ? &je : &jmp, 6, 0); 376 | } 377 | else 378 | if (GetAsyncKeyState(VK_F7) && (keyPressed == 1 || (keyPressed > 40 && keyPressed % 10 == 0))) { 379 | frameStep = true; 380 | } 381 | } 382 | 383 | 384 | return oPresent(pDevice, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); 385 | } 386 | 387 | 388 | //Hook functions copied from AltimorTASDK 389 | bool get_module_bounds(const std::wstring name, uintptr_t* start, uintptr_t* end) 390 | { 391 | const auto module = GetModuleHandle(name.c_str()); 392 | if (module == nullptr) 393 | return false; 394 | 395 | MODULEINFO info; 396 | GetModuleInformation(GetCurrentProcess(), module, &info, sizeof(info)); 397 | *start = (uintptr_t)(info.lpBaseOfDll); 398 | *end = *start + info.SizeOfImage; 399 | return true; 400 | } 401 | 402 | // Scan for a byte pattern with a mask in the form of "xxx???xxx". 403 | uintptr_t sigscan(const std::wstring name, const char* sig, const char* mask) 404 | { 405 | uintptr_t start, end; 406 | if (!get_module_bounds(name, &start, &end)) 407 | throw std::runtime_error("Module not loaded"); 408 | 409 | const auto last_scan = end - strlen(mask) + 1; 410 | 411 | for (auto addr = start; addr < last_scan; addr++) { 412 | for (size_t i = 0;; i++) { 413 | if (mask[i] == '\0') 414 | return addr; 415 | if (mask[i] != '?' && sig[i] != *(char*)(addr + i)) 416 | break; 417 | } 418 | } 419 | 420 | return NULL; 421 | } 422 | DWORD WINAPI MainThread(LPVOID hModule) 423 | { 424 | phandle = GetCurrentProcess(); 425 | if (!phandle) { 426 | exit(0); 427 | } 428 | base_address = (DWORD)GetModuleHandle(L"MBTL.exe"); 429 | if (!base_address) { 430 | exit(0); 431 | } 432 | 433 | p1_address = *(DWORD*)(sigscan( 434 | L"MBTL.exe", 435 | "\x7D\x27\x69\xc8", 436 | "xxxx") + 0xA); 437 | 438 | pause = (int*)(*(DWORD*)(sigscan( 439 | L"MBTL.exe", 440 | "\x33\xF6\x3B\x0D", 441 | "xxxx") + 0x4)); 442 | pause_address2 = sigscan( 443 | L"MBTL.exe", 444 | "\x0F\x84\x5b\x07\x00\x00", 445 | "xxxxxx"); 446 | 447 | 448 | objCount = (int*)(*(DWORD*)(sigscan( 449 | L"MBTL.exe", 450 | "\x8D\x4D\xDC\xA3", 451 | "xxxx") + 0x4)); 452 | objList_address = (DWORD)(objCount)+0x4; 453 | 454 | DWORD temp = sigscan( 455 | L"MBTL.exe", 456 | "\xC7\x47\x10\x00\x00\x00\x00\xff\x35", 457 | "xxxxxxxxx"); 458 | resolutionY = (int*)(*(DWORD*)(temp + 0x9)); 459 | resolutionX = (int*)(*(DWORD*)(temp + 0x9 + 0x6)); 460 | 461 | cameraPosX = (int*)(*(DWORD*)(sigscan( 462 | L"MBTL.exe", 463 | "\xC1\xE7\x07\xBE", 464 | "xxxx") + 0xA)); 465 | 466 | cameraPosY = cameraPosX + 0x1; 467 | 468 | cameraZoom = (float*)(cameraPosX + 0x3); 469 | 470 | mINI::INIFile file("dll_loader.ini"); 471 | mINI::INIStructure ini; 472 | if (file.read(ini)) { 473 | if (ini.has("hitbox_viewer")) { 474 | if (ini["hitbox_viewer"].has("toggle_hitbox_on_launch")) { 475 | toggleHitbox = ini["hitbox_viewer"]["toggle_hitbox_on_launch"] == "1"; 476 | } 477 | if (ini["hitbox_viewer"].has("unlock_additional_color_slots")) { 478 | unlockColorSlots = ini["hitbox_viewer"]["unlock_additional_color_slots"] == "1"; 479 | } 480 | if (ini["hitbox_viewer"].has("color_slot_numbers")) { 481 | pal_num = std::stoi(ini["hitbox_viewer"]["color_slot_numbers"]);// maximum is 42 482 | } 483 | } 484 | } 485 | if (unlockColorSlots) { 486 | DWORD p = (DWORD)(sigscan( 487 | L"MBTL.exe", 488 | "\xb9\x20\x00\x00\x00\xc6\x00\x00", 489 | "xxxxxxxx") + 0x5); 490 | WriteProcessMemory(phandle, (LPVOID)(p), new BYTE[3]{ 0x90,0x90,0x90 }, 3, 0); 491 | 492 | BYTE pal[42]; 493 | for (int i = 0; i < 42; i++) { 494 | if (i < pal_num) { 495 | pal[i] = 1; 496 | } 497 | else { 498 | pal[i] = 0; 499 | } 500 | } 501 | DWORD address = *(DWORD*)(sigscan( 502 | L"MBTL.exe", 503 | "\x8a\x84\xc7", 504 | "xxx") + 0x3); 505 | 506 | for (int i = 0; i < 0x20; i++) { 507 | WriteProcessMemory(phandle, (LPVOID)(address+i*0x30), pal, 42, 0); 508 | } 509 | } 510 | 511 | TCHAR szDllPath[MAX_PATH] = { 0 }; 512 | GetSystemDirectory(szDllPath, MAX_PATH); 513 | std::wstring sPath = szDllPath; 514 | 515 | while (!vtable) 516 | { 517 | Sleep(1000); 518 | 519 | DWORD* ptr = (DWORD*)(sigscan(L"MBTL.exe", "\x89\x7d\xf8\x8b\x47", "xxxxx")); 520 | if (ptr != nullptr) { 521 | ptr = (DWORD*)*(ptr - 1); 522 | if (ptr != nullptr) { 523 | ptr = (DWORD*)*(ptr); 524 | if (ptr != nullptr) { 525 | ptr = (DWORD*)*(ptr + 1); 526 | if (ptr != nullptr) { 527 | ptr = (DWORD*)*(ptr + 1); 528 | } 529 | } 530 | } 531 | 532 | } 533 | if (ptr != nullptr) { 534 | vtable = *(void***)ptr; 535 | } 536 | /* 537 | 538 | vtable = *(void***)(sigscan( 539 | sPath + L"\\d3d9.dll", 540 | "\xC7\x06\x00\x00\x00\x00\x89\x86\x00\x00\x00\x00\x89\x86", 541 | "xx????xx????xx") + 0x2); 542 | */ 543 | } 544 | 545 | // Hook Present 546 | oPresent = (f_Present)vtable[17]; 547 | 548 | DetourRestoreAfterWith(); 549 | 550 | DetourTransactionBegin(); 551 | DetourUpdateThread(GetCurrentThread()); 552 | 553 | DetourAttach(&(LPVOID&)oPresent, Hooked_Present); 554 | DetourTransactionCommit(); 555 | 556 | 557 | return false; 558 | 559 | } 560 | 561 | 562 | 563 | BOOL APIENTRY DllMain(HMODULE hModule, 564 | DWORD ul_reason_for_call, 565 | LPVOID lpReserved 566 | ) 567 | { 568 | switch (ul_reason_for_call) 569 | { 570 | case DLL_PROCESS_ATTACH: 571 | CreateThread(0, 0, MainThread, hModule, 0, 0); 572 | break; 573 | case DLL_THREAD_ATTACH: 574 | case DLL_THREAD_DETACH: 575 | case DLL_PROCESS_DETACH: 576 | break; 577 | } 578 | return TRUE; 579 | } -------------------------------------------------------------------------------- /hitbox overlay/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // 從 Windows 標頭排除不常使用的項目 4 | // Windows 標頭檔 5 | #include 6 | -------------------------------------------------------------------------------- /hitbox overlay/hitbox overlay.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {0F14E1BC-A90B-4C0A-BD15-D6690E35909C} 24 | Win32Proj 25 | hitboxoverlay 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)detours;$(DXSDK_DIR)Include;$(SolutionDir)mINI 76 | $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;$(SolutionDir)detours;$(DXSDK_DIR)Lib\x86 77 | 78 | 79 | true 80 | $(DXSDK_DIR)Include;$(SolutionDir)detours;$(IncludePath) 81 | $(SolutionDir)detours;$(DXSDK_DIR)Lib\x64;$(LibraryPath) 82 | 83 | 84 | false 85 | $(DXSDK_DIR)Include;$(SolutionDir)detours;$(IncludePath);$(SolutionDir)mINI 86 | $(DXSDK_DIR)Lib\x86;$(SolutionDir)detours;$(WindowsSDK_LibraryPath_x86);$(VC_LibraryPath_x86) 87 | MBTL_hitbox_overlay 88 | 89 | 90 | false 91 | $(DXSDK_DIR)Include;$(SolutionDir)detours;$(IncludePath) 92 | $(SolutionDir)detours;$(DXSDK_DIR)Lib\x64;$(LibraryPath) 93 | 94 | 95 | 96 | Use 97 | Level3 98 | Disabled 99 | true 100 | WIN32;_DEBUG;HITBOXOVERLAY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 101 | true 102 | pch.h 103 | 104 | 105 | Windows 106 | true 107 | false 108 | 109 | 110 | 111 | 112 | Use 113 | Level3 114 | Disabled 115 | true 116 | _DEBUG;HITBOXOVERLAY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 117 | true 118 | pch.h 119 | 120 | 121 | Windows 122 | true 123 | false 124 | 125 | 126 | 127 | 128 | Use 129 | Level3 130 | MaxSpeed 131 | true 132 | true 133 | true 134 | WIN32;NDEBUG;HITBOXOVERLAY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 135 | true 136 | pch.h 137 | 138 | 139 | Windows 140 | true 141 | true 142 | true 143 | false 144 | 145 | 146 | 147 | 148 | Use 149 | Level3 150 | MaxSpeed 151 | true 152 | true 153 | true 154 | NDEBUG;HITBOXOVERLAY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 155 | true 156 | pch.h 157 | 158 | 159 | Windows 160 | true 161 | true 162 | true 163 | false 164 | detours.lib;d3d9.lib;d3dx9.lib;%(AdditionalDependencies) 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | Create 175 | Create 176 | Create 177 | Create 178 | 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /hitbox overlay/hitbox overlay.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 標頭檔 20 | 21 | 22 | 標頭檔 23 | 24 | 25 | 26 | 27 | 來源檔案 28 | 29 | 30 | 來源檔案 31 | 32 | 33 | -------------------------------------------------------------------------------- /hitbox overlay/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: 對應到先行編譯標頭的來源檔案 2 | 3 | #include "pch.h" 4 | 5 | // 使用先行編譯的標頭時,需要來源檔案才能使編譯成功。 6 | -------------------------------------------------------------------------------- /hitbox overlay/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: 此為先行編譯的標頭檔。 2 | // 以下所列檔案只會編譯一次,可改善之後組建的組建效能。 3 | // 這也會影響 IntelliSense 效能,包括程式碼完成以及許多程式碼瀏覽功能。 4 | // 但此處所列的檔案,如果其中任一在組建之間進行了更新,即會重新編譯所有檔案。 5 | // 請勿於此處新增會經常更新的檔案,如此將會對於效能優勢產生負面的影響。 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // 請於此新增您要先行編譯的標頭 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /mINI/mINI.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * Copyright (c) 2018 Danijel Durakovic 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is furnished to do 10 | * so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // 26 | // /mINI/ v0.9.11 27 | // An INI file reader and writer for the modern age. 28 | // 29 | /////////////////////////////////////////////////////////////////////////////// 30 | // 31 | // A tiny utility library for manipulating INI files with a straightforward 32 | // API and a minimal footprint. It conforms to the (somewhat) standard INI 33 | // format - sections and keys are case insensitive and all leading and 34 | // trailing whitespace is ignored. Comments are lines that begin with a 35 | // semicolon. Trailing comments are allowed on section lines. 36 | // 37 | // Files are read on demand, upon which data is kept in memory and the file 38 | // is closed. This utility supports lazy writing, which only writes changes 39 | // and updates to a file and preserves custom formatting and comments. A lazy 40 | // write invoked by a write() call will read the output file, find what 41 | // changes have been made and update the file accordingly. If you only need to 42 | // generate files, use generate() instead. Section and key order is preserved 43 | // on read, write and insert. 44 | // 45 | /////////////////////////////////////////////////////////////////////////////// 46 | // 47 | // /* BASIC USAGE EXAMPLE: */ 48 | // 49 | // /* read from file */ 50 | // mINI::INIFile file("myfile.ini"); 51 | // mINI::INIStructure ini; 52 | // file.read(ini); 53 | // 54 | // /* read value; gets a reference to actual value in the structure. 55 | // if key or section don't exist, a new empty value will be created */ 56 | // std::string& value = ini["section"]["key"]; 57 | // 58 | // /* read value safely; gets a copy of value in the structure. 59 | // does not alter the structure */ 60 | // std::string value = ini.get("section").get("key"); 61 | // 62 | // /* set or update values */ 63 | // ini["section"]["key"] = "value"; 64 | // 65 | // /* set multiple values */ 66 | // ini["section2"].set({ 67 | // {"key1", "value1"}, 68 | // {"key2", "value2"} 69 | // }); 70 | // 71 | // /* write updates back to file, preserving comments and formatting */ 72 | // file.write(ini); 73 | // 74 | // /* or generate a file (overwrites the original) */ 75 | // file.generate(ini); 76 | // 77 | /////////////////////////////////////////////////////////////////////////////// 78 | // 79 | // Long live the INI file!!! 80 | // 81 | /////////////////////////////////////////////////////////////////////////////// 82 | 83 | #ifndef MINI_INI_H_ 84 | #define MINI_INI_H_ 85 | 86 | #include 87 | #include 88 | #include 89 | #include 90 | #include 91 | #include 92 | #include 93 | #include 94 | #include 95 | #include 96 | 97 | namespace mINI 98 | { 99 | namespace INIStringUtil 100 | { 101 | const char* const whitespaceDelimiters = " \t\n\r\f\v"; 102 | inline void trim(std::string& str) 103 | { 104 | str.erase(str.find_last_not_of(whitespaceDelimiters) + 1); 105 | str.erase(0, str.find_first_not_of(whitespaceDelimiters)); 106 | } 107 | #ifndef MINI_CASE_SENSITIVE 108 | inline void toLower(std::string& str) 109 | { 110 | std::transform(str.begin(), str.end(), str.begin(), [](const char c) { 111 | return static_cast(std::tolower(c)); 112 | }); 113 | } 114 | #endif 115 | inline void replace(std::string& str, std::string const& a, std::string const& b) 116 | { 117 | if (!a.empty()) 118 | { 119 | std::size_t pos = 0; 120 | while ((pos = str.find(a, pos)) != std::string::npos) 121 | { 122 | str.replace(pos, a.size(), b); 123 | pos += b.size(); 124 | } 125 | } 126 | } 127 | #ifdef _WIN32 128 | const char* const endl = "\r\n"; 129 | #else 130 | const char* const endl = "\n"; 131 | #endif 132 | } 133 | 134 | template 135 | class INIMap 136 | { 137 | private: 138 | using T_DataIndexMap = std::unordered_map; 139 | using T_DataItem = std::pair; 140 | using T_DataContainer = std::vector; 141 | using T_MultiArgs = typename std::vector>; 142 | 143 | T_DataIndexMap dataIndexMap; 144 | T_DataContainer data; 145 | 146 | inline std::size_t setEmpty(std::string& key) 147 | { 148 | std::size_t index = data.size(); 149 | dataIndexMap[key] = index; 150 | data.emplace_back(key, T()); 151 | return index; 152 | } 153 | 154 | public: 155 | using const_iterator = typename T_DataContainer::const_iterator; 156 | 157 | INIMap() { } 158 | 159 | INIMap(INIMap const& other) 160 | { 161 | std::size_t data_size = other.data.size(); 162 | for (std::size_t i = 0; i < data_size; ++i) 163 | { 164 | auto const& key = other.data[i].first; 165 | auto const& obj = other.data[i].second; 166 | data.emplace_back(key, obj); 167 | } 168 | dataIndexMap = T_DataIndexMap(other.dataIndexMap); 169 | } 170 | 171 | T& operator[](std::string key) 172 | { 173 | INIStringUtil::trim(key); 174 | #ifndef MINI_CASE_SENSITIVE 175 | INIStringUtil::toLower(key); 176 | #endif 177 | auto it = dataIndexMap.find(key); 178 | bool hasIt = (it != dataIndexMap.end()); 179 | std::size_t index = (hasIt) ? it->second : setEmpty(key); 180 | return data[index].second; 181 | } 182 | T get(std::string key) const 183 | { 184 | INIStringUtil::trim(key); 185 | #ifndef MINI_CASE_SENSITIVE 186 | INIStringUtil::toLower(key); 187 | #endif 188 | auto it = dataIndexMap.find(key); 189 | if (it == dataIndexMap.end()) 190 | { 191 | return T(); 192 | } 193 | return T(data[it->second].second); 194 | } 195 | bool has(std::string key) const 196 | { 197 | INIStringUtil::trim(key); 198 | #ifndef MINI_CASE_SENSITIVE 199 | INIStringUtil::toLower(key); 200 | #endif 201 | return (dataIndexMap.count(key) == 1); 202 | } 203 | void set(std::string key, T obj) 204 | { 205 | INIStringUtil::trim(key); 206 | #ifndef MINI_CASE_SENSITIVE 207 | INIStringUtil::toLower(key); 208 | #endif 209 | auto it = dataIndexMap.find(key); 210 | if (it != dataIndexMap.end()) 211 | { 212 | data[it->second].second = obj; 213 | } 214 | else 215 | { 216 | dataIndexMap[key] = data.size(); 217 | data.emplace_back(key, obj); 218 | } 219 | } 220 | void set(T_MultiArgs const& multiArgs) 221 | { 222 | for (auto const& it : multiArgs) 223 | { 224 | auto const& key = it.first; 225 | auto const& obj = it.second; 226 | set(key, obj); 227 | } 228 | } 229 | bool remove(std::string key) 230 | { 231 | INIStringUtil::trim(key); 232 | #ifndef MINI_CASE_SENSITIVE 233 | INIStringUtil::toLower(key); 234 | #endif 235 | auto it = dataIndexMap.find(key); 236 | if (it != dataIndexMap.end()) 237 | { 238 | std::size_t index = it->second; 239 | data.erase(data.begin() + index); 240 | dataIndexMap.erase(it); 241 | for (auto& it2 : dataIndexMap) 242 | { 243 | auto& vi = it2.second; 244 | if (vi > index) 245 | { 246 | vi--; 247 | } 248 | } 249 | return true; 250 | } 251 | return false; 252 | } 253 | void clear() 254 | { 255 | data.clear(); 256 | dataIndexMap.clear(); 257 | } 258 | std::size_t size() const 259 | { 260 | return data.size(); 261 | } 262 | const_iterator begin() const { return data.begin(); } 263 | const_iterator end() const { return data.end(); } 264 | }; 265 | 266 | using INIStructure = INIMap>; 267 | 268 | namespace INIParser 269 | { 270 | using T_ParseValues = std::pair; 271 | 272 | enum class PDataType : char 273 | { 274 | PDATA_NONE, 275 | PDATA_COMMENT, 276 | PDATA_SECTION, 277 | PDATA_KEYVALUE, 278 | PDATA_UNKNOWN 279 | }; 280 | 281 | inline PDataType parseLine(std::string line, T_ParseValues& parseData) 282 | { 283 | parseData.first.clear(); 284 | parseData.second.clear(); 285 | INIStringUtil::trim(line); 286 | if (line.empty()) 287 | { 288 | return PDataType::PDATA_NONE; 289 | } 290 | char firstCharacter = line[0]; 291 | if (firstCharacter == ';') 292 | { 293 | return PDataType::PDATA_COMMENT; 294 | } 295 | if (firstCharacter == '[') 296 | { 297 | auto commentAt = line.find_first_of(';'); 298 | if (commentAt != std::string::npos) 299 | { 300 | line = line.substr(0, commentAt); 301 | } 302 | auto closingBracketAt = line.find_last_of(']'); 303 | if (closingBracketAt != std::string::npos) 304 | { 305 | auto section = line.substr(1, closingBracketAt - 1); 306 | INIStringUtil::trim(section); 307 | parseData.first = section; 308 | return PDataType::PDATA_SECTION; 309 | } 310 | } 311 | auto lineNorm = line; 312 | INIStringUtil::replace(lineNorm, "\\=", " "); 313 | auto equalsAt = lineNorm.find_first_of('='); 314 | if (equalsAt != std::string::npos) 315 | { 316 | auto key = line.substr(0, equalsAt); 317 | INIStringUtil::trim(key); 318 | INIStringUtil::replace(key, "\\=", "="); 319 | auto value = line.substr(equalsAt + 1); 320 | INIStringUtil::trim(value); 321 | parseData.first = key; 322 | parseData.second = value; 323 | return PDataType::PDATA_KEYVALUE; 324 | } 325 | return PDataType::PDATA_UNKNOWN; 326 | } 327 | } 328 | 329 | class INIReader 330 | { 331 | public: 332 | using T_LineData = std::vector; 333 | using T_LineDataPtr = std::shared_ptr; 334 | 335 | private: 336 | std::ifstream fileReadStream; 337 | T_LineDataPtr lineData; 338 | 339 | T_LineData readFile() 340 | { 341 | std::string fileContents; 342 | fileReadStream.seekg(0, std::ios::end); 343 | fileContents.resize(static_cast(fileReadStream.tellg())); 344 | fileReadStream.seekg(0, std::ios::beg); 345 | std::size_t fileSize = fileContents.size(); 346 | fileReadStream.read(&fileContents[0], fileSize); 347 | fileReadStream.close(); 348 | T_LineData output; 349 | if (fileSize == 0) 350 | { 351 | return output; 352 | } 353 | std::string buffer; 354 | buffer.reserve(50); 355 | for (std::size_t i = 0; i < fileSize; ++i) 356 | { 357 | char& c = fileContents[i]; 358 | if (c == '\n') 359 | { 360 | output.emplace_back(buffer); 361 | buffer.clear(); 362 | continue; 363 | } 364 | if (c != '\0' && c != '\r') 365 | { 366 | buffer += c; 367 | } 368 | } 369 | output.emplace_back(buffer); 370 | return output; 371 | } 372 | 373 | public: 374 | INIReader(std::string const& filename, bool keepLineData = false) 375 | { 376 | fileReadStream.open(filename, std::ios::in | std::ios::binary); 377 | if (keepLineData) 378 | { 379 | lineData = std::make_shared(); 380 | } 381 | } 382 | ~INIReader() { } 383 | 384 | bool operator>>(INIStructure& data) 385 | { 386 | if (!fileReadStream.is_open()) 387 | { 388 | return false; 389 | } 390 | T_LineData fileLines = readFile(); 391 | std::string section; 392 | bool inSection = false; 393 | INIParser::T_ParseValues parseData; 394 | for (auto const& line : fileLines) 395 | { 396 | auto parseResult = INIParser::parseLine(line, parseData); 397 | if (parseResult == INIParser::PDataType::PDATA_SECTION) 398 | { 399 | inSection = true; 400 | data[section = parseData.first]; 401 | } 402 | else if (inSection && parseResult == INIParser::PDataType::PDATA_KEYVALUE) 403 | { 404 | auto const& key = parseData.first; 405 | auto const& value = parseData.second; 406 | data[section][key] = value; 407 | } 408 | if (lineData && parseResult != INIParser::PDataType::PDATA_UNKNOWN) 409 | { 410 | if (parseResult == INIParser::PDataType::PDATA_KEYVALUE && !inSection) 411 | { 412 | continue; 413 | } 414 | lineData->emplace_back(line); 415 | } 416 | } 417 | return true; 418 | } 419 | T_LineDataPtr getLines() 420 | { 421 | return lineData; 422 | } 423 | }; 424 | 425 | class INIGenerator 426 | { 427 | private: 428 | std::ofstream fileWriteStream; 429 | 430 | public: 431 | bool prettyPrint = false; 432 | 433 | INIGenerator(std::string const& filename) 434 | { 435 | fileWriteStream.open(filename, std::ios::out | std::ios::binary); 436 | } 437 | ~INIGenerator() { } 438 | 439 | bool operator<<(INIStructure const& data) 440 | { 441 | if (!fileWriteStream.is_open()) 442 | { 443 | return false; 444 | } 445 | if (!data.size()) 446 | { 447 | return true; 448 | } 449 | auto it = data.begin(); 450 | for (;;) 451 | { 452 | auto const& section = it->first; 453 | auto const& collection = it->second; 454 | fileWriteStream 455 | << "[" 456 | << section 457 | << "]"; 458 | if (collection.size()) 459 | { 460 | fileWriteStream << INIStringUtil::endl; 461 | auto it2 = collection.begin(); 462 | for (;;) 463 | { 464 | auto key = it2->first; 465 | INIStringUtil::replace(key, "=", "\\="); 466 | auto value = it2->second; 467 | INIStringUtil::trim(value); 468 | fileWriteStream 469 | << key 470 | << ((prettyPrint) ? " = " : "=") 471 | << value; 472 | if (++it2 == collection.end()) 473 | { 474 | break; 475 | } 476 | fileWriteStream << INIStringUtil::endl; 477 | } 478 | } 479 | if (++it == data.end()) 480 | { 481 | break; 482 | } 483 | fileWriteStream << INIStringUtil::endl; 484 | if (prettyPrint) 485 | { 486 | fileWriteStream << INIStringUtil::endl; 487 | } 488 | } 489 | return true; 490 | } 491 | }; 492 | 493 | class INIWriter 494 | { 495 | private: 496 | using T_LineData = std::vector; 497 | using T_LineDataPtr = std::shared_ptr; 498 | 499 | std::string filename; 500 | 501 | T_LineData getLazyOutput(T_LineDataPtr const& lineData, INIStructure& data, INIStructure& original) 502 | { 503 | T_LineData output; 504 | INIParser::T_ParseValues parseData; 505 | std::string sectionCurrent; 506 | bool parsingSection = false; 507 | bool continueToNextSection = false; 508 | bool discardNextEmpty = false; 509 | bool writeNewKeys = false; 510 | std::size_t lastKeyLine = 0; 511 | for (auto line = lineData->begin(); line != lineData->end(); ++line) 512 | { 513 | if (!writeNewKeys) 514 | { 515 | auto parseResult = INIParser::parseLine(*line, parseData); 516 | if (parseResult == INIParser::PDataType::PDATA_SECTION) 517 | { 518 | if (parsingSection) 519 | { 520 | writeNewKeys = true; 521 | parsingSection = false; 522 | --line; 523 | continue; 524 | } 525 | sectionCurrent = parseData.first; 526 | if (data.has(sectionCurrent)) 527 | { 528 | parsingSection = true; 529 | continueToNextSection = false; 530 | discardNextEmpty = false; 531 | output.emplace_back(*line); 532 | lastKeyLine = output.size(); 533 | } 534 | else 535 | { 536 | continueToNextSection = true; 537 | discardNextEmpty = true; 538 | continue; 539 | } 540 | } 541 | else if (parseResult == INIParser::PDataType::PDATA_KEYVALUE) 542 | { 543 | if (continueToNextSection) 544 | { 545 | continue; 546 | } 547 | if (data.has(sectionCurrent)) 548 | { 549 | auto& collection = data[sectionCurrent]; 550 | auto const& key = parseData.first; 551 | auto const& value = parseData.second; 552 | if (collection.has(key)) 553 | { 554 | auto outputValue = collection[key]; 555 | if (value == outputValue) 556 | { 557 | output.emplace_back(*line); 558 | } 559 | else 560 | { 561 | INIStringUtil::trim(outputValue); 562 | auto lineNorm = *line; 563 | INIStringUtil::replace(lineNorm, "\\=", " "); 564 | auto equalsAt = lineNorm.find_first_of('='); 565 | auto valueAt = lineNorm.find_first_not_of( 566 | INIStringUtil::whitespaceDelimiters, 567 | equalsAt + 1 568 | ); 569 | std::string outputLine = line->substr(0, valueAt); 570 | if (prettyPrint && equalsAt + 1 == valueAt) 571 | { 572 | outputLine += " "; 573 | } 574 | outputLine += outputValue; 575 | output.emplace_back(outputLine); 576 | } 577 | lastKeyLine = output.size(); 578 | } 579 | } 580 | } 581 | else 582 | { 583 | if (discardNextEmpty && line->empty()) 584 | { 585 | discardNextEmpty = false; 586 | } 587 | else if (parseResult != INIParser::PDataType::PDATA_UNKNOWN) 588 | { 589 | output.emplace_back(*line); 590 | } 591 | } 592 | } 593 | if (writeNewKeys || std::next(line) == lineData->end()) 594 | { 595 | T_LineData linesToAdd; 596 | if (data.has(sectionCurrent) && original.has(sectionCurrent)) 597 | { 598 | auto const& collection = data[sectionCurrent]; 599 | auto const& collectionOriginal = original[sectionCurrent]; 600 | for (auto const& it : collection) 601 | { 602 | auto key = it.first; 603 | if (collectionOriginal.has(key)) 604 | { 605 | continue; 606 | } 607 | auto value = it.second; 608 | INIStringUtil::replace(key, "=", "\\="); 609 | INIStringUtil::trim(value); 610 | linesToAdd.emplace_back( 611 | key + ((prettyPrint) ? " = " : "=") + value 612 | ); 613 | } 614 | } 615 | if (!linesToAdd.empty()) 616 | { 617 | output.insert( 618 | output.begin() + lastKeyLine, 619 | linesToAdd.begin(), 620 | linesToAdd.end() 621 | ); 622 | } 623 | if (writeNewKeys) 624 | { 625 | writeNewKeys = false; 626 | --line; 627 | } 628 | } 629 | } 630 | for (auto const& it : data) 631 | { 632 | auto const& section = it.first; 633 | if (original.has(section)) 634 | { 635 | continue; 636 | } 637 | if (prettyPrint && output.size() > 0 && !output.back().empty()) 638 | { 639 | output.emplace_back(); 640 | } 641 | output.emplace_back("[" + section + "]"); 642 | auto const& collection = it.second; 643 | for (auto const& it2 : collection) 644 | { 645 | auto key = it2.first; 646 | auto value = it2.second; 647 | INIStringUtil::replace(key, "=", "\\="); 648 | INIStringUtil::trim(value); 649 | output.emplace_back( 650 | key + ((prettyPrint) ? " = " : "=") + value 651 | ); 652 | } 653 | } 654 | return output; 655 | } 656 | 657 | public: 658 | bool prettyPrint = false; 659 | 660 | INIWriter(std::string const& filename) 661 | : filename(filename) 662 | { 663 | } 664 | ~INIWriter() { } 665 | 666 | bool operator<<(INIStructure& data) 667 | { 668 | struct stat buf; 669 | bool fileExists = (stat(filename.c_str(), &buf) == 0); 670 | if (!fileExists) 671 | { 672 | INIGenerator generator(filename); 673 | generator.prettyPrint = prettyPrint; 674 | return generator << data; 675 | } 676 | INIStructure originalData; 677 | T_LineDataPtr lineData; 678 | bool readSuccess = false; 679 | { 680 | INIReader reader(filename, true); 681 | if ((readSuccess = reader >> originalData)) 682 | { 683 | lineData = reader.getLines(); 684 | } 685 | } 686 | if (!readSuccess) 687 | { 688 | return false; 689 | } 690 | T_LineData output = getLazyOutput(lineData, data, originalData); 691 | std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary); 692 | if (fileWriteStream.is_open()) 693 | { 694 | if (output.size()) 695 | { 696 | auto line = output.begin(); 697 | for (;;) 698 | { 699 | fileWriteStream << *line; 700 | if (++line == output.end()) 701 | { 702 | break; 703 | } 704 | fileWriteStream << INIStringUtil::endl; 705 | } 706 | } 707 | return true; 708 | } 709 | return false; 710 | } 711 | }; 712 | 713 | class INIFile 714 | { 715 | private: 716 | std::string filename; 717 | 718 | public: 719 | INIFile(std::string const& filename) 720 | : filename(filename) 721 | { } 722 | 723 | ~INIFile() { } 724 | 725 | bool read(INIStructure& data) const 726 | { 727 | if (data.size()) 728 | { 729 | data.clear(); 730 | } 731 | if (filename.empty()) 732 | { 733 | return false; 734 | } 735 | INIReader reader(filename); 736 | return reader >> data; 737 | } 738 | bool generate(INIStructure const& data, bool pretty = false) const 739 | { 740 | if (filename.empty()) 741 | { 742 | return false; 743 | } 744 | INIGenerator generator(filename); 745 | generator.prettyPrint = pretty; 746 | return generator << data; 747 | } 748 | bool write(INIStructure& data, bool pretty = false) const 749 | { 750 | if (filename.empty()) 751 | { 752 | return false; 753 | } 754 | INIWriter writer(filename); 755 | writer.prettyPrint = pretty; 756 | return writer << data; 757 | } 758 | }; 759 | } 760 | 761 | #endif // MINI_INI_H_ --------------------------------------------------------------------------------