├── .gitattributes ├── .gitignore ├── DivaHook ├── DivaHook.vcxproj ├── DivaHook.vcxproj.filters ├── rom │ ├── components.ini │ ├── keyconfig.ini │ └── playerdata.ini └── src │ ├── Components │ ├── CameraController.cpp │ ├── CameraController.h │ ├── ComponentsManager.cpp │ ├── ComponentsManager.h │ ├── CustomPlayerData.h │ ├── DebugComponent.cpp │ ├── DebugComponent.h │ ├── EmulatorComponent.cpp │ ├── EmulatorComponent.h │ ├── FastLoader.cpp │ ├── FastLoader.h │ ├── FrameRateManager.cpp │ ├── FrameRateManager.h │ ├── GameState.h │ ├── Input │ │ ├── InputBufferType.h │ │ ├── InputEmulator.cpp │ │ ├── InputEmulator.h │ │ ├── InputState.cpp │ │ ├── InputState.h │ │ ├── JvsButtons.h │ │ ├── TouchPanelEmulator.cpp │ │ ├── TouchPanelEmulator.h │ │ ├── TouchPanelState.h │ │ ├── TouchSliderEmulator.cpp │ │ ├── TouchSliderEmulator.h │ │ ├── TouchSliderState.cpp │ │ └── TouchSliderState.h │ ├── PlayerData.h │ ├── PlayerDataManager.cpp │ ├── PlayerDataManager.h │ ├── StageManager.cpp │ ├── StageManager.h │ ├── SysTimer.cpp │ └── SysTimer.h │ ├── Constants.h │ ├── FileSystem │ ├── ConfigFile.cpp │ ├── ConfigFile.h │ ├── TextFile.cpp │ └── TextFile.h │ ├── Input │ ├── Bindings │ │ ├── Binding.cpp │ │ ├── Binding.h │ │ ├── Ds4Binding.cpp │ │ ├── Ds4Binding.h │ │ ├── IInputBinding.h │ │ ├── KeyboardBinding.cpp │ │ ├── KeyboardBinding.h │ │ ├── MouseBinding.cpp │ │ └── MouseBinding.h │ ├── DirectInput │ │ ├── Controller.cpp │ │ ├── Controller.h │ │ ├── DirectInput.cpp │ │ ├── DirectInput.h │ │ ├── DirectInputDevice.cpp │ │ ├── DirectInputDevice.h │ │ ├── DirectInputMouse.cpp │ │ ├── DirectInputMouse.h │ │ └── Ds4 │ │ │ ├── Ds4Button.h │ │ │ ├── Ds4State.cpp │ │ │ ├── Ds4State.h │ │ │ ├── DualShock4.cpp │ │ │ └── DualShock4.h │ ├── IInputDevice.h │ ├── KeyConfig │ │ ├── Config.cpp │ │ ├── Config.h │ │ ├── KeyString.cpp │ │ ├── KeyString.h │ │ ├── KeyStringHash.cpp │ │ └── KeyStringHash.h │ ├── Keyboard │ │ ├── Keyboard.cpp │ │ ├── Keyboard.h │ │ ├── KeyboardState.cpp │ │ └── KeyboardState.h │ └── Mouse │ │ ├── Mouse.cpp │ │ ├── Mouse.h │ │ └── MouseState.h │ ├── MainModule.cpp │ ├── MainModule.h │ ├── Utilities │ ├── EnumBitwiseOperations.h │ ├── Math.cpp │ ├── Math.h │ ├── Operations.cpp │ ├── Operations.h │ ├── Stopwatch.cpp │ ├── Stopwatch.h │ ├── Vec2.cpp │ ├── Vec2.h │ ├── Vec3.cpp │ └── Vec3.h │ ├── dllmain.cpp │ └── targetver.h ├── LICENSE ├── Prepatch ├── Prepatch.vcxproj ├── Prepatch.vcxproj.filters ├── rom │ └── patch.txt └── src │ ├── Patch │ ├── Patch.cpp │ ├── Patch.h │ ├── PatchData.cpp │ ├── PatchData.h │ ├── Patcher.cpp │ └── Patcher.h │ ├── StringOperations │ ├── Operations.cpp │ └── Operations.h │ └── main.cpp ├── README.md ├── TotallyLegitArcadeController.sln └── TotallyLegitArcadeController ├── TotallyLegitArcadeController.filters ├── TotallyLegitArcadeController.vcxproj └── src ├── Injection ├── DllInjector.cpp └── DllInjector.h └── main.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | # Source files 2 | *.c text diff=cpp 3 | *.cc text diff=cpp 4 | *.cxx text diff=cpp 5 | *.cpp text diff=cpp 6 | *.c++ text diff=cpp 7 | *.hpp text diff=cpp 8 | *.h text diff=cpp 9 | *.h++ text diff=cpp 10 | *.hh text diff=cpp 11 | 12 | # Compiled Object files 13 | *.slo binary 14 | *.lo binary 15 | *.o binary 16 | *.obj binary 17 | 18 | # Precompiled Headers 19 | *.gch binary 20 | *.pch binary 21 | -------------------------------------------------------------------------------- /.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 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | bin/ 24 | bin-int/ 25 | [Bb]in/ 26 | [Oo]bj/ 27 | [Ll]og/ 28 | 29 | # Visual Studio 2015/2017 cache/options directory 30 | .vs/ 31 | # Uncomment if you have tasks that create the project's static files in wwwroot 32 | #wwwroot/ 33 | 34 | # Visual Studio 2017 auto generated files 35 | Generated\ Files/ 36 | 37 | # MSTest test Results 38 | [Tt]est[Rr]esult*/ 39 | [Bb]uild[Ll]og.* 40 | 41 | # NUNIT 42 | *.VisualState.xml 43 | TestResult.xml 44 | 45 | # Build Results of an ATL Project 46 | [Dd]ebugPS/ 47 | [Rr]eleasePS/ 48 | dlldata.c 49 | 50 | # Benchmark Results 51 | BenchmarkDotNet.Artifacts/ 52 | 53 | # .NET Core 54 | project.lock.json 55 | project.fragment.lock.json 56 | artifacts/ 57 | **/Properties/launchSettings.json 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_i.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *.log 83 | *.vspscc 84 | *.vssscc 85 | .builds 86 | *.pidb 87 | *.svclog 88 | *.scc 89 | 90 | # Chutzpah Test files 91 | _Chutzpah* 92 | 93 | # Visual C++ cache files 94 | ipch/ 95 | *.aps 96 | *.ncb 97 | *.opendb 98 | *.opensdf 99 | *.sdf 100 | *.cachefile 101 | *.VC.db 102 | *.VC.VC.opendb 103 | 104 | # Visual Studio profiler 105 | *.psess 106 | *.vsp 107 | *.vspx 108 | *.sap 109 | 110 | # Visual Studio Trace Files 111 | *.e2e 112 | 113 | # TFS 2012 Local Workspace 114 | $tf/ 115 | 116 | # Guidance Automation Toolkit 117 | *.gpState 118 | 119 | # ReSharper is a .NET coding add-in 120 | _ReSharper*/ 121 | *.[Rr]e[Ss]harper 122 | *.DotSettings.user 123 | 124 | # JustCode is a .NET coding add-in 125 | .JustCode 126 | 127 | # TeamCity is a build add-in 128 | _TeamCity* 129 | 130 | # DotCover is a Code Coverage Tool 131 | *.dotCover 132 | 133 | # AxoCover is a Code Coverage Tool 134 | .axoCover/* 135 | !.axoCover/settings.json 136 | 137 | # Visual Studio code coverage results 138 | *.coverage 139 | *.coveragexml 140 | 141 | # NCrunch 142 | _NCrunch_* 143 | .*crunch*.local.xml 144 | nCrunchTemp_* 145 | 146 | # MightyMoose 147 | *.mm.* 148 | AutoTest.Net/ 149 | 150 | # Web workbench (sass) 151 | .sass-cache/ 152 | 153 | # Installshield output folder 154 | [Ee]xpress/ 155 | 156 | # DocProject is a documentation generator add-in 157 | DocProject/buildhelp/ 158 | DocProject/Help/*.HxT 159 | DocProject/Help/*.HxC 160 | DocProject/Help/*.hhc 161 | DocProject/Help/*.hhk 162 | DocProject/Help/*.hhp 163 | DocProject/Help/Html2 164 | DocProject/Help/html 165 | 166 | # Click-Once directory 167 | publish/ 168 | 169 | # Publish Web Output 170 | *.[Pp]ublish.xml 171 | *.azurePubxml 172 | # Note: Comment the next line if you want to checkin your web deploy settings, 173 | # but database connection strings (with potential passwords) will be unencrypted 174 | *.pubxml 175 | *.publishproj 176 | 177 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 178 | # checkin your Azure Web App publish settings, but sensitive information contained 179 | # in these scripts will be unencrypted 180 | PublishScripts/ 181 | 182 | # NuGet Packages 183 | *.nupkg 184 | # The packages folder can be ignored because of Package Restore 185 | **/[Pp]ackages/* 186 | # except build/, which is used as an MSBuild target. 187 | !**/[Pp]ackages/build/ 188 | # Uncomment if necessary however generally it will be regenerated when needed 189 | #!**/[Pp]ackages/repositories.config 190 | # NuGet v3's project.json files produces more ignorable files 191 | *.nuget.props 192 | *.nuget.targets 193 | 194 | # Microsoft Azure Build Output 195 | csx/ 196 | *.build.csdef 197 | 198 | # Microsoft Azure Emulator 199 | ecf/ 200 | rcf/ 201 | 202 | # Windows Store app package directories and files 203 | AppPackages/ 204 | BundleArtifacts/ 205 | Package.StoreAssociation.xml 206 | _pkginfo.txt 207 | *.appx 208 | 209 | # Visual Studio cache files 210 | # files ending in .cache can be ignored 211 | *.[Cc]ache 212 | # but keep track of directories ending in .cache 213 | !*.[Cc]ache/ 214 | 215 | # Others 216 | ClientBin/ 217 | ~$* 218 | *~ 219 | *.dbmdl 220 | *.dbproj.schemaview 221 | *.jfm 222 | *.pfx 223 | *.publishsettings 224 | orleans.codegen.cs 225 | 226 | # Including strong name files can present a security risk 227 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 228 | #*.snk 229 | 230 | # Since there are multiple workflows, uncomment next line to ignore bower_components 231 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 232 | #bower_components/ 233 | 234 | # RIA/Silverlight projects 235 | Generated_Code/ 236 | 237 | # Backup & report files from converting an old project file 238 | # to a newer Visual Studio version. Backup files are not needed, 239 | # because we have git ;-) 240 | _UpgradeReport_Files/ 241 | Backup*/ 242 | UpgradeLog*.XML 243 | UpgradeLog*.htm 244 | ServiceFabricBackup/ 245 | *.rptproj.bak 246 | 247 | # SQL Server files 248 | *.mdf 249 | *.ldf 250 | *.ndf 251 | 252 | # Business Intelligence projects 253 | *.rdl.data 254 | *.bim.layout 255 | *.bim_*.settings 256 | *.rptproj.rsuser 257 | 258 | # Microsoft Fakes 259 | FakesAssemblies/ 260 | 261 | # GhostDoc plugin setting file 262 | *.GhostDoc.xml 263 | 264 | # Node.js Tools for Visual Studio 265 | .ntvs_analysis.dat 266 | node_modules/ 267 | 268 | # Visual Studio 6 build log 269 | *.plg 270 | 271 | # Visual Studio 6 workspace options file 272 | *.opt 273 | 274 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 275 | *.vbw 276 | 277 | # Visual Studio LightSwitch build output 278 | **/*.HTMLClient/GeneratedArtifacts 279 | **/*.DesktopClient/GeneratedArtifacts 280 | **/*.DesktopClient/ModelManifest.xml 281 | **/*.Server/GeneratedArtifacts 282 | **/*.Server/ModelManifest.xml 283 | _Pvt_Extensions 284 | 285 | # Paket dependency manager 286 | .paket/paket.exe 287 | paket-files/ 288 | 289 | # FAKE - F# Make 290 | .fake/ 291 | 292 | # JetBrains Rider 293 | .idea/ 294 | *.sln.iml 295 | 296 | # CodeRush 297 | .cr/ 298 | 299 | # Python Tools for Visual Studio (PTVS) 300 | __pycache__/ 301 | *.pyc 302 | 303 | # Cake - Uncomment if you are using it 304 | # tools/** 305 | # !tools/packages.config 306 | 307 | # Tabs Studio 308 | *.tss 309 | 310 | # Telerik's JustMock configuration file 311 | *.jmconfig 312 | 313 | # BizTalk build output 314 | *.btp.cs 315 | *.btm.cs 316 | *.odx.cs 317 | *.xsd.cs 318 | 319 | # OpenCover UI analysis results 320 | OpenCover/ 321 | 322 | # Azure Stream Analytics local run output 323 | ASALocalRun/ 324 | 325 | # MSBuild Binary and Structured Log 326 | *.binlog 327 | 328 | # NVidia Nsight GPU debugger configuration file 329 | *.nvuser 330 | 331 | # MFractors (Xamarin productivity tool) working folder 332 | .mfractor/ 333 | -------------------------------------------------------------------------------- /DivaHook/DivaHook.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15.0 15 | {69BCF67B-34D9-4424-A2A8-3A056E9D38A6} 16 | Win32Proj 17 | DivaHook 18 | 10.0.17763.0 19 | 20 | 21 | 22 | DynamicLibrary 23 | true 24 | v141 25 | Unicode 26 | 27 | 28 | DynamicLibrary 29 | false 30 | v141 31 | true 32 | Unicode 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | true 49 | divahook 50 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 51 | $(SolutionDir)$(ProjectName)\bin-int\$(Platform)-$(Configuration)\ 52 | 53 | 54 | false 55 | divahook 56 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 57 | $(SolutionDir)$(ProjectName)\bin-int\$(Platform)-$(Configuration)\ 58 | 59 | 60 | 61 | NotUsing 62 | Level3 63 | Disabled 64 | true 65 | WIN32;_DEBUG;DIVAHOOK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 66 | true 67 | 68 | 69 | stdcpp17 70 | 71 | 72 | Windows 73 | true 74 | dinput8.lib;dxguid.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 75 | 76 | 77 | 78 | 79 | NotUsing 80 | Level3 81 | MaxSpeed 82 | true 83 | true 84 | true 85 | WIN32;NDEBUG;DIVAHOOK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 86 | true 87 | 88 | 89 | stdcpp17 90 | 91 | 92 | Windows 93 | true 94 | true 95 | true 96 | dinput8.lib;dxguid.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /DivaHook/DivaHook.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 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | Header Files 59 | 60 | 61 | Header Files 62 | 63 | 64 | Header Files 65 | 66 | 67 | Header Files 68 | 69 | 70 | Header Files 71 | 72 | 73 | Header Files 74 | 75 | 76 | Header Files 77 | 78 | 79 | Header Files 80 | 81 | 82 | Header Files 83 | 84 | 85 | Header Files 86 | 87 | 88 | Header Files 89 | 90 | 91 | Header Files 92 | 93 | 94 | Header Files 95 | 96 | 97 | Header Files 98 | 99 | 100 | Header Files 101 | 102 | 103 | Header Files 104 | 105 | 106 | Header Files 107 | 108 | 109 | Header Files 110 | 111 | 112 | Header Files 113 | 114 | 115 | Header Files 116 | 117 | 118 | Header Files 119 | 120 | 121 | Header Files 122 | 123 | 124 | Header Files 125 | 126 | 127 | Header Files 128 | 129 | 130 | Header Files 131 | 132 | 133 | Header Files 134 | 135 | 136 | Header Files 137 | 138 | 139 | Header Files 140 | 141 | 142 | Header Files 143 | 144 | 145 | Header Files 146 | 147 | 148 | Header Files 149 | 150 | 151 | Header Files 152 | 153 | 154 | Header Files 155 | 156 | 157 | Header Files 158 | 159 | 160 | Header Files 161 | 162 | 163 | Header Files 164 | 165 | 166 | Header Files 167 | 168 | 169 | 170 | 171 | Source Files 172 | 173 | 174 | Source Files 175 | 176 | 177 | Source Files 178 | 179 | 180 | Source Files 181 | 182 | 183 | Source Files 184 | 185 | 186 | Source Files 187 | 188 | 189 | Source Files 190 | 191 | 192 | Source Files 193 | 194 | 195 | Source Files 196 | 197 | 198 | Source Files 199 | 200 | 201 | Source Files 202 | 203 | 204 | Source Files 205 | 206 | 207 | Source Files 208 | 209 | 210 | Source Files 211 | 212 | 213 | Source Files 214 | 215 | 216 | Source Files 217 | 218 | 219 | Source Files 220 | 221 | 222 | Source Files 223 | 224 | 225 | Source Files 226 | 227 | 228 | Source Files 229 | 230 | 231 | Source Files 232 | 233 | 234 | Source Files 235 | 236 | 237 | Source Files 238 | 239 | 240 | Source Files 241 | 242 | 243 | Source Files 244 | 245 | 246 | Source Files 247 | 248 | 249 | Source Files 250 | 251 | 252 | Source Files 253 | 254 | 255 | Source Files 256 | 257 | 258 | Source Files 259 | 260 | 261 | Source Files 262 | 263 | 264 | Source Files 265 | 266 | 267 | Source Files 268 | 269 | 270 | Source Files 271 | 272 | 273 | Source Files 274 | 275 | 276 | Source Files 277 | 278 | 279 | Source Files 280 | 281 | 282 | Source Files 283 | 284 | 285 | Source Files 286 | 287 | 288 | Source Files 289 | 290 | 291 | 292 | 293 | 294 | -------------------------------------------------------------------------------- /DivaHook/rom/components.ini: -------------------------------------------------------------------------------- 1 | # components.ini 2 | # defines which components will be enabled 3 | 4 | # emulates game input through mouse and keyboard. 5 | # controls can be set inside the keyconfig.ini file. 6 | input_emulator = true 7 | touch_slider_emulator = true 8 | touch_panel_emulator = true 9 | 10 | # freezes the PV select timer at 39 seconds. 11 | sys_timer = true 12 | 13 | # loads user defined const values from the playerdata.ini config 14 | # and writes them to the game's PlayerData struct. 15 | player_data_manager = false 16 | 17 | # adjusts 2D and 3D animations to retain their original speed at different frame rates. 18 | # only use this component if you are running this game at higher than 60 FPS. 19 | frame_rate_manager = false 20 | 21 | # sets an unlimited per session play count for the normal game mode. 22 | # this means the player won't be sent back to the title screen after 2 plays. 23 | stage_manager = false 24 | 25 | # skip unnecessary DATA_INITIALIZE loading time, speed up SYSTEM_STARTUP and skip the startup WARNING message. 26 | # further improvements can be achieved by shortening the duration of the pv_999 script file as it's test loaded during the SYSTEM_STARTUP. 27 | fast_loader = true 28 | 29 | # allows for a user controllable camera which can be toggled using F3, 30 | # can be controlled using W/A/S/D to move, SPACE/CTRL to ascend/descend, Q/E to rotate, R/F to zoom in/out 31 | # and holding SHIFT/ALT to speed up or slow down these controls. 32 | camera_controller = false 33 | 34 | # lets the user change the current game state using the F4 - F8 keys, enable the dw_gui / DATA_TESTs 35 | # and speed up 2D animations / menu navigation by holding SHIFT + TAB. 36 | # enabling this component is not recommended for most users. 37 | debug_component = false -------------------------------------------------------------------------------- /DivaHook/rom/keyconfig.ini: -------------------------------------------------------------------------------- 1 | # keyconfig.ini 2 | # defines the input_emulator key bindings 3 | # multiple keys are to be specified comma separated 4 | 5 | # Options: 6 | 7 | # allows the user to mouse wheel scroll through the PV selection list 8 | mouse_scroll_pv_selection = true 9 | # the interval it takes for the emulated slider touch points to move from one contact point to another. 10 | # in most cases this does not need editing. 11 | touch_slider_emulation_speed = 750.0 12 | 13 | # JVS Buttons: 14 | JVS_TEST = F1 15 | JVS_SERVICE = F2 16 | 17 | JVS_START = Enter, Ds4_Options 18 | JVS_TRIANGLE = W, I, Ds4_Triangle, Ds4_DPad_Up 19 | JVS_SQUARE = A, J, Ds4_Square, Ds4_DPad_Left 20 | JVS_CROSS = S, K, Ds4_Cross, Ds4_DPad_Down 21 | JVS_CIRCLE = D, L, Ds4_Circle, Ds4_DPad_Right 22 | 23 | JVS_LEFT = Q, U, Up, Ds4_L1, Ds4_L_Stick_Up, Ds4_R_Stick_Up 24 | JVS_RIGHT = E, O, Down, Ds4_R1, Ds4_L_Stick_Down, Ds4_R_Stick_Down 25 | 26 | # Touch Slider: 27 | LEFT_SIDE_SLIDE_LEFT = Q, Ds4_L_Stick_Left 28 | LEFT_SIDE_SLIDE_RIGHT = E, Ds4_L_Stick_Right 29 | 30 | RIGHT_SIDE_SLIDE_LEFT = U, Ds4_R_Stick_Left 31 | RIGHT_SIDE_SLIDE_RIGHT = O, Ds4_R_Stick_Right 32 | 33 | # --- KEYBOARD KEY NAMES: --- 34 | 35 | # - Standard Keys 36 | # uppercase "A" to "Z", "0" to "9" 37 | 38 | # - NumPad Keys 39 | # "NumPad0" to "NumPad9" 40 | # "Plus", "Minus", "Divide", "Multiply" 41 | 42 | # - Function Keys 43 | # "F1" to "F24" 44 | 45 | # - Shift Keys 46 | # "LeftShift", "RightShift" 47 | 48 | # - Control Keys 49 | # "LeftControl", "RightControl" 50 | 51 | # - Arrow Keys 52 | # "Up", "Down", "Left", "Right" 53 | 54 | # - Special Keys 55 | # "Enter", "Tab", "Backspace", "Insert", "Delete", "Home", "End", "PageUp", "PageDown", "Escape", "Comma", "Period", "Slash" 56 | 57 | # --- DUALSHOCK 4 BUTTON NAMES: --- 58 | 59 | # - Face Buttons 60 | # "Ds4_Square", "Ds4_Cross", "Ds4_Circle", "Ds4_Triangle" 61 | 62 | # - Standard Buttons 63 | # "Ds4_Share", "Ds4_Options", "Ds4_PS", "Ds4_Touch", "Ds4_L1", "Ds4_R1" 64 | 65 | # - D-Pad Directions 66 | # "Ds4_DPad_Up", "Ds4_DPad_Right", "Ds4_DPad_Down", "Ds4_DPad_Left" 67 | 68 | # - Trigger Buttons 69 | # "Ds4_L_Trigger", "Ds4_R_Trigger" 70 | 71 | # - Left Joystick 72 | # "Ds4_L_Stick_Up", "Ds4_L_Stick_Right", "Ds4_L_Stick_Down", "Ds4_L_Stick_Left", "Ds4_L3" 73 | 74 | # - Right Joystick 75 | # "Ds4_R_Stick_Up", "Ds4_R_Stick_Right", "Ds4_R_Stick_Down", "Ds4_R_Stick_Left", "Ds4_R3" -------------------------------------------------------------------------------- /DivaHook/rom/playerdata.ini: -------------------------------------------------------------------------------- 1 | # playerdata.ini 2 | # defines constant values to be loaded into the PlayerData struct 3 | # this file has to be encoded using utf-8 4 | 5 | player_name = NO-NAME 6 | 7 | # IDs defined in rom/gm_plate_tbl.farc/gm_plate_id.bin 8 | level_plate_id = 0 9 | 10 | # IDs same as gam_skin%03d 11 | skin_equip = 0 12 | 13 | # IDs defined in rom/gm_btn_se_tbl.farc/gm_btn_se_id.bin 14 | btn_se_equip = -1 15 | 16 | # IDs defined in rom/gm_slide_se_tbl.farc/gm_slide_se_id.bin 17 | slide_se_equip = -1 18 | 19 | # IDs defined in rom/gm_chainslide_se_tbl.farc/gm_chainslide_se_id.bin 20 | chainslide_se_equip = -1 -------------------------------------------------------------------------------- /DivaHook/src/Components/CameraController.cpp: -------------------------------------------------------------------------------- 1 | #include "CameraController.h" 2 | #include 3 | #include "Input/InputState.h" 4 | #include "ComponentsManager.h" 5 | #include "../MainModule.h" 6 | #include "../Input/Mouse/Mouse.h" 7 | #include "../Input/Keyboard/Keyboard.h" 8 | #include "../Input/Bindings/KeyboardBinding.h" 9 | 10 | #define GLUT_CURSOR_RIGHT_ARROW 0x0000 11 | #define GLUT_CURSOR_NONE 0x0065 12 | 13 | using namespace DivaHook::Input; 14 | using namespace DivaHook::Utilities; 15 | 16 | namespace DivaHook::Components 17 | { 18 | CameraController::CameraController() 19 | { 20 | } 21 | 22 | CameraController::~CameraController() 23 | { 24 | delete ToggleBinding; 25 | 26 | delete ForwardBinding; 27 | delete BackwardBinding; 28 | delete LeftBinding; 29 | delete RightBinding; 30 | 31 | delete UpBinding; 32 | delete DownBinding; 33 | delete ClockwiseBinding; 34 | delete CounterClockwiseBinding; 35 | delete ZoomInBinding; 36 | delete ZoomOutBinding; 37 | 38 | delete FastBinding; 39 | delete SlowBinding; 40 | } 41 | 42 | const char* CameraController::GetDisplayName() 43 | { 44 | return "camera_controller"; 45 | } 46 | 47 | void CameraController::Initialize(ComponentsManager* manager) 48 | { 49 | componentsManager = manager; 50 | 51 | printf("CameraController::Initialize(): Initialized\n"); 52 | 53 | for (int i = 0; i < sizeof(cameraSetterAddresses) / sizeof(void*); i++) 54 | { 55 | DWORD oldProtect; 56 | VirtualProtect((void*)cameraSetterAddresses[i], sizeof(uint8_t), PAGE_EXECUTE_READWRITE, &oldProtect); 57 | 58 | originalSetterBytes[i] = *(uint8_t*)cameraSetterAddresses[i]; 59 | } 60 | 61 | ToggleBinding = new Binding(); 62 | ToggleBinding->AddBinding(new KeyboardBinding(VK_F3)); 63 | 64 | ForwardBinding = new Binding(); 65 | ForwardBinding->AddBinding(new KeyboardBinding('W')); 66 | BackwardBinding = new Binding(); 67 | BackwardBinding->AddBinding(new KeyboardBinding('S')); 68 | LeftBinding = new Binding(); 69 | LeftBinding->AddBinding(new KeyboardBinding('A')); 70 | RightBinding = new Binding(); 71 | RightBinding->AddBinding(new KeyboardBinding('D')); 72 | 73 | UpBinding = new Binding(); 74 | UpBinding->AddBinding(new KeyboardBinding(VK_SPACE)); 75 | DownBinding = new Binding(); 76 | DownBinding->AddBinding(new KeyboardBinding(VK_CONTROL)); 77 | 78 | ClockwiseBinding = new Binding(); 79 | ClockwiseBinding->AddBinding(new KeyboardBinding('E')); 80 | CounterClockwiseBinding = new Binding(); 81 | CounterClockwiseBinding->AddBinding(new KeyboardBinding('Q')); 82 | 83 | ZoomInBinding = new Binding(); 84 | ZoomInBinding->AddBinding(new KeyboardBinding('R')); 85 | ZoomOutBinding = new Binding(); 86 | ZoomOutBinding->AddBinding(new KeyboardBinding('F')); 87 | 88 | FastBinding = new Binding(); 89 | FastBinding->AddBinding(new KeyboardBinding(VK_SHIFT)); 90 | SlowBinding = new Binding(); 91 | SlowBinding->AddBinding(new KeyboardBinding(VK_MENU)); 92 | 93 | camera = (Camera*)CAMERA_ADDRESS; 94 | } 95 | 96 | void CameraController::Update() 97 | { 98 | return; 99 | } 100 | 101 | void CameraController::UpdateInput() 102 | { 103 | if (ToggleBinding->AnyTapped()) 104 | { 105 | SetControls(!GetIsEnabled()); 106 | return; 107 | } 108 | 109 | if (!GetIsEnabled()) 110 | return; 111 | 112 | auto keyboard = Keyboard::GetInstance(); 113 | auto mouse = Mouse::GetInstance(); 114 | 115 | bool forward = ForwardBinding->AnyDown(); 116 | bool backward = BackwardBinding->AnyDown(); 117 | bool left = LeftBinding->AnyDown(); 118 | bool right = RightBinding->AnyDown(); 119 | 120 | bool up = UpBinding->AnyDown(); 121 | bool down = DownBinding->AnyDown(); 122 | 123 | bool fast = FastBinding->AnyDown(); 124 | bool slow = SlowBinding->AnyDown(); 125 | 126 | bool clockwise = ClockwiseBinding->AnyDown(); 127 | bool counterclockwise = CounterClockwiseBinding->AnyDown(); 128 | 129 | bool zoomin = ZoomInBinding->AnyDown(); 130 | bool zoomout = ZoomOutBinding->AnyDown(); 131 | 132 | float speed = GetElapsedTime() * (fast ? fastSpeed : slow ? slowSpeed : normalSpeed); 133 | 134 | if (forward ^ backward) 135 | camera->Position += PointFromAngle(verticalRotation + (forward ? +0.0f : -180.0f), speed); 136 | 137 | if (left ^ right) 138 | camera->Position += PointFromAngle(verticalRotation + (right ? +90.0f : -90.0f), speed); 139 | 140 | if (up ^ down) 141 | camera->Position.Y += speed * (up ? +0.25f : -0.25f); 142 | 143 | if (clockwise ^ counterclockwise) 144 | camera->Rotation += speed * (clockwise ? -1.0f : +1.0f); 145 | 146 | if (zoomin ^ zoomout) 147 | { 148 | camera->HorizontalFov += speed * (zoomin ? -1.0f : +1.0f); 149 | camera->HorizontalFov = std::clamp(camera->HorizontalFov, +1.0f, +170.0f); 150 | } 151 | 152 | if (mouse->HasMoved()) 153 | { 154 | SetMouseWindowCenter(); 155 | 156 | auto delta = mouse->GetDeltaPosition(); 157 | 158 | verticalRotation += delta.x * sensitivity; 159 | horizontalRotation -= delta.y * (sensitivity / 5.0f); 160 | 161 | horizontalRotation = std::clamp(horizontalRotation, -75.0f, +75.0f); 162 | } 163 | 164 | ((InputState*)*(uint64_t*)INPUT_STATE_PTR_ADDRESS)->HideCursor(); 165 | 166 | Vec2 focus = PointFromAngle(verticalRotation, 1.0f); 167 | camera->Focus.X = camera->Position.X + focus.X; 168 | camera->Focus.Z = camera->Position.Z + focus.Y; 169 | 170 | camera->Focus.Y = camera->Position.Y + PointFromAngle(horizontalRotation, 5.0f).X; 171 | } 172 | 173 | void CameraController::SetControls(bool value) 174 | { 175 | if (GetIsEnabled() == value) 176 | return; 177 | 178 | SetIsEnabled(value); 179 | componentsManager->SetUpdateGameInput(!value); 180 | 181 | printf("CameraController::SetControls(): enabled = %s\n", GetIsEnabled() ? "true" : "false"); 182 | 183 | typedef void __stdcall _glutSetCursor(int); 184 | auto glutSetCursor = (_glutSetCursor*)GLUT_SET_CURSOR_ADDRESS; 185 | 186 | // hide cursor 187 | glutSetCursor(value ? GLUT_CURSOR_NONE : GLUT_CURSOR_RIGHT_ARROW); 188 | 189 | if (value) 190 | { 191 | // disable camera setters 192 | for (int i = 0; i < sizeof(cameraSetterAddresses) / sizeof(void*); i++) 193 | *(uint8_t*)cameraSetterAddresses[i] = RET_OPCODE; 194 | 195 | // set initial camera angle 196 | Vec2 camXz = Vec2(camera->Position.X, camera->Position.Z); 197 | Vec2 focusXz = Vec2(camera->Focus.X, camera->Focus.Z); 198 | verticalRotation = AngleFromPoints(camXz, focusXz); 199 | 200 | horizontalRotation = 0; 201 | camera->Rotation = defaultRotation; 202 | camera->HorizontalFov = defaultFov; 203 | } 204 | else 205 | { 206 | // restore camera setters 207 | for (int i = 0; i < sizeof(cameraSetterAddresses) / sizeof(void*); i++) 208 | *(uint8_t*)cameraSetterAddresses[i] = originalSetterBytes[i]; 209 | } 210 | } 211 | 212 | void CameraController::SetMouseWindowCenter() 213 | { 214 | RECT windowRect = MainModule::GetWindowBounds(); 215 | 216 | int centerX = windowRect.left + (windowRect.right - windowRect.left) / 2; 217 | int centerY = windowRect.top + (windowRect.bottom - windowRect.top) / 2; 218 | 219 | Mouse::GetInstance()->SetPosition(centerX, centerY); 220 | } 221 | 222 | bool CameraController::GetIsEnabled() 223 | { 224 | return isEnabled; 225 | } 226 | 227 | void CameraController::SetIsEnabled(bool value) 228 | { 229 | isEnabled = value; 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /DivaHook/src/Components/CameraController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "EmulatorComponent.h" 3 | #include "../Constants.h" 4 | #include "../Input/Bindings/Binding.h" 5 | #include "../Utilities/Math.h" 6 | 7 | namespace DivaHook::Components 8 | { 9 | struct Camera 10 | { 11 | Utilities::Vec3 Position; 12 | Utilities::Vec3 Focus; 13 | float Rotation; 14 | float HorizontalFov; 15 | float VerticalFov; 16 | }; 17 | 18 | class CameraController : public EmulatorComponent 19 | { 20 | public: 21 | Input::Binding* ToggleBinding; 22 | 23 | Input::Binding* ForwardBinding; 24 | Input::Binding* BackwardBinding; 25 | Input::Binding* LeftBinding; 26 | Input::Binding* RightBinding; 27 | 28 | Input::Binding* UpBinding; 29 | Input::Binding* DownBinding; 30 | Input::Binding* FastBinding; 31 | Input::Binding* SlowBinding; 32 | 33 | Input::Binding* ClockwiseBinding; 34 | Input::Binding* CounterClockwiseBinding; 35 | 36 | Input::Binding* ZoomInBinding; 37 | Input::Binding* ZoomOutBinding; 38 | 39 | CameraController(); 40 | ~CameraController(); 41 | 42 | virtual const char* GetDisplayName() override; 43 | 44 | virtual void Initialize(ComponentsManager*) override; 45 | virtual void Update() override; 46 | virtual void UpdateInput() override; 47 | 48 | void SetControls(bool value); 49 | 50 | bool GetIsEnabled(); 51 | 52 | private: 53 | const float fastSpeed = 0.1f; 54 | const float slowSpeed = 0.0005f; 55 | const float normalSpeed = 0.005f; 56 | 57 | const float defaultRotation = 0.0f; 58 | const float defaultFov = 70.0f; 59 | const float sensitivity = 0.25f; 60 | 61 | ComponentsManager* componentsManager; 62 | float verticalRotation; 63 | float horizontalRotation; 64 | 65 | bool isEnabled; 66 | Camera* camera; 67 | 68 | uint8_t originalSetterBytes[4]; 69 | void* cameraSetterAddresses[4] = 70 | { 71 | (void*)CAMERA_POS_SETTER_ADDRESS, 72 | (void*)CAMERA_INTR_SETTER_ADDRESS, 73 | (void*)CAMERA_ROT_SETTER_ADDRESS, 74 | (void*)CAMERA_PERS_SETTER_ADDRESS, 75 | }; 76 | 77 | void SetMouseWindowCenter(); 78 | void SetIsEnabled(bool value); 79 | }; 80 | } 81 | -------------------------------------------------------------------------------- /DivaHook/src/Components/ComponentsManager.cpp: -------------------------------------------------------------------------------- 1 | #include "ComponentsManager.h" 2 | #include "../FileSystem/ConfigFile.h" 3 | #include "../MainModule.h" 4 | #include "Input/InputEmulator.h" 5 | #include "Input/TouchSliderEmulator.h" 6 | #include "Input/TouchPanelEmulator.h" 7 | #include "SysTimer.h" 8 | #include "PlayerDataManager.h" 9 | #include "FrameRateManager.h" 10 | #include "FastLoader.h" 11 | #include "StageManager.h" 12 | #include "CameraController.h" 13 | #include "DebugComponent.h" 14 | 15 | using ConfigFile = DivaHook::FileSystem::ConfigFile; 16 | 17 | namespace DivaHook::Components 18 | { 19 | typedef void EngineUpdateInput(void*); 20 | 21 | ComponentsManager::ComponentsManager() 22 | { 23 | } 24 | 25 | ComponentsManager::~ComponentsManager() 26 | { 27 | } 28 | 29 | void ComponentsManager::ParseAddComponents() 30 | { 31 | EmulatorComponent *allComponents[] 32 | { 33 | new InputEmulator(), 34 | new TouchSliderEmulator(), 35 | new TouchPanelEmulator(), 36 | new SysTimer(), 37 | new PlayerDataManager(), 38 | new FrameRateManager(), 39 | new FastLoader(), 40 | new StageManager(), 41 | new CameraController(), 42 | new DebugComponent(), 43 | }; 44 | 45 | ConfigFile componentsConfig(MainModule::GetModuleDirectory(), COMPONENTS_CONFIG_FILE_NAME); 46 | bool success = componentsConfig.OpenRead(); 47 | 48 | if (!success) 49 | { 50 | printf("ComponentsManager::ParseAddComponents(): Unable to parse %s\n", COMPONENTS_CONFIG_FILE_NAME.c_str()); 51 | return; 52 | } 53 | 54 | size_t componentCount = sizeof(allComponents) / sizeof(EmulatorComponent*); 55 | components.reserve(componentCount); 56 | 57 | std::string trueString = "true", falseString = "false"; 58 | 59 | for (int i = 0; i < componentCount; i++) 60 | { 61 | std::string *value; 62 | 63 | auto name = allComponents[i]->GetDisplayName(); 64 | //printf("ComponentsManager::ParseAddComponents(): searching name: %s\n", name); 65 | 66 | if (componentsConfig.TryGetValue(name, &value)) 67 | { 68 | //printf("ComponentsManager::ParseAddComponents(): %s found\n", name); 69 | 70 | if (*value == trueString) 71 | { 72 | //printf("ComponentsManager::ParseAddComponents(): enabling %s...\n", name); 73 | components.push_back(allComponents[i]); 74 | } 75 | else if (*value == falseString) 76 | { 77 | //printf("ComponentsManager::ParseAddComponents(): disabling %s...\n", name); 78 | } 79 | else 80 | { 81 | //printf("ComponentsManager::ParseAddComponents(): invalid value %s for component %s\n", value, name); 82 | } 83 | 84 | delete value; 85 | } 86 | else 87 | { 88 | //printf("ParseAddComponents(): component %s not found\n", name); 89 | delete allComponents[i]; 90 | } 91 | } 92 | } 93 | 94 | 95 | void ComponentsManager::Initialize() 96 | { 97 | dwGuiDisplay = (DwGuiDisplay*)*(uint64_t*)DW_GUI_DISPLAY_INSTANCE_PTR_ADDRESS; 98 | 99 | ParseAddComponents(); 100 | updateStopwatch.Start(); 101 | 102 | for (auto& component : components) 103 | component->Initialize(this); 104 | } 105 | 106 | void ComponentsManager::Update() 107 | { 108 | elpasedTime = updateStopwatch.Restart(); 109 | 110 | for (auto& component : components) 111 | { 112 | component->SetElapsedTime(elpasedTime); 113 | component->Update(); 114 | } 115 | } 116 | 117 | void ComponentsManager::UpdateInput() 118 | { 119 | if (!GetIsInputEmulatorUsed()) 120 | { 121 | uint64_t* inputStatePtr = (uint64_t*)INPUT_STATE_PTR_ADDRESS; 122 | 123 | // poll input using the original PollInput function we overwrote with the update hook instead 124 | if (inputStatePtr != nullptr) 125 | ((EngineUpdateInput*)ENGINE_UPDATE_INPUT_ADDRESS)((void*)*inputStatePtr); 126 | } 127 | 128 | for (auto& component : components) 129 | component->UpdateInput(); 130 | } 131 | 132 | void ComponentsManager::OnFocusGain() 133 | { 134 | for (auto& component : components) 135 | component->OnFocusGain(); 136 | } 137 | 138 | void ComponentsManager::OnFocusLost() 139 | { 140 | for (auto& component : components) 141 | component->OnFocusLost(); 142 | } 143 | 144 | void ComponentsManager::Dispose() 145 | { 146 | for (auto& component : components) 147 | delete component; 148 | } 149 | } -------------------------------------------------------------------------------- /DivaHook/src/Components/ComponentsManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "EmulatorComponent.h" 3 | #include "../Utilities/Stopwatch.h" 4 | #include 5 | 6 | namespace DivaHook::Components 7 | { 8 | const std::string COMPONENTS_CONFIG_FILE_NAME = "components.ini"; 9 | 10 | // Incomplete type 11 | struct DwGuiDisplay 12 | { 13 | void* vftable; 14 | void* active; 15 | void* cap; 16 | void* on; 17 | void* move; 18 | void* widget; 19 | }; 20 | 21 | class ComponentsManager 22 | { 23 | public: 24 | ComponentsManager(); 25 | ~ComponentsManager(); 26 | void Initialize(); 27 | void Update(); 28 | void UpdateInput(); 29 | void OnFocusGain(); 30 | void OnFocusLost(); 31 | void Dispose(); 32 | 33 | inline bool GetIsInputEmulatorUsed() { return isInputEmulatorUsed; }; 34 | inline void SetIsInputEmulatorUsed(bool value) { isInputEmulatorUsed = value; }; 35 | 36 | inline bool GetUpdateGameInput() { return updateGameInput; }; 37 | inline void SetUpdateGameInput(bool value) { updateGameInput = value; } 38 | 39 | inline bool IsDwGuiActive() { return dwGuiDisplay->active != nullptr; }; 40 | inline bool IsDwGuiHovered() { return dwGuiDisplay->on != nullptr; }; 41 | 42 | private: 43 | DwGuiDisplay* dwGuiDisplay; 44 | 45 | bool isInputEmulatorUsed = false; 46 | bool updateGameInput = true; 47 | 48 | float elpasedTime; 49 | Utilities::Stopwatch updateStopwatch; 50 | std::vector components; 51 | 52 | void ParseAddComponents(); 53 | }; 54 | } -------------------------------------------------------------------------------- /DivaHook/src/Components/CustomPlayerData.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace DivaHook::Components 5 | { 6 | struct CustomPlayerData 7 | { 8 | std::string *PlayerName; 9 | int LevelPlateId; 10 | int SkinEquip; 11 | int BtnSeEquip; 12 | int SlideSeEquip; 13 | int ChainslideSeEquip; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /DivaHook/src/Components/DebugComponent.cpp: -------------------------------------------------------------------------------- 1 | #include "DebugComponent.h" 2 | #include "../Constants.h" 3 | 4 | namespace DivaHook::Components 5 | { 6 | const char* GameStateNames[] = 7 | { 8 | "STARTUP", 9 | "ADVERTISE", 10 | "GAME", 11 | "DATA_TEST", 12 | "TEST_MODE", 13 | "APP_ERROR", 14 | "MAX", 15 | }; 16 | 17 | const char* SubGameStateNames[] = 18 | { 19 | "DATA_INITIALIZE", 20 | "SYSTEM_STARTUP", 21 | "SYSTEM_STARTUP_ERROR", 22 | "WARNING", 23 | "LOGO", 24 | "RATING", 25 | "DEMO", 26 | "TITLE", 27 | "RANKING", 28 | "SCORE_RANKING", 29 | "CM", 30 | "PHOTO_MODE_DEMO", 31 | "SELECTOR", 32 | "GAME_MAIN", 33 | "GAME_SEL", 34 | "STAGE_RESULT", 35 | "SCREEN_SHOT_SEL", 36 | "SCREEN_SHOT_RESULT", 37 | "GAME_OVER", 38 | "DATA_TEST_MAIN", 39 | "DATA_TEST_MISC", 40 | "DATA_TEST_OBJ", 41 | "DATA_TEST_STG", 42 | "DATA_TEST_MOT", 43 | "DATA_TEST_COLLISION", 44 | "DATA_TEST_SPR", 45 | "DATA_TEST_AET", 46 | "DATA_TEST_AUTH_3D", 47 | "DATA_TEST_CHR", 48 | "DATA_TEST_ITEM", 49 | "DATA_TEST_PERF", 50 | "DATA_TEST_PVSCRIPT", 51 | "DATA_TEST_PRINT", 52 | "DATA_TEST_CARD", 53 | "DATA_TEST_OPD", 54 | "DATA_TEST_SLIDER", 55 | "DATA_TEST_GLITTER", 56 | "DATA_TEST_GRAPHICS", 57 | "DATA_TEST_COLLECTION_CARD", 58 | "TEST_MODE_MAIN", 59 | "APP_ERROR", 60 | "MAX", 61 | }; 62 | 63 | const char* DataTestNames[] = 64 | { 65 | "MAIN TEST", 66 | "MISC TEST", 67 | "OBJECT TEST", 68 | "STAGE TEST", 69 | "MOTION TEST", 70 | "COLLISION TEST", 71 | "SPRITE TEST", 72 | "2DAUTH TEST", 73 | "3DAUTH TEST", 74 | "CHARA TEST", 75 | "ITEM TEST", 76 | "PERFORMANCE TEST", 77 | "PVSCRIPT TEST", 78 | "PRINT TEST", 79 | "CARD TEST", 80 | "OPD TEST", 81 | "SLIDER TEST", 82 | "GLITTER TEST", 83 | "GRAPHICS TEST", 84 | "COLLECTION CARD TEST", 85 | }; 86 | 87 | typedef void ChangeGameState(GameState); 88 | ChangeGameState* changeGameState = (ChangeGameState*)CHANGE_MODE_ADDRESS; 89 | 90 | typedef void ChangeSubState(GameState, SubGameState); 91 | ChangeSubState* changeSubState = (ChangeSubState*)CHANGE_SUB_MODE_ADDRESS; 92 | 93 | DebugComponent::DebugComponent() 94 | { 95 | } 96 | 97 | DebugComponent::~DebugComponent() 98 | { 99 | } 100 | 101 | const char* DebugComponent::GetDisplayName() 102 | { 103 | return "debug_component"; 104 | } 105 | 106 | void DebugComponent::Initialize(ComponentsManager*) 107 | { 108 | printf("DebugComponent::Initialize(): Initialized\n"); 109 | 110 | InjectPatches(); 111 | 112 | // In case the FrameRateManager isn't enabled 113 | DWORD oldProtect; 114 | VirtualProtect((void*)AET_FRAME_DURATION_ADDRESS, sizeof(float), PAGE_EXECUTE_READWRITE, &oldProtect); 115 | } 116 | 117 | void DebugComponent::Update() 118 | { 119 | if (dataTestMain) 120 | { 121 | Input::Keyboard::GetInstance()->PollInput(); 122 | UpdateDataTestMain(); 123 | } 124 | } 125 | 126 | void DebugComponent::UpdateInput() 127 | { 128 | auto keyboard = Input::Keyboard::GetInstance(); 129 | 130 | // fast forward menus 131 | if (keyboard->IsDown(VK_SHIFT)) 132 | { 133 | float* frameDuration = (float*)AET_FRAME_DURATION_ADDRESS; 134 | 135 | if (keyboard->IsDown(VK_TAB)) 136 | *frameDuration = 1.0f / (GetGameFrameRate() / aetSpeedUpFactor); 137 | else if (keyboard->IsReleased(VK_TAB)) 138 | *frameDuration = 1.0f / 60.0f; 139 | } 140 | 141 | for (size_t i = 0; i < _countof(gameStateKeyMappings); i++) 142 | { 143 | if (keyboard->IsTapped(gameStateKeyMappings[i].KeyCode)) 144 | InternalChangeGameState(gameStateKeyMappings[i].State); 145 | } 146 | } 147 | 148 | void DebugComponent::InjectPatches() 149 | { 150 | const struct { void* Address; std::initializer_list Data; } patches[] = 151 | { 152 | // Prevent the DATA_TEST game state from exiting on the first frame 153 | { (void*)0x0000000140284B01, { 0x00 } }, 154 | // Enable dw_gui sprite draw calls 155 | { (void*)0x0000000140192601, { 0x00 } }, 156 | // Update the dw_gui display 157 | { (void*)0x0000000140302600, { 0xB0, 0x01 } }, 158 | // Draw the dw_gui display 159 | { (void*)0x0000000140302610, { 0xB0, 0x01 } }, 160 | // Enable the dw_gui widgets 161 | { (void*)0x0000000140192D00, { 0xB8, 0x01, 0x00, 0x00, 0x00, 0xC3 } }, 162 | }; 163 | 164 | for (size_t i = 0; i < _countof(patches); i++) 165 | InjectCode(patches[i].Address, patches[i].Data); 166 | } 167 | 168 | void DebugComponent::SetConsoleForeground() 169 | { 170 | HWND consoleHandle = GetConsoleWindow(); 171 | 172 | if (consoleHandle == NULL) 173 | return; 174 | 175 | WINDOWPLACEMENT place = { sizeof(WINDOWPLACEMENT) }; 176 | GetWindowPlacement(consoleHandle, &place); 177 | 178 | switch (place.showCmd) 179 | { 180 | case SW_SHOWMAXIMIZED: 181 | ShowWindow(consoleHandle, SW_SHOWMAXIMIZED); 182 | break; 183 | case SW_SHOWMINIMIZED: 184 | ShowWindow(consoleHandle, SW_RESTORE); 185 | break; 186 | default: 187 | ShowWindow(consoleHandle, SW_NORMAL); 188 | break; 189 | } 190 | 191 | SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE); 192 | SetForegroundWindow(consoleHandle); 193 | } 194 | 195 | void DebugComponent::PrintDataTestMain() 196 | { 197 | system("cls"); 198 | printf(" DATA TEST MAIN:\n\n"); 199 | 200 | for (int i = SUB_DATA_TEST_MISC; i <= SUB_DATA_TEST_COLLECTION_CARD; i++) 201 | printf("%s %s\n", i == selectionIndex ? "->" : " ", DataTestNames[i - SUB_DATA_TEST_MAIN]); 202 | 203 | printf("\n"); 204 | SetConsoleForeground(); 205 | } 206 | 207 | void DebugComponent::InternalChangeGameState(GameState state) 208 | { 209 | changeGameState(state); 210 | printDataTestMain = dataTestMain = (state == GS_DATA_TEST); 211 | } 212 | 213 | void DebugComponent::UpdateDataTestMain() 214 | { 215 | auto keyboard = Input::Keyboard::GetInstance(); 216 | 217 | if (keyboard->IsIntervalTapped(VK_UP)) 218 | { 219 | selectionIndex--; 220 | printDataTestMain = true; 221 | } 222 | 223 | if (keyboard->IsIntervalTapped(VK_DOWN)) 224 | { 225 | selectionIndex++; 226 | printDataTestMain = true; 227 | } 228 | 229 | if (selectionIndex > SUB_DATA_TEST_COLLECTION_CARD) 230 | selectionIndex = SUB_DATA_TEST_MISC; 231 | 232 | if (selectionIndex < SUB_DATA_TEST_MISC) 233 | selectionIndex = SUB_DATA_TEST_COLLECTION_CARD; 234 | 235 | if (keyboard->IsTapped(VK_RETURN)) 236 | { 237 | dataTestMain = false; 238 | 239 | printf("[%s] -> [%s]\n", SubGameStateNames[SUB_DATA_TEST_MAIN], SubGameStateNames[selectionIndex]); 240 | changeSubState(GS_DATA_TEST, (SubGameState)selectionIndex); 241 | } 242 | 243 | if (printDataTestMain) 244 | { 245 | PrintDataTestMain(); 246 | printDataTestMain = false; 247 | } 248 | } 249 | 250 | void DebugComponent::InjectCode(void* address, const std::initializer_list &data) 251 | { 252 | const size_t byteCount = data.size() * sizeof(uint8_t); 253 | 254 | DWORD oldProtect; 255 | VirtualProtect(address, byteCount, PAGE_EXECUTE_READWRITE, &oldProtect); 256 | 257 | memcpy(address, data.begin(), byteCount); 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /DivaHook/src/Components/DebugComponent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "EmulatorComponent.h" 3 | #include "GameState.h" 4 | #include "../Input/Keyboard/Keyboard.h" 5 | 6 | namespace DivaHook::Components 7 | { 8 | class DebugComponent : public EmulatorComponent 9 | { 10 | public: 11 | DebugComponent(); 12 | ~DebugComponent(); 13 | 14 | virtual const char* GetDisplayName() override; 15 | 16 | virtual void Initialize(ComponentsManager*) override; 17 | virtual void Update() override; 18 | virtual void UpdateInput() override; 19 | 20 | private: 21 | const float aetSpeedUpFactor = 4.0f; 22 | 23 | bool dataTestMain = false; 24 | bool printDataTestMain = false; 25 | int selectionIndex = SUB_DATA_TEST_MISC; 26 | 27 | const struct { BYTE KeyCode; GameState State; } gameStateKeyMappings[5] = 28 | { 29 | { VK_F4, GS_ADVERTISE }, 30 | { VK_F5, GS_GAME }, 31 | { VK_F6, GS_DATA_TEST }, 32 | { VK_F7, GS_TEST_MODE }, 33 | { VK_F8, GS_APP_ERROR }, 34 | }; 35 | 36 | void InjectPatches(); 37 | void SetConsoleForeground(); 38 | void PrintDataTestMain(); 39 | void InternalChangeGameState(GameState state); 40 | void UpdateDataTestMain(); 41 | void InjectCode(void* address, const std::initializer_list &data); 42 | }; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /DivaHook/src/Components/EmulatorComponent.cpp: -------------------------------------------------------------------------------- 1 | #include "EmulatorComponent.h" 2 | #include "../Constants.h" 3 | 4 | namespace DivaHook::Components 5 | { 6 | EmulatorComponent::EmulatorComponent() 7 | { 8 | } 9 | 10 | EmulatorComponent::~EmulatorComponent() 11 | { 12 | } 13 | 14 | void EmulatorComponent::SetElapsedTime(float value) 15 | { 16 | elapsedTime = value; 17 | } 18 | 19 | float EmulatorComponent::GetElapsedTime() 20 | { 21 | return elapsedTime == 0.0f ? (1000.0f / 60.0f) : elapsedTime; 22 | } 23 | 24 | float EmulatorComponent::GetFrameRate() 25 | { 26 | return 1000.0f / GetElapsedTime(); 27 | } 28 | 29 | float EmulatorComponent::GetGameFrameRate() 30 | { 31 | return *(float*)FRAME_RATE_ADDRESS; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /DivaHook/src/Components/EmulatorComponent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace DivaHook::Components 4 | { 5 | class ComponentsManager; 6 | 7 | class EmulatorComponent 8 | { 9 | public: 10 | EmulatorComponent(); 11 | ~EmulatorComponent(); 12 | 13 | virtual const char* GetDisplayName() = 0; 14 | 15 | virtual void Initialize(ComponentsManager*) = 0; 16 | virtual void Update() = 0; 17 | 18 | virtual void UpdateInput() {}; 19 | virtual void OnFocusGain() {}; 20 | virtual void OnFocusLost() {}; 21 | 22 | void SetElapsedTime(float value); 23 | float GetElapsedTime(); 24 | float GetFrameRate(); 25 | float GetGameFrameRate(); 26 | 27 | private: 28 | float elapsedTime; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /DivaHook/src/Components/FastLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "FastLoader.h" 2 | #include "../Constants.h" 3 | #include 4 | 5 | namespace DivaHook::Components 6 | { 7 | FastLoader::FastLoader() 8 | { 9 | } 10 | 11 | FastLoader::~FastLoader() 12 | { 13 | } 14 | 15 | const char* FastLoader::GetDisplayName() 16 | { 17 | return "fast_loader"; 18 | } 19 | 20 | void FastLoader::Initialize(ComponentsManager*) 21 | { 22 | } 23 | 24 | void FastLoader::Update() 25 | { 26 | if (dataInitialized) 27 | return; 28 | 29 | previousGameState = currentGameState; 30 | currentGameState = *(GameState*)CURRENT_GAME_STATE_ADDRESS; 31 | 32 | if (currentGameState == GS_STARTUP) 33 | { 34 | typedef void UpdateTask(); 35 | UpdateTask* updateTask = (UpdateTask*)UPDATE_TASKS_ADDRESS; 36 | 37 | // speed up TaskSystemStartup 38 | for (int i = 0; i < updatesPerFrame; i++) 39 | updateTask(); 40 | 41 | constexpr int DATA_INITIALIZED = 3; 42 | 43 | // skip TaskDataInit 44 | *(int*)(DATA_INIT_STATE_ADDRESS) = DATA_INITIALIZED; 45 | 46 | // skip TaskWarning 47 | *(int*)(SYSTEM_WARNING_ELAPSED_ADDRESS) = 3939; 48 | } 49 | else if (previousGameState == GS_STARTUP) 50 | { 51 | dataInitialized = true; 52 | printf("FastLoader::Update(): Data Initialized\n"); 53 | } 54 | } 55 | 56 | void FastLoader::UpdateInput() 57 | { 58 | return; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /DivaHook/src/Components/FastLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "EmulatorComponent.h" 3 | #include "GameState.h" 4 | 5 | namespace DivaHook::Components 6 | { 7 | class FastLoader : public EmulatorComponent 8 | { 9 | public: 10 | FastLoader(); 11 | ~FastLoader(); 12 | 13 | virtual const char* GetDisplayName() override; 14 | 15 | virtual void Initialize(ComponentsManager*) override; 16 | virtual void Update() override; 17 | virtual void UpdateInput() override; 18 | 19 | private: 20 | const int updatesPerFrame = 39; 21 | 22 | GameState currentGameState; 23 | GameState previousGameState; 24 | bool dataInitialized = false; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /DivaHook/src/Components/FrameRateManager.cpp: -------------------------------------------------------------------------------- 1 | #include "FrameRateManager.h" 2 | #include "../Constants.h" 3 | #include "GameState.h" 4 | #include 5 | #include 6 | 7 | namespace DivaHook::Components 8 | { 9 | FrameRateManager::FrameRateManager() 10 | { 11 | } 12 | 13 | FrameRateManager::~FrameRateManager() 14 | { 15 | } 16 | 17 | const char* FrameRateManager::GetDisplayName() 18 | { 19 | return "frame_rate_manager"; 20 | } 21 | 22 | void FrameRateManager::Initialize(ComponentsManager*) 23 | { 24 | pvFrameRate = (float*)PV_FRAME_RATE_ADDRESS; 25 | frameSpeed = (float*)FRAME_SPEED_ADDRESS; 26 | aetFrameDuration = (float*)AET_FRAME_DURATION_ADDRESS; 27 | 28 | // The default is expected to be 1.0 / 60.0 29 | defaultAetFrameDuration = *aetFrameDuration; 30 | 31 | // This const variable is stored inside a data segment so we don't want to throw any access violations 32 | DWORD oldProtect; 33 | VirtualProtect((void*)AET_FRAME_DURATION_ADDRESS, sizeof(float), PAGE_EXECUTE_READWRITE, &oldProtect); 34 | } 35 | 36 | void FrameRateManager::Update() 37 | { 38 | float frameRate = RoundFrameRate(GetGameFrameRate()); 39 | 40 | *aetFrameDuration = 1.0f / frameRate; 41 | *pvFrameRate = frameRate; 42 | 43 | bool inGame = *(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME; 44 | 45 | if (inGame) 46 | { 47 | // During the GAME state the frame rate will be handled by the PvFrameRate instead 48 | 49 | constexpr float defaultFrameSpeed = 1.0f; 50 | constexpr float defaultFrameRate = 60.0f; 51 | 52 | // This PV struct creates a copy of the PvFrameRate & PvFrameSpeed during the loading screen 53 | // so we'll make sure to keep updating it as well. 54 | // Each new motion also creates its own copy of these values but keeping track of the active motions is annoying 55 | // and they usually change multiple times per PV anyway so this should suffice for now 56 | float* pvStructPvFrameRate = (float*)(0x0000000140CDD978 + 0x2BF98); 57 | float* pvStructPvFrameSpeed = (float*)(0x0000000140CDD978 + 0x2BF9C); 58 | 59 | *pvStructPvFrameRate = *pvFrameRate; 60 | *pvStructPvFrameSpeed = (defaultFrameRate / *pvFrameRate); 61 | 62 | *frameSpeed = defaultFrameSpeed; 63 | } 64 | else 65 | { 66 | *frameSpeed = *aetFrameDuration / defaultAetFrameDuration; 67 | } 68 | } 69 | 70 | float FrameRateManager::RoundFrameRate(float frameRate) 71 | { 72 | constexpr float roundingThreshold = 4.0f; 73 | 74 | for (int i = 0; i < sizeof(commonRefreshRates) / sizeof(float); i++) 75 | { 76 | float refreshRate = commonRefreshRates[i]; 77 | 78 | if (frameRate > refreshRate - roundingThreshold && frameRate < refreshRate + roundingThreshold) 79 | frameRate = refreshRate; 80 | } 81 | 82 | return frameRate; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /DivaHook/src/Components/FrameRateManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "EmulatorComponent.h" 3 | 4 | namespace DivaHook::Components 5 | { 6 | class FrameRateManager : public EmulatorComponent 7 | { 8 | public: 9 | FrameRateManager(); 10 | ~FrameRateManager(); 11 | 12 | virtual const char* GetDisplayName() override; 13 | 14 | virtual void Initialize(ComponentsManager*) override; 15 | virtual void Update() override; 16 | 17 | private: 18 | float *pvFrameRate; 19 | float *frameSpeed; 20 | float *aetFrameDuration; 21 | float defaultAetFrameDuration; 22 | 23 | float commonRefreshRates[5] 24 | { 25 | 60.0f, 26 | 75.0f, 27 | 120.0f, 28 | 144.0f, 29 | 240.0f, 30 | }; 31 | 32 | float RoundFrameRate(float frameRate); 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /DivaHook/src/Components/GameState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace DivaHook::Components 5 | { 6 | enum GameState : uint32_t 7 | { 8 | GS_STARTUP, 9 | GS_ADVERTISE, 10 | GS_GAME, 11 | GS_DATA_TEST, 12 | GS_TEST_MODE, 13 | GS_APP_ERROR, 14 | GS_MAX, 15 | }; 16 | 17 | enum SubGameState : uint32_t 18 | { 19 | SUB_DATA_INITIALIZE, 20 | SUB_SYSTEM_STARTUP, 21 | SUB_SYSTEM_STARTUP_ERROR, 22 | SUB_WARNING, 23 | SUB_LOGO, 24 | SUB_RATING, 25 | SUB_DEMO, 26 | SUB_TITLE, 27 | SUB_RANKING, 28 | SUB_SCORE_RANKING, 29 | SUB_CM, 30 | SUB_PHOTO_MODE_DEMO, 31 | SUB_SELECTOR, 32 | SUB_GAME_MAIN, 33 | SUB_GAME_SEL, 34 | SUB_STAGE_RESULT, 35 | SUB_SCREEN_SHOT_SEL, 36 | SUB_SCREEN_SHOT_RESULT, 37 | SUB_GAME_OVER, 38 | SUB_DATA_TEST_MAIN, 39 | SUB_DATA_TEST_MISC, 40 | SUB_DATA_TEST_OBJ, 41 | SUB_DATA_TEST_STG, 42 | SUB_DATA_TEST_MOT, 43 | SUB_DATA_TEST_COLLISION, 44 | SUB_DATA_TEST_SPR, 45 | SUB_DATA_TEST_AET, 46 | SUB_DATA_TEST_AUTH_3D, 47 | SUB_DATA_TEST_CHR, 48 | SUB_DATA_TEST_ITEM, 49 | SUB_DATA_TEST_PERF, 50 | SUB_DATA_TEST_PVSCRIPT, 51 | SUB_DATA_TEST_PRINT, 52 | SUB_DATA_TEST_CARD, 53 | SUB_DATA_TEST_OPD, 54 | SUB_DATA_TEST_SLIDER, 55 | SUB_DATA_TEST_GLITTER, 56 | SUB_DATA_TEST_GRAPHICS, 57 | SUB_DATA_TEST_COLLECTION_CARD, 58 | SUB_TEST_MODE_MAIN, 59 | SUB_APP_ERROR, 60 | SUB_MAX, 61 | }; 62 | } -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/InputBufferType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace DivaHook::Components 4 | { 5 | enum InputBufferType 6 | { 7 | InputBufferType_Tapped, 8 | InputBufferType_Released, 9 | InputBufferType_Down, 10 | InputBufferType_DoubleTapped, 11 | InputBufferType_IntervalTapped, 12 | InputBufferType_Max, 13 | }; 14 | } -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/InputEmulator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "windows.h" 3 | #include "InputEmulator.h" 4 | #include "../ComponentsManager.h" 5 | #include "../../Constants.h" 6 | #include "../../MainModule.h" 7 | #include "../../Input/Bindings/KeyboardBinding.h" 8 | #include "../../Input/Bindings/MouseBinding.h" 9 | #include "../../Input/Bindings/Ds4Binding.h" 10 | #include "../../Input/KeyConfig/Config.h" 11 | #include "../../Utilities/Operations.h" 12 | #include "../../Utilities/EnumBitwiseOperations.h" 13 | #include "../../FileSystem/ConfigFile.h" 14 | 15 | const std::string KEY_CONFIG_FILE_NAME = "keyconfig.ini"; 16 | 17 | using namespace DivaHook::Input; 18 | using namespace DivaHook::Input::KeyConfig; 19 | using namespace DivaHook::Utilities; 20 | 21 | namespace DivaHook::Components 22 | { 23 | InputEmulator::InputEmulator() 24 | { 25 | } 26 | 27 | InputEmulator::~InputEmulator() 28 | { 29 | delete TestBinding; 30 | delete ServiceBinding; 31 | 32 | delete StartBinding; 33 | delete SankakuBinding; 34 | delete ShikakuBinding; 35 | delete BatsuBinding; 36 | delete MaruBinding; 37 | 38 | delete LeftBinding; 39 | delete RightBinding; 40 | } 41 | 42 | const char* InputEmulator::GetDisplayName() 43 | { 44 | return "input_emulator"; 45 | } 46 | 47 | void InputEmulator::Initialize(ComponentsManager* manager) 48 | { 49 | componentsManager = manager; 50 | componentsManager->SetIsInputEmulatorUsed(true); 51 | 52 | inputState = GetInputStatePtr((void*)INPUT_STATE_PTR_ADDRESS); 53 | inputState->HideCursor(); 54 | 55 | TestBinding = new Binding(); 56 | ServiceBinding = new Binding(); 57 | StartBinding = new Binding(); 58 | 59 | SankakuBinding = new Binding(); 60 | ShikakuBinding = new Binding(); 61 | BatsuBinding = new Binding(); 62 | MaruBinding = new Binding(); 63 | 64 | LeftBinding = new Binding(); 65 | RightBinding = new Binding(); 66 | 67 | FileSystem::ConfigFile configFile(MainModule::GetModuleDirectory(), KEY_CONFIG_FILE_NAME); 68 | configFile.OpenRead(); 69 | 70 | Config::BindConfigKeys(configFile.ConfigMap, "JVS_TEST", *TestBinding, { "F1" }); 71 | Config::BindConfigKeys(configFile.ConfigMap, "JVS_SERVICE", *ServiceBinding, { "F2" }); 72 | Config::BindConfigKeys(configFile.ConfigMap, "JVS_START", *StartBinding, { "Enter" }); 73 | Config::BindConfigKeys(configFile.ConfigMap, "JVS_TRIANGLE", *SankakuBinding, { "W", "I" }); 74 | Config::BindConfigKeys(configFile.ConfigMap, "JVS_SQUARE", *ShikakuBinding, { "A", "J" }); 75 | Config::BindConfigKeys(configFile.ConfigMap, "JVS_CROSS", *BatsuBinding, { "S", "K" }); 76 | Config::BindConfigKeys(configFile.ConfigMap, "JVS_CIRCLE", *MaruBinding, { "D", "L" }); 77 | Config::BindConfigKeys(configFile.ConfigMap, "JVS_LEFT", *LeftBinding, { "Q", "U" }); 78 | Config::BindConfigKeys(configFile.ConfigMap, "JVS_RIGHT", *RightBinding, { "E", "O" }); 79 | 80 | mouseScrollPvSelection = configFile.GetBooleanValue("mouse_scroll_pv_selection"); 81 | } 82 | 83 | void InputEmulator::Update() 84 | { 85 | return; 86 | } 87 | 88 | void InputEmulator::OnFocusLost() 89 | { 90 | // to prevent buttons from being "stuck" 91 | inputState->ClearState(); 92 | inputState->HideCursor(); 93 | } 94 | 95 | void InputEmulator::UpdateInput() 96 | { 97 | if (!componentsManager->GetUpdateGameInput()) 98 | return; 99 | 100 | if (!componentsManager->IsDwGuiActive()) 101 | { 102 | UpdateJvsInput(); 103 | 104 | if (mouseScrollPvSelection && !componentsManager->IsDwGuiHovered()) 105 | UpdateMousePvScroll(); 106 | } 107 | 108 | UpdateDwGuiInput(); 109 | } 110 | 111 | void InputEmulator::UpdateJvsInput() 112 | { 113 | auto tappedFunc = [](void* binding) { return ((Binding*)binding)->AnyTapped(); }; 114 | auto releasedFunc = [](void* binding) { return ((Binding*)binding)->AnyReleased(); }; 115 | auto downFunc = [](void* binding) { return ((Binding*)binding)->AnyDown(); }; 116 | 117 | lastDownState = inputState->Down.Buttons; 118 | 119 | inputState->Tapped.Buttons = GetJvsButtonsState(tappedFunc); 120 | inputState->Released.Buttons = GetJvsButtonsState(releasedFunc); 121 | inputState->Down.Buttons = GetJvsButtonsState(downFunc); 122 | inputState->DoubleTapped.Buttons = GetJvsButtonsState(tappedFunc); 123 | inputState->IntervalTapped.Buttons = GetJvsButtonsState(tappedFunc); 124 | 125 | if ((lastDownState &= inputState->Tapped.Buttons) != 0) 126 | inputState->Down.Buttons ^= inputState->Tapped.Buttons; 127 | 128 | // repress held down buttons to not block input 129 | //inputState->Down.Buttons ^= inputState->Tapped.Buttons; 130 | } 131 | 132 | void InputEmulator::UpdateDwGuiInput() 133 | { 134 | auto keyboard = Keyboard::GetInstance(); 135 | auto mouse = Mouse::GetInstance(); 136 | 137 | auto pos = mouse->GetRelativePosition(); 138 | inputState->MouseX = (int)pos.x; 139 | inputState->MouseY = (int)pos.y; 140 | 141 | auto deltaPos = mouse->GetDeltaPosition(); 142 | inputState->MouseDeltaX = (int)deltaPos.x; 143 | inputState->MouseDeltaY = (int)deltaPos.y; 144 | 145 | inputState->Key = GetKeyState(); 146 | 147 | for (int i = 0; i < sizeof(keyBits) / sizeof(KeyBit); i++) 148 | UpdateInputBit(keyBits[i].Bit, keyBits[i].KeyCode); 149 | 150 | for (int i = InputBufferType_Tapped; i < InputBufferType_Max; i++) 151 | { 152 | inputState->SetBit(scrollUpBit, mouse->GetIsScrolledUp(), (InputBufferType)i); 153 | inputState->SetBit(scrollDownBit, mouse->GetIsScrolledDown(), (InputBufferType)i); 154 | } 155 | } 156 | 157 | void InputEmulator::UpdateMousePvScroll() 158 | { 159 | // I originally wanted to use a MouseBinding set to JVS_LEFT / JVS_RIGHT 160 | // but that ended up being too slow because a PV slot can only be scrolled to once the scroll animation has finished playing 161 | int* slotsToScroll = (int*)PV_SEL_SLOTS_TO_SCROLL; 162 | 163 | auto mouse = Mouse::GetInstance(); 164 | if (mouse->GetIsScrolledUp()) 165 | *slotsToScroll -= 1; 166 | if (mouse->GetIsScrolledDown()) 167 | *slotsToScroll += 1; 168 | } 169 | 170 | InputState* InputEmulator::GetInputStatePtr(void *address) 171 | { 172 | return (InputState*)(*(uint64_t*)address); 173 | } 174 | 175 | JvsButtons InputEmulator::GetJvsButtonsState(bool(*buttonTestFunc)(void*)) 176 | { 177 | JvsButtons buttons = JVS_NONE; 178 | 179 | if (buttonTestFunc(TestBinding)) 180 | buttons |= JVS_TEST; 181 | if (buttonTestFunc(ServiceBinding)) 182 | buttons |= JVS_SERVICE; 183 | 184 | if (buttonTestFunc(StartBinding)) 185 | buttons |= JVS_START; 186 | 187 | if (buttonTestFunc(SankakuBinding)) 188 | buttons |= JVS_TRIANGLE; 189 | if (buttonTestFunc(ShikakuBinding)) 190 | buttons |= JVS_SQUARE; 191 | if (buttonTestFunc(BatsuBinding)) 192 | buttons |= JVS_CROSS; 193 | if (buttonTestFunc(MaruBinding)) 194 | buttons |= JVS_CIRCLE; 195 | 196 | if (buttonTestFunc(LeftBinding)) 197 | buttons |= JVS_L; 198 | if (buttonTestFunc(RightBinding)) 199 | buttons |= JVS_R; 200 | 201 | return buttons; 202 | } 203 | 204 | char InputEmulator::GetKeyState() 205 | { 206 | auto keyboard = Keyboard::GetInstance(); 207 | 208 | bool upper = keyboard->IsDown(VK_SHIFT); 209 | constexpr char caseDifference = 'A' - 'a'; 210 | 211 | char inputKey = 0x00; 212 | 213 | for (char key = '0'; key < 'Z'; key++) 214 | { 215 | if (keyboard->IsIntervalTapped(key)) 216 | inputKey = (upper || key < 'A') ? key : (key - caseDifference); 217 | } 218 | 219 | if (keyboard->IsIntervalTapped(VK_BACK)) 220 | inputKey = 0x08; 221 | 222 | if (keyboard->IsIntervalTapped(VK_TAB)) 223 | inputKey = 0x09; 224 | 225 | if (keyboard->IsIntervalTapped(VK_SPACE)) 226 | inputKey = 0x20; 227 | 228 | return inputKey; 229 | } 230 | 231 | void InputEmulator::UpdateInputBit(uint32_t bit, uint8_t keycode) 232 | { 233 | auto keyboard = Keyboard::GetInstance(); 234 | 235 | inputState->SetBit(bit, keyboard->IsTapped(keycode), InputBufferType_Tapped); 236 | inputState->SetBit(bit, keyboard->IsReleased(keycode), InputBufferType_Released); 237 | inputState->SetBit(bit, keyboard->IsDown(keycode), InputBufferType_Down); 238 | inputState->SetBit(bit, keyboard->IsDoubleTapped(keycode), InputBufferType_DoubleTapped); 239 | inputState->SetBit(bit, keyboard->IsIntervalTapped(keycode), InputBufferType_IntervalTapped); 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/InputEmulator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "InputState.h" 5 | #include "../EmulatorComponent.h" 6 | #include "../../Input/Bindings/Binding.h" 7 | 8 | namespace DivaHook::Components 9 | { 10 | struct KeyBit 11 | { 12 | uint32_t Bit; 13 | uint8_t KeyCode; 14 | }; 15 | 16 | class InputEmulator : public EmulatorComponent 17 | { 18 | public: 19 | Input::Binding* TestBinding; 20 | Input::Binding* ServiceBinding; 21 | 22 | Input::Binding* StartBinding; 23 | Input::Binding* SankakuBinding; 24 | Input::Binding* ShikakuBinding; 25 | Input::Binding* BatsuBinding; 26 | Input::Binding* MaruBinding; 27 | 28 | Input::Binding* LeftBinding; 29 | Input::Binding* RightBinding; 30 | 31 | InputEmulator(); 32 | ~InputEmulator(); 33 | 34 | virtual const char* GetDisplayName() override; 35 | 36 | virtual void Initialize(ComponentsManager*) override; 37 | virtual void Update() override; 38 | virtual void UpdateInput() override; 39 | 40 | virtual void OnFocusLost() override; 41 | 42 | private: 43 | ComponentsManager* componentsManager; 44 | 45 | bool mouseScrollPvSelection = false; 46 | const uint32_t scrollUpBit = 99; 47 | const uint32_t scrollDownBit = 100; 48 | 49 | KeyBit keyBits[20] = 50 | { 51 | { 5, VK_LEFT }, 52 | { 6, VK_RIGHT }, 53 | 54 | { 29, VK_SPACE }, 55 | { 39, 'A' }, 56 | { 43, 'E' }, 57 | { 42, 'D' }, 58 | { 55, 'Q' }, 59 | { 57, 'S' }, // unsure 60 | { 61, 'W' }, 61 | { 63, 'Y' }, 62 | { 84, 'L' }, // unsure 63 | 64 | { 80, VK_RETURN }, 65 | { 81, VK_SHIFT }, 66 | { 82, VK_CONTROL }, 67 | { 83, VK_MENU }, 68 | 69 | { 91, VK_UP }, 70 | { 93, VK_DOWN }, 71 | 72 | { 96, MK_LBUTTON }, 73 | { 97, VK_MBUTTON }, 74 | { 98, MK_RBUTTON }, 75 | }; 76 | 77 | InputState* inputState; 78 | JvsButtons lastDownState; 79 | 80 | void UpdateJvsInput(); 81 | void UpdateDwGuiInput(); 82 | void UpdateMousePvScroll(); 83 | InputState* GetInputStatePtr(void *address); 84 | JvsButtons GetJvsButtonsState(bool(*buttonTestFunc)(void*)); 85 | char GetKeyState(); 86 | 87 | void UpdateInputBit(uint32_t bit, uint8_t keycode); 88 | }; 89 | } 90 | -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/InputState.cpp: -------------------------------------------------------------------------------- 1 | #include "InputState.h" 2 | #include 3 | #include 4 | 5 | namespace DivaHook::Components 6 | { 7 | void InputState::ClearState() 8 | { 9 | memset(this, 0, sizeof(InputState)); 10 | } 11 | 12 | void InputState::HideCursor() 13 | { 14 | MouseX = INT32_MIN; 15 | MouseY = INT32_MIN; 16 | MouseDeltaX = 0; 17 | MouseDeltaY = 0; 18 | } 19 | 20 | void InputState::SetBit(uint32_t bit, bool value, InputBufferType inputType) 21 | { 22 | uint8_t* data = GetInputBuffer(inputType); 23 | 24 | if (data == nullptr || bit < 0 || bit >= MAX_BUTTON_BIT) 25 | return; 26 | 27 | int byteIndex = (bit / 8); 28 | int bitIndex = (bit % 8); 29 | 30 | BYTE mask = (1 << bitIndex); 31 | 32 | data[byteIndex] = value ? (data[byteIndex] | mask) : (data[byteIndex] & ~mask); 33 | } 34 | 35 | uint8_t* InputState::GetInputBuffer(InputBufferType inputType) 36 | { 37 | switch (inputType) 38 | { 39 | case InputBufferType_Tapped: 40 | return (uint8_t*)&Tapped; 41 | 42 | case InputBufferType_Released: 43 | return (uint8_t*)&Released; 44 | 45 | case InputBufferType_Down: 46 | return (uint8_t*)&Down; 47 | 48 | case InputBufferType_DoubleTapped: 49 | return (uint8_t*)&DoubleTapped; 50 | 51 | case InputBufferType_IntervalTapped: 52 | return (uint8_t*)&IntervalTapped; 53 | 54 | default: 55 | return nullptr; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/InputState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "JvsButtons.h" 3 | #include "InputBufferType.h" 4 | 5 | namespace DivaHook::Components 6 | { 7 | const int MAX_BUTTON_BIT = 0x6F; 8 | 9 | // The button state is larger than the size of a register 10 | // but only the first 32 bits are used during normal gameplay 11 | // so this will provide the convenience of still being able to access them through a bit field 12 | union ButtonState 13 | { 14 | JvsButtons Buttons; 15 | uint32_t State[4]; 16 | }; 17 | 18 | // total sizeof() == 0x20E0 19 | struct InputState 20 | { 21 | ButtonState Tapped; 22 | ButtonState Released; 23 | 24 | ButtonState Down; 25 | uint32_t Padding_20[4]; 26 | 27 | ButtonState DoubleTapped; 28 | uint32_t Padding_30[4]; 29 | 30 | ButtonState IntervalTapped; 31 | uint32_t Padding_38[12]; 32 | 33 | int32_t MouseX; 34 | int32_t MouseY; 35 | int32_t MouseDeltaX; 36 | int32_t MouseDeltaY; 37 | 38 | uint32_t Padding_AC[8]; 39 | uint8_t Padding_D0[3]; 40 | char Key; 41 | 42 | void ClearState(); 43 | void HideCursor(); 44 | void SetBit(uint32_t bit, bool value, InputBufferType inputType); 45 | uint8_t* GetInputBuffer(InputBufferType inputType); 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/JvsButtons.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace DivaHook::Components 5 | { 6 | enum JvsButtons : uint32_t 7 | { 8 | JVS_NONE = 0 << 0x00, // 0x0 9 | 10 | JVS_TEST = 1 << 0x00, // 0x1 11 | JVS_SERVICE = 1 << 0x01, // 0x2 12 | 13 | JVS_START = 1 << 0x02, // 0x4 14 | JVS_TRIANGLE = 1 << 0x07, // 0x80 15 | JVS_SQUARE = 1 << 0x08, // 0x100 16 | JVS_CROSS = 1 << 0x09, // 0x200 17 | JVS_CIRCLE = 1 << 0x0A, // 0x400 18 | JVS_L = 1 << 0x0B, // 0x800 19 | JVS_R = 1 << 0x0C, // 0x1000 20 | 21 | JVS_SW1 = 1 << 0x12, // 0x40000 22 | JVS_SW2 = 1 << 0x13, // 0x80000 23 | }; 24 | } -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/TouchPanelEmulator.cpp: -------------------------------------------------------------------------------- 1 | #include "TouchPanelEmulator.h" 2 | #include 3 | #include "../ComponentsManager.h" 4 | #include "../../Constants.h" 5 | #include "../../Input/Mouse/Mouse.h" 6 | #include "../../Input/Keyboard/Keyboard.h" 7 | 8 | using namespace DivaHook::Input; 9 | 10 | namespace DivaHook::Components 11 | { 12 | TouchPanelEmulator::TouchPanelEmulator() 13 | { 14 | } 15 | 16 | TouchPanelEmulator::~TouchPanelEmulator() 17 | { 18 | } 19 | 20 | const char* TouchPanelEmulator::GetDisplayName() 21 | { 22 | return "touch_panel_emulator"; 23 | } 24 | 25 | void TouchPanelEmulator::Initialize(ComponentsManager* manager) 26 | { 27 | componentsManager = manager; 28 | state = GetTouchStatePtr((void*)TASK_TOUCH_ADDRESS); 29 | } 30 | 31 | void TouchPanelEmulator::Update() 32 | { 33 | state->ConnectionState = 1; 34 | } 35 | 36 | void TouchPanelEmulator::UpdateInput() 37 | { 38 | if (!componentsManager->GetUpdateGameInput() || componentsManager->IsDwGuiActive() || componentsManager->IsDwGuiHovered()) 39 | return; 40 | 41 | // TODO: rescale TouchReaction aet position 42 | auto keyboard = Keyboard::GetInstance(); 43 | auto pos = Mouse::GetInstance()->GetRelativePosition(); 44 | 45 | state->XPosition = (float)pos.x; 46 | state->YPosition = (float)pos.y; 47 | 48 | bool down = keyboard->IsDown(VK_LBUTTON); 49 | bool released = keyboard->IsReleased(VK_LBUTTON); 50 | 51 | state->ContactType = (down ? 0x2 : released ? 0x1 : 0x0); 52 | state->Pressure = (float)(state->ContactType != 0); 53 | } 54 | 55 | TouchPanelState* TouchPanelEmulator::GetTouchStatePtr(void *address) 56 | { 57 | return (TouchPanelState*)address; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/TouchPanelEmulator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../EmulatorComponent.h" 3 | #include "TouchPanelState.h" 4 | 5 | namespace DivaHook::Components 6 | { 7 | class TouchPanelEmulator : public EmulatorComponent 8 | { 9 | public: 10 | TouchPanelEmulator(); 11 | ~TouchPanelEmulator(); 12 | 13 | virtual const char* GetDisplayName() override; 14 | 15 | virtual void Initialize(ComponentsManager*) override; 16 | virtual void Update() override; 17 | virtual void UpdateInput() override; 18 | 19 | private: 20 | ComponentsManager* componentsManager; 21 | 22 | TouchPanelState* state; 23 | TouchPanelState* GetTouchStatePtr(void *address); 24 | }; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/TouchPanelState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace DivaHook::Components 4 | { 5 | struct TouchPanelState 6 | { 7 | int Padding00[0x1E]; 8 | int ConnectionState; 9 | int Padding01[0x06]; 10 | float XPosition; 11 | float YPosition; 12 | float Pressure; 13 | int ContactType; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/TouchSliderEmulator.cpp: -------------------------------------------------------------------------------- 1 | #include "TouchSliderEmulator.h" 2 | #include "../ComponentsManager.h" 3 | #include "../../Constants.h" 4 | #include "../../MainModule.h" 5 | #include "../../Input/Mouse/Mouse.h" 6 | #include "../../Input/Keyboard/Keyboard.h" 7 | #include "../../Input/Bindings/KeyboardBinding.h" 8 | #include "../../Input/KeyConfig/Config.h" 9 | #include "../../FileSystem/ConfigFile.h" 10 | #include "../../Utilities/Math.h" 11 | #include 12 | #include 13 | 14 | using namespace DivaHook::Input; 15 | using namespace DivaHook::Input::KeyConfig; 16 | using namespace DivaHook::Utilities; 17 | 18 | namespace DivaHook::Components 19 | { 20 | const std::string KEY_CONFIG_FILE_NAME = "keyconfig.ini"; 21 | 22 | TouchSliderEmulator::TouchSliderEmulator() 23 | { 24 | } 25 | 26 | TouchSliderEmulator::~TouchSliderEmulator() 27 | { 28 | delete LeftSideSlideLeft; 29 | delete LeftSideSlideRight; 30 | 31 | delete RightSideSlideLeft; 32 | delete RightSideSlideRight; 33 | } 34 | 35 | const char* TouchSliderEmulator::GetDisplayName() 36 | { 37 | return "touch_slider_emulator"; 38 | } 39 | 40 | void TouchSliderEmulator::Initialize(ComponentsManager* manager) 41 | { 42 | componentsManager = manager; 43 | sliderState = (TouchSliderState*)SLIDER_CTRL_TASK_ADDRESS; 44 | 45 | LeftSideSlideLeft = new Binding(); 46 | LeftSideSlideRight = new Binding(); 47 | 48 | RightSideSlideLeft = new Binding(); 49 | RightSideSlideRight = new Binding(); 50 | 51 | FileSystem::ConfigFile configFile(MainModule::GetModuleDirectory(), KEY_CONFIG_FILE_NAME); 52 | configFile.OpenRead(); 53 | 54 | Config::BindConfigKeys(configFile.ConfigMap, "LEFT_SIDE_SLIDE_LEFT", *LeftSideSlideLeft, { "Q" }); 55 | Config::BindConfigKeys(configFile.ConfigMap, "LEFT_SIDE_SLIDE_RIGHT", *LeftSideSlideRight, { "E" }); 56 | 57 | Config::BindConfigKeys(configFile.ConfigMap, "RIGHT_SIDE_SLIDE_LEFT", *RightSideSlideLeft, { "U" }); 58 | Config::BindConfigKeys(configFile.ConfigMap, "RIGHT_SIDE_SLIDE_RIGHT", *RightSideSlideRight, { "O" }); 59 | 60 | float touchSliderEmulationSpeed = configFile.GetFloatValue("touch_slider_emulation_speed"); 61 | 62 | if (touchSliderEmulationSpeed != 0.0f) 63 | sliderSpeed = touchSliderEmulationSpeed; 64 | } 65 | 66 | void TouchSliderEmulator::Update() 67 | { 68 | sliderState->State = SLIDER_OK; 69 | } 70 | 71 | void TouchSliderEmulator::UpdateInput() 72 | { 73 | if (!componentsManager->GetUpdateGameInput() || componentsManager->IsDwGuiActive()) 74 | return; 75 | 76 | sliderIncrement = GetElapsedTime() / sliderSpeed; 77 | 78 | constexpr float sensorStep = (1.0f / SLIDER_SENSORS); 79 | 80 | EmulateSliderInput(LeftSideSlideLeft, LeftSideSlideRight, ContactPoints[0], 0.0f, 0.5f); 81 | EmulateSliderInput(RightSideSlideLeft, RightSideSlideRight, ContactPoints[1], 0.5f + sensorStep, 1.0f + sensorStep); 82 | 83 | sliderState->ResetSensors(); 84 | 85 | for (int i = 0; i < CONTACT_POINTS; i++) 86 | ApplyContactPoint(ContactPoints[i], i); 87 | } 88 | 89 | void TouchSliderEmulator::OnFocusLost() 90 | { 91 | sliderState->ResetSensors(); 92 | } 93 | 94 | void TouchSliderEmulator::EmulateSliderInput(Binding *leftBinding, Binding *rightBinding, ContactPoint &contactPoint, float start, float end) 95 | { 96 | bool leftDown = leftBinding->AnyDown(); 97 | bool rightDown = rightBinding->AnyDown(); 98 | 99 | if (leftDown) 100 | contactPoint.Position -= sliderIncrement; 101 | else if (rightDown) 102 | contactPoint.Position += sliderIncrement; 103 | 104 | if (contactPoint.Position < start) 105 | contactPoint.Position = end; 106 | 107 | if (contactPoint.Position > end) 108 | contactPoint.Position = start; 109 | 110 | bool leftTapped = leftBinding->AnyTapped(); 111 | bool rightTapped = rightBinding->AnyTapped(); 112 | 113 | if (leftTapped || rightTapped) 114 | contactPoint.Position = (start + end) / 2.0f; 115 | 116 | contactPoint.InContact = leftDown || rightDown; 117 | } 118 | 119 | void TouchSliderEmulator::ApplyContactPoint(ContactPoint &contactPoint, int section) 120 | { 121 | sliderState->SectionTouched[section] = contactPoint.InContact; 122 | 123 | int pressure = contactPoint.InContact ? FULL_PRESSURE : NO_PRESSURE; 124 | float position = std::clamp(contactPoint.Position, 0.0f, 1.0f); 125 | 126 | if (contactPoint.InContact) 127 | { 128 | int sensor = (int)(position * (SLIDER_SENSORS - 1)); 129 | 130 | sliderState->SetSensor(sensor, pressure); 131 | } 132 | 133 | constexpr float startRange = -1.0f; 134 | constexpr float endRange = +1.0f; 135 | 136 | sliderState->SectionPositions[section] = contactPoint.InContact ? (ConvertRange(0.0f, 1.0f, startRange, endRange, position)) : 0.0f; 137 | } 138 | } -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/TouchSliderEmulator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../EmulatorComponent.h" 3 | #include "TouchSliderState.h" 4 | #include "../../Input/Bindings/Binding.h" 5 | 6 | namespace DivaHook::Components 7 | { 8 | constexpr int SLIDER_INPUTS = 4; 9 | constexpr int CONTACT_POINTS = 2; 10 | 11 | struct ContactPoint 12 | { 13 | float Position; 14 | bool InContact; 15 | }; 16 | 17 | class TouchSliderEmulator : public EmulatorComponent 18 | { 19 | public: 20 | Input::Binding* LeftSideSlideLeft; 21 | Input::Binding* LeftSideSlideRight; 22 | 23 | Input::Binding* RightSideSlideLeft; 24 | Input::Binding* RightSideSlideRight; 25 | 26 | TouchSliderEmulator(); 27 | ~TouchSliderEmulator(); 28 | 29 | virtual const char* GetDisplayName() override; 30 | 31 | virtual void Initialize(ComponentsManager*) override; 32 | virtual void Update() override; 33 | virtual void UpdateInput() override; 34 | 35 | virtual void OnFocusLost() override; 36 | 37 | private: 38 | ComponentsManager* componentsManager; 39 | float sliderSpeed = 750.0f; 40 | float sliderIncrement; 41 | 42 | TouchSliderState *sliderState; 43 | ContactPoint ContactPoints[CONTACT_POINTS]; 44 | 45 | void EmulateSliderInput(Input::Binding *leftBinding, Input::Binding *rightBinding, ContactPoint &contactPoint, float start, float end); 46 | void ApplyContactPoint(ContactPoint &contactPoint, int section); 47 | }; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/TouchSliderState.cpp: -------------------------------------------------------------------------------- 1 | #include "TouchSliderState.h" 2 | 3 | namespace DivaHook::Components 4 | { 5 | void TouchSliderState::SetSensor(int index, int value) 6 | { 7 | if (index < 0 || index >= SLIDER_SENSORS) 8 | return; 9 | 10 | SensorPressureLevels[index] = value; 11 | SensorTouched[index].IsTouched = value > 0; 12 | } 13 | 14 | void TouchSliderState::ResetSensors() 15 | { 16 | for (int i = 0; i < SLIDER_SENSORS; i++) 17 | SetSensor(i, NO_PRESSURE); 18 | } 19 | } -------------------------------------------------------------------------------- /DivaHook/src/Components/Input/TouchSliderState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #define SLIDER_OK 3 5 | #define SLIDER_SECTIONS 4 6 | #define SLIDER_SENSORS 32 7 | 8 | #define NO_PRESSURE 0 9 | #define FULL_PRESSURE 180 10 | 11 | namespace DivaHook::Components 12 | { 13 | struct TouchSliderState 14 | { 15 | uint8_t Padding0000[112]; 16 | 17 | int32_t State; 18 | 19 | uint8_t Padding0074[20 + 12]; 20 | 21 | int32_t SensorPressureLevels[SLIDER_SENSORS]; 22 | 23 | uint8_t Padding0108[52 - 12]; 24 | 25 | float SectionPositions[SLIDER_SECTIONS]; 26 | int SectionConnections[SLIDER_SECTIONS]; 27 | uint8_t Padding015C[4]; 28 | bool SectionTouched[SLIDER_SECTIONS]; 29 | 30 | uint8_t Padding013C[3128 - 52 - 40]; 31 | 32 | struct 33 | { 34 | uint8_t Padding00[2]; 35 | bool IsTouched; 36 | uint8_t Padding[45]; 37 | } SensorTouched[SLIDER_SENSORS]; 38 | 39 | void SetSensor(int index, int value); 40 | void ResetSensors(); 41 | }; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /DivaHook/src/Components/PlayerData.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | struct PlayerData 5 | { 6 | int8_t use_card; 7 | int8_t freeplay; 8 | int8_t field_2; 9 | int8_t field_3; 10 | int32_t card_type; 11 | int32_t field_8; 12 | int32_t field_C; 13 | int32_t field_10; 14 | int32_t field_14; 15 | int32_t field_18; 16 | int32_t field_1C; 17 | int32_t field_20; 18 | int32_t field_24; 19 | int32_t field_28; 20 | int32_t field_2C; 21 | int32_t field_30; 22 | int32_t field_34; 23 | int32_t field_38; 24 | int32_t field_3C; 25 | int32_t field_40; 26 | int32_t field_44; 27 | int32_t field_48; 28 | int32_t field_4C; 29 | int32_t field_50; 30 | int32_t field_54; 31 | int32_t field_58; 32 | int32_t field_5C; 33 | int32_t field_60; 34 | int32_t field_64; 35 | int32_t field_68; 36 | int32_t field_6C; 37 | int32_t field_70; 38 | int32_t field_74; 39 | int32_t field_78; 40 | int32_t field_7C; 41 | int32_t field_80; 42 | int32_t field_84; 43 | int32_t field_88; 44 | int32_t field_8C; 45 | int32_t field_90; 46 | int32_t field_94; 47 | int32_t field_98; 48 | int32_t field_9C; 49 | int32_t field_A0; 50 | int32_t field_A4; 51 | int32_t field_A8; 52 | int32_t field_AC; 53 | int32_t field_B0; 54 | int32_t field_B4; 55 | int32_t field_B8; 56 | int32_t field_BC; 57 | int32_t field_C0; 58 | int32_t field_C4; 59 | int32_t field_C8; 60 | int32_t field_CC; 61 | int32_t play_data_id; 62 | int32_t accept_index; 63 | int32_t start_index; 64 | int32_t field_DC; 65 | char* player_name; 66 | int32_t field_E8; 67 | int32_t field_EC; 68 | int32_t field_F0; 69 | int32_t field_F4; 70 | int32_t field_F8; 71 | int32_t field_FC; 72 | char* level_name; 73 | int32_t field_108; 74 | int32_t field_10C; 75 | int32_t field_110; 76 | int32_t field_114; 77 | int32_t field_118; 78 | int32_t field_11C; 79 | int32_t field_120; 80 | int32_t level_plate_id; 81 | int32_t field_128; 82 | int32_t vocaloid_point; 83 | int32_t hp_vol; 84 | int32_t act_toggle; 85 | int32_t act_vol; 86 | int32_t act_slide_vol; 87 | int32_t field_140; 88 | int32_t field_144; 89 | int32_t field_148; 90 | int32_t field_14C; 91 | int32_t field_150; 92 | int32_t field_154; 93 | int32_t field_158; 94 | int32_t field_15C; 95 | int32_t field_160; 96 | int32_t field_164; 97 | int32_t field_168; 98 | int32_t field_16C; 99 | int32_t field_170; 100 | int32_t field_174; 101 | int32_t field_178; 102 | int32_t field_17C; 103 | int32_t field_180; 104 | int32_t field_184; 105 | int32_t field_188; 106 | int32_t field_18C; 107 | int32_t field_190; 108 | int32_t field_194; 109 | int32_t field_198; 110 | int32_t field_19C; 111 | int32_t field_1A0; 112 | int32_t field_1A4; 113 | int32_t field_1A8; 114 | int32_t field_1AC; 115 | int32_t field_1B0; 116 | int32_t field_1B4; 117 | int32_t field_1B8; 118 | int32_t field_1BC; 119 | int32_t field_1C0; 120 | int32_t field_1C4; 121 | int32_t field_1C8; 122 | int32_t field_1CC; 123 | int32_t field_1D0; 124 | int32_t field_1D4; 125 | int32_t field_1D8; 126 | int32_t field_1DC; 127 | int32_t field_1E0; 128 | int32_t field_1E4; 129 | int32_t field_1E8; 130 | int32_t field_1EC; 131 | int32_t field_1F0; 132 | int32_t field_1F4; 133 | int32_t field_1F8; 134 | int32_t field_1FC; 135 | int32_t field_200; 136 | int32_t field_204; 137 | int32_t field_208; 138 | int32_t field_20C; 139 | int32_t field_210; 140 | int32_t field_214; 141 | int32_t field_218; 142 | int32_t field_21C; 143 | int32_t field_220; 144 | int32_t field_224; 145 | int32_t field_228; 146 | int32_t field_22C; 147 | int32_t field_230; 148 | int32_t field_234; 149 | int32_t field_238; 150 | int32_t field_23C; 151 | int32_t field_240; 152 | int32_t field_244; 153 | int32_t field_248; 154 | int32_t field_24C; 155 | int32_t field_250; 156 | int32_t field_254; 157 | int32_t field_258; 158 | int32_t field_25C; 159 | int32_t field_260; 160 | int32_t field_264; 161 | int32_t field_268; 162 | int32_t field_26C; 163 | int32_t field_270; 164 | int32_t field_274; 165 | int32_t field_278; 166 | int32_t field_27C; 167 | int32_t field_280; 168 | int32_t field_284; 169 | int32_t field_288; 170 | int32_t field_28C; 171 | int32_t field_290; 172 | int32_t field_294; 173 | int32_t field_298; 174 | int32_t field_29C; 175 | int32_t field_2A0; 176 | int32_t field_2A4; 177 | int32_t field_2A8; 178 | int32_t field_2AC; 179 | int8_t use_pv_module_equip; 180 | int8_t ch_pv_module_equip; 181 | int8_t field_2B2; 182 | int8_t field_2B3; 183 | int32_t module_filter_kind; 184 | int32_t field_2B8; 185 | int32_t field_2BC; 186 | int32_t field_2C0; 187 | int32_t field_2C4; 188 | int32_t field_2C8; 189 | int32_t field_2CC; 190 | int32_t field_2D0; 191 | int32_t field_2D4; 192 | int32_t field_2D8; 193 | int32_t field_2DC; 194 | int32_t field_2E0; 195 | int32_t field_2E4; 196 | int32_t field_2E8; 197 | int32_t field_2EC; 198 | int32_t field_2F0; 199 | int32_t field_2F4; 200 | int32_t field_2F8; 201 | int32_t field_2FC; 202 | int32_t field_300; 203 | int32_t field_304; 204 | int32_t field_308; 205 | int32_t field_30C; 206 | int32_t field_310; 207 | int32_t field_314; 208 | int32_t field_318; 209 | int32_t field_31C; 210 | int32_t field_320; 211 | int32_t field_324; 212 | int32_t field_328; 213 | int32_t field_32C; 214 | int32_t field_330; 215 | int32_t field_334; 216 | int32_t field_338; 217 | int32_t field_33C; 218 | int32_t field_340; 219 | int32_t field_344; 220 | int32_t field_348; 221 | int32_t field_34C; 222 | int32_t field_350; 223 | int32_t field_354; 224 | int32_t field_358; 225 | int32_t field_35C; 226 | int32_t field_360; 227 | int32_t field_364; 228 | int32_t field_368; 229 | int32_t field_36C; 230 | int32_t field_370; 231 | int32_t field_374; 232 | int32_t field_378; 233 | int32_t field_37C; 234 | int32_t field_380; 235 | int32_t field_384; 236 | int32_t field_388; 237 | int32_t field_38C; 238 | int32_t field_390; 239 | int32_t field_394; 240 | int32_t field_398; 241 | int32_t field_39C; 242 | int32_t field_3A0; 243 | int32_t field_3A4; 244 | int32_t field_3A8; 245 | int32_t field_3AC; 246 | int32_t field_3B0; 247 | int32_t field_3B4; 248 | int32_t field_3B8; 249 | int32_t field_3BC; 250 | int32_t field_3C0; 251 | int32_t field_3C4; 252 | int32_t field_3C8; 253 | int32_t field_3CC; 254 | int32_t field_3D0; 255 | int32_t field_3D4; 256 | int32_t field_3D8; 257 | int32_t field_3DC; 258 | int32_t field_3E0; 259 | int32_t field_3E4; 260 | int32_t field_3E8; 261 | int32_t field_3EC; 262 | int32_t field_3F0; 263 | int32_t field_3F4; 264 | int32_t field_3F8; 265 | int32_t field_3FC; 266 | int32_t field_400; 267 | int32_t field_404; 268 | int32_t field_408; 269 | int32_t field_40C; 270 | int32_t field_410; 271 | int32_t field_414; 272 | int32_t field_418; 273 | int32_t field_41C; 274 | int32_t field_420; 275 | int32_t field_424; 276 | int32_t field_428; 277 | int32_t field_42C; 278 | int32_t field_430; 279 | int32_t field_434; 280 | int32_t field_438; 281 | int32_t field_43C; 282 | int32_t field_440; 283 | int32_t field_444; 284 | int32_t field_448; 285 | int32_t field_44C; 286 | int32_t field_450; 287 | int32_t field_454; 288 | int32_t field_458; 289 | int32_t field_45C; 290 | int32_t field_460; 291 | int32_t field_464; 292 | int32_t field_468; 293 | int32_t field_46C; 294 | int32_t field_470; 295 | int32_t field_474; 296 | int32_t field_478; 297 | int32_t field_47C; 298 | int32_t field_480; 299 | int32_t field_484; 300 | int32_t field_488; 301 | int32_t field_48C; 302 | int32_t field_490; 303 | int32_t field_494; 304 | int32_t field_498; 305 | int32_t field_49C; 306 | int32_t field_4A0; 307 | int32_t field_4A4; 308 | int32_t field_4A8; 309 | int32_t field_4AC; 310 | int32_t field_4B0; 311 | int32_t field_4B4; 312 | int32_t field_4B8; 313 | int32_t field_4BC; 314 | int32_t field_4C0; 315 | int32_t field_4C4; 316 | int32_t field_4C8; 317 | int32_t field_4CC; 318 | int32_t field_4D0; 319 | int32_t field_4D4; 320 | int32_t field_4D8; 321 | int32_t field_4DC; 322 | int32_t field_4E0; 323 | int32_t field_4E4; 324 | int32_t field_4E8; 325 | int32_t field_4EC; 326 | int32_t field_4F0; 327 | int32_t field_4F4; 328 | int32_t field_4F8; 329 | int32_t field_4FC; 330 | int32_t field_500; 331 | int32_t field_504; 332 | int32_t field_508; 333 | int32_t field_50C; 334 | int32_t field_510; 335 | int32_t field_514; 336 | int32_t field_518; 337 | int32_t field_51C; 338 | int32_t field_520; 339 | int32_t field_524; 340 | int32_t field_528; 341 | int32_t field_52C; 342 | int32_t field_530; 343 | int32_t field_534; 344 | int32_t field_538; 345 | int32_t field_53C; 346 | int32_t field_540; 347 | int32_t field_544; 348 | int32_t skin_equip; 349 | int32_t skin_equip_cmn; 350 | int32_t use_pv_skin_equip; 351 | int32_t btn_se_equip; 352 | int32_t btn_se_equip_cmn; 353 | int32_t use_pv_btn_se_equip; 354 | int32_t slide_se_equip; 355 | int32_t slide_se_equip_cmn; 356 | int32_t use_pv_slide_se_equip; 357 | int32_t chainslide_se_equip; 358 | int32_t chainslide_se_equip_cmn; 359 | int32_t use_pv_chainslide_se_equip; 360 | int32_t slidertouch_se_equip; 361 | int32_t slidertouch_se_equip_cmn; 362 | int32_t use_pv_slidertouch_se_equip; 363 | int32_t field_584; 364 | int32_t field_588; 365 | int32_t field_58C; 366 | int32_t field_590; 367 | int32_t field_594; 368 | int32_t field_598; 369 | int32_t field_59C; 370 | int32_t field_5A0; 371 | int32_t field_5A4; 372 | int32_t field_5A8; 373 | int32_t field_5AC; 374 | int32_t field_5B0; 375 | int32_t field_5B4; 376 | int32_t field_5B8; 377 | int32_t field_5BC; 378 | int32_t field_5C0; 379 | int32_t field_5C4; 380 | int32_t field_5C8; 381 | int32_t field_5CC; 382 | int32_t field_5D0; 383 | int32_t field_5D4; 384 | int32_t field_5D8; 385 | int32_t field_5DC; 386 | int32_t field_5E0; 387 | int32_t field_5E4; 388 | int32_t field_5E8; 389 | int32_t field_5EC; 390 | int32_t field_5F0; 391 | int32_t field_5F4; 392 | int32_t field_5F8; 393 | int32_t field_5FC; 394 | int32_t field_600; 395 | int32_t field_604; 396 | int32_t field_608; 397 | int32_t field_60C; 398 | int32_t field_610; 399 | int32_t field_614; 400 | int32_t field_618; 401 | int32_t field_61C; 402 | int32_t field_620; 403 | int32_t field_624; 404 | int32_t field_628; 405 | int32_t field_62C; 406 | int32_t field_630; 407 | }; -------------------------------------------------------------------------------- /DivaHook/src/Components/PlayerDataManager.cpp: -------------------------------------------------------------------------------- 1 | #include "PlayerDataManager.h" 2 | #include 3 | #include "../MainModule.h" 4 | #include "../Constants.h" 5 | #include "../Input/Keyboard/Keyboard.h" 6 | #include "../FileSystem/ConfigFile.h" 7 | #include "../Constants.h" 8 | 9 | const std::string PLAYER_DATA_FILE_NAME = "playerdata.ini"; 10 | 11 | namespace DivaHook::Components 12 | { 13 | PlayerDataManager::PlayerDataManager() 14 | { 15 | } 16 | 17 | PlayerDataManager::~PlayerDataManager() 18 | { 19 | if (customPlayerData != nullptr) 20 | delete customPlayerData; 21 | } 22 | 23 | const char* PlayerDataManager::GetDisplayName() 24 | { 25 | return "player_data_manager"; 26 | } 27 | 28 | void PlayerDataManager::Initialize(ComponentsManager*) 29 | { 30 | playerData = (PlayerData*)PLAYER_DATA_ADDRESS; 31 | 32 | ApplyPatch(); 33 | LoadConfig(); 34 | ApplyCustomData(); 35 | } 36 | 37 | void PlayerDataManager::Update() 38 | { 39 | ApplyCustomData(); 40 | 41 | if (false && Input::Keyboard::GetInstance()->IsTapped(VK_F12)) 42 | { 43 | printf("PlayerDataManager::Update(): Loading config...\n"); 44 | LoadConfig(); 45 | } 46 | } 47 | 48 | void PlayerDataManager::ApplyPatch() 49 | { 50 | DWORD oldProtect; 51 | VirtualProtect((void*)SET_DEFAULT_PLAYER_DATA_ADDRESS, sizeof(uint8_t), PAGE_EXECUTE_READWRITE, &oldProtect); 52 | { 53 | // prevent the PlayerData from being reset 54 | *(uint8_t*)(SET_DEFAULT_PLAYER_DATA_ADDRESS) = RET_OPCODE; 55 | } 56 | VirtualProtect((void*)SET_DEFAULT_PLAYER_DATA_ADDRESS, sizeof(uint8_t), oldProtect, &oldProtect); 57 | } 58 | 59 | void PlayerDataManager::LoadConfig() 60 | { 61 | if (playerData == nullptr) 62 | return; 63 | 64 | FileSystem::ConfigFile config(MainModule::GetModuleDirectory(), PLAYER_DATA_FILE_NAME); 65 | 66 | if (!config.OpenRead()) 67 | return; 68 | 69 | if (customPlayerData != nullptr) 70 | delete customPlayerData; 71 | 72 | customPlayerData = new CustomPlayerData(); 73 | config.TryGetValue("player_name", &customPlayerData->PlayerName); 74 | 75 | customPlayerData->LevelPlateId = config.GetIntegerValue("level_plate_id"); 76 | customPlayerData->SkinEquip = config.GetIntegerValue("skin_equip"); 77 | customPlayerData->BtnSeEquip = config.GetIntegerValue("btn_se_equip"); 78 | customPlayerData->SlideSeEquip = config.GetIntegerValue("slide_se_equip"); 79 | customPlayerData->ChainslideSeEquip = config.GetIntegerValue("chainslide_se_equip"); 80 | } 81 | 82 | void PlayerDataManager::ApplyCustomData() 83 | { 84 | // don't want to overwrite the default values 85 | auto setIfNotEqual = [](int *target, int value, int comparison) 86 | { 87 | if (value != comparison) 88 | *target = value; 89 | }; 90 | 91 | setIfNotEqual(&playerData->level_plate_id, customPlayerData->LevelPlateId, 0); 92 | setIfNotEqual(&playerData->skin_equip, customPlayerData->SkinEquip, 0); 93 | setIfNotEqual(&playerData->btn_se_equip, customPlayerData->BtnSeEquip, -1); 94 | setIfNotEqual(&playerData->slide_se_equip, customPlayerData->SlideSeEquip, -1); 95 | setIfNotEqual(&playerData->chainslide_se_equip, customPlayerData->ChainslideSeEquip, -1); 96 | 97 | if (customPlayerData->PlayerName != nullptr) 98 | { 99 | playerData->field_DC = 0x10; 100 | playerData->player_name = (char*)customPlayerData->PlayerName->c_str(); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /DivaHook/src/Components/PlayerDataManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "EmulatorComponent.h" 3 | #include "PlayerData.h" 4 | #include "CustomPlayerData.h" 5 | #include 6 | 7 | namespace DivaHook::Components 8 | { 9 | class PlayerDataManager : public EmulatorComponent 10 | { 11 | public: 12 | PlayerDataManager(); 13 | ~PlayerDataManager(); 14 | 15 | virtual const char* GetDisplayName() override; 16 | 17 | virtual void Initialize(ComponentsManager*) override; 18 | virtual void Update() override; 19 | 20 | private: 21 | PlayerData* playerData; 22 | CustomPlayerData* customPlayerData; 23 | 24 | void ApplyPatch(); 25 | void LoadConfig(); 26 | void ApplyCustomData(); 27 | }; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /DivaHook/src/Components/StageManager.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samyuu/TotallyLegitArcadeController/327265b0e9c6c7e26d1bc5516e7293b02b7fef0e/DivaHook/src/Components/StageManager.cpp -------------------------------------------------------------------------------- /DivaHook/src/Components/StageManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "EmulatorComponent.h" 3 | #include 4 | 5 | namespace DivaHook::Components 6 | { 7 | class StageManager : public EmulatorComponent 8 | { 9 | public: 10 | StageManager(); 11 | ~StageManager(); 12 | 13 | virtual const char* GetDisplayName() override; 14 | 15 | virtual void Initialize(ComponentsManager*) override; 16 | virtual void Update() override; 17 | 18 | private: 19 | int32_t GetPlayCount(); 20 | }; 21 | } -------------------------------------------------------------------------------- /DivaHook/src/Components/SysTimer.cpp: -------------------------------------------------------------------------------- 1 | #include "SysTimer.h" 2 | #include "../Constants.h" 3 | 4 | namespace DivaHook::Components 5 | { 6 | SysTimer::SysTimer() 7 | { 8 | } 9 | 10 | SysTimer::~SysTimer() 11 | { 12 | } 13 | 14 | const char* SysTimer::GetDisplayName() 15 | { 16 | return "sys_timer"; 17 | } 18 | 19 | void SysTimer::Initialize(ComponentsManager*) 20 | { 21 | selPvTime = GetSysTimePtr((void*)SEL_PV_TIME_ADDRESS); 22 | } 23 | 24 | void SysTimer::Update() 25 | { 26 | // account for the decrement that occures during this frame 27 | *selPvTime = SEL_PV_FREEZE_TIME * SYS_TIME_FACTOR + 1; 28 | } 29 | 30 | int* SysTimer::GetSysTimePtr(void *address) 31 | { 32 | return (int*)address; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /DivaHook/src/Components/SysTimer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "EmulatorComponent.h" 3 | 4 | namespace DivaHook::Components 5 | { 6 | class SysTimer : public EmulatorComponent 7 | { 8 | const int SYS_TIME_FACTOR = 60; 9 | const int SEL_PV_FREEZE_TIME = 39; 10 | 11 | public: 12 | SysTimer(); 13 | ~SysTimer(); 14 | 15 | virtual const char* GetDisplayName() override; 16 | 17 | virtual void Initialize(ComponentsManager*) override; 18 | virtual void Update() override; 19 | 20 | private: 21 | int* selPvTime; 22 | int* GetSysTimePtr(void *address); 23 | }; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /DivaHook/src/Constants.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | constexpr uint8_t NOP_OPCODE = 0x90; 5 | constexpr uint8_t RET_OPCODE = 0xC3; 6 | constexpr uint8_t JMP_OPCODE = 0xE9; 7 | 8 | constexpr uint64_t ENGINE_UPDATE_HOOK_TARGET_ADDRESS = 0x000000014018CC40; 9 | constexpr uint64_t ENGINE_UPDATE_INPUT_ADDRESS = 0x000000014018CBB0; 10 | 11 | constexpr uint64_t CURRENT_GAME_STATE_ADDRESS = 0x0000000140EDA810; 12 | constexpr uint64_t RESOLUTION_WIDTH_ADDRESS = 0x0000000140EDA8BC; 13 | constexpr uint64_t RESOLUTION_HEIGHT_ADDRESS = 0x0000000140EDA8C0; 14 | 15 | constexpr uint64_t SYSTEM_WARNING_ELAPSED_ADDRESS = (0x00000001411A1430 + 0x68); 16 | constexpr uint64_t DATA_INIT_STATE_ADDRESS = 0x0000000140EDA7A8; 17 | 18 | constexpr uint64_t AET_FRAME_DURATION_ADDRESS = 0x00000001409A0A58; 19 | constexpr uint64_t PV_FRAME_RATE_ADDRESS = 0x0000000140EDA7CC; 20 | constexpr uint64_t FRAME_SPEED_ADDRESS = 0x0000000140EDA798; 21 | constexpr uint64_t FRAME_RATE_ADDRESS = 0x0000000140EDA6D0; 22 | 23 | constexpr uint64_t DW_GUI_DISPLAY_INSTANCE_PTR_ADDRESS = 0x0000000141190108; 24 | constexpr uint64_t INPUT_STATE_PTR_ADDRESS = 0x0000000140EDA330; 25 | constexpr uint64_t SLIDER_CTRL_TASK_ADDRESS = 0x000000014CC5DE40; 26 | constexpr uint64_t TASK_TOUCH_ADDRESS = 0x000000014CC9EC30; 27 | constexpr uint64_t SEL_PV_TIME_ADDRESS = 0x000000014CC12498; 28 | constexpr uint64_t PLAYER_DATA_ADDRESS = 0x00000001411A8850; 29 | constexpr uint64_t SET_DEFAULT_PLAYER_DATA_ADDRESS = 0x00000001404A7370; 30 | constexpr uint64_t PLAYS_PER_SESSION_GETTER_ADDRESS = 0x000000014038AEE0; 31 | constexpr uint64_t PV_SEL_SLOTS_TO_SCROLL = 0x000000014CC12470; 32 | 33 | constexpr uint64_t CAMERA_ADDRESS = 0x0000000140FBC2C0; 34 | constexpr uint64_t CAMERA_POS_SETTER_ADDRESS = 0x00000001401F9460; 35 | constexpr uint64_t CAMERA_INTR_SETTER_ADDRESS = 0x00000001401F93F0; 36 | constexpr uint64_t CAMERA_ROT_SETTER_ADDRESS = 0x00000001401F9480; 37 | constexpr uint64_t CAMERA_PERS_SETTER_ADDRESS = 0x00000001401F9430; 38 | 39 | constexpr uint64_t UPDATE_TASKS_ADDRESS = 0x000000014019B980; 40 | constexpr uint64_t GLUT_SET_CURSOR_ADDRESS = 0x00000001408B68E6; 41 | constexpr uint64_t CHANGE_MODE_ADDRESS = 0x00000001401953D0; 42 | constexpr uint64_t CHANGE_SUB_MODE_ADDRESS = 0x0000000140195260; -------------------------------------------------------------------------------- /DivaHook/src/FileSystem/ConfigFile.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ConfigFile.h" 3 | #include "../Utilities/Operations.h" 4 | 5 | namespace DivaHook::FileSystem 6 | { 7 | ConfigFile::ConfigFile(const std::string &path) : TextFile(path) 8 | { 9 | return; 10 | } 11 | 12 | ConfigFile::ConfigFile(const std::string &directory, const std::string &file) : TextFile(directory, file) 13 | { 14 | return; 15 | } 16 | 17 | bool ConfigFile::TryGetValue(const std::string &key, std::string **value) 18 | { 19 | auto pair = ConfigMap.find(key); 20 | bool found = pair != ConfigMap.end(); 21 | 22 | *value = found ? new std::string(pair->second) : nullptr; 23 | return found; 24 | } 25 | 26 | int ConfigFile::GetIntegerValue(const std::string& key) 27 | { 28 | auto pair = ConfigMap.find(key); 29 | bool found = pair != ConfigMap.end(); 30 | 31 | return found ? atoi(pair->second.c_str()) : 0; 32 | } 33 | 34 | bool ConfigFile::GetBooleanValue(const std::string& key) 35 | { 36 | auto pair = ConfigMap.find(key); 37 | bool found = pair != ConfigMap.end(); 38 | 39 | return found ? pair->second == "true" : false; 40 | } 41 | 42 | float ConfigFile::GetFloatValue(const std::string & key) 43 | { 44 | auto pair = ConfigMap.find(key); 45 | bool found = pair != ConfigMap.end(); 46 | 47 | return found ? (float)atof(pair->second.c_str()) : 0.0f; 48 | } 49 | 50 | void ConfigFile::Parse(std::ifstream &fileStream) 51 | { 52 | std::string line; 53 | 54 | while (std::getline(fileStream, line)) 55 | { 56 | if (IsComment(line)) 57 | continue; 58 | 59 | auto splitline = Utilities::Split(line, "="); 60 | 61 | for (auto &line : splitline) 62 | Utilities::Trim(line); 63 | 64 | ConfigMap.insert(std::make_pair(splitline[0], splitline[1])); 65 | } 66 | } 67 | 68 | bool ConfigFile::IsComment(const std::string &line) 69 | { 70 | return line.size() <= 0 || line[0] == '#' || line._Starts_with("//"); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /DivaHook/src/FileSystem/ConfigFile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TextFile.h" 4 | #include 5 | 6 | namespace DivaHook::FileSystem 7 | { 8 | class ConfigFile : public TextFile 9 | { 10 | public: 11 | ConfigFile(const std::string &path); 12 | ConfigFile(const std::string &directory, const std::string &file); 13 | 14 | std::unordered_map ConfigMap; 15 | 16 | bool TryGetValue(const std::string &key, std::string **value); 17 | int GetIntegerValue(const std::string& key); 18 | bool GetBooleanValue(const std::string& key); 19 | float GetFloatValue(const std::string& key); 20 | 21 | protected: 22 | virtual void Parse(std::ifstream &fileStream) override; 23 | 24 | private: 25 | bool IsComment(const std::string &line); 26 | }; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /DivaHook/src/FileSystem/TextFile.cpp: -------------------------------------------------------------------------------- 1 | #include "TextFile.h" 2 | #include 3 | 4 | namespace fs = std::filesystem; 5 | 6 | namespace DivaHook::FileSystem 7 | { 8 | TextFile::TextFile(const std::string &path) 9 | { 10 | FileName = path; 11 | } 12 | 13 | TextFile::TextFile(const std::string &directory, const std::string &file) 14 | { 15 | auto fullPath = directory + "/" + file; 16 | FileName = fullPath; 17 | } 18 | 19 | TextFile::~TextFile() 20 | { 21 | } 22 | 23 | bool TextFile::OpenRead() 24 | { 25 | fs::path configPath(FileName); 26 | 27 | if (!fs::exists(configPath)) 28 | return false; 29 | 30 | std::ifstream fileStream(configPath.string().c_str()); 31 | 32 | if (!fileStream.is_open()) 33 | return false; 34 | 35 | Parse(fileStream); 36 | 37 | fileStream.close(); 38 | 39 | return true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /DivaHook/src/FileSystem/TextFile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace DivaHook::FileSystem 7 | { 8 | class TextFile 9 | { 10 | public: 11 | std::string FileName; 12 | 13 | TextFile(const std::string &path); 14 | TextFile(const std::string &directory, const std::string &file); 15 | ~TextFile(); 16 | 17 | bool OpenRead(); 18 | 19 | protected: 20 | virtual void Parse(std::ifstream &fileStream) = 0; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Bindings/Binding.cpp: -------------------------------------------------------------------------------- 1 | #include "Binding.h" 2 | 3 | namespace DivaHook::Input 4 | { 5 | Binding::Binding() 6 | { 7 | } 8 | 9 | Binding::~Binding() 10 | { 11 | for (auto& binding : InputBindings) 12 | delete binding; 13 | } 14 | 15 | void Binding::AddBinding(IInputBinding* inputBinding) 16 | { 17 | InputBindings.push_back(inputBinding); 18 | } 19 | 20 | bool Binding::AnyDown() 21 | { 22 | for (const auto& binding : InputBindings) 23 | { 24 | if (binding->IsDown()) 25 | return true; 26 | } 27 | 28 | return false; 29 | } 30 | 31 | bool Binding::AnyTapped() 32 | { 33 | for (const auto& binding : InputBindings) 34 | { 35 | if (binding->IsTapped()) 36 | return true; 37 | } 38 | 39 | return false; 40 | } 41 | 42 | bool Binding::AnyReleased() 43 | { 44 | for (const auto& binding : InputBindings) 45 | { 46 | if (binding->IsReleased()) 47 | return true; 48 | } 49 | 50 | return false; 51 | } 52 | 53 | int Binding::GetDownCount() 54 | { 55 | int count = 0; 56 | 57 | for (const auto& binding : InputBindings) 58 | { 59 | if (binding->IsDown()) 60 | count++; 61 | } 62 | 63 | return count; 64 | } 65 | 66 | int Binding::GetTappedCount() 67 | { 68 | int count = 0; 69 | 70 | for (const auto& binding : InputBindings) 71 | { 72 | if (binding->IsTapped()) 73 | count++; 74 | } 75 | 76 | return count; 77 | } 78 | 79 | int Binding::GetReleasedCount() 80 | { 81 | int count = 0; 82 | 83 | for (const auto& binding : InputBindings) 84 | { 85 | if (binding->IsReleased()) 86 | count++; 87 | } 88 | 89 | return count; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Bindings/Binding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "IInputBinding.h" 4 | 5 | namespace DivaHook::Input 6 | { 7 | class Binding 8 | { 9 | public: 10 | std::vector InputBindings; 11 | 12 | Binding(); 13 | ~Binding(); 14 | 15 | void AddBinding(IInputBinding* inputBinding); 16 | 17 | bool AnyDown(); 18 | bool AnyTapped(); 19 | bool AnyReleased(); 20 | 21 | int GetDownCount(); 22 | int GetTappedCount(); 23 | int GetReleasedCount(); 24 | }; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Bindings/Ds4Binding.cpp: -------------------------------------------------------------------------------- 1 | #include "Ds4Binding.h" 2 | 3 | namespace DivaHook::Input 4 | { 5 | #define Ds4InstanceCheckDefault(checkFunc) (DualShock4::InstanceInitialized() ? DualShock4::GetInstance()->checkFunc : false) 6 | 7 | Ds4Binding::Ds4Binding(Ds4Button button) : Button(button) 8 | { 9 | } 10 | 11 | Ds4Binding::~Ds4Binding() 12 | { 13 | } 14 | 15 | bool Ds4Binding::IsDown() 16 | { 17 | return Ds4InstanceCheckDefault(IsDown(Button)); 18 | } 19 | 20 | bool Ds4Binding::IsTapped() 21 | { 22 | return Ds4InstanceCheckDefault(IsTapped(Button)); 23 | } 24 | 25 | bool Ds4Binding::IsReleased() 26 | { 27 | return Ds4InstanceCheckDefault(IsReleased(Button)); 28 | } 29 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/Bindings/Ds4Binding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "IInputBinding.h" 3 | #include "../DirectInput/Ds4/DualShock4.h" 4 | 5 | namespace DivaHook::Input 6 | { 7 | class Ds4Binding : public IInputBinding 8 | { 9 | public: 10 | Ds4Button Button; 11 | 12 | Ds4Binding(Ds4Button button); 13 | ~Ds4Binding(); 14 | 15 | bool IsDown() override; 16 | bool IsTapped() override; 17 | bool IsReleased() override; 18 | }; 19 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/Bindings/IInputBinding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace DivaHook::Input 4 | { 5 | class IInputBinding 6 | { 7 | public: 8 | virtual bool IsDown() = 0; 9 | virtual bool IsTapped() = 0; 10 | virtual bool IsReleased() = 0; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Bindings/KeyboardBinding.cpp: -------------------------------------------------------------------------------- 1 | #include "KeyboardBinding.h" 2 | 3 | namespace DivaHook::Input 4 | { 5 | KeyboardBinding::KeyboardBinding(BYTE keycode) : Keycode(keycode) 6 | { 7 | } 8 | 9 | KeyboardBinding::~KeyboardBinding() 10 | { 11 | } 12 | 13 | bool KeyboardBinding::IsDown() 14 | { 15 | return Keyboard::GetInstance()->IsDown(Keycode); 16 | } 17 | 18 | bool KeyboardBinding::IsTapped() 19 | { 20 | return Keyboard::GetInstance()->IsTapped(Keycode); 21 | } 22 | 23 | bool KeyboardBinding::IsReleased() 24 | { 25 | return Keyboard::GetInstance()->IsReleased(Keycode); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Bindings/KeyboardBinding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "IInputBinding.h" 3 | #include "../Keyboard/Keyboard.h" 4 | 5 | namespace DivaHook::Input 6 | { 7 | class KeyboardBinding : public IInputBinding 8 | { 9 | public: 10 | BYTE Keycode; 11 | 12 | KeyboardBinding(BYTE keycode); 13 | ~KeyboardBinding(); 14 | 15 | bool IsDown() override; 16 | bool IsTapped() override; 17 | bool IsReleased() override; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Bindings/MouseBinding.cpp: -------------------------------------------------------------------------------- 1 | #include "MouseBinding.h" 2 | #include "../Keyboard/Keyboard.h" 3 | 4 | namespace DivaHook::Input 5 | { 6 | MouseBinding::MouseBinding(MouseAction action) : Action(action) 7 | { 8 | } 9 | 10 | MouseBinding::~MouseBinding() 11 | { 12 | } 13 | 14 | bool MouseBinding::IsDown() 15 | { 16 | switch (Action) 17 | { 18 | case MouseAction_LeftButton: 19 | return Keyboard::GetInstance()->IsDown(MK_LBUTTON); 20 | case MouseAction_RightButton: 21 | return Keyboard::GetInstance()->IsDown(MK_RBUTTON); 22 | case MouseAction_MiddleButton: 23 | return Keyboard::GetInstance()->IsDown(MK_MBUTTON); 24 | case MouseAction_ScrollUp: 25 | return Mouse::GetInstance()->GetIsScrolledUp(); 26 | case MouseAction_ScrollDown: 27 | return Mouse::GetInstance()->GetIsScrolledDown(); 28 | default: 29 | return false; 30 | } 31 | } 32 | 33 | bool MouseBinding::IsTapped() 34 | { 35 | switch (Action) 36 | { 37 | case MouseAction_LeftButton: 38 | return Keyboard::GetInstance()->IsTapped(MK_LBUTTON); 39 | case MouseAction_RightButton: 40 | return Keyboard::GetInstance()->IsTapped(MK_RBUTTON); 41 | case MouseAction_MiddleButton: 42 | return Keyboard::GetInstance()->IsTapped(MK_MBUTTON); 43 | case MouseAction_ScrollUp: 44 | return Mouse::GetInstance()->GetIsScrolledUp(); 45 | case MouseAction_ScrollDown: 46 | return Mouse::GetInstance()->GetIsScrolledDown(); 47 | default: 48 | return false; 49 | } 50 | } 51 | 52 | bool MouseBinding::IsReleased() 53 | { 54 | switch (Action) 55 | { 56 | case MouseAction_LeftButton: 57 | return Keyboard::GetInstance()->IsReleased(MK_LBUTTON); 58 | case MouseAction_RightButton: 59 | return Keyboard::GetInstance()->IsReleased(MK_RBUTTON); 60 | case MouseAction_MiddleButton: 61 | return Keyboard::GetInstance()->IsReleased(MK_MBUTTON); 62 | case MouseAction_ScrollUp: 63 | return Mouse::GetInstance()->GetWasScrolledUp(); 64 | case MouseAction_ScrollDown: 65 | return Mouse::GetInstance()->GetWasScrolledDown(); 66 | default: 67 | return false; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Bindings/MouseBinding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "IInputBinding.h" 3 | #include "../Mouse/Mouse.h" 4 | 5 | namespace DivaHook::Input 6 | { 7 | enum MouseAction 8 | { 9 | MouseAction_LeftButton, 10 | MouseAction_RightButton, 11 | MouseAction_MiddleButton, 12 | MouseAction_ScrollUp, 13 | MouseAction_ScrollDown, 14 | }; 15 | 16 | class MouseBinding : public IInputBinding 17 | { 18 | public: 19 | MouseAction Action; 20 | 21 | MouseBinding(MouseAction action); 22 | ~MouseBinding(); 23 | 24 | bool IsDown() override; 25 | bool IsTapped() override; 26 | bool IsReleased() override; 27 | }; 28 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/Controller.cpp: -------------------------------------------------------------------------------- 1 | #include "Controller.h" 2 | 3 | namespace DivaHook::Input 4 | { 5 | Controller::Controller() 6 | { 7 | } 8 | 9 | Controller::~Controller() 10 | { 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/Controller.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "DirectInputDevice.h" 3 | 4 | namespace DivaHook::Input 5 | { 6 | class Controller : public DirectInputDevice 7 | { 8 | protected: 9 | Controller(); 10 | ~Controller(); 11 | }; 12 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/DirectInput.cpp: -------------------------------------------------------------------------------- 1 | #include "DirectInput.h" 2 | 3 | namespace DivaHook::Input 4 | { 5 | IDirectInput8 *IDirectInputInstance = nullptr; 6 | 7 | HRESULT InitializeDirectInput(HMODULE module) 8 | { 9 | HRESULT result = DirectInput8Create(module, DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&IDirectInputInstance, nullptr); 10 | return result; 11 | } 12 | 13 | bool DirectInputInitialized() 14 | { 15 | return IDirectInputInstance != nullptr; 16 | } 17 | 18 | void DisposeDirectInput() 19 | { 20 | if (IDirectInputInstance == nullptr) 21 | return; 22 | 23 | IDirectInputInstance->Release(); 24 | IDirectInputInstance = nullptr; 25 | } 26 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/DirectInput.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define DIRECTINPUT_VERSION 0x0800 3 | #include 4 | 5 | namespace DivaHook::Input 6 | { 7 | extern IDirectInput8 *IDirectInputInstance; 8 | 9 | HRESULT InitializeDirectInput(HMODULE module); 10 | bool DirectInputInitialized(); 11 | void DisposeDirectInput(); 12 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/DirectInputDevice.cpp: -------------------------------------------------------------------------------- 1 | #include "DirectInputDevice.h" 2 | 3 | namespace DivaHook::Input 4 | { 5 | HRESULT DirectInputDevice::DI_CreateDevice(const GUID &guid) 6 | { 7 | if (!DirectInputInitialized()) 8 | return DIERR_NOTINITIALIZED; 9 | 10 | HRESULT result = IDirectInputInstance->CreateDevice(guid, &directInputdevice, NULL); 11 | return result; 12 | } 13 | 14 | HRESULT DirectInputDevice::DI_SetDataFormat(LPCDIDATAFORMAT dataFormat) 15 | { 16 | HRESULT result = directInputdevice->SetDataFormat(dataFormat); 17 | return result; 18 | } 19 | 20 | HRESULT DirectInputDevice::DI_SetCooperativeLevel(HWND windowHandle, DWORD flags) 21 | { 22 | HRESULT result = directInputdevice->SetCooperativeLevel(windowHandle, flags); 23 | return result; 24 | } 25 | 26 | HRESULT DirectInputDevice::DI_Acquire() 27 | { 28 | HRESULT result = directInputdevice->Acquire(); 29 | return result; 30 | } 31 | 32 | HRESULT DirectInputDevice::DI_Unacquire() 33 | { 34 | HRESULT result = directInputdevice->Unacquire(); 35 | return result; 36 | } 37 | 38 | HRESULT DirectInputDevice::DI_Release() 39 | { 40 | HRESULT result = directInputdevice->Release(); 41 | return result; 42 | } 43 | 44 | HRESULT DirectInputDevice::DI_Poll() 45 | { 46 | HRESULT result = directInputdevice->Poll(); 47 | return result; 48 | } 49 | 50 | HRESULT DirectInputDevice::DI_GetDeviceState(DWORD size, LPVOID data) 51 | { 52 | HRESULT result = directInputdevice->GetDeviceState(size, data); 53 | return result; 54 | } 55 | 56 | void DirectInputDevice::DI_Dispose() 57 | { 58 | if (directInputdevice == nullptr) 59 | return; 60 | 61 | HRESULT result = NULL; 62 | 63 | result = DI_Unacquire(); 64 | result = DI_Release(); 65 | } 66 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/DirectInputDevice.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "DirectInput.h" 3 | 4 | namespace DivaHook::Input 5 | { 6 | class DirectInputDevice 7 | { 8 | protected: 9 | IDirectInputDevice8 *directInputdevice; 10 | 11 | HRESULT DI_CreateDevice(const GUID& guid); 12 | HRESULT DI_SetDataFormat(LPCDIDATAFORMAT dataFormat); 13 | HRESULT DI_SetCooperativeLevel(HWND windowHandle, DWORD flags); 14 | HRESULT DI_Acquire(); 15 | HRESULT DI_Unacquire(); 16 | HRESULT DI_Release(); 17 | HRESULT DI_Poll(); 18 | HRESULT DI_GetDeviceState(DWORD size, LPVOID data); 19 | 20 | void DI_Dispose(); 21 | }; 22 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/DirectInputMouse.cpp: -------------------------------------------------------------------------------- 1 | #include "DirectInputMouse.h" 2 | 3 | namespace DivaHook::Input 4 | { 5 | DirectInputMouse::DirectInputMouse() 6 | { 7 | HRESULT result = NULL; 8 | 9 | result = DI_CreateDevice(GUID_SysMouse); 10 | 11 | if (FAILED(result)) 12 | return; 13 | 14 | result = DI_SetDataFormat(&c_dfDIMouse); 15 | result = DI_Acquire(); 16 | } 17 | 18 | DirectInputMouse::~DirectInputMouse() 19 | { 20 | DI_Dispose(); 21 | } 22 | 23 | bool DirectInputMouse::Poll() 24 | { 25 | if (!DirectInputInitialized()) 26 | return FALSE; 27 | 28 | HRESULT result = NULL; 29 | 30 | result = DI_Poll(); 31 | result = DI_GetDeviceState(sizeof(mouseState), &mouseState); 32 | 33 | return !FAILED(result); 34 | } 35 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/DirectInputMouse.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "DirectInputDevice.h" 3 | 4 | namespace DivaHook::Input 5 | { 6 | class DirectInputMouse : public DirectInputDevice 7 | { 8 | public: 9 | DirectInputMouse(); 10 | ~DirectInputMouse(); 11 | 12 | bool Poll(); 13 | 14 | inline long GetXPosition() { return mouseState.lX; }; 15 | inline long GetYPosition() { return mouseState.lY; }; 16 | inline long GetMouseWheel() { return mouseState.lZ; }; 17 | 18 | private: 19 | DIMOUSESTATE mouseState; 20 | }; 21 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/Ds4/Ds4Button.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace DivaHook::Input 4 | { 5 | enum Direction 6 | { 7 | DIR_UP, 8 | DIR_RIGHT, 9 | DIR_DOWN, 10 | DIR_LEFT 11 | }; 12 | 13 | enum Ds4Button : int 14 | { 15 | DS4_SQUARE = 0, 16 | DS4_CROSS = 1, 17 | DS4_CIRCLE = 2, 18 | DS4_TRIANGLE = 3, 19 | 20 | DS4_L1 = 4, 21 | DS4_R1 = 5, 22 | 23 | DS4_L_TRIGGER = 6, 24 | DS4_R_TRIGGER = 7, 25 | 26 | DS4_SHARE = 8, 27 | DS4_OPTIONS = 9, 28 | 29 | DS4_L3 = 10, 30 | DS4_R3 = 11, 31 | 32 | DS4_PS = 12, 33 | DS4_TOUCH = 13, 34 | 35 | DS4_DPAD_UP, 36 | DS4_DPAD_RIGHT, 37 | DS4_DPAD_DOWN, 38 | DS4_DPAD_LEFT, 39 | 40 | DS4_L_STICK_UP, 41 | DS4_L_STICK_RIGHT, 42 | DS4_L_STICK_DOWN, 43 | DS4_L_STICK_LEFT, 44 | 45 | DS4_R_STICK_UP, 46 | DS4_R_STICK_RIGHT, 47 | DS4_R_STICK_DOWN, 48 | DS4_R_STICK_LEFT, 49 | 50 | DS4_BUTTON_MAX, 51 | }; 52 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/Ds4/Ds4State.cpp: -------------------------------------------------------------------------------- 1 | #include "Ds4State.h" 2 | 3 | namespace DivaHook::Input 4 | { 5 | Joystick::Joystick() : XAxis(0.0f), YAxis(0.0f) 6 | { 7 | return; 8 | }; 9 | 10 | Joystick::Joystick(float xAxis, float yAxis) : XAxis(xAxis), YAxis(yAxis) 11 | { 12 | return; 13 | }; 14 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/Ds4/Ds4State.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../DirectInput.h" 3 | #include "Ds4Button.h" 4 | 5 | namespace DivaHook::Input 6 | { 7 | struct Joystick 8 | { 9 | FLOAT XAxis, YAxis; 10 | 11 | Joystick(); 12 | Joystick(float xAxis, float yAxis); 13 | }; 14 | 15 | struct Dpad 16 | { 17 | BOOL IsDown; 18 | FLOAT Angle; 19 | Joystick Stick; 20 | }; 21 | 22 | struct Trigger 23 | { 24 | FLOAT Axis; 25 | }; 26 | 27 | struct Ds4State 28 | { 29 | DIJOYSTATE2 DI_JoyState; 30 | 31 | BYTE Buttons[DS4_BUTTON_MAX]; 32 | 33 | Dpad Dpad; 34 | Joystick LeftStick; 35 | Joystick RightStick; 36 | Trigger LeftTrigger; 37 | Trigger RightTrigger; 38 | }; 39 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/Ds4/DualShock4.cpp: -------------------------------------------------------------------------------- 1 | #include "DualShock4.h" 2 | #include "../../../Utilities/Math.h" 3 | #include "../../../MainModule.h" 4 | #include 5 | 6 | namespace DivaHook::Input 7 | { 8 | DualShock4* DualShock4::instance; 9 | 10 | DualShock4::DualShock4() 11 | { 12 | } 13 | 14 | DualShock4::~DualShock4() 15 | { 16 | DI_Dispose(); 17 | } 18 | 19 | bool DualShock4::TryInitializeInstance() 20 | { 21 | if (InstanceInitialized()) 22 | return true; 23 | 24 | if (!DirectInputInitialized()) 25 | return false; 26 | 27 | DualShock4 *dualShock4 = new DualShock4(); 28 | 29 | bool success = dualShock4->Initialize(); 30 | instance = success ? dualShock4 : nullptr; 31 | 32 | if (!success) 33 | delete dualShock4; 34 | 35 | return success; 36 | } 37 | 38 | bool DualShock4::Initialize() 39 | { 40 | HRESULT result = NULL; 41 | 42 | const size_t guidCount = sizeof(GUID_Ds4) / sizeof(GUID); 43 | for (size_t i = 0; i < guidCount; i++) 44 | { 45 | result = DI_CreateDevice(GUID_Ds4[i]); 46 | 47 | if (!FAILED(result)) 48 | break; 49 | else if (i == guidCount - 1) 50 | return false; 51 | } 52 | 53 | if (FAILED(result = DI_SetDataFormat(&c_dfDIJoystick2))) 54 | return false; 55 | 56 | result = DI_Acquire(); 57 | 58 | return true; 59 | } 60 | 61 | bool DualShock4::PollInput() 62 | { 63 | lastState = currentState; 64 | 65 | HRESULT result = NULL; 66 | result = DI_Poll(); 67 | result = DI_GetDeviceState(sizeof(DIJOYSTATE2), ¤tState.DI_JoyState); 68 | 69 | if (result != DI_OK) 70 | return false; 71 | 72 | UpdateInternalDs4State(currentState); 73 | 74 | for (int button = 0; button < DS4_BUTTON_MAX; button++) 75 | currentState.Buttons[button] = GetButtonState(currentState, (Ds4Button)button); 76 | 77 | return true; 78 | } 79 | 80 | void DualShock4::UpdateInternalDs4State(Ds4State &state) 81 | { 82 | if (state.Dpad.IsDown = state.DI_JoyState.rgdwPOV[0] != -1) 83 | { 84 | state.Dpad.Angle = (state.DI_JoyState.rgdwPOV[0] / 100.0f); 85 | 86 | auto direction = Utilities::GetDirection(state.Dpad.Angle); 87 | state.Dpad.Stick = { direction.Y, -direction.X }; 88 | } 89 | else 90 | { 91 | state.Dpad.Angle = 0; 92 | state.Dpad.Stick = Joystick(); 93 | } 94 | 95 | state.LeftStick = NormalizeStick(state.DI_JoyState.lX, state.DI_JoyState.lY); 96 | state.RightStick = NormalizeStick(state.DI_JoyState.lZ, state.DI_JoyState.lRz); 97 | 98 | state.LeftTrigger = { NormalizeTrigger(state.DI_JoyState.lRx) }; 99 | state.RightTrigger = { NormalizeTrigger(state.DI_JoyState.lRy) }; 100 | } 101 | 102 | bool DualShock4::IsDown(Ds4Button button) 103 | { 104 | return currentState.Buttons[button]; 105 | } 106 | 107 | bool DualShock4::IsUp(Ds4Button button) 108 | { 109 | return !IsDown(button); 110 | } 111 | 112 | bool DualShock4::IsTapped(Ds4Button button) 113 | { 114 | return IsDown(button) && WasUp(button); 115 | } 116 | 117 | bool DualShock4::IsReleased(Ds4Button button) 118 | { 119 | return IsUp(button) && WasDown(button); 120 | } 121 | 122 | bool DualShock4::WasDown(Ds4Button button) 123 | { 124 | return lastState.Buttons[button]; 125 | } 126 | 127 | bool DualShock4::WasUp(Ds4Button button) 128 | { 129 | return !WasDown(button); 130 | } 131 | 132 | bool DualShock4::MatchesDirection(Joystick joystick, Direction directionEnum, float threshold) 133 | { 134 | switch (directionEnum) 135 | { 136 | case DivaHook::Input::DIR_UP: 137 | return joystick.YAxis <= -threshold; 138 | 139 | case DivaHook::Input::DIR_RIGHT: 140 | return joystick.XAxis >= +threshold; 141 | 142 | case DivaHook::Input::DIR_DOWN: 143 | return joystick.YAxis >= +threshold; 144 | 145 | case DivaHook::Input::DIR_LEFT: 146 | return joystick.XAxis <= -threshold; 147 | 148 | default: 149 | return false; 150 | } 151 | } 152 | 153 | bool DualShock4::GetButtonState(Ds4State &state, Ds4Button button) 154 | { 155 | if (button >= DS4_SQUARE && button <= DS4_TOUCH) 156 | return state.DI_JoyState.rgbButtons[button]; 157 | 158 | if (button >= DS4_DPAD_UP && button <= DS4_DPAD_LEFT) 159 | return state.Dpad.IsDown ? MatchesDirection(state.Dpad.Stick, (Direction)(button - DS4_DPAD_UP), dpadThreshold) : false; 160 | 161 | if (button >= DS4_L_STICK_UP && button <= DS4_L_STICK_LEFT) 162 | return MatchesDirection(state.LeftStick, (Direction)(button - DS4_L_STICK_UP), joystickThreshold); 163 | 164 | if (button >= DS4_R_STICK_UP && button <= DS4_R_STICK_LEFT) 165 | return MatchesDirection(state.RightStick, (Direction)(button - DS4_R_STICK_UP), joystickThreshold); 166 | 167 | return false; 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /DivaHook/src/Input/DirectInput/Ds4/DualShock4.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Controller.h" 3 | #include "../../IInputDevice.h" 4 | #include "Ds4State.h" 5 | 6 | namespace DivaHook::Input 7 | { 8 | // DualShock 4 Wireless Controller Product GUIDs: 9 | const GUID GUID_Ds4[2] = 10 | { 11 | // First Generation: {05C4054C-0000-0000-0000-504944564944} 12 | { 0x05C4054C, 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } }, 13 | // Second Generation: {09CC054C-0000-0000-0000-504944564944} 14 | { 0x09CC054C, 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } }, 15 | }; 16 | 17 | class DualShock4 : public Controller, public IInputDevice 18 | { 19 | public: 20 | DualShock4(); 21 | ~DualShock4(); 22 | 23 | static bool TryInitializeInstance(); 24 | 25 | bool Initialize(); 26 | bool PollInput() override; 27 | 28 | bool IsDown(Ds4Button button); 29 | bool IsUp(Ds4Button button); 30 | bool IsTapped(Ds4Button button); 31 | bool IsReleased(Ds4Button button); 32 | bool WasDown(Ds4Button button); 33 | bool WasUp(Ds4Button button); 34 | 35 | inline Joystick GetLeftStick() { return currentState.LeftStick; }; 36 | inline Joystick GetRightStick() { return currentState.RightStick; }; 37 | inline Joystick GetDpad() { return currentState.Dpad.Stick; }; 38 | 39 | static inline bool InstanceInitialized() { return instance != nullptr; }; 40 | static inline DualShock4* GetInstance() { return instance; }; 41 | static inline void DeleteInstance() { delete instance; instance = nullptr; }; 42 | 43 | private: 44 | static DualShock4* instance; 45 | 46 | Ds4State lastState; 47 | Ds4State currentState; 48 | 49 | const float triggerThreshold = 0.5f; 50 | const float joystickThreshold = 0.5f; 51 | const float dpadThreshold = 0.5f; 52 | 53 | inline float NormalizeTrigger(long value) { return (float)value / USHRT_MAX; }; 54 | inline float NormalizeStick(long value) { return (float)value / USHRT_MAX * 2.0f - 1.0f; }; 55 | inline Joystick NormalizeStick(long x, long y) { return Joystick(NormalizeStick(x), NormalizeStick(y)); }; 56 | 57 | void UpdateInternalDs4State(Ds4State &state); 58 | 59 | bool MatchesDirection(Joystick joystick, Direction directionEnum, float threshold); 60 | bool GetButtonState(Ds4State &state, Ds4Button button); 61 | }; 62 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/IInputDevice.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace DivaHook::Input 4 | { 5 | class IInputDevice 6 | { 7 | public: 8 | virtual bool PollInput() = 0; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /DivaHook/src/Input/KeyConfig/Config.cpp: -------------------------------------------------------------------------------- 1 | #include "Config.h" 2 | #include "windows.h" 3 | #include "../Bindings/KeyboardBinding.h" 4 | #include "../Bindings/Ds4Binding.h" 5 | #include "../../Utilities/Operations.h" 6 | 7 | namespace DivaHook::Input::KeyConfig 8 | { 9 | KeycodeMap Config::Keymap = 10 | { 11 | // NumPad Keys 12 | { "NumPad0", VK_NUMPAD0 }, 13 | { "NumPad1", VK_NUMPAD1 }, 14 | { "NumPad2", VK_NUMPAD2 }, 15 | { "NumPad3", VK_NUMPAD3 }, 16 | { "NumPad4", VK_NUMPAD4 }, 17 | { "NumPad5", VK_NUMPAD5 }, 18 | { "NumPad6", VK_NUMPAD6 }, 19 | { "NumPad7", VK_NUMPAD7 }, 20 | { "NumPad8", VK_NUMPAD8 }, 21 | { "NumPad9", VK_NUMPAD9 }, 22 | { "Plus", VK_ADD }, 23 | { "Minus", VK_SUBTRACT }, 24 | { "Divide", VK_DIVIDE }, 25 | { "Multiply", VK_MULTIPLY }, 26 | // F-Keys 27 | { "F1", VK_F1 }, 28 | { "F2", VK_F2 }, 29 | { "F3", VK_F3 }, 30 | { "F4", VK_F4 }, 31 | { "F5", VK_F5 }, 32 | { "F6", VK_F6 }, 33 | { "F7", VK_F7 }, 34 | { "F8", VK_F8 }, 35 | { "F9", VK_F9 }, 36 | { "F10", VK_F10 }, 37 | { "F11", VK_F11 }, 38 | { "F12", VK_F12 }, 39 | { "F13", VK_F13 }, 40 | { "F14", VK_F14 }, 41 | { "F15", VK_F15 }, 42 | { "F16", VK_F16 }, 43 | { "F17", VK_F17 }, 44 | { "F18", VK_F18 }, 45 | { "F19", VK_F19 }, 46 | { "F20", VK_F20 }, 47 | { "F21", VK_F21 }, 48 | { "F22", VK_F22 }, 49 | { "F23", VK_F23 }, 50 | { "F24", VK_F24 }, 51 | // Shift Keys 52 | { "LeftShift", VK_LSHIFT }, 53 | { "LShift", VK_LSHIFT }, 54 | { "RightShift", VK_RSHIFT }, 55 | { "RShift", VK_RSHIFT }, 56 | // Control Keys 57 | { "LeftControl", VK_LCONTROL }, 58 | { "LControl", VK_LCONTROL }, 59 | { "LCtrl", VK_LCONTROL }, 60 | { "RightControl", VK_RCONTROL }, 61 | { "RControl", VK_RCONTROL }, 62 | { "RCtrl", VK_RCONTROL }, 63 | // Arrow Keys 64 | { "Up", VK_UP }, 65 | { "Down", VK_DOWN }, 66 | { "Left", VK_LEFT }, 67 | { "Right", VK_RIGHT }, 68 | // Special Keys 69 | { "Enter", VK_RETURN }, 70 | { "Return", VK_RETURN }, 71 | { "Tab", VK_TAB }, 72 | { "Back", VK_BACK }, 73 | { "Backspace", VK_BACK }, 74 | { "Insert", VK_INSERT }, 75 | { "Ins", VK_INSERT }, 76 | { "Delete", VK_DELETE }, 77 | { "Del", VK_DELETE }, 78 | { "Home", VK_HOME }, 79 | { "End", VK_END }, 80 | { "PageUp", VK_PRIOR }, 81 | { "PageDown", VK_NEXT }, 82 | { "ESC", VK_ESCAPE }, 83 | { "Escape", VK_ESCAPE }, 84 | { "Comma", VK_OEM_COMMA }, 85 | { "Period", VK_OEM_PERIOD }, 86 | { "Slash", VK_OEM_2 }, 87 | }; 88 | 89 | Ds4ButtonMap Config::Ds4Map = 90 | { 91 | // Face Buttons 92 | { "DS4_SQUARE", DS4_SQUARE }, 93 | { "Ds4_Square", DS4_SQUARE }, 94 | 95 | { "DS4_CROSS", DS4_CROSS }, 96 | { "Ds4_Cross", DS4_CROSS }, 97 | 98 | { "DS4_CIRCLE", DS4_CIRCLE }, 99 | { "Ds4_Circle", DS4_CIRCLE }, 100 | 101 | { "DS4_TRIANGLE", DS4_TRIANGLE }, 102 | { "Ds4_Triangle", DS4_TRIANGLE }, 103 | 104 | // Standard Buttons 105 | { "DS4_SHARE", DS4_SHARE }, 106 | { "Ds4_Share", DS4_SHARE }, 107 | 108 | { "DS4_OPTIONS", DS4_OPTIONS }, 109 | { "Ds4_Options", DS4_OPTIONS }, 110 | 111 | { "DS4_PS", DS4_PS }, 112 | { "Ds4_PS", DS4_PS }, 113 | 114 | { "DS4_TOUCH", DS4_TOUCH }, 115 | { "Ds4_Touch", DS4_TOUCH }, 116 | 117 | { "DS4_L1", DS4_L1 }, 118 | { "Ds4_L1", DS4_L1 }, 119 | 120 | { "DS4_R1", DS4_R1 }, 121 | { "Ds4_R1", DS4_R1 }, 122 | 123 | // D-Pad Directions 124 | { "DS4_DPAD_UP", DS4_DPAD_UP }, 125 | { "Ds4_DPad_Up", DS4_DPAD_UP }, 126 | 127 | { "DS4_DPAD_RIGHT", DS4_DPAD_RIGHT }, 128 | { "Ds4_DPad_Right", DS4_DPAD_RIGHT }, 129 | 130 | { "DS4_DPAD_DOWN", DS4_DPAD_DOWN }, 131 | { "Ds4_DPad_Down", DS4_DPAD_DOWN }, 132 | 133 | { "DS4_DPAD_LEFT", DS4_DPAD_LEFT }, 134 | { "Ds4_DPad_Left", DS4_DPAD_LEFT }, 135 | 136 | // Trigger Buttons 137 | { "DS4_L_TRIGGER", DS4_L_TRIGGER }, 138 | { "Ds4_L_Trigger", DS4_L_TRIGGER }, 139 | 140 | { "DS4_R_TRIGGER", DS4_R_TRIGGER }, 141 | { "Ds4_R_Trigger", DS4_R_TRIGGER }, 142 | 143 | // Joystick Buttons 144 | { "DS4_L3", DS4_L3 }, 145 | { "Ds4_L3", DS4_L3 }, 146 | 147 | { "DS4_R3", DS4_R3 }, 148 | { "Ds4_R3", DS4_R3 }, 149 | 150 | // Left Joystick 151 | { "DS4_L_STICK_UP", DS4_L_STICK_UP }, 152 | { "Ds4_L_Stick_Up", DS4_L_STICK_UP }, 153 | 154 | { "DS4_L_STICK_RIGHT", DS4_L_STICK_RIGHT }, 155 | { "Ds4_L_Stick_Right", DS4_L_STICK_RIGHT }, 156 | 157 | { "DS4_L_STICK_DOWN", DS4_L_STICK_DOWN }, 158 | { "Ds4_L_Stick_Down", DS4_L_STICK_DOWN }, 159 | 160 | { "DS4_L_STICK_LEFT", DS4_L_STICK_LEFT }, 161 | { "Ds4_L_Stick_Left", DS4_L_STICK_LEFT }, 162 | 163 | // Right Joystick 164 | { "DS4_R_STICK_UP", DS4_R_STICK_UP }, 165 | { "Ds4_R_Stick_Up", DS4_R_STICK_UP }, 166 | 167 | { "DS4_R_STICK_RIGHT", DS4_R_STICK_RIGHT }, 168 | { "Ds4_R_Stick_Right", DS4_R_STICK_RIGHT }, 169 | 170 | { "DS4_R_STICK_DOWN", DS4_R_STICK_DOWN }, 171 | { "Ds4_R_Stick_Down", DS4_R_STICK_DOWN }, 172 | 173 | { "DS4_R_STICK_LEFT", DS4_R_STICK_LEFT }, 174 | { "Ds4_R_Stick_Left", DS4_R_STICK_LEFT }, 175 | }; 176 | 177 | void Config::BindConfigKeys(std::unordered_map &configMap, const char *configKeyName, Binding &bindObj, std::vector defaultKeys) 178 | { 179 | std::vector keys; 180 | 181 | auto configPair = configMap.find(configKeyName); 182 | 183 | // config variable was found in the ini 184 | if (configPair != configMap.end()) 185 | { 186 | keys = Utilities::Split(configPair->second, ","); 187 | } 188 | else 189 | { 190 | keys = defaultKeys; 191 | } 192 | 193 | for (std::string key : keys) 194 | { 195 | Utilities::Trim(key); 196 | 197 | // Applies only for Single-Character keys 198 | if (key.length() == 1) 199 | { 200 | bindObj.AddBinding(new KeyboardBinding(key[0])); 201 | } 202 | else // for special key names 203 | { 204 | auto keycode = Config::Keymap.find(key.c_str()); 205 | 206 | // name is known in the special keys map 207 | if (keycode != Config::Keymap.end()) 208 | { 209 | bindObj.AddBinding(new KeyboardBinding(keycode->second)); 210 | } 211 | else 212 | { 213 | // just gonna be lazy for now and put this inside an else statement 214 | auto ds4Button = Config::Ds4Map.find(key.c_str()); 215 | 216 | if (ds4Button != Config::Ds4Map.end()) 217 | { 218 | bindObj.AddBinding(new Ds4Binding(ds4Button->second)); 219 | } 220 | else 221 | { 222 | printf("Config::BindConfigKeys(): Unable to parse key: '%s'\n", key.c_str()); 223 | } 224 | } 225 | } 226 | } 227 | } 228 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/KeyConfig/Config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "KeyString.h" 5 | #include "KeyStringHash.h" 6 | #include "../Bindings/Binding.h" 7 | #include "../DirectInput/Ds4/Ds4Button.h" 8 | 9 | namespace DivaHook::Input::KeyConfig 10 | { 11 | typedef std::unordered_map KeycodeMap; 12 | typedef std::unordered_map Ds4ButtonMap; 13 | 14 | class Config 15 | { 16 | public: 17 | static KeycodeMap Keymap; 18 | static Ds4ButtonMap Ds4Map; 19 | 20 | static void BindConfigKeys(std::unordered_map &configMap, const char *configKeyName, Binding &bindObj, std::vector defaultKeys); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /DivaHook/src/Input/KeyConfig/KeyString.cpp: -------------------------------------------------------------------------------- 1 | #include "KeyString.h" 2 | 3 | namespace DivaHook::Input::KeyConfig 4 | { 5 | KeyString::KeyString(const char* str) : value(str) 6 | { 7 | } 8 | 9 | bool KeyString::operator==(const KeyString& rsv) const 10 | { 11 | return !_strcmpi(value.c_str(), rsv.value.c_str()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DivaHook/src/Input/KeyConfig/KeyString.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace DivaHook::Input::KeyConfig 5 | { 6 | struct KeyString 7 | { 8 | std::string value; 9 | 10 | KeyString(const char* str); 11 | bool operator==(const KeyString& rsv) const; 12 | }; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /DivaHook/src/Input/KeyConfig/KeyStringHash.cpp: -------------------------------------------------------------------------------- 1 | #include "KeyStringHash.h" 2 | #include 3 | 4 | namespace DivaHook::Input::KeyConfig 5 | { 6 | size_t KeyStringHash::operator()(const KeyString& key) const 7 | { 8 | std::string ret = key.value; 9 | std::transform(ret.begin(), ret.end(), ret.begin(), 10 | [](unsigned char c) { return std::tolower(c, std::locale()); }); 11 | return std::hash()(ret); 12 | } 13 | } -------------------------------------------------------------------------------- /DivaHook/src/Input/KeyConfig/KeyStringHash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "KeyString.h" 3 | 4 | namespace DivaHook::Input::KeyConfig 5 | { 6 | struct KeyStringHash 7 | { 8 | size_t operator()(const KeyString& key) const; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Keyboard/Keyboard.cpp: -------------------------------------------------------------------------------- 1 | #include "Keyboard.h" 2 | 3 | namespace DivaHook::Input 4 | { 5 | Keyboard* Keyboard::instance; 6 | 7 | Keyboard::Keyboard() 8 | { 9 | } 10 | 11 | Keyboard* Keyboard::GetInstance() 12 | { 13 | if (instance == nullptr) 14 | instance = new Keyboard(); 15 | 16 | return instance; 17 | } 18 | 19 | bool Keyboard::PollInput() 20 | { 21 | lastState = currentState; 22 | 23 | float elapsed = keyIntervalWatch.Restart(); 24 | 25 | for (BYTE i = 0; i < KEYBOARD_KEYS; i++) 26 | { 27 | // DOWN 28 | bool isDown = GetAsyncKeyState(i) < 0; 29 | currentState.KeyStates[i] = isDown; 30 | 31 | // DOUBLE TAPPED 32 | bool isTapped = IsTapped(i); 33 | keyDoubleTapStates[i] = isTapped ? keyDoubleTapWatches[i].Restart() <= DOUBLE_TAP_THRESHOLD : false; 34 | 35 | // INTERVAL TAPPED 36 | keyIntervalTapStates[i] = isTapped; 37 | 38 | if (isTapped) 39 | { 40 | keyIntervalTapTimes[i] = 0; 41 | keyIntervalInitials[i] = true; 42 | } 43 | else if (isDown) 44 | { 45 | float threshold = keyIntervalInitials[i] ? INTERVAL_TAP_DELAY_THRESHOLD : INTERVAL_TAP_THRESHOLD; 46 | 47 | bool intervalTapped = (keyIntervalTapTimes[i] += elapsed) > threshold; 48 | keyIntervalTapStates[i] = intervalTapped; 49 | 50 | if (intervalTapped) 51 | { 52 | keyIntervalTapTimes[i] = 0; 53 | keyIntervalInitials[i] = false; 54 | } 55 | } 56 | } 57 | 58 | return true; 59 | } 60 | 61 | bool Keyboard::IsDown(BYTE keycode) 62 | { 63 | return currentState.IsDown(keycode); 64 | } 65 | 66 | bool Keyboard::IsUp(BYTE keycode) 67 | { 68 | return !IsDown(keycode); 69 | } 70 | 71 | bool Keyboard::IsTapped(BYTE keycode) 72 | { 73 | return IsDown(keycode) && WasUp(keycode); 74 | } 75 | 76 | bool Keyboard::IsDoubleTapped(BYTE keycode) 77 | { 78 | return keyDoubleTapStates[keycode]; 79 | } 80 | 81 | bool Keyboard::IsReleased(BYTE keycode) 82 | { 83 | return IsUp(keycode) && WasDown(keycode); 84 | } 85 | 86 | inline bool Keyboard::WasDown(BYTE keycode) 87 | { 88 | return lastState.IsDown(keycode); 89 | } 90 | 91 | inline bool Keyboard::WasUp(BYTE keycode) 92 | { 93 | return !WasDown(keycode); 94 | } 95 | 96 | bool Keyboard::IsIntervalTapped(BYTE keycode) 97 | { 98 | return keyIntervalTapStates[keycode]; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Keyboard/Keyboard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../IInputDevice.h" 3 | #include "KeyboardState.h" 4 | #include "../../Utilities/Stopwatch.h" 5 | 6 | using Stopwatch = DivaHook::Utilities::Stopwatch; 7 | 8 | namespace DivaHook::Input 9 | { 10 | constexpr float DOUBLE_TAP_THRESHOLD = 200.0f; 11 | constexpr float INTERVAL_TAP_DELAY_THRESHOLD = 500.0f; 12 | constexpr float INTERVAL_TAP_THRESHOLD = 75.0f; 13 | 14 | class Keyboard : public IInputDevice 15 | { 16 | public: 17 | static Keyboard* GetInstance(); 18 | 19 | bool PollInput() override; 20 | bool IsDown(BYTE keycode); 21 | bool IsUp(BYTE keycode); 22 | bool IsTapped(BYTE keycode); 23 | bool IsDoubleTapped(BYTE keycode); 24 | bool IsReleased(BYTE keycode); 25 | bool IsIntervalTapped(BYTE keycode); 26 | 27 | bool WasDown(BYTE keycode); 28 | bool WasUp(BYTE keycode); 29 | 30 | private: 31 | Keyboard(); 32 | KeyboardState lastState; 33 | KeyboardState currentState; 34 | 35 | Stopwatch keyIntervalWatch; 36 | 37 | BYTE keyDoubleTapStates[KEYBOARD_KEYS]; 38 | Stopwatch keyDoubleTapWatches[KEYBOARD_KEYS]; 39 | 40 | BOOL keyIntervalInitials[KEYBOARD_KEYS]; 41 | BYTE keyIntervalTapStates[KEYBOARD_KEYS]; 42 | FLOAT keyIntervalTapTimes[KEYBOARD_KEYS]; 43 | 44 | static Keyboard* instance; 45 | }; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Keyboard/KeyboardState.cpp: -------------------------------------------------------------------------------- 1 | #include "KeyboardState.h" 2 | 3 | namespace DivaHook::Input 4 | { 5 | bool KeyboardState::IsDown(BYTE keycode) 6 | { 7 | return KeyStates[keycode]; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Keyboard/KeyboardState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace DivaHook::Input 5 | { 6 | const int KEYBOARD_KEYS = 0xFF; 7 | 8 | struct KeyboardState 9 | { 10 | BYTE KeyStates[KEYBOARD_KEYS]; 11 | 12 | bool IsDown(BYTE keycode); 13 | }; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Mouse/Mouse.cpp: -------------------------------------------------------------------------------- 1 | #include "Mouse.h" 2 | #include "../../MainModule.h" 3 | 4 | namespace DivaHook::Input 5 | { 6 | Mouse* Mouse::instance; 7 | 8 | Mouse::Mouse() 9 | { 10 | directInputMouse = new DirectInputMouse(); 11 | } 12 | 13 | Mouse::~Mouse() 14 | { 15 | if (directInputMouse != nullptr) 16 | delete directInputMouse; 17 | } 18 | 19 | Mouse* Mouse::GetInstance() 20 | { 21 | if (instance == nullptr) 22 | instance = new Mouse(); 23 | 24 | return instance; 25 | } 26 | 27 | POINT Mouse::GetPosition() 28 | { 29 | return currentState.Position; 30 | } 31 | 32 | POINT Mouse::GetRelativePosition() 33 | { 34 | return currentState.RelativePosition; 35 | } 36 | 37 | POINT Mouse::GetDeltaPosition() 38 | { 39 | return 40 | { 41 | currentState.Position.x - lastState.Position.x, 42 | currentState.Position.y - lastState.Position.y 43 | }; 44 | } 45 | 46 | long Mouse::GetMouseWheel() 47 | { 48 | return currentState.MouseWheel; 49 | } 50 | 51 | long Mouse::GetDeltaMouseWheel() 52 | { 53 | return currentState.MouseWheel - lastState.MouseWheel; 54 | } 55 | 56 | bool Mouse::HasMoved() 57 | { 58 | POINT delta = GetDeltaPosition(); 59 | return delta.x != 0 || delta.y != 0; 60 | } 61 | 62 | bool Mouse::GetIsScrolledUp() 63 | { 64 | return currentState.ScrolledUp; 65 | } 66 | 67 | bool Mouse::GetIsScrolledDown() 68 | { 69 | return currentState.ScrolledDown; 70 | } 71 | 72 | bool Mouse::GetWasScrolledUp() 73 | { 74 | return lastState.ScrolledUp; 75 | } 76 | 77 | bool Mouse::GetWasScrolledDown() 78 | { 79 | return lastState.ScrolledDown; 80 | } 81 | 82 | void Mouse::SetPosition(int x, int y) 83 | { 84 | lastState.Position.x = x; 85 | lastState.Position.y = y; 86 | SetCursorPos(x, y); 87 | } 88 | 89 | bool Mouse::PollInput() 90 | { 91 | lastState = currentState; 92 | 93 | GetCursorPos(¤tState.Position); 94 | currentState.RelativePosition = currentState.Position; 95 | 96 | if (MainModule::DivaWindowHandle != NULL) 97 | ScreenToClient(MainModule::DivaWindowHandle, ¤tState.RelativePosition); 98 | 99 | if (directInputMouse != nullptr) 100 | { 101 | if (directInputMouse->Poll()) 102 | currentState.MouseWheel += directInputMouse->GetMouseWheel(); 103 | 104 | currentState.ScrolledUp = (GetDeltaMouseWheel() > 0); 105 | currentState.ScrolledDown = (GetDeltaMouseWheel() < 0); 106 | } 107 | 108 | return true; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Mouse/Mouse.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../IInputDevice.h" 3 | #include "../DirectInput/DirectInputMouse.h" 4 | #include "MouseState.h" 5 | 6 | namespace DivaHook::Input 7 | { 8 | class Mouse : public IInputDevice 9 | { 10 | public: 11 | ~Mouse(); 12 | 13 | static Mouse* GetInstance(); 14 | 15 | bool PollInput() override; 16 | 17 | POINT GetPosition(); 18 | POINT GetRelativePosition(); 19 | POINT GetDeltaPosition(); 20 | 21 | long GetMouseWheel(); 22 | long GetDeltaMouseWheel(); 23 | 24 | bool HasMoved(); 25 | bool GetIsScrolledUp(); 26 | bool GetIsScrolledDown(); 27 | bool GetWasScrolledUp(); 28 | bool GetWasScrolledDown(); 29 | 30 | void SetPosition(int x, int y); 31 | 32 | private: 33 | Mouse(); 34 | MouseState lastState; 35 | MouseState currentState; 36 | DirectInputMouse* directInputMouse = nullptr; 37 | 38 | static Mouse* instance; 39 | }; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /DivaHook/src/Input/Mouse/MouseState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace DivaHook::Input 5 | { 6 | struct MouseState 7 | { 8 | POINT Position; 9 | POINT RelativePosition; 10 | long MouseWheel; 11 | bool ScrolledUp; 12 | bool ScrolledDown; 13 | }; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /DivaHook/src/MainModule.cpp: -------------------------------------------------------------------------------- 1 | #include "MainModule.h" 2 | #include 3 | 4 | namespace DivaHook 5 | { 6 | typedef std::filesystem::path fspath; 7 | 8 | std::string *MainModule::moduleDirectory; 9 | 10 | const wchar_t* MainModule::DivaWindowName = L"Hatsune Miku Project DIVA Arcade Future Tone"; 11 | const wchar_t* MainModule::GlutDefaultName = L"GLUT"; 12 | 13 | HWND MainModule::DivaWindowHandle; 14 | HMODULE MainModule::Module; 15 | 16 | std::string MainModule::GetModuleDirectory() 17 | { 18 | if (moduleDirectory == nullptr) 19 | { 20 | CHAR modulePathBuffer[MAX_PATH]; 21 | GetModuleFileNameA(MainModule::Module, modulePathBuffer, MAX_PATH); 22 | 23 | fspath configPath = fspath(modulePathBuffer).parent_path(); 24 | moduleDirectory = new std::string(configPath.u8string()); 25 | } 26 | 27 | return *moduleDirectory; 28 | } 29 | 30 | RECT MainModule::GetWindowBounds() 31 | { 32 | RECT windowRect; 33 | GetWindowRect(DivaWindowHandle, &windowRect); 34 | 35 | return windowRect; 36 | } 37 | } -------------------------------------------------------------------------------- /DivaHook/src/MainModule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace DivaHook 6 | { 7 | class MainModule 8 | { 9 | private: 10 | static std::string *moduleDirectory; 11 | 12 | public: 13 | static const wchar_t* DivaWindowName; 14 | static const wchar_t* GlutDefaultName; 15 | 16 | static HWND DivaWindowHandle; 17 | static HMODULE Module; 18 | 19 | static std::string GetModuleDirectory(); 20 | static RECT GetWindowBounds(); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /DivaHook/src/Utilities/EnumBitwiseOperations.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace DivaHook::Utilities 4 | { 5 | template inline T operator~ (T a) { return (T)~(int)a; } 6 | template inline T operator| (T a, T b) { return (T)((int)a | (int)b); } 7 | template inline T operator& (T a, T b) { return (T)((int)a & (int)b); } 8 | template inline T operator^ (T a, T b) { return (T)((int)a ^ (int)b); } 9 | template inline T& operator|= (T& a, T b) { return (T&)((int&)a |= (int)b); } 10 | template inline T& operator&= (T& a, T b) { return (T&)((int&)a &= (int)b); } 11 | template inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int)b); } 12 | } -------------------------------------------------------------------------------- /DivaHook/src/Utilities/Math.cpp: -------------------------------------------------------------------------------- 1 | #define _USE_MATH_DEFINES 2 | #include "Math.h" 3 | 4 | namespace DivaHook::Utilities 5 | { 6 | float ToDegrees(float radians) 7 | { 8 | return radians * (180.0f / M_PI); 9 | } 10 | 11 | float ToRadians(float degrees) 12 | { 13 | return (degrees * M_PI) / 180.0f; 14 | } 15 | 16 | Vec2 GetDirection(float degrees) 17 | { 18 | float radians = ToRadians(degrees); 19 | return Vec2(cos(radians), sin(radians)); 20 | } 21 | 22 | Vec2 PointFromAngle(float degrees, float distance) 23 | { 24 | float radians = ToRadians(degrees + 90.0f); 25 | return Vec2(-1 * std::cos(radians) * distance, -1 * std::sin(radians) * distance); 26 | } 27 | 28 | float AngleFromPoints(Vec2 p0, Vec2 p1) 29 | { 30 | return (float)(std::atan2(p1.Y - p0.Y, p1.X - p0.X) * 180.0 / M_PI) + 90.0f; 31 | } 32 | 33 | float ConvertRange(float originalStart, float originalEnd, float newStart, float newEnd, float value) 34 | { 35 | return newStart + ((value - originalStart) * (newEnd - newStart) / (originalEnd - originalStart)); 36 | } 37 | } -------------------------------------------------------------------------------- /DivaHook/src/Utilities/Math.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Vec2.h" 4 | #include "Vec3.h" 5 | 6 | namespace DivaHook::Utilities 7 | { 8 | float ToDegrees(float radians); 9 | float ToRadians(float degrees); 10 | 11 | Vec2 GetDirection(float degrees); 12 | Vec2 PointFromAngle(float degrees, float distance); 13 | float AngleFromPoints(Vec2 p0, Vec2 p1); 14 | float ConvertRange(float originalStart, float originalEnd, float newStart, float newEnd, float value); 15 | } -------------------------------------------------------------------------------- /DivaHook/src/Utilities/Operations.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Operations.h" 3 | 4 | namespace DivaHook::Utilities 5 | { 6 | std::vector Split(const std::string& str, const std::string& delim) 7 | { 8 | std::vector tokens; 9 | size_t prev = 0, pos = 0; 10 | do 11 | { 12 | pos = str.find(delim, prev); 13 | if (pos == std::string::npos) 14 | pos = str.length(); 15 | 16 | std::string token = str.substr(prev, pos - prev); 17 | 18 | if (!token.empty()) 19 | tokens.push_back(token); 20 | 21 | prev = pos + delim.length(); 22 | } while (pos < str.length() && prev < str.length()); 23 | 24 | return tokens; 25 | } 26 | 27 | void LeftTrim(std::string &s) 28 | { 29 | s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) 30 | { 31 | return !std::isspace(ch); 32 | })); 33 | } 34 | 35 | void RightTrim(std::string &s) 36 | { 37 | s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) 38 | { 39 | return !std::isspace(ch); 40 | }).base(), s.end()); 41 | } 42 | 43 | void Trim(std::string &s) 44 | { 45 | s = trim(s); 46 | } 47 | 48 | std::string trim(const std::string& str, const std::string& whitespace) 49 | { 50 | const size_t strBegin = str.find_first_not_of(whitespace); 51 | 52 | if (strBegin == std::string::npos) 53 | return ""; 54 | 55 | const size_t strEnd = str.find_last_not_of(whitespace); 56 | const size_t strRange = strEnd - strBegin + 1; 57 | 58 | return str.substr(strBegin, strRange); 59 | } 60 | } -------------------------------------------------------------------------------- /DivaHook/src/Utilities/Operations.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace DivaHook::Utilities 8 | { 9 | std::vector Split(const std::string& str, const std::string& delim); 10 | 11 | void LeftTrim(std::string &s); 12 | void RightTrim(std::string &s); 13 | void Trim(std::string &s); 14 | 15 | std::string trim(const std::string& str, const std::string& whitespace = " \t"); 16 | } 17 | -------------------------------------------------------------------------------- /DivaHook/src/Utilities/Stopwatch.cpp: -------------------------------------------------------------------------------- 1 | #include "Stopwatch.h" 2 | 3 | namespace DivaHook::Utilities 4 | { 5 | Stopwatch::Stopwatch() 6 | { 7 | } 8 | 9 | Stopwatch::~Stopwatch() 10 | { 11 | } 12 | 13 | void Stopwatch::Start() 14 | { 15 | start = high_resolution_clock::now(); 16 | } 17 | 18 | float Stopwatch::Stop() 19 | { 20 | end = high_resolution_clock::now(); 21 | return GetElapsed(); 22 | } 23 | 24 | float Stopwatch::Restart() 25 | { 26 | float elapsed = Stop(); 27 | Start(); 28 | 29 | return elapsed; 30 | } 31 | 32 | float Stopwatch::GetElapsed() 33 | { 34 | return (float)(chrono::duration_cast(end - start).count() / TIME_FACTOR); 35 | } 36 | } -------------------------------------------------------------------------------- /DivaHook/src/Utilities/Stopwatch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace chrono = std::chrono; 5 | 6 | typedef chrono::time_point steady_clock; 7 | typedef chrono::high_resolution_clock high_resolution_clock; 8 | 9 | namespace DivaHook::Utilities 10 | { 11 | class Stopwatch 12 | { 13 | const float TIME_FACTOR = 1000.0f; 14 | 15 | public: 16 | Stopwatch(); 17 | ~Stopwatch(); 18 | 19 | void Start(); 20 | float Stop(); 21 | float Restart(); 22 | 23 | float GetElapsed(); 24 | 25 | private: 26 | steady_clock start; 27 | steady_clock end; 28 | }; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /DivaHook/src/Utilities/Vec2.cpp: -------------------------------------------------------------------------------- 1 | #include "Vec2.h" 2 | 3 | namespace DivaHook::Utilities 4 | { 5 | Vec2::Vec2() 6 | { 7 | }; 8 | 9 | Vec2::Vec2(float x, float y) : X(x), Y(y) 10 | { 11 | }; 12 | 13 | Vec2 Vec2::operator+(Vec2 value) 14 | { 15 | return Vec2(X + value.X, Y + value.Y); 16 | } 17 | 18 | void Vec2::operator+=(const Vec2 &value) 19 | { 20 | X += value.X; 21 | Y += value.Y; 22 | } 23 | 24 | Vec2 Vec2::operator-(Vec2 value) 25 | { 26 | return Vec2(X - value.X, Y - value.Y); 27 | } 28 | 29 | void Vec2::operator-=(const Vec2 &value) 30 | { 31 | X -= value.X; 32 | Y -= value.Y; 33 | } 34 | } -------------------------------------------------------------------------------- /DivaHook/src/Utilities/Vec2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace DivaHook::Utilities 4 | { 5 | struct Vec2 6 | { 7 | float X, Y; 8 | 9 | Vec2(); 10 | Vec2(float x, float y); 11 | 12 | Vec2 operator+(Vec2 value); 13 | void operator+=(const Vec2 &value); 14 | 15 | Vec2 operator-(Vec2 value); 16 | void operator-=(const Vec2 &value); 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /DivaHook/src/Utilities/Vec3.cpp: -------------------------------------------------------------------------------- 1 | #include "Vec3.h" 2 | 3 | namespace DivaHook::Utilities 4 | { 5 | Vec3::Vec3() 6 | { 7 | }; 8 | 9 | Vec3::Vec3(float x, float y, float z) : X(x), Y(y), Z(z) 10 | { 11 | }; 12 | 13 | Vec3 Vec3::operator+(Vec2 value) 14 | { 15 | return Vec3(X + value.X, Y, Z + value.Y); 16 | } 17 | 18 | void Vec3::operator+=(const Vec2 &value) 19 | { 20 | X += value.X; 21 | Z += value.Y; 22 | } 23 | 24 | Vec3 Vec3::operator-(Vec2 value) 25 | { 26 | return Vec3(X - value.X, Y, Z - value.Y); 27 | } 28 | 29 | void Vec3::operator-=(const Vec2 &value) 30 | { 31 | X -= value.X; 32 | Z -= value.Y; 33 | } 34 | 35 | Vec3 Vec3::operator+(Vec3 value) 36 | { 37 | return Vec3(X + value.X, Y + value.Y, Z + value.Z); 38 | } 39 | 40 | void Vec3::operator+=(const Vec3 &value) 41 | { 42 | X += value.X; 43 | Y += value.Y; 44 | Z += value.Z; 45 | } 46 | 47 | Vec3 Vec3::operator-(Vec3 value) 48 | { 49 | return Vec3(X - value.X, Y - value.Y, Z - value.Z); 50 | } 51 | 52 | void Vec3::operator-=(const Vec3 &value) 53 | { 54 | X -= value.X; 55 | Y -= value.Y; 56 | Z -= value.Z; 57 | } 58 | } -------------------------------------------------------------------------------- /DivaHook/src/Utilities/Vec3.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Vec2.h" 3 | 4 | namespace DivaHook::Utilities 5 | { 6 | struct Vec3 7 | { 8 | float X, Y, Z; 9 | 10 | Vec3(); 11 | Vec3(float x, float y, float z); 12 | 13 | // Vec2 14 | Vec3 operator+(Vec2 value); 15 | void operator+=(const Vec2 &value); 16 | 17 | Vec3 operator-(Vec2 value); 18 | void operator-=(const Vec2 &value); 19 | 20 | // Vec3 21 | Vec3 operator+(Vec3 value); 22 | void operator+=(const Vec3 &value); 23 | 24 | Vec3 operator-(Vec3 value); 25 | void operator-=(const Vec3 &value); 26 | }; 27 | } -------------------------------------------------------------------------------- /DivaHook/src/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Constants.h" 4 | #include "MainModule.h" 5 | #include "Input/Mouse/Mouse.h" 6 | #include "Input/Keyboard/Keyboard.h" 7 | #include "Input/DirectInput/DirectInput.h" 8 | #include "Input/DirectInput/Ds4/DualShock4.h" 9 | #include "Components/ComponentsManager.h" 10 | 11 | LRESULT CALLBACK MessageWindowProcessCallback(HWND, UINT, WPARAM, LPARAM); 12 | DWORD WINAPI WindowMessageDispatcher(LPVOID); 13 | VOID RegisterMessageWindowClass(); 14 | 15 | struct 16 | { 17 | DWORD ID = NULL; 18 | HANDLE Handle = NULL; 19 | } MessageThread; 20 | 21 | const wchar_t *MessageWindowClassName = TEXT("MessageWindowClass"); 22 | const wchar_t *MessageWindowName = TEXT("MessageWindowTitle"); 23 | 24 | namespace DivaHook 25 | { 26 | Components::ComponentsManager ComponentsManager; 27 | bool DeviceConnected = true; 28 | bool FirstUpdateTick = true; 29 | bool HasWindowFocus, HadWindowFocus; 30 | 31 | void* InstallHook(void* source, void* destination, int length) 32 | { 33 | const DWORD minLen = 0xE; 34 | 35 | if (length < minLen) 36 | return NULL; 37 | 38 | BYTE stub[] = 39 | { 40 | 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ?ptr [$+6] 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ptr??? 42 | }; 43 | 44 | void* trampoline = VirtualAlloc(0, length + sizeof(stub), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 45 | 46 | DWORD oldProtect; 47 | VirtualProtect(source, length, PAGE_EXECUTE_READWRITE, &oldProtect); 48 | 49 | DWORD64 returnAddress = (DWORD64)source + length; 50 | 51 | // trampoline 52 | memcpy(stub + 6, &returnAddress, 8); 53 | 54 | memcpy((void*)((DWORD_PTR)trampoline), source, length); 55 | memcpy((void*)((DWORD_PTR)trampoline + length), stub, sizeof(stub)); 56 | 57 | // orig 58 | memcpy(stub + 6, &destination, 8); 59 | memcpy(source, stub, sizeof(stub)); 60 | 61 | for (int i = minLen; i < length; i++) 62 | *(BYTE*)((DWORD_PTR)source + i) = NOP_OPCODE; 63 | 64 | VirtualProtect(source, length, oldProtect, &oldProtect); 65 | 66 | return (void*)((DWORD_PTR)trampoline); 67 | } 68 | 69 | void InitializeTick() 70 | { 71 | RegisterMessageWindowClass(); 72 | if ((MessageThread.Handle = CreateThread(0, 0, WindowMessageDispatcher, 0, 0, 0)) == NULL) 73 | printf("InitializeTick(): CreateThread() Error: %d\n", GetLastError()); 74 | 75 | MainModule::DivaWindowHandle = FindWindow(0, MainModule::DivaWindowName); 76 | if (MainModule::DivaWindowHandle == NULL) 77 | MainModule::DivaWindowHandle = FindWindow(0, MainModule::GlutDefaultName); 78 | 79 | HRESULT diInitResult = Input::InitializeDirectInput(MainModule::Module); 80 | if (FAILED(diInitResult)) 81 | printf("InitializeTick(): Failed to initialize DirectInput. Error: 0x%08X\n", diInitResult); 82 | 83 | ComponentsManager.Initialize(); 84 | } 85 | 86 | void UpdateTick() 87 | { 88 | if (FirstUpdateTick) 89 | { 90 | FirstUpdateTick = false; 91 | InitializeTick(); 92 | } 93 | 94 | if (DeviceConnected) 95 | { 96 | DeviceConnected = false; 97 | 98 | if (!Input::DualShock4::InstanceInitialized()) 99 | { 100 | if (Input::DualShock4::TryInitializeInstance()) 101 | printf("UpdateTick(): DualShock4 connected and initialized\n"); 102 | } 103 | } 104 | 105 | ComponentsManager.Update(); 106 | 107 | HadWindowFocus = HasWindowFocus; 108 | HasWindowFocus = MainModule::DivaWindowHandle == NULL || GetForegroundWindow() == MainModule::DivaWindowHandle; 109 | 110 | if (HasWindowFocus) 111 | { 112 | Input::Keyboard::GetInstance()->PollInput(); 113 | Input::Mouse::GetInstance()->PollInput(); 114 | 115 | if (Input::DualShock4::GetInstance() != nullptr) 116 | { 117 | if (!Input::DualShock4::GetInstance()->PollInput()) 118 | { 119 | Input::DualShock4::DeleteInstance(); 120 | printf("UpdateTick(): DualShock4 connection lost\n"); 121 | } 122 | } 123 | 124 | ComponentsManager.UpdateInput(); 125 | } 126 | 127 | if (HasWindowFocus && !HadWindowFocus) 128 | ComponentsManager.OnFocusGain(); 129 | 130 | if (!HasWindowFocus && HadWindowFocus) 131 | ComponentsManager.OnFocusLost(); 132 | } 133 | 134 | void InstallHooks() 135 | { 136 | InstallHook((void*)ENGINE_UPDATE_HOOK_TARGET_ADDRESS, (void*)UpdateTick, 0xE); 137 | } 138 | 139 | void Dispose() 140 | { 141 | ComponentsManager.Dispose(); 142 | 143 | delete Input::Keyboard::GetInstance(); 144 | delete Input::Mouse::GetInstance(); 145 | delete Input::DualShock4::GetInstance(); 146 | 147 | Input::DisposeDirectInput(); 148 | 149 | PostThreadMessage(MessageThread.ID, WM_QUIT, 0, 0); 150 | } 151 | } 152 | 153 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 154 | { 155 | switch (ul_reason_for_call) 156 | { 157 | case DLL_PROCESS_ATTACH: 158 | printf("DllMain(): Installing hooks...\n"); 159 | 160 | DivaHook::InstallHooks(); 161 | DivaHook::MainModule::Module = hModule; 162 | break; 163 | 164 | case DLL_PROCESS_DETACH: 165 | DivaHook::Dispose(); 166 | break; 167 | } 168 | 169 | return TRUE; 170 | } 171 | 172 | DWORD WINAPI WindowMessageDispatcher(LPVOID lpParam) 173 | { 174 | HWND windowHandle = CreateWindowW( 175 | MessageWindowClassName, 176 | MessageWindowName, 177 | WS_OVERLAPPEDWINDOW, 178 | CW_USEDEFAULT, CW_USEDEFAULT, 179 | CW_USEDEFAULT, CW_USEDEFAULT, 180 | NULL, NULL, 181 | DivaHook::MainModule::Module, 182 | NULL); 183 | 184 | if (!windowHandle) 185 | { 186 | printf("WindowMessageDispatcher(): CreateWindowW() Error: %d\n", GetLastError()); 187 | return 1; 188 | } 189 | 190 | MessageThread.ID = GetCurrentThreadId(); 191 | 192 | MSG message; 193 | DWORD returnValue; 194 | 195 | printf("WindowMessageDispatcher(): Entering message loop...\n"); 196 | 197 | while (1) 198 | { 199 | returnValue = GetMessage(&message, NULL, 0, 0); 200 | if (returnValue != -1) 201 | { 202 | TranslateMessage(&message); 203 | DispatchMessage(&message); 204 | } 205 | else 206 | { 207 | printf("WindowMessageDispatcher(): GetMessage() Error: %d\n", returnValue); 208 | } 209 | } 210 | 211 | DestroyWindow(windowHandle); 212 | return 0; 213 | } 214 | 215 | BOOL RegisterDeviceInterface(HWND hWnd, HDEVNOTIFY *hDeviceNotify) 216 | { 217 | DEV_BROADCAST_DEVICEINTERFACE NotificationFilter = {}; 218 | 219 | NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); 220 | NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 221 | 222 | *hDeviceNotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); 223 | 224 | return *hDeviceNotify != NULL; 225 | } 226 | 227 | LRESULT CALLBACK MessageWindowProcessCallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 228 | { 229 | switch (message) 230 | { 231 | case WM_CREATE: 232 | { 233 | HDEVNOTIFY hDevNotify = NULL; 234 | 235 | if (!RegisterDeviceInterface(hWnd, &hDevNotify)) 236 | printf("MessageWindowProcessCallback(): RegisterDeviceInterface() Error: %d\n", GetLastError()); 237 | 238 | break; 239 | } 240 | 241 | case WM_DEVICECHANGE: 242 | { 243 | switch (wParam) 244 | { 245 | case DBT_DEVICEARRIVAL: 246 | DivaHook::DeviceConnected = true; 247 | break; 248 | 249 | default: 250 | break; 251 | } 252 | } 253 | 254 | default: 255 | return DefWindowProc(hWnd, message, wParam, lParam); 256 | } 257 | 258 | return 0; 259 | } 260 | 261 | VOID RegisterMessageWindowClass() 262 | { 263 | WNDCLASS windowClass = { }; 264 | 265 | windowClass.lpfnWndProc = MessageWindowProcessCallback; 266 | windowClass.hInstance = DivaHook::MainModule::Module; 267 | windowClass.lpszClassName = MessageWindowClassName; 268 | 269 | RegisterClass(&windowClass); 270 | } 271 | -------------------------------------------------------------------------------- /DivaHook/src/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samyuu/TotallyLegitArcadeController/327265b0e9c6c7e26d1bc5516e7293b02b7fef0e/DivaHook/src/targetver.h -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 nop 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Prepatch/Prepatch.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15.0 15 | {79E6DFBD-EA77-4498-A306-9E0F13AA16A1} 16 | Prepatch 17 | 10.0.17763.0 18 | 19 | 20 | 21 | Application 22 | true 23 | v141 24 | MultiByte 25 | 26 | 27 | Application 28 | false 29 | v141 30 | true 31 | MultiByte 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | $(SolutionDir)$(ProjectName)\bin-int\$(Platform)-$(Configuration)\ 47 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 48 | prepatch 49 | 50 | 51 | $(SolutionDir)$(ProjectName)\bin-int\$(Platform)-$(Configuration)\ 52 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 53 | prepatch 54 | 55 | 56 | 57 | Level3 58 | Disabled 59 | true 60 | true 61 | 62 | 63 | 64 | 65 | 66 | 67 | Level3 68 | MaxSpeed 69 | true 70 | true 71 | true 72 | true 73 | 74 | 75 | 76 | 77 | true 78 | true 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Prepatch/Prepatch.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 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | -------------------------------------------------------------------------------- /Prepatch/rom/patch.txt: -------------------------------------------------------------------------------- 1 | // patch.txt for Hatsune Miku Project DIVA Arcade Future Tone 2 | // Version 7.10.00 (VERSION B/REVISION 3) 3 | // 2018-09-14T 14:26:44+09:00 4 | # file: patch.txt 5 | # author: samyuu 6 | # version: 1.00.00 7 | # date: 2019/03/17 8 | # image_base: 0x140000C00 9 | 10 | // Address : Length : Original bytes : Patched bytes 11 | 12 | // Use GLUT_CURSOR_RIGHT_ARROW instead of GLUT_CURSOR_NONE 13 | 0x000000014019341B : 0x0001 : 65 : 00 14 | 15 | // Disable the keychip time bomb 16 | 0x0000000140210820 : 0x0006 : 40 53 48 83 EC 20 : B8 00 00 00 00 C3 17 | 18 | // Always return true for the SelCredit enter SelPv check 19 | 0x0000000140393610 : 0x0006 : 40 53 48 83 EC 20 : B0 01 C3 90 90 90 20 | 21 | // Just completely ignore all SYSTEM_STARTUP errors 22 | 0x00000001403F5080 : 0x0001 : 40 : C3 23 | 24 | // Always exit TASK_MODE_APP_ERROR on the first frame 25 | 0x00000001403F73A7 : 0x0002 : 74 26 : 90 90 26 | 0x00000001403F73C3 : 0x0003 : 0F 45 CA : 89 D1 90 27 | 28 | // Ignore the EngineClear variable to clear the framebuffer at all resolutions 29 | 0x0000000140501480 : 0x0002 : 74 0C : 90 90 30 | 0x0000000140501515 : 0x0002 : 74 2F : 90 90 31 | 32 | // Don't update the touch slider state so we can write our own 33 | 0x000000014061579B : 0x0009 : 89 41 F4 8B 42 E0 89 41 F8 : 90 90 90 8B 42 E0 90 90 90 34 | 35 | // Write ram files to the current directory instead of Y:/SBZV/ram 36 | 0x000000014066CF09 : 0x0003 : 0F 85 D7 : E9 D8 00 37 | 38 | // *But of course we have a valid keychip*, return true 39 | 0x000000014066E820 : 0x0006 : 0F B6 05 E3 65 62 : B8 01 00 00 00 C3 40 | 41 | // Skip parts of the network check state 42 | 0x00000001406717B1 : 0x0004 : 0F 85 21 03 : E9 22 03 00 43 | 44 | // Set the initial DHCP WAIT timer value to 0 45 | 0x00000001406724E7 : 0x0002 : A0 8C : 00 00 46 | 47 | // Ignore SYSTEM_STARTUP Location Server checks 48 | 0x00000001406732A2 : 0x0002 : 75 1E : 90 90 -------------------------------------------------------------------------------- /Prepatch/src/Patch/Patch.cpp: -------------------------------------------------------------------------------- 1 | #include "Patch.h" 2 | #include 3 | #include "../StringOperations/Operations.h" 4 | 5 | namespace Patch 6 | { 7 | Patch::Patch() 8 | { 9 | } 10 | 11 | Patch::~Patch() 12 | { 13 | for (auto& patchData : PatchDataVector) 14 | delete patchData; 15 | } 16 | 17 | bool Patch::ParseFile(const std::string& patchPath) 18 | { 19 | printf("Patch::ParseFile(): Opening patch file...\n"); 20 | 21 | std::ifstream fileStream(patchPath); 22 | 23 | if (!fileStream.is_open()) 24 | { 25 | printf("Patch::ParseFile(): Unable to open input file: %s\n", patchPath.c_str()); 26 | return FALSE; 27 | } 28 | 29 | printf("Patch::ParseFile(): Parsing patch file...\n"); 30 | 31 | std::string commentPrefix = "//"; 32 | std::string headerPrefix = "#"; 33 | std::string seperator = ":"; 34 | std::string byteSeperator = " "; 35 | 36 | std::string line; 37 | while (getline(fileStream, line)) 38 | { 39 | if (!line.compare(0, commentPrefix.size(), commentPrefix)) 40 | continue; 41 | 42 | if (!line.compare(0, headerPrefix.size(), headerPrefix)) 43 | { 44 | auto split = StringOperations::Split(line, seperator); 45 | 46 | if (split.size() != 2) 47 | continue; 48 | 49 | auto type = split[0].substr(1); 50 | auto value = split[1]; 51 | StringOperations::Trim(type); 52 | StringOperations::Trim(value); 53 | 54 | if (type == "file") 55 | FileName = value; 56 | else if (type == "author") 57 | Author = value; 58 | else if (type == "version") 59 | Version = value; 60 | else if (type == "date") 61 | Date = value; 62 | else if (type == "image_base") 63 | ImageBase = _strtoi64(value.c_str(), nullptr, 16); 64 | 65 | continue; 66 | } 67 | 68 | auto valueSplit = StringOperations::Split(line, seperator); 69 | 70 | if (valueSplit.size() != 4) 71 | continue; 72 | 73 | for (auto& str : valueSplit) 74 | StringOperations::Trim(str); 75 | 76 | char* buffer; 77 | auto patchData = new PatchData(); 78 | 79 | patchData->Address = _strtoi64(valueSplit[0].c_str(), &buffer, 16); 80 | if (buffer == nullptr) 81 | continue; 82 | 83 | patchData->Length = strtol(valueSplit[1].c_str(), &buffer, 16); 84 | if (buffer == nullptr) 85 | continue; 86 | 87 | auto originalBytesString = StringOperations::Split(valueSplit[2], byteSeperator); 88 | auto patchedBytesString = StringOperations::Split(valueSplit[3], byteSeperator); 89 | 90 | patchData->OriginalBytes = new BYTE[patchData->Length]; 91 | for (int i = 0; i < patchData->Length; i++) 92 | patchData->OriginalBytes[i] = strtol(originalBytesString[i].c_str(), nullptr, 16); 93 | 94 | patchData->PatchedBytes = new BYTE[patchData->Length]; 95 | for (int i = 0; i < patchData->Length; i++) 96 | patchData->PatchedBytes[i] = strtol(patchedBytesString[i].c_str(), nullptr, 16); 97 | 98 | PatchDataVector.push_back(patchData); 99 | } 100 | 101 | return TRUE; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Prepatch/src/Patch/Patch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "PatchData.h" 6 | 7 | namespace Patch 8 | { 9 | class Patch 10 | { 11 | public: 12 | std::string FileName; 13 | std::string Author; 14 | std::string Version; 15 | std::string Date; 16 | DWORD64 ImageBase; 17 | std::vector PatchDataVector; 18 | 19 | Patch(); 20 | ~Patch(); 21 | bool ParseFile(const std::string& patchPath); 22 | }; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /Prepatch/src/Patch/PatchData.cpp: -------------------------------------------------------------------------------- 1 | #include "PatchData.h" 2 | 3 | namespace Patch 4 | { 5 | Patch::PatchData::PatchData() 6 | { 7 | } 8 | 9 | Patch::PatchData::~PatchData() 10 | { 11 | if (OriginalBytes != nullptr) 12 | delete[] OriginalBytes; 13 | 14 | if (PatchedBytes != nullptr) 15 | delete[] PatchedBytes; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Prepatch/src/Patch/PatchData.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace Patch 5 | { 6 | struct PatchData 7 | { 8 | DWORD64 Address; 9 | DWORD Length; 10 | BYTE* OriginalBytes; 11 | BYTE* PatchedBytes; 12 | 13 | PatchData(); 14 | ~PatchData(); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /Prepatch/src/Patch/Patcher.cpp: -------------------------------------------------------------------------------- 1 | #include "Patcher.h" 2 | 3 | namespace Patch 4 | { 5 | static bool EndsWith(const std::string& str, const std::string& suffix) 6 | { 7 | return str.size() >= suffix.size() && 0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix); 8 | } 9 | 10 | Patcher::Patcher() 11 | { 12 | } 13 | 14 | Patcher::~Patcher() 15 | { 16 | if (patch != nullptr) 17 | delete patch; 18 | } 19 | 20 | bool Patcher::LoadPatchFile(std::string patchFile) 21 | { 22 | printf("Patcher::LoadPatchFile(): Opening patch file...\n"); 23 | 24 | patch = new Patch(); 25 | bool result = patch->ParseFile(patchFile); 26 | 27 | if (result) 28 | { 29 | printf("Patcher::LoadPatchFile(): Patch file loaded\n"); 30 | } 31 | else 32 | { 33 | printf("Patcher::LoadPatchFile(): Failed to load patch file\n"); 34 | } 35 | 36 | return result; 37 | } 38 | 39 | bool Patcher::PatchProgram(std::string executablePath) 40 | { 41 | if (patch == nullptr) 42 | { 43 | printf("Patcher::PatchProgram(): No patch has been loaded.\n"); 44 | return FALSE; 45 | } 46 | 47 | if (!EndsWith(executablePath, ".exe")) 48 | { 49 | printf("Patcher::PatchProgram(): The input file is not an executable\n"); 50 | return FALSE; 51 | } 52 | 53 | FILE* file = nullptr; 54 | auto error = fopen_s(&file, executablePath.c_str(), "rb"); 55 | 56 | if (file == nullptr) 57 | { 58 | printf("Patcher::PatchProgram(): Unable to open input file %s. Error: 0x%X\n", executablePath.c_str(), error); 59 | return FALSE; 60 | } 61 | 62 | fseek(file, 0, SEEK_END); 63 | int fileSize = ftell(file); 64 | rewind(file); 65 | 66 | BYTE* buffer = new BYTE[fileSize]; 67 | 68 | fread(buffer, 1, fileSize, file); 69 | fclose(file); 70 | 71 | fopen_s(&file, executablePath.c_str(), "wb"); 72 | fwrite(buffer, 1, fileSize, file); 73 | 74 | for (auto& patchData : patch->PatchDataVector) 75 | { 76 | printf("Patcher::PatchProgram(): Patching - Address: 0x%016I64X Data: ", patchData->Address); 77 | for (int i = 0; i < patchData->Length; i++) 78 | printf("%02X", patchData->PatchedBytes[i]); 79 | printf("\n"); 80 | 81 | auto fileAddress = patchData->Address - patch->ImageBase; 82 | 83 | fseek(file, fileAddress, SEEK_SET); 84 | fwrite(patchData->PatchedBytes, 1, patchData->Length, file); 85 | } 86 | 87 | printf("Patcher::PatchProgram(): Patches applied\n"); 88 | printf("Patcher::PatchProgram(): Closing file...\n"); 89 | 90 | fclose(file); 91 | delete[] buffer; 92 | 93 | return TRUE; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Prepatch/src/Patch/Patcher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "Patch.h" 5 | 6 | namespace Patch 7 | { 8 | class Patcher 9 | { 10 | public: 11 | Patcher(); 12 | ~Patcher(); 13 | bool LoadPatchFile(std::string patchFile); 14 | bool PatchProgram(std::string executablePath); 15 | 16 | private: 17 | Patch* patch; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /Prepatch/src/StringOperations/Operations.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Operations.h" 3 | 4 | namespace StringOperations 5 | { 6 | std::vector Split(const std::string& str, const std::string& delim) 7 | { 8 | std::vector tokens; 9 | size_t prev = 0, pos = 0; 10 | do 11 | { 12 | pos = str.find(delim, prev); 13 | if (pos == std::string::npos) 14 | pos = str.length(); 15 | 16 | std::string token = str.substr(prev, pos - prev); 17 | 18 | if (!token.empty()) 19 | tokens.push_back(token); 20 | 21 | prev = pos + delim.length(); 22 | } while (pos < str.length() && prev < str.length()); 23 | 24 | return tokens; 25 | } 26 | 27 | void LeftTrim(std::string &s) 28 | { 29 | s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) 30 | { 31 | return !std::isspace(ch); 32 | })); 33 | } 34 | 35 | void RightTrim(std::string &s) 36 | { 37 | s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) 38 | { 39 | return !std::isspace(ch); 40 | }).base(), s.end()); 41 | } 42 | 43 | void Trim(std::string &s) 44 | { 45 | LeftTrim(s); 46 | RightTrim(s); 47 | } 48 | } -------------------------------------------------------------------------------- /Prepatch/src/StringOperations/Operations.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace StringOperations 8 | { 9 | std::vector Split(const std::string& str, const std::string& delim); 10 | 11 | void LeftTrim(std::string &s); 12 | void RightTrim(std::string &s); 13 | void Trim(std::string &s); 14 | } 15 | -------------------------------------------------------------------------------- /Prepatch/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "Patch/Patcher.h" 2 | 3 | const std::string PATCH_FILE_FILE_NAME = "patch.txt"; 4 | const std::string DIVA_PROCESS_NAME = "diva.exe"; 5 | 6 | int GetDirectorySeperatorPosition(std::string path) 7 | { 8 | for (int i = path.size() - 1; i >= 0; i--) 9 | { 10 | auto currentChar = path[i]; 11 | if (currentChar == '\\' || currentChar == '/') 12 | return i; 13 | } 14 | 15 | return -1; 16 | } 17 | 18 | std::string GetModuleDirectory() 19 | { 20 | HMODULE module = GetModuleHandleW(NULL); 21 | CHAR modulePathBuffer[MAX_PATH]; 22 | GetModuleFileName(module, modulePathBuffer, MAX_PATH); 23 | 24 | auto modulePath = std::string(modulePathBuffer); 25 | int seperatorPos = GetDirectorySeperatorPosition(modulePath); 26 | 27 | if (seperatorPos != -1) 28 | return std::string(modulePathBuffer).substr(0, seperatorPos); 29 | 30 | return NULL; 31 | } 32 | 33 | bool DoesFileExist(std::string filePath) 34 | { 35 | auto fileAttrib = GetFileAttributes(filePath.c_str()); 36 | return fileAttrib != INVALID_FILE_ATTRIBUTES; 37 | } 38 | 39 | int main(int argc, char** argv) 40 | { 41 | printf("main(): Checking %s location...\n", PATCH_FILE_FILE_NAME.c_str()); 42 | 43 | auto moduleDirectory = GetModuleDirectory(); 44 | auto patchPath = moduleDirectory + "/" + PATCH_FILE_FILE_NAME; 45 | 46 | if (!DoesFileExist(patchPath)) 47 | { 48 | printf("main(): Unable to locate %s\n", PATCH_FILE_FILE_NAME.c_str()); 49 | printf("main(): Press enter to exit..."); 50 | std::cin.get(); 51 | return EXIT_FAILURE; 52 | } 53 | else 54 | { 55 | printf("main(): %s successfully located\n", PATCH_FILE_FILE_NAME.c_str()); 56 | } 57 | 58 | printf("main(): Checking executable location...\n"); 59 | 60 | if (argc < 2) 61 | { 62 | printf("main(): Insufficient number of arguments supplied\n"); 63 | printf("main(): Please drag the target %s on top of this executable to apply the patches\n", DIVA_PROCESS_NAME.c_str()); 64 | printf("main(): Press enter to exit..."); 65 | std::cin.get(); 66 | return EXIT_FAILURE; 67 | } 68 | 69 | std::string executablePath = std::string(argv[1]); 70 | 71 | if (!DoesFileExist(executablePath)) 72 | { 73 | printf("main(): Unable to locate %s\n", executablePath.c_str()); 74 | printf("main(): Press enter to exit..."); 75 | std::cin.get(); 76 | return EXIT_FAILURE; 77 | } 78 | else 79 | { 80 | printf("main(): %s successfully located\n", executablePath.c_str()); 81 | } 82 | 83 | Patch::Patcher patcher; 84 | patcher.LoadPatchFile(patchPath); 85 | patcher.PatchProgram(executablePath); 86 | 87 | printf("main(): Press enter to exit..."); 88 | std::cin.get(); 89 | return EXIT_SUCCESS; 90 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Totally Legit Arcade Controller (TLAC) 2 | ELAC's reborn big brother 3 | 4 | # Description 5 | This program consists of three parts: 6 | ##### Prepatch: 7 | Used for applying the static patches from the `patch.txt` file to allow the game to successfully boot past all startup checks. 8 | ##### Divahook: 9 | Installs a hook on the game's update routine to update its components. 10 | ##### TLAC: 11 | Injects the divahook dll inside the game's process. 12 | 13 | ## Components 14 | The available components can be toggled inside the `components.ini` config file. Currently available are: 15 | * input_emulator 16 | * touch_slider_emulator 17 | * touch_panel_emulator 18 | * sys_timer 19 | * player_data_manager 20 | * frame_rate_manager 21 | * stage_manager 22 | * fast_loader 23 | * camera_controller 24 | * debug_component 25 | 26 | ## Controls 27 | Input bindings can be set inside the `keyconfig.ini` config file. Currently supported are keyboard and DualShock 4 controller input. 28 | Key and button names are listed inside this config. 29 | 30 | ## Player Data 31 | If enabled the PlayerDataManager writes constant values from the `playerdata.ini` config file to the game's memory. 32 | This allows the user to set their player name, a level plate ID to be shown during the song select, equip a skin to be loaded during gameplay and button / slide sounds to be applied to all songs played. 33 | This config file **must be** encoded using UTF-8. 34 | 35 | ## Debug Component 36 | This component enables diva's internal dw_gui and makes the hidden DATA_TESTs accessible. 37 | The current game state can be changed using the F4 - F8 keys with F6 being a recreation of the original DATA_TEST_MAIN inside the console which can be controlled using the up / down arrow + enter key. 38 | 39 | # Usage 40 | First **once per update** patch a clean `diva.exe` using the `prepatch.exe` program by passing the `diva.exe` path to it as its first command line argument; This can be done by dragging the diva executable on top of the prepatch executable inside the windows file explorer. It is strongly recommended to always create a backup of the original diva executable first. 41 | 42 | To start diva run `diva.exe` like normal, to enable the components start `tlac.exe` **while** diva is running. 43 | Do this **every time** you wish to run diva. 44 | 45 | Diva has a few notable command line arguments including `-w` to start in windowed mode and `-hdtv1080` to increase the resolution to 1920x1080. 46 | 47 | # Binaries 48 | Pre-compiled binaries for the latest major updates can be found under the [releases](https://github.com/samyuu/TotallyLegitArcadeController/releases) tab. 49 | -------------------------------------------------------------------------------- /TotallyLegitArcadeController.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2050 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DivaHook", "DivaHook\DivaHook.vcxproj", "{69BCF67B-34D9-4424-A2A8-3A056E9D38A6}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TotallyLegitArcadeController", "TotallyLegitArcadeController\TotallyLegitArcadeController.vcxproj", "{B50A691D-DDEC-46E0-90CE-A46EF190D2A3}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Prepatch", "Prepatch\Prepatch.vcxproj", "{79E6DFBD-EA77-4498-A306-9E0F13AA16A1}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|x64 = Debug|x64 15 | Release|x64 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {69BCF67B-34D9-4424-A2A8-3A056E9D38A6}.Debug|x64.ActiveCfg = Debug|x64 19 | {69BCF67B-34D9-4424-A2A8-3A056E9D38A6}.Debug|x64.Build.0 = Debug|x64 20 | {69BCF67B-34D9-4424-A2A8-3A056E9D38A6}.Release|x64.ActiveCfg = Release|x64 21 | {69BCF67B-34D9-4424-A2A8-3A056E9D38A6}.Release|x64.Build.0 = Release|x64 22 | {B50A691D-DDEC-46E0-90CE-A46EF190D2A3}.Debug|x64.ActiveCfg = Debug|x64 23 | {B50A691D-DDEC-46E0-90CE-A46EF190D2A3}.Debug|x64.Build.0 = Debug|x64 24 | {B50A691D-DDEC-46E0-90CE-A46EF190D2A3}.Release|x64.ActiveCfg = Release|x64 25 | {B50A691D-DDEC-46E0-90CE-A46EF190D2A3}.Release|x64.Build.0 = Release|x64 26 | {79E6DFBD-EA77-4498-A306-9E0F13AA16A1}.Debug|x64.ActiveCfg = Debug|x64 27 | {79E6DFBD-EA77-4498-A306-9E0F13AA16A1}.Debug|x64.Build.0 = Debug|x64 28 | {79E6DFBD-EA77-4498-A306-9E0F13AA16A1}.Release|x64.ActiveCfg = Release|x64 29 | {79E6DFBD-EA77-4498-A306-9E0F13AA16A1}.Release|x64.Build.0 = Release|x64 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {41A2E0D2-365A-43B8-BA48-A9A9A4B78CFD} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /TotallyLegitArcadeController/TotallyLegitArcadeController.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 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | -------------------------------------------------------------------------------- /TotallyLegitArcadeController/TotallyLegitArcadeController.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15.0 15 | {B50A691D-DDEC-46E0-90CE-A46EF190D2A3} 16 | TotallyLegitArcadeController 17 | 10.0.17763.0 18 | TotallyLegitArcadeController 19 | 20 | 21 | 22 | Application 23 | true 24 | v141 25 | MultiByte 26 | 27 | 28 | Application 29 | false 30 | v141 31 | true 32 | MultiByte 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | tlac 48 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 49 | $(SolutionDir)$(ProjectName)\bin-int\$(Platform)-$(Configuration)\ 50 | 51 | 52 | tlac 53 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 54 | $(SolutionDir)$(ProjectName)\bin-int\$(Platform)-$(Configuration)\ 55 | 56 | 57 | 58 | Level3 59 | Disabled 60 | true 61 | true 62 | 63 | 64 | 65 | 66 | Level3 67 | MaxSpeed 68 | true 69 | true 70 | true 71 | true 72 | 73 | 74 | true 75 | true 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /TotallyLegitArcadeController/src/Injection/DllInjector.cpp: -------------------------------------------------------------------------------- 1 | #include "DllInjector.h" 2 | 3 | namespace Injection 4 | { 5 | int DllInjector::GetProcessID(const std::string& processName) 6 | { 7 | HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 8 | PROCESSENTRY32 structprocsnapshot = { 0 }; 9 | 10 | structprocsnapshot.dwSize = sizeof(PROCESSENTRY32); 11 | 12 | if (snapshot == INVALID_HANDLE_VALUE || Process32First(snapshot, &structprocsnapshot) == FALSE) 13 | return NULL; 14 | 15 | while (Process32Next(snapshot, &structprocsnapshot)) 16 | { 17 | if (!strcmp(structprocsnapshot.szExeFile, processName.c_str())) 18 | { 19 | CloseHandle(snapshot); 20 | 21 | printf("DllInjector::GetProcessID(): Process %s found. Process ID: %d\n", processName.c_str(), structprocsnapshot.th32ProcessID); 22 | return structprocsnapshot.th32ProcessID; 23 | } 24 | } 25 | CloseHandle(snapshot); 26 | 27 | printf("DllInjector::GetProcessID(): Process %s not found\n", processName.c_str()); 28 | return NULL; 29 | } 30 | 31 | bool DllInjector::InjectDll(const int &processId, const std::string &dllPath) 32 | { 33 | long dllSize = dllPath.length() + 1; 34 | HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); 35 | 36 | if (hProc == NULL) 37 | { 38 | printf("DllInjector::InjectDll(): Failed to OpenProcess() target. Error: 0x%X\n", GetLastError()); 39 | return false; 40 | } 41 | 42 | printf("DllInjector::InjectDll(): Opening target process...\n"); 43 | 44 | LPVOID myAlloc = VirtualAllocEx(hProc, NULL, dllSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 45 | if (myAlloc == NULL) 46 | { 47 | printf("DllInjector::InjectDll(): Failed to allocate memory in target process. Error: 0x%X\n", GetLastError()); 48 | return false; 49 | } 50 | 51 | printf("DllInjector::InjectDll(): Allocating memory in targer process...\n"); 52 | 53 | int isWriteOK = WriteProcessMemory(hProc, myAlloc, dllPath.c_str(), dllSize, 0); 54 | if (isWriteOK == 0) 55 | { 56 | printf("DllInjector::InjectDll(): Failed to WriteProcessMemory() in target. Error: 0x%X\n", GetLastError()); 57 | return false; 58 | } 59 | printf("DllInjector::InjectDll(): Creating remote thread in target process...\n"); 60 | 61 | DWORD threadId; 62 | LPTHREAD_START_ROUTINE addrLoadLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("kernel32"), "LoadLibraryA"); 63 | HANDLE threadReturn = CreateRemoteThread(hProc, NULL, 0, addrLoadLibrary, myAlloc, 0, &threadId); 64 | 65 | if (threadReturn == NULL) 66 | { 67 | printf("DllInjector::InjectDll(): Failed to CreateRemoteThread() in target. Error: 0x%X\n", GetLastError()); 68 | return false; 69 | } 70 | 71 | if ((hProc != NULL) && (myAlloc != NULL) && (isWriteOK != ERROR_INVALID_HANDLE) && (threadReturn != NULL)) 72 | { 73 | printf("DllInjector::InjectDll(): The Dll has been successfully injected\n"); 74 | return true; 75 | } 76 | 77 | return false; 78 | } 79 | 80 | bool DllInjector::InjectDll(const std::string& processName, const std::string &dllPath) 81 | { 82 | return InjectDll(GetProcessID(processName), dllPath); 83 | } 84 | } -------------------------------------------------------------------------------- /TotallyLegitArcadeController/src/Injection/DllInjector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #pragma comment(lib, "Shlwapi.lib") 7 | 8 | namespace Injection 9 | { 10 | class DllInjector 11 | { 12 | public: 13 | int GetProcessID(const std::string& processName); 14 | bool InjectDll(const int &processId, const std::string &dllPath); 15 | bool InjectDll(const std::string& processName, const std::string &dllPath); 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /TotallyLegitArcadeController/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "Injection/DllInjector.h" 2 | 3 | const char* TLAC_VERSION = "2.00.00"; 4 | 5 | const std::string DIVA_PROCESS_NAME = "diva.exe"; 6 | const std::string DIVA_HOOK_DLL_NAME = "divahook.dll"; 7 | 8 | char waitDisplayStrings[8][6] = 9 | { 10 | "o....", 11 | ".o...", 12 | "..o..", 13 | "...o.", 14 | "....o", 15 | "...o.", 16 | "..o..", 17 | ".o...", 18 | }; 19 | 20 | int GetDirectorySeperatorPosition(std::string path) 21 | { 22 | for (int i = path.size() - 1; i >= 0; i--) 23 | { 24 | auto currentChar = path[i]; 25 | if (currentChar == '\\' || currentChar == '/') 26 | return i; 27 | } 28 | 29 | return -1; 30 | } 31 | 32 | std::string GetModuleDirectory() 33 | { 34 | HMODULE module = GetModuleHandleW(NULL); 35 | CHAR modulePathBuffer[MAX_PATH]; 36 | GetModuleFileName(module, modulePathBuffer, MAX_PATH); 37 | 38 | auto modulePath = std::string(modulePathBuffer); 39 | int seperatorPos = GetDirectorySeperatorPosition(modulePath); 40 | 41 | if (seperatorPos != -1) 42 | return std::string(modulePathBuffer).substr(0, seperatorPos); 43 | 44 | return NULL; 45 | } 46 | 47 | void PrintProgramInfo() 48 | { 49 | printf("// -------------------------------------------------\n"); 50 | 51 | #ifdef _DEBUG 52 | printf("// -- DEBUG_BUILD: --\n//\n"); 53 | #endif 54 | 55 | printf("// Totally Legit Arcade Controller (TLAC) \n"); 56 | printf("// \n"); 57 | printf("// v.%s -by samyuu \n", TLAC_VERSION); 58 | printf("// -------------------------------------------------\n"); 59 | } 60 | 61 | COORD GetConsoleCursorPosition(HANDLE hConsoleOutput) 62 | { 63 | CONSOLE_SCREEN_BUFFER_INFO cbsi; 64 | GetConsoleScreenBufferInfo(hConsoleOutput, &cbsi); 65 | return cbsi.dwCursorPosition; 66 | } 67 | 68 | void WaitExit(int duration = 6000, int iterations = 32 + 1) 69 | { 70 | DWORD interval = duration / iterations; 71 | 72 | auto consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); 73 | 74 | CONSOLE_CURSOR_INFO cursorInfo; 75 | GetConsoleCursorInfo(consoleHandle, &cursorInfo); 76 | 77 | cursorInfo.bVisible = false; 78 | SetConsoleCursorInfo(consoleHandle, &cursorInfo); 79 | { 80 | auto prerPos = GetConsoleCursorPosition(consoleHandle); 81 | 82 | for (int i = 0; i < iterations; i++) 83 | { 84 | SetConsoleCursorPosition(consoleHandle, prerPos); 85 | printf("%s", waitDisplayStrings[i % 8]); 86 | Sleep(interval); 87 | } 88 | } 89 | cursorInfo.bVisible = true; 90 | SetConsoleCursorInfo(consoleHandle, &cursorInfo); 91 | } 92 | 93 | bool DoesFileExist(std::string filePath) 94 | { 95 | auto fileAttrib = GetFileAttributes(filePath.c_str()); 96 | return fileAttrib != INVALID_FILE_ATTRIBUTES; 97 | } 98 | 99 | int main(int argc, char** argv) 100 | { 101 | PrintProgramInfo(); 102 | 103 | auto moduleDirectory = GetModuleDirectory(); 104 | auto dllPath = moduleDirectory + "/" + DIVA_HOOK_DLL_NAME; 105 | 106 | if (!DoesFileExist(dllPath)) 107 | { 108 | printf("main(): Unable to locate %s\n", DIVA_HOOK_DLL_NAME.c_str()); 109 | printf("main(): Press enter to exit..."); 110 | std::cin.get(); 111 | return EXIT_FAILURE; 112 | } 113 | else 114 | { 115 | printf("main(): %s successfully located\n", DIVA_HOOK_DLL_NAME.c_str()); 116 | } 117 | 118 | Injection::DllInjector injector; 119 | bool result = injector.InjectDll(DIVA_PROCESS_NAME, dllPath); 120 | 121 | if (!result) 122 | { 123 | printf("main(): Injection failed. Press enter to exit..."); 124 | std::cin.get(); 125 | return EXIT_FAILURE; 126 | } 127 | 128 | printf("main(): Exiting "); 129 | 130 | WaitExit(); 131 | return EXIT_SUCCESS; 132 | } 133 | --------------------------------------------------------------------------------