├── .gitattributes ├── .gitignore ├── Match3Solver.sln ├── Match3Solver ├── App.config ├── App.xaml ├── App.xaml.cs ├── Calculations.txt ├── Capture │ ├── CaptureProcess.cs │ ├── EntryPoint.cs │ ├── Exceptions.cs │ ├── Hook │ │ ├── BaseDXHook.cs │ │ ├── Common │ │ │ ├── Element.cs │ │ │ ├── FramesPerSecond.cs │ │ │ ├── IOverlay.cs │ │ │ ├── IOverlayElement.cs │ │ │ ├── ImageElement.cs │ │ │ ├── Overlay.cs │ │ │ └── TextElement.cs │ │ ├── D3D9.cs │ │ ├── DX11 │ │ │ ├── ContextState.cs │ │ │ ├── DXFont.cs │ │ │ ├── DXImage.cs │ │ │ ├── DXOverlayEngine.cs │ │ │ ├── DXSprite.cs │ │ │ ├── DeviceManager.cs │ │ │ ├── RendererBase.cs │ │ │ └── ScreenAlignedQuadRenderer.cs │ │ ├── DX9 │ │ │ └── DXOverlayEngine.cs │ │ ├── DX9FormatExtension.cs │ │ ├── DXGI.cs │ │ ├── DXHookD3D10.cs │ │ ├── DXHookD3D10_1.cs │ │ ├── DXHookD3D11.cs │ │ ├── DXHookD3D9.cs │ │ ├── FramesPerSecond.cs │ │ ├── Hook.cs │ │ ├── HookManager.cs │ │ ├── IDXHook.cs │ │ ├── SafeHGlobal.cs │ │ └── TextDisplay.cs │ ├── Interface │ │ ├── CaptureConfig.cs │ │ ├── CaptureInterface.cs │ │ ├── Direct3DVersion.cs │ │ ├── DisplayTextEventArgs.cs │ │ ├── DrawOverlayEventArgs.cs │ │ ├── ImageFormat.cs │ │ ├── MessageReceivedEventArgs.cs │ │ ├── MessageType.cs │ │ ├── Screenshot.cs │ │ ├── ScreenshotExtensions.cs │ │ ├── ScreenshotReceivedEventArgs.cs │ │ └── ScreenshotRequest.cs │ ├── NativeMethods.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ └── SharpDX │ │ ├── Component.cs │ │ ├── ComponentBase.cs │ │ └── IComponent.cs ├── CutoffConverter.cs ├── EasyHook32.dll ├── EasyHook32Svc.exe ├── EasyHook64.dll ├── EasyHook64Svc.exe ├── EasyLoad32.dll ├── EasyLoad64.dll ├── GameHook.cs ├── Icon.ico ├── Icon.png ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Match3Solver.csproj ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ ├── bHeartHeadH.png │ ├── bHeartHeadV.png │ ├── bHeartTailH.png │ └── bHeartTailV.png ├── SolverInterface.cs ├── SolverUtils.cs ├── UIFunctions.cs ├── app.manifest ├── packages.config └── resultItem.cs └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.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 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb -------------------------------------------------------------------------------- /Match3Solver.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31005.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Match3Solver", "Match3Solver\Match3Solver.csproj", "{1C6187B4-3D0F-4821-A051-BD4A48320838}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {1C6187B4-3D0F-4821-A051-BD4A48320838}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {1C6187B4-3D0F-4821-A051-BD4A48320838}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {1C6187B4-3D0F-4821-A051-BD4A48320838}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {1C6187B4-3D0F-4821-A051-BD4A48320838}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B85F0CD1-6305-4223-9D3A-B4B71916CD62} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Match3Solver/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Match3Solver/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Match3Solver/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace Match3Solver 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Match3Solver/Calculations.txt: -------------------------------------------------------------------------------- 1 | 180x180 2 | 3 | 1379 x 335 4 | 1379 - 180 = 5 | 6 | 3840 x 2160 7 | 1200x335 = start 8 | 9 | 31.25% 10 | 15.5% 11 | 12 | -8 13 | 14 | //0 - Broken heart - {#FF5F1282} 15 | //1 - Heart - {#FFF553B4} 16 | //2 - Stamina - {#FFA3ABC3} 17 | //3 - Sentiment - {#FF51C1C6} 18 | //4 - Blue - {#FF115CA8} 19 | //5 - Red - {#FFE55949} 20 | //6 - Green - {#FF8EB94A} 21 | //7 - Gold - {#FFBF6D16} 22 | //8 - Bell - {#FFDDB842} 23 | 24 | 117 25 | 119 26 | 27 | 1200x335 28 | +27x+29 29 | 1227x364 30 | 31 | 0.3195 32 | 0.1685 33 | 34 | 121-29-161 35 | 200-36-135 36 | 149-158-185 37 | 67-183-189 38 | 55-137-205 | 21-104-155 39 | 225-70-53 | 222-64-46 40 | 148-172-88 | 129-174-63 41 | 228-138-66 | 221-127-45 42 | 214-173-41 43 | -------------------------------------------------------------------------------- /Match3Solver/Capture/CaptureProcess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using EasyHook; 6 | using System.Runtime.Remoting; 7 | using System.Runtime.Remoting.Channels.Ipc; 8 | using System.IO; 9 | using Capture.Interface; 10 | using System.Diagnostics; 11 | using System.Threading; 12 | using Capture.Hook; 13 | using System.Security.Principal; 14 | using System.Security.Cryptography; 15 | using System.Security.AccessControl; 16 | using System.Runtime.Remoting.Channels; 17 | using System.Runtime.Serialization.Formatters; 18 | 19 | namespace Capture 20 | { 21 | public class CaptureProcess : IDisposable 22 | { 23 | /// 24 | /// Must be null to allow a random channel name to be generated 25 | /// 26 | string _channelName = null; 27 | private IpcServerChannel _screenshotServer; 28 | private CaptureInterface _serverInterface; 29 | public Process Process { get; set; } 30 | 31 | /// 32 | /// Prepares capturing in the target process. Note that the process must not already be hooked, and must have a . 33 | /// 34 | /// The process to inject into 35 | /// Thrown if the does not have a window handle. This could mean that the process does not have a UI, or that the process has not yet finished starting. 36 | /// Thrown if the is already hooked 37 | /// Thrown if the injection failed - see the InnerException for more details. 38 | /// The target process will have its main window brought to the foreground after successful injection. 39 | public CaptureProcess(Process process, CaptureConfig config, CaptureInterface captureInterface) 40 | { 41 | // If the process doesn't have a mainwindowhandle yet, skip it (we need to be able to get the hwnd to set foreground etc) 42 | if (process.MainWindowHandle == IntPtr.Zero) 43 | { 44 | throw new ProcessHasNoWindowHandleException(); 45 | } 46 | 47 | // Skip if the process is already hooked (and we want to hook multiple applications) 48 | if (HookManager.IsHooked(process.Id)) 49 | { 50 | throw new ProcessAlreadyHookedException(); 51 | } 52 | 53 | captureInterface.ProcessId = process.Id; 54 | _serverInterface = captureInterface; 55 | //_serverInterface = new CaptureInterface() { ProcessId = process.Id }; 56 | 57 | // Initialise the IPC server (with our instance of _serverInterface) 58 | _screenshotServer = RemoteHooking.IpcCreateServer( 59 | ref _channelName, 60 | WellKnownObjectMode.Singleton, 61 | _serverInterface); 62 | 63 | try 64 | { 65 | 66 | // Inject DLL into target process 67 | RemoteHooking.Inject( 68 | process.Id, 69 | InjectionOptions.Default, 70 | typeof(CaptureInterface).Assembly.Location,//"Capture.dll", // 32-bit version (the same because AnyCPU) could use different assembly that links to 32-bit C++ helper dll 71 | typeof(CaptureInterface).Assembly.Location, //"Capture.dll", // 64-bit version (the same because AnyCPU) could use different assembly that links to 64-bit C++ helper dll 72 | // the optional parameter list... 73 | _channelName, // The name of the IPC channel for the injected assembly to connect to 74 | config 75 | ); 76 | } 77 | catch (Exception e) 78 | { 79 | throw new InjectionFailedException(e); 80 | } 81 | 82 | HookManager.AddHookedProcess(process.Id); 83 | 84 | Process = process; 85 | 86 | // Ensure the target process is in the foreground, 87 | // this prevents an issue where the target app appears to be in 88 | // the foreground but does not receive any user inputs. 89 | // Note: the first Alt+Tab out of the target application after injection 90 | // may still be an issue - switching between windowed and 91 | // fullscreen fixes the issue however (see ScreenshotInjection.cs for another option) 92 | BringProcessWindowToFront(); 93 | } 94 | 95 | public CaptureInterface CaptureInterface 96 | { 97 | get { return _serverInterface; } 98 | } 99 | 100 | ~CaptureProcess() 101 | { 102 | Dispose(false); 103 | } 104 | 105 | 106 | #region Private methods 107 | 108 | /// 109 | /// Bring the target window to the front and wait for it to be visible 110 | /// 111 | /// If the window does not come to the front within approx. 30 seconds an exception is raised 112 | public void BringProcessWindowToFront() 113 | { 114 | if (this.Process == null) 115 | return; 116 | IntPtr handle = this.Process.MainWindowHandle; 117 | int i = 0; 118 | 119 | while (!NativeMethods.IsWindowInForeground(handle)) 120 | { 121 | if (i == 0) 122 | { 123 | // Initial sleep if target window is not in foreground - just to let things settle 124 | Thread.Sleep(250); 125 | } 126 | 127 | if (NativeMethods.IsIconic(handle)) 128 | { 129 | // Minimized so send restore 130 | NativeMethods.ShowWindow(handle, NativeMethods.WindowShowStyle.Restore); 131 | } 132 | else 133 | { 134 | // Already Maximized or Restored so just bring to front 135 | NativeMethods.SetForegroundWindow(handle); 136 | } 137 | Thread.Sleep(250); 138 | 139 | // Check if the target process main window is now in the foreground 140 | if (NativeMethods.IsWindowInForeground(handle)) 141 | { 142 | // Leave enough time for screen to redraw 143 | Thread.Sleep(1000); 144 | return; 145 | } 146 | 147 | // Prevent an infinite loop 148 | if (i > 120) // about 30secs 149 | { 150 | throw new Exception("Could not set process window to the foreground"); 151 | } 152 | i++; 153 | } 154 | } 155 | 156 | #endregion 157 | 158 | #region IDispose 159 | 160 | private bool _disposed = false; 161 | public void Dispose() 162 | { 163 | Dispose(true); 164 | GC.SuppressFinalize(this); 165 | } 166 | 167 | protected virtual void Dispose(bool disposing) 168 | { 169 | if (!_disposed) 170 | { 171 | if (disposing) 172 | { 173 | // Disconnect the IPC (which causes the remote entry point to exit) 174 | _serverInterface.Disconnect(); 175 | } 176 | 177 | _disposed = true; 178 | } 179 | } 180 | 181 | #endregion 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /Match3Solver/Capture/EntryPoint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Capture.Hook; 6 | using Capture.Interface; 7 | using System.Threading.Tasks; 8 | using System.Runtime.Remoting.Channels.Ipc; 9 | 10 | namespace Capture 11 | { 12 | public class EntryPoint : EasyHook.IEntryPoint 13 | { 14 | List _directXHooks = new List(); 15 | IDXHook _directXHook = null; 16 | private CaptureInterface _interface; 17 | private System.Threading.ManualResetEvent _runWait; 18 | ClientCaptureInterfaceEventProxy _clientEventProxy = new ClientCaptureInterfaceEventProxy(); 19 | IpcServerChannel _clientServerChannel = null; 20 | 21 | public EntryPoint( 22 | EasyHook.RemoteHooking.IContext context, 23 | String channelName, 24 | CaptureConfig config) 25 | { 26 | // Get reference to IPC to host application 27 | // Note: any methods called or events triggered against _interface will execute in the host process. 28 | _interface = EasyHook.RemoteHooking.IpcConnectClient(channelName); 29 | 30 | // We try to ping immediately, if it fails then injection fails 31 | _interface.Ping(); 32 | 33 | #region Allow client event handlers (bi-directional IPC) 34 | 35 | // Attempt to create a IpcServerChannel so that any event handlers on the client will function correctly 36 | System.Collections.IDictionary properties = new System.Collections.Hashtable(); 37 | properties["name"] = channelName; 38 | properties["portName"] = channelName + Guid.NewGuid().ToString("N"); // random portName so no conflict with existing channels of channelName 39 | 40 | System.Runtime.Remoting.Channels.BinaryServerFormatterSinkProvider binaryProv = new System.Runtime.Remoting.Channels.BinaryServerFormatterSinkProvider(); 41 | binaryProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; 42 | 43 | System.Runtime.Remoting.Channels.Ipc.IpcServerChannel _clientServerChannel = new System.Runtime.Remoting.Channels.Ipc.IpcServerChannel(properties, binaryProv); 44 | System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(_clientServerChannel, false); 45 | 46 | #endregion 47 | } 48 | 49 | public void Run( 50 | EasyHook.RemoteHooking.IContext context, 51 | String channelName, 52 | CaptureConfig config) 53 | { 54 | // When not using GAC there can be issues with remoting assemblies resolving correctly 55 | // this is a workaround that ensures that the current assembly is correctly associated 56 | AppDomain currentDomain = AppDomain.CurrentDomain; 57 | currentDomain.AssemblyResolve += (sender, args) => 58 | { 59 | return this.GetType().Assembly.FullName == args.Name ? this.GetType().Assembly : null; 60 | }; 61 | 62 | // NOTE: This is running in the target process 63 | _interface.Message(MessageType.Information, "Injected into process Id:{0}.", EasyHook.RemoteHooking.GetCurrentProcessId()); 64 | 65 | _runWait = new System.Threading.ManualResetEvent(false); 66 | _runWait.Reset(); 67 | try 68 | { 69 | // Initialise the Hook 70 | if (!InitialiseDirectXHook(config)) 71 | { 72 | return; 73 | } 74 | _interface.Disconnected += _clientEventProxy.DisconnectedProxyHandler; 75 | 76 | // Important Note: 77 | // accessing the _interface from within a _clientEventProxy event handler must always 78 | // be done on a different thread otherwise it will cause a deadlock 79 | 80 | _clientEventProxy.Disconnected += () => 81 | { 82 | // We can now signal the exit of the Run method 83 | _runWait.Set(); 84 | }; 85 | 86 | // We start a thread here to periodically check if the host is still running 87 | // If the host process stops then we will automatically uninstall the hooks 88 | StartCheckHostIsAliveThread(); 89 | 90 | // Wait until signaled for exit either when a Disconnect message from the host 91 | // or if the the check is alive has failed to Ping the host. 92 | _runWait.WaitOne(); 93 | 94 | // we need to tell the check host thread to exit (if it hasn't already) 95 | StopCheckHostIsAliveThread(); 96 | 97 | // Dispose of the DXHook so any installed hooks are removed correctly 98 | DisposeDirectXHook(); 99 | } 100 | catch (Exception e) 101 | { 102 | _interface.Message(MessageType.Error, "An unexpected error occured: {0}", e.ToString()); 103 | } 104 | finally 105 | { 106 | try 107 | { 108 | _interface.Message(MessageType.Information, "Disconnecting from process {0}", EasyHook.RemoteHooking.GetCurrentProcessId()); 109 | } 110 | catch 111 | { 112 | } 113 | 114 | // Remove the client server channel (that allows client event handlers) 115 | System.Runtime.Remoting.Channels.ChannelServices.UnregisterChannel(_clientServerChannel); 116 | 117 | // Always sleep long enough for any remaining messages to complete sending 118 | System.Threading.Thread.Sleep(100); 119 | } 120 | } 121 | 122 | private void DisposeDirectXHook() 123 | { 124 | if (_directXHooks != null) 125 | { 126 | try 127 | { 128 | _interface.Message(MessageType.Debug, "Disposing of hooks..."); 129 | } 130 | catch (System.Runtime.Remoting.RemotingException) { } // Ignore channel remoting errors 131 | 132 | // Dispose of the hooks so they are removed 133 | foreach (var dxHook in _directXHooks) 134 | dxHook.Dispose(); 135 | 136 | _directXHooks.Clear(); 137 | } 138 | } 139 | 140 | private bool InitialiseDirectXHook(CaptureConfig config) 141 | { 142 | Direct3DVersion version = config.Direct3DVersion; 143 | 144 | List loadedVersions = new List(); 145 | 146 | bool isX64Process = EasyHook.RemoteHooking.IsX64Process(EasyHook.RemoteHooking.GetCurrentProcessId()); 147 | _interface.Message(MessageType.Information, "Remote process is a {0}-bit process.", isX64Process ? "64" : "32"); 148 | 149 | try 150 | { 151 | if (version == Direct3DVersion.AutoDetect || version == Direct3DVersion.Unknown) 152 | { 153 | // Attempt to determine the correct version based on loaded module. 154 | // In most cases this will work fine, however it is perfectly ok for an application to use a D3D10 device along with D3D11 devices 155 | // so the version might matched might not be the one you want to use 156 | IntPtr d3D9Loaded = IntPtr.Zero; 157 | IntPtr d3D10Loaded = IntPtr.Zero; 158 | IntPtr d3D10_1Loaded = IntPtr.Zero; 159 | IntPtr d3D11Loaded = IntPtr.Zero; 160 | IntPtr d3D11_1Loaded = IntPtr.Zero; 161 | 162 | int delayTime = 100; 163 | int retryCount = 0; 164 | while (d3D9Loaded == IntPtr.Zero && d3D10Loaded == IntPtr.Zero && d3D10_1Loaded == IntPtr.Zero && d3D11Loaded == IntPtr.Zero && d3D11_1Loaded == IntPtr.Zero) 165 | { 166 | retryCount++; 167 | d3D9Loaded = NativeMethods.GetModuleHandle("d3d9.dll"); 168 | d3D10Loaded = NativeMethods.GetModuleHandle("d3d10.dll"); 169 | d3D10_1Loaded = NativeMethods.GetModuleHandle("d3d10_1.dll"); 170 | d3D11Loaded = NativeMethods.GetModuleHandle("d3d11.dll"); 171 | d3D11_1Loaded = NativeMethods.GetModuleHandle("d3d11_1.dll"); 172 | System.Threading.Thread.Sleep(delayTime); 173 | 174 | if (retryCount * delayTime > 5000) 175 | { 176 | _interface.Message(MessageType.Error, "Unsupported Direct3D version, or Direct3D DLL not loaded within 5 seconds."); 177 | return false; 178 | } 179 | } 180 | 181 | version = Direct3DVersion.Unknown; 182 | if (d3D11_1Loaded != IntPtr.Zero) 183 | { 184 | _interface.Message(MessageType.Debug, "Autodetect found Direct3D 11.1"); 185 | version = Direct3DVersion.Direct3D11_1; 186 | loadedVersions.Add(version); 187 | } 188 | if (d3D11Loaded != IntPtr.Zero) 189 | { 190 | _interface.Message(MessageType.Debug, "Autodetect found Direct3D 11"); 191 | version = Direct3DVersion.Direct3D11; 192 | loadedVersions.Add(version); 193 | } 194 | if (d3D10_1Loaded != IntPtr.Zero) 195 | { 196 | _interface.Message(MessageType.Debug, "Autodetect found Direct3D 10.1"); 197 | version = Direct3DVersion.Direct3D10_1; 198 | loadedVersions.Add(version); 199 | } 200 | if (d3D10Loaded != IntPtr.Zero) 201 | { 202 | _interface.Message(MessageType.Debug, "Autodetect found Direct3D 10"); 203 | version = Direct3DVersion.Direct3D10; 204 | loadedVersions.Add(version); 205 | } 206 | if (d3D9Loaded != IntPtr.Zero) 207 | { 208 | _interface.Message(MessageType.Debug, "Autodetect found Direct3D 9"); 209 | version = Direct3DVersion.Direct3D9; 210 | loadedVersions.Add(version); 211 | } 212 | } 213 | else 214 | { 215 | // If not autodetect, assume specified version is loaded 216 | loadedVersions.Add(version); 217 | } 218 | 219 | foreach (var dxVersion in loadedVersions) 220 | { 221 | version = dxVersion; 222 | switch (version) 223 | { 224 | case Direct3DVersion.Direct3D9: 225 | _directXHook = new DXHookD3D9(_interface); 226 | break; 227 | case Direct3DVersion.Direct3D10: 228 | _directXHook = new DXHookD3D10(_interface); 229 | break; 230 | case Direct3DVersion.Direct3D10_1: 231 | _directXHook = new DXHookD3D10_1(_interface); 232 | break; 233 | case Direct3DVersion.Direct3D11: 234 | _directXHook = new DXHookD3D11(_interface); 235 | break; 236 | //case Direct3DVersion.Direct3D11_1: 237 | // _directXHook = new DXHookD3D11_1(_interface); 238 | // return; 239 | default: 240 | _interface.Message(MessageType.Error, "Unsupported Direct3D version: {0}", version); 241 | return false; 242 | } 243 | 244 | _directXHook.Config = config; 245 | _directXHook.Hook(); 246 | 247 | _directXHooks.Add(_directXHook); 248 | } 249 | 250 | return true; 251 | 252 | } 253 | catch (Exception e) 254 | { 255 | // Notify the host/server application about this error 256 | _interface.Message(MessageType.Error, "Error in InitialiseHook: {0}", e.ToString()); 257 | return false; 258 | } 259 | } 260 | 261 | #region Check Host Is Alive 262 | 263 | Task _checkAlive; 264 | long _stopCheckAlive = 0; 265 | 266 | /// 267 | /// Begin a background thread to check periodically that the host process is still accessible on its IPC channel 268 | /// 269 | private void StartCheckHostIsAliveThread() 270 | { 271 | _checkAlive = new Task(() => 272 | { 273 | try 274 | { 275 | while (System.Threading.Interlocked.Read(ref _stopCheckAlive) == 0) 276 | { 277 | System.Threading.Thread.Sleep(1000); 278 | 279 | // .NET Remoting exceptions will throw RemotingException 280 | _interface.Ping(); 281 | } 282 | } 283 | catch // We will assume that any exception means that the hooks need to be removed. 284 | { 285 | // Signal the Run method so that it can exit 286 | _runWait.Set(); 287 | } 288 | }); 289 | 290 | _checkAlive.Start(); 291 | } 292 | 293 | /// 294 | /// Tell the _checkAlive thread that it can exit if it hasn't already 295 | /// 296 | private void StopCheckHostIsAliveThread() 297 | { 298 | System.Threading.Interlocked.Increment(ref _stopCheckAlive); 299 | } 300 | 301 | #endregion 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Exceptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture 7 | { 8 | /// 9 | /// Indicates that the provided process does not have a window handle. 10 | /// 11 | public class ProcessHasNoWindowHandleException : Exception 12 | { 13 | public ProcessHasNoWindowHandleException() 14 | : base("The process does not have a window handle.") 15 | { 16 | } 17 | } 18 | 19 | public class ProcessAlreadyHookedException : Exception 20 | { 21 | public ProcessAlreadyHookedException() 22 | : base("The process is already hooked.") 23 | { 24 | } 25 | } 26 | 27 | public class InjectionFailedException : Exception 28 | { 29 | public InjectionFailedException(Exception innerException) 30 | : base("Injection to the target process failed. See InnerException for more detail.", innerException) 31 | { 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/Common/Element.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Remoting; 5 | using System.Security.Permissions; 6 | using System.Text; 7 | 8 | namespace Capture.Hook.Common 9 | { 10 | [Serializable] 11 | public abstract class Element: IOverlayElement, IDisposable 12 | { 13 | public virtual bool Hidden { get; set; } 14 | 15 | ~Element() 16 | { 17 | Dispose(false); 18 | } 19 | 20 | public virtual void Frame() 21 | { 22 | } 23 | 24 | public virtual object Clone() 25 | { 26 | return MemberwiseClone(); 27 | } 28 | 29 | 30 | public void Dispose() 31 | { 32 | Dispose(true); 33 | GC.SuppressFinalize(this); 34 | } 35 | 36 | /// 37 | /// Releases unmanaged and optionally managed resources 38 | /// 39 | /// true if disposing both unmanaged and managed 40 | protected virtual void Dispose(bool disposing) 41 | { 42 | if (disposing) 43 | { 44 | } 45 | } 46 | 47 | protected void SafeDispose(IDisposable disposableObj) 48 | { 49 | if (disposableObj != null) 50 | disposableObj.Dispose(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/Common/FramesPerSecond.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Hook.Common 7 | { 8 | [Serializable] 9 | public class FramesPerSecond: TextElement 10 | { 11 | string _fpsFormat = "{0:N0} fps"; 12 | public override string Text 13 | { 14 | get 15 | { 16 | return String.Format(_fpsFormat, GetFPS()); 17 | } 18 | set 19 | { 20 | _fpsFormat = value; 21 | } 22 | } 23 | 24 | int _frames = 0; 25 | int _lastTickCount = 0; 26 | float _lastFrameRate = 0; 27 | 28 | public FramesPerSecond(System.Drawing.Font font) 29 | : base(font) 30 | { 31 | } 32 | 33 | /// 34 | /// Must be called each frame 35 | /// 36 | public override void Frame() 37 | { 38 | _frames++; 39 | if (Math.Abs(Environment.TickCount - _lastTickCount) > 1000) 40 | { 41 | _lastFrameRate = (float)_frames * 1000 / Math.Abs(Environment.TickCount - _lastTickCount); 42 | _lastTickCount = Environment.TickCount; 43 | _frames = 0; 44 | } 45 | } 46 | 47 | /// 48 | /// Return the current frames per second 49 | /// 50 | /// 51 | public float GetFPS() 52 | { 53 | return _lastFrameRate; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/Common/IOverlay.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using SharpDX; 6 | 7 | namespace Capture.Hook.Common 8 | { 9 | public interface IOverlay: IOverlayElement 10 | { 11 | List Elements { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/Common/IOverlayElement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using SharpDX; 6 | 7 | namespace Capture.Hook.Common 8 | { 9 | public interface IOverlayElement : ICloneable 10 | { 11 | bool Hidden { get; set; } 12 | 13 | void Frame(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/Common/ImageElement.cs: -------------------------------------------------------------------------------- 1 | using Capture.Interface; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace Capture.Hook.Common 8 | { 9 | [Serializable] 10 | public class ImageElement: Element 11 | { 12 | /// 13 | /// The image file bytes 14 | /// 15 | public virtual byte[] Image { get; set; } 16 | 17 | System.Drawing.Bitmap _bitmap = null; 18 | internal virtual System.Drawing.Bitmap Bitmap { 19 | get 20 | { 21 | if (_bitmap == null && Image != null) 22 | { 23 | _bitmap = Image.ToBitmap(); 24 | _ownsBitmap = true; 25 | } 26 | 27 | return _bitmap; 28 | } 29 | set { _bitmap = value; } 30 | } 31 | 32 | /// 33 | /// This value is multiplied with the source color (e.g. White will result in same color as source image) 34 | /// 35 | /// 36 | /// Defaults to . 37 | /// 38 | public virtual System.Drawing.Color Tint { get; set; } = System.Drawing.Color.White; 39 | 40 | /// 41 | /// The location of where to render this image element 42 | /// 43 | public virtual System.Drawing.Point Location { get; set; } 44 | 45 | public float Angle { get; set; } 46 | 47 | public float Scale { get; set; } = 1.0f; 48 | 49 | public string Filename { get; set; } 50 | 51 | bool _ownsBitmap = false; 52 | 53 | public ImageElement() { } 54 | 55 | public ImageElement(string filename): 56 | this(new System.Drawing.Bitmap(filename), true) 57 | { 58 | Filename = filename; 59 | } 60 | 61 | public ImageElement(System.Drawing.Bitmap bitmap, bool ownsImage = false) 62 | { 63 | Tint = System.Drawing.Color.White; 64 | this.Bitmap = bitmap; 65 | _ownsBitmap = ownsImage; 66 | Scale = 1.0f; 67 | } 68 | 69 | protected override void Dispose(bool disposing) 70 | { 71 | base.Dispose(disposing); 72 | 73 | if (disposing) 74 | { 75 | if (_ownsBitmap) 76 | { 77 | SafeDispose(this.Bitmap); 78 | this.Bitmap = null; 79 | } 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/Common/Overlay.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Hook.Common 7 | { 8 | [Serializable] 9 | public class Overlay: IOverlay 10 | { 11 | List _elements = new List(); 12 | public virtual List Elements 13 | { 14 | get { return _elements; } 15 | set { _elements = value; } 16 | } 17 | 18 | public virtual bool Hidden 19 | { 20 | get; 21 | set; 22 | } 23 | 24 | public virtual void Frame() 25 | { 26 | foreach (var element in Elements) 27 | { 28 | element.Frame(); 29 | } 30 | } 31 | 32 | public virtual object Clone() 33 | { 34 | return MemberwiseClone(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/Common/TextElement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Hook.Common 7 | { 8 | [Serializable] 9 | public class TextElement: Element 10 | { 11 | public virtual string Text { get; set; } 12 | public virtual System.Drawing.Font Font { get; set; } = System.Drawing.SystemFonts.DefaultFont; 13 | public virtual System.Drawing.Color Color { get; set; } = System.Drawing.Color.Black; 14 | public virtual System.Drawing.Point Location { get; set; } 15 | public virtual bool AntiAliased { get; set; } = false; 16 | 17 | public TextElement() { } 18 | 19 | public TextElement(System.Drawing.Font font) 20 | { 21 | Font = font; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/D3D9.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace Capture.Hook 8 | { 9 | /// 10 | /// The full list of IDirect3DDevice9 functions with the correct index 11 | /// 12 | public enum Direct3DDevice9FunctionOrdinals : short 13 | { 14 | QueryInterface = 0, 15 | AddRef = 1, 16 | Release = 2, 17 | TestCooperativeLevel = 3, 18 | GetAvailableTextureMem = 4, 19 | EvictManagedResources = 5, 20 | GetDirect3D = 6, 21 | GetDeviceCaps = 7, 22 | GetDisplayMode = 8, 23 | GetCreationParameters = 9, 24 | SetCursorProperties = 10, 25 | SetCursorPosition = 11, 26 | ShowCursor = 12, 27 | CreateAdditionalSwapChain = 13, 28 | GetSwapChain = 14, 29 | GetNumberOfSwapChains = 15, 30 | Reset = 16, 31 | Present = 17, 32 | GetBackBuffer = 18, 33 | GetRasterStatus = 19, 34 | SetDialogBoxMode = 20, 35 | SetGammaRamp = 21, 36 | GetGammaRamp = 22, 37 | CreateTexture = 23, 38 | CreateVolumeTexture = 24, 39 | CreateCubeTexture = 25, 40 | CreateVertexBuffer = 26, 41 | CreateIndexBuffer = 27, 42 | CreateRenderTarget = 28, 43 | CreateDepthStencilSurface = 29, 44 | UpdateSurface = 30, 45 | UpdateTexture = 31, 46 | GetRenderTargetData = 32, 47 | GetFrontBufferData = 33, 48 | StretchRect = 34, 49 | ColorFill = 35, 50 | CreateOffscreenPlainSurface = 36, 51 | SetRenderTarget = 37, 52 | GetRenderTarget = 38, 53 | SetDepthStencilSurface = 39, 54 | GetDepthStencilSurface = 40, 55 | BeginScene = 41, 56 | EndScene = 42, 57 | Clear = 43, 58 | SetTransform = 44, 59 | GetTransform = 45, 60 | MultiplyTransform = 46, 61 | SetViewport = 47, 62 | GetViewport = 48, 63 | SetMaterial = 49, 64 | GetMaterial = 50, 65 | SetLight = 51, 66 | GetLight = 52, 67 | LightEnable = 53, 68 | GetLightEnable = 54, 69 | SetClipPlane = 55, 70 | GetClipPlane = 56, 71 | SetRenderState = 57, 72 | GetRenderState = 58, 73 | CreateStateBlock = 59, 74 | BeginStateBlock = 60, 75 | EndStateBlock = 61, 76 | SetClipStatus = 62, 77 | GetClipStatus = 63, 78 | GetTexture = 64, 79 | SetTexture = 65, 80 | GetTextureStageState = 66, 81 | SetTextureStageState = 67, 82 | GetSamplerState = 68, 83 | SetSamplerState = 69, 84 | ValidateDevice = 70, 85 | SetPaletteEntries = 71, 86 | GetPaletteEntries = 72, 87 | SetCurrentTexturePalette = 73, 88 | GetCurrentTexturePalette = 74, 89 | SetScissorRect = 75, 90 | GetScissorRect = 76, 91 | SetSoftwareVertexProcessing = 77, 92 | GetSoftwareVertexProcessing = 78, 93 | SetNPatchMode = 79, 94 | GetNPatchMode = 80, 95 | DrawPrimitive = 81, 96 | DrawIndexedPrimitive = 82, 97 | DrawPrimitiveUP = 83, 98 | DrawIndexedPrimitiveUP = 84, 99 | ProcessVertices = 85, 100 | CreateVertexDeclaration = 86, 101 | SetVertexDeclaration = 87, 102 | GetVertexDeclaration = 88, 103 | SetFVF = 89, 104 | GetFVF = 90, 105 | CreateVertexShader = 91, 106 | SetVertexShader = 92, 107 | GetVertexShader = 93, 108 | SetVertexShaderConstantF = 94, 109 | GetVertexShaderConstantF = 95, 110 | SetVertexShaderConstantI = 96, 111 | GetVertexShaderConstantI = 97, 112 | SetVertexShaderConstantB = 98, 113 | GetVertexShaderConstantB = 99, 114 | SetStreamSource = 100, 115 | GetStreamSource = 101, 116 | SetStreamSourceFreq = 102, 117 | GetStreamSourceFreq = 103, 118 | SetIndices = 104, 119 | GetIndices = 105, 120 | CreatePixelShader = 106, 121 | SetPixelShader = 107, 122 | GetPixelShader = 108, 123 | SetPixelShaderConstantF = 109, 124 | GetPixelShaderConstantF = 110, 125 | SetPixelShaderConstantI = 111, 126 | GetPixelShaderConstantI = 112, 127 | SetPixelShaderConstantB = 113, 128 | GetPixelShaderConstantB = 114, 129 | DrawRectPatch = 115, 130 | DrawTriPatch = 116, 131 | DeletePatch = 117, 132 | CreateQuery = 118, 133 | } 134 | 135 | public enum Direct3DDevice9ExFunctionOrdinals : short 136 | { 137 | SetConvolutionMonoKernel = 119, 138 | ComposeRects = 120, 139 | PresentEx = 121, 140 | GetGPUThreadPriority = 122, 141 | SetGPUThreadPriority = 123, 142 | WaitForVBlank = 124, 143 | CheckResourceResidency = 125, 144 | SetMaximumFrameLatency = 126, 145 | GetMaximumFrameLatency = 127, 146 | CheckDeviceState_ = 128, 147 | CreateRenderTargetEx = 129, 148 | CreateOffscreenPlainSurfaceEx = 130, 149 | CreateDepthStencilSurfaceEx = 131, 150 | ResetEx = 132, 151 | GetDisplayModeEx = 133, 152 | } 153 | 154 | } 155 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/DX11/ContextState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Hook.DX11 7 | { 8 | public class ContextState 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/DX11/DXFont.cs: -------------------------------------------------------------------------------- 1 | // Adapted from Frank Luna's "Sprites and Text" example here: http://www.d3dcoder.net/resources.htm 2 | // checkout his books here: http://www.d3dcoder.net/default.htm 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using SharpDX.Direct3D11; 8 | using SharpDX; 9 | using System.Diagnostics; 10 | 11 | namespace Capture.Hook.DX11 12 | { 13 | public class DXFont : IDisposable 14 | { 15 | Device _device; 16 | DeviceContext _deviceContext; 17 | 18 | public DXFont(Device device, DeviceContext deviceContext) 19 | { 20 | _device = device; 21 | _deviceContext = deviceContext; 22 | _initialized = false; 23 | _fontSheetTex = null; 24 | _fontSheetSRV = null; 25 | _texWidth = 1024; 26 | _texHeight = 0; 27 | _spaceWidth = 0; 28 | _charHeight = 0; 29 | } 30 | 31 | public void Dispose() 32 | { 33 | if (_fontSheetTex != null) 34 | _fontSheetTex.Dispose(); 35 | if (_fontSheetSRV != null) 36 | _fontSheetSRV.Dispose(); 37 | 38 | _fontSheetTex = null; 39 | _fontSheetSRV = null; 40 | _device = null; 41 | _deviceContext = null; 42 | } 43 | 44 | enum STYLE 45 | { 46 | STYLE_NORMAL = 0, 47 | STYLE_BOLD = 1, 48 | STYLE_ITALIC = 2, 49 | STYLE_BOLD_ITALIC = 3, 50 | STYLE_UNDERLINE = 4, 51 | STYLE_STRIKEOUT = 8 52 | }; 53 | 54 | bool _initialized; 55 | const char StartChar = (char)33; 56 | const char EndChar = (char)127; 57 | const uint NumChars = EndChar - StartChar; 58 | ShaderResourceView _fontSheetSRV; 59 | Texture2D _fontSheetTex; 60 | int _texWidth, _texHeight; 61 | Rectangle[] _charRects = new Rectangle[NumChars]; 62 | int _spaceWidth, _charHeight; 63 | 64 | public bool Initialize(string FontName, float FontSize, System.Drawing.FontStyle FontStyle, bool AntiAliased) 65 | { 66 | Debug.Assert(!_initialized); 67 | System.Drawing.Font font = new System.Drawing.Font(FontName, FontSize, FontStyle, System.Drawing.GraphicsUnit.Pixel); 68 | 69 | System.Drawing.Text.TextRenderingHint hint = AntiAliased ? System.Drawing.Text.TextRenderingHint.AntiAlias : System.Drawing.Text.TextRenderingHint.SystemDefault; 70 | 71 | int tempSize = (int)(FontSize * 2); 72 | using (System.Drawing.Bitmap charBitmap = new System.Drawing.Bitmap(tempSize, tempSize, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) 73 | { 74 | using (System.Drawing.Graphics charGraphics = System.Drawing.Graphics.FromImage(charBitmap)) 75 | { 76 | charGraphics.PageUnit = System.Drawing.GraphicsUnit.Pixel; 77 | charGraphics.TextRenderingHint = hint; 78 | 79 | MeasureChars(font, charGraphics); 80 | 81 | using (var fontSheetBitmap = new System.Drawing.Bitmap(_texWidth, _texHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) 82 | { 83 | using (var fontSheetGraphics = System.Drawing.Graphics.FromImage(fontSheetBitmap)) 84 | { 85 | fontSheetGraphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; 86 | fontSheetGraphics.Clear(System.Drawing.Color.FromArgb(0, System.Drawing.Color.Black)); 87 | 88 | BuildFontSheetBitmap(font, charGraphics, charBitmap, fontSheetGraphics); 89 | 90 | if (!BuildFontSheetTexture(fontSheetBitmap)) 91 | { 92 | return false; 93 | } 94 | } 95 | //System.Drawing.Bitmap bm = new System.Drawing.Bitmap(fontSheetBitmap); 96 | //bm.Save(@"C:\temp\test.png"); 97 | } 98 | } 99 | } 100 | 101 | _initialized = true; 102 | 103 | return true; 104 | } 105 | 106 | private bool BuildFontSheetTexture(System.Drawing.Bitmap fontSheetBitmap) 107 | { 108 | System.Drawing.Imaging.BitmapData bmData; 109 | 110 | bmData = fontSheetBitmap.LockBits(new System.Drawing.Rectangle(0, 0, _texWidth, _texHeight), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 111 | Texture2DDescription texDesc = new Texture2DDescription(); 112 | texDesc.Width = _texWidth; 113 | texDesc.Height = _texHeight; 114 | texDesc.MipLevels = 1; 115 | texDesc.ArraySize = 1; 116 | texDesc.Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm; 117 | texDesc.SampleDescription.Count = 1; 118 | texDesc.SampleDescription.Quality = 0; 119 | texDesc.Usage = ResourceUsage.Immutable; 120 | texDesc.BindFlags = BindFlags.ShaderResource; 121 | texDesc.CpuAccessFlags = CpuAccessFlags.None; 122 | texDesc.OptionFlags = ResourceOptionFlags.None; 123 | 124 | 125 | SharpDX.DataBox data; 126 | data.DataPointer = bmData.Scan0; 127 | data.RowPitch = _texWidth * 4; 128 | data.SlicePitch = 0; 129 | 130 | _fontSheetTex = new Texture2D(_device, texDesc, new[] { data }); 131 | if (_fontSheetTex == null) 132 | return false; 133 | 134 | ShaderResourceViewDescription srvDesc = new ShaderResourceViewDescription(); 135 | srvDesc.Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm; 136 | srvDesc.Dimension = SharpDX.Direct3D.ShaderResourceViewDimension.Texture2D; 137 | srvDesc.Texture2D.MipLevels = 1; 138 | srvDesc.Texture2D.MostDetailedMip = 0; 139 | 140 | _fontSheetSRV = new ShaderResourceView(_device, _fontSheetTex, srvDesc); 141 | if (_fontSheetSRV == null) 142 | return false; 143 | 144 | fontSheetBitmap.UnlockBits(bmData); 145 | 146 | return true; 147 | } 148 | 149 | void MeasureChars(System.Drawing.Font font, System.Drawing.Graphics charGraphics) 150 | { 151 | char[] allChars = new char[NumChars]; 152 | 153 | for (char i = (char)0; i < NumChars; ++i) 154 | allChars[i] = (char)(StartChar + i); 155 | 156 | System.Drawing.SizeF size; 157 | size = charGraphics.MeasureString(new String(allChars), font, new System.Drawing.PointF(0, 0), System.Drawing.StringFormat.GenericDefault); 158 | 159 | _charHeight = (int)(size.Height + 0.5f); 160 | 161 | int numRows = (int)(size.Width / _texWidth) + 1; 162 | _texHeight = (numRows * _charHeight) + 1; 163 | 164 | System.Drawing.StringFormat sf = System.Drawing.StringFormat.GenericDefault; 165 | sf.FormatFlags |= System.Drawing.StringFormatFlags.MeasureTrailingSpaces; 166 | size = charGraphics.MeasureString(" ", font, 0, sf); 167 | _spaceWidth = (int)(size.Width + 0.5f); 168 | } 169 | 170 | void BuildFontSheetBitmap(System.Drawing.Font font, System.Drawing.Graphics charGraphics, System.Drawing.Bitmap charBitmap, System.Drawing.Graphics fontSheetGraphics) 171 | { 172 | System.Drawing.Brush whiteBrush = System.Drawing.Brushes.White; 173 | int fontSheetX = 0; 174 | int fontSheetY = 0; 175 | 176 | 177 | for (int i = 0; i < NumChars; ++i) 178 | { 179 | charGraphics.Clear(System.Drawing.Color.FromArgb(0, System.Drawing.Color.Black)); 180 | charGraphics.DrawString(((char)(StartChar + i)).ToString(), font, whiteBrush, new System.Drawing.PointF(0.0f, 0.0f)); 181 | 182 | int minX = GetCharMinX(charBitmap); 183 | int maxX = GetCharMaxX(charBitmap); 184 | int charWidth = maxX - minX + 1; 185 | 186 | if (fontSheetX + charWidth >= _texWidth) 187 | { 188 | fontSheetX = 0; 189 | fontSheetY += (int)(_charHeight) + 1; 190 | } 191 | 192 | _charRects[i] = new Rectangle(fontSheetX, fontSheetY, charWidth, _charHeight); 193 | 194 | fontSheetGraphics.DrawImage(charBitmap, fontSheetX, fontSheetY, new System.Drawing.Rectangle(minX, 0, charWidth, _charHeight), System.Drawing.GraphicsUnit.Pixel); 195 | 196 | fontSheetX += charWidth + 1; 197 | } 198 | } 199 | 200 | private int GetCharMaxX(System.Drawing.Bitmap charBitmap) 201 | { 202 | int width = charBitmap.Width; 203 | int height = charBitmap.Height; 204 | 205 | for (int x = width - 1; x >= 0; --x) 206 | { 207 | for (int y = 0; y < height; ++y) 208 | { 209 | System.Drawing.Color color; 210 | 211 | color = charBitmap.GetPixel(x, y); 212 | if (color.A > 0) 213 | return x; 214 | } 215 | } 216 | 217 | return width - 1; 218 | } 219 | 220 | private int GetCharMinX(System.Drawing.Bitmap charBitmap) 221 | { 222 | int width = charBitmap.Width; 223 | int height = charBitmap.Height; 224 | 225 | for (int x = 0; x < width; ++x) 226 | { 227 | for (int y = 0; y < height; ++y) 228 | { 229 | System.Drawing.Color color; 230 | 231 | color = charBitmap.GetPixel(x, y); 232 | if (color.A > 0) 233 | return x; 234 | } 235 | } 236 | 237 | return 0; 238 | } 239 | 240 | public ShaderResourceView GetFontSheetSRV() 241 | { 242 | Debug.Assert(_initialized); 243 | 244 | return _fontSheetSRV; 245 | } 246 | 247 | public Rectangle GetCharRect(char c) 248 | { 249 | Debug.Assert(_initialized); 250 | 251 | return _charRects[c - StartChar]; 252 | } 253 | 254 | public int GetSpaceWidth() 255 | { 256 | Debug.Assert(_initialized); 257 | 258 | return _spaceWidth; 259 | } 260 | 261 | public int GetCharHeight() 262 | { 263 | Debug.Assert(_initialized); 264 | 265 | return _charHeight; 266 | } 267 | 268 | } 269 | } 270 | 271 | 272 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/DX11/DXImage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using SharpDX.Direct3D11; 6 | using SharpDX; 7 | using System.Diagnostics; 8 | 9 | namespace Capture.Hook.DX11 10 | { 11 | public class DXImage : Component 12 | { 13 | Device _device; 14 | DeviceContext _deviceContext; 15 | Texture2D _tex; 16 | ShaderResourceView _texSRV; 17 | int _texWidth, _texHeight; 18 | bool _initialised = false; 19 | 20 | public int Width 21 | { 22 | get 23 | { 24 | return _texWidth; 25 | } 26 | } 27 | 28 | public int Height 29 | { 30 | get 31 | { 32 | return _texHeight; 33 | } 34 | } 35 | 36 | public Device Device 37 | { 38 | get { return _device; } 39 | } 40 | 41 | public DXImage(Device device, DeviceContext deviceContext): base("DXImage") 42 | { 43 | _device = device; 44 | _deviceContext = deviceContext; 45 | _tex = null; 46 | _texSRV = null; 47 | _texWidth = 0; 48 | _texHeight = 0; 49 | } 50 | 51 | public bool Initialise(System.Drawing.Bitmap bitmap) 52 | { 53 | RemoveAndDispose(ref _tex); 54 | RemoveAndDispose(ref _texSRV); 55 | 56 | //Debug.Assert(bitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb); 57 | System.Drawing.Imaging.BitmapData bmData; 58 | 59 | _texWidth = bitmap.Width; 60 | _texHeight = bitmap.Height; 61 | 62 | bmData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, _texWidth, _texHeight), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 63 | try 64 | { 65 | Texture2DDescription texDesc = new Texture2DDescription(); 66 | texDesc.Width = _texWidth; 67 | texDesc.Height = _texHeight; 68 | texDesc.MipLevels = 1; 69 | texDesc.ArraySize = 1; 70 | texDesc.Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm; 71 | texDesc.SampleDescription.Count = 1; 72 | texDesc.SampleDescription.Quality = 0; 73 | texDesc.Usage = ResourceUsage.Immutable; 74 | texDesc.BindFlags = BindFlags.ShaderResource; 75 | texDesc.CpuAccessFlags = CpuAccessFlags.None; 76 | texDesc.OptionFlags = ResourceOptionFlags.None; 77 | 78 | SharpDX.DataBox data; 79 | data.DataPointer = bmData.Scan0; 80 | data.RowPitch = bmData.Stride;// _texWidth * 4; 81 | data.SlicePitch = 0; 82 | 83 | _tex = ToDispose(new Texture2D(_device, texDesc, new[] { data })); 84 | if (_tex == null) 85 | return false; 86 | 87 | ShaderResourceViewDescription srvDesc = new ShaderResourceViewDescription(); 88 | srvDesc.Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm; 89 | srvDesc.Dimension = SharpDX.Direct3D.ShaderResourceViewDimension.Texture2D; 90 | srvDesc.Texture2D.MipLevels = 1; 91 | srvDesc.Texture2D.MostDetailedMip = 0; 92 | 93 | _texSRV = ToDispose(new ShaderResourceView(_device, _tex, srvDesc)); 94 | if (_texSRV == null) 95 | return false; 96 | } 97 | finally 98 | { 99 | bitmap.UnlockBits(bmData); 100 | } 101 | 102 | _initialised = true; 103 | 104 | return true; 105 | } 106 | 107 | public ShaderResourceView GetSRV() 108 | { 109 | Debug.Assert(_initialised); 110 | return _texSRV; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/DX11/DXOverlayEngine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Capture.Hook.Common; 6 | using SharpDX.Direct3D11; 7 | using SharpDX; 8 | using System.Diagnostics; 9 | 10 | namespace Capture.Hook.DX11 11 | { 12 | internal class DXOverlayEngine: Component 13 | { 14 | public List Overlays { get; set; } 15 | public bool DeferredContext 16 | { 17 | get 18 | { 19 | return _deviceContext.TypeInfo == DeviceContextType.Deferred; 20 | } 21 | } 22 | 23 | bool _initialised = false; 24 | bool _initialising = false; 25 | 26 | Device _device; 27 | DeviceContext _deviceContext; 28 | Texture2D _renderTarget; 29 | RenderTargetView _renderTargetView; 30 | DXSprite _spriteEngine; 31 | Dictionary _fontCache = new Dictionary(); 32 | Dictionary _imageCache = new Dictionary(); 33 | 34 | public DXOverlayEngine() 35 | { 36 | Overlays = new List(); 37 | } 38 | 39 | private void EnsureInitiliased() 40 | { 41 | if (!_initialised) 42 | throw new InvalidOperationException("DXOverlayEngine must be initialised."); 43 | } 44 | 45 | public bool Initialise(SharpDX.DXGI.SwapChain swapChain) 46 | { 47 | return Initialise(swapChain.GetDevice(), swapChain.GetBackBuffer(0)); 48 | } 49 | 50 | public bool Initialise(Device device, Texture2D renderTarget) 51 | { 52 | if (_initialising) 53 | return false; 54 | 55 | _initialising = true; 56 | 57 | try 58 | { 59 | 60 | _device = device; 61 | _renderTarget = renderTarget; 62 | try 63 | { 64 | _deviceContext = ToDispose(new DeviceContext(_device)); 65 | } 66 | catch (SharpDXException) 67 | { 68 | _deviceContext = _device.ImmediateContext; 69 | } 70 | 71 | _renderTargetView = ToDispose(new RenderTargetView(_device, _renderTarget)); 72 | 73 | //if (DeferredContext) 74 | //{ 75 | // ViewportF[] viewportf = { new ViewportF(0, 0, _renderTarget.Description.Width, _renderTarget.Description.Height, 0, 1) }; 76 | // _deviceContext.Rasterizer.SetViewports(viewportf); 77 | // _deviceContext.OutputMerger.SetTargets(_renderTargetView); 78 | //} 79 | 80 | _spriteEngine = new DXSprite(_device, _deviceContext); 81 | if (!_spriteEngine.Initialize()) 82 | return false; 83 | 84 | // Initialise any resources required for overlay elements 85 | InitialiseElementResources(); 86 | 87 | _initialised = true; 88 | return true; 89 | } 90 | finally 91 | { 92 | _initialising = false; 93 | } 94 | } 95 | 96 | void InitialiseElementResources() 97 | { 98 | foreach (var overlay in Overlays) 99 | { 100 | foreach (var element in overlay.Elements) 101 | { 102 | var textElement = element as TextElement; 103 | var imageElement = element as ImageElement; 104 | 105 | if (textElement != null) 106 | { 107 | GetFontForTextElement(textElement); 108 | } 109 | else if (imageElement != null) 110 | { 111 | GetImageForImageElement(imageElement); 112 | } 113 | } 114 | } 115 | } 116 | 117 | private void Begin() 118 | { 119 | //if (!DeferredContext) 120 | //{ 121 | SharpDX.Mathematics.Interop.RawViewportF[] viewportf = { new ViewportF(0, 0, _renderTarget.Description.Width, _renderTarget.Description.Height, 0, 1) }; 122 | _deviceContext.Rasterizer.SetViewports(viewportf); 123 | _deviceContext.OutputMerger.SetTargets(_renderTargetView); 124 | //} 125 | } 126 | 127 | /// 128 | /// Draw the overlay(s) 129 | /// 130 | public void Draw() 131 | { 132 | EnsureInitiliased(); 133 | 134 | Begin(); 135 | 136 | foreach (var overlay in Overlays) 137 | { 138 | if (overlay.Hidden) 139 | continue; 140 | 141 | foreach (var element in overlay.Elements) 142 | { 143 | if (element.Hidden) 144 | continue; 145 | 146 | var textElement = element as TextElement; 147 | var imageElement = element as ImageElement; 148 | 149 | if (textElement != null) 150 | { 151 | DXFont font = GetFontForTextElement(textElement); 152 | if (font != null && !String.IsNullOrEmpty(textElement.Text)) 153 | _spriteEngine.DrawString(textElement.Location.X, textElement.Location.Y, textElement.Text, textElement.Color, font); 154 | } 155 | else if (imageElement != null) 156 | { 157 | DXImage image = GetImageForImageElement(imageElement); 158 | if (image != null) 159 | _spriteEngine.DrawImage(imageElement.Location.X, imageElement.Location.Y, imageElement.Scale, imageElement.Angle, imageElement.Tint, image); 160 | } 161 | } 162 | } 163 | 164 | End(); 165 | } 166 | 167 | private void End() 168 | { 169 | if (DeferredContext) 170 | { 171 | var commandList = _deviceContext.FinishCommandList(true); 172 | _device.ImmediateContext.ExecuteCommandList(commandList, true); 173 | commandList.Dispose(); 174 | } 175 | } 176 | 177 | DXFont GetFontForTextElement(TextElement element) 178 | { 179 | DXFont result = null; 180 | 181 | string fontKey = String.Format("{0}{1}{2}{3}", element.Font.Name, element.Font.Size, element.Font.Style, element.AntiAliased); 182 | 183 | if (!_fontCache.TryGetValue(fontKey, out result)) 184 | { 185 | result = ToDispose(new DXFont(_device, _deviceContext)); 186 | result.Initialize(element.Font.Name, element.Font.Size, element.Font.Style, element.AntiAliased); 187 | _fontCache[fontKey] = result; 188 | } 189 | return result; 190 | } 191 | 192 | DXImage GetImageForImageElement(ImageElement element) 193 | { 194 | DXImage result = null; 195 | 196 | if (!_imageCache.TryGetValue(element, out result)) 197 | { 198 | result = ToDispose(new DXImage(_device, _deviceContext)); 199 | result.Initialise(element.Bitmap); 200 | _imageCache[element] = result; 201 | } 202 | 203 | return result; 204 | } 205 | 206 | /// 207 | /// Releases unmanaged and optionally managed resources 208 | /// 209 | /// true if disposing both unmanaged and managed 210 | protected override void Dispose(bool disposing) 211 | { 212 | if (true) 213 | { 214 | _device = null; 215 | } 216 | } 217 | 218 | void SafeDispose(DisposeBase disposableObj) 219 | { 220 | if (disposableObj != null) 221 | disposableObj.Dispose(); 222 | } 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/DX11/DeviceManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Hook.DX11 7 | { 8 | // Copyright (c) 2013 Justin Stenning 9 | // Adapted from original code by Alexandre Mutel 10 | // 11 | //---------------------------------------------------------------------------- 12 | // Copyright (c) 2010-2013 SharpDX - Alexandre Mutel 13 | // 14 | // Permission is hereby granted, free of charge, to any person obtaining a copy 15 | // of this software and associated documentation files (the "Software"), to deal 16 | // in the Software without restriction, including without limitation the rights 17 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | // copies of the Software, and to permit persons to whom the Software is 19 | // furnished to do so, subject to the following conditions: 20 | // 21 | // The above copyright notice and this permission notice shall be included in 22 | // all copies or substantial portions of the Software. 23 | // 24 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 | // THE SOFTWARE. 31 | using System; 32 | using System.Collections.Generic; 33 | using System.Linq; 34 | using System.Text; 35 | 36 | using SharpDX.Direct3D; 37 | using SharpDX.Direct3D11; 38 | 39 | public class DeviceManager : SharpDX.Component 40 | { 41 | // Direct3D Objects 42 | protected SharpDX.Direct3D11.Device d3dDevice; 43 | protected SharpDX.Direct3D11.DeviceContext d3dContext; 44 | 45 | /// 46 | /// Gets the Direct3D11 device. 47 | /// 48 | public SharpDX.Direct3D11.Device Direct3DDevice { get { return d3dDevice; } } 49 | 50 | /// 51 | /// Gets the Direct3D11 immediate context. 52 | /// 53 | public SharpDX.Direct3D11.DeviceContext Direct3DContext { get { return d3dContext; } } 54 | 55 | public DeviceManager(Device device) 56 | { 57 | d3dDevice = device; 58 | d3dContext = device.ImmediateContext; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/DX11/RendererBase.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Capture.Hook.DX11 3 | { 4 | // Copyright (c) 2013 Justin Stenning 5 | // Adapted from original code by Alexandre Mutel 6 | // 7 | //---------------------------------------------------------------------------- 8 | // Copyright (c) 2010-2013 SharpDX - Alexandre Mutel 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | using SharpDX; 28 | using System; 29 | using System.Collections.Generic; 30 | using System.Linq; 31 | using System.Text; 32 | using System.Threading.Tasks; 33 | 34 | public abstract class RendererBase : Component 35 | { 36 | public DeviceManager DeviceManager { get; protected set; } 37 | public virtual bool Show { get; set; } 38 | public Matrix World; 39 | 40 | public RendererBase() 41 | { 42 | World = Matrix.Identity; 43 | Show = true; 44 | } 45 | 46 | /// 47 | /// Initialize with the provided deviceManager 48 | /// 49 | /// 50 | public virtual void Initialize(DeviceManager dm) 51 | { 52 | this.DeviceManager = dm; 53 | 54 | // The device is already initialized, create 55 | // any device resources immediately. 56 | if (this.DeviceManager.Direct3DDevice != null) 57 | { 58 | CreateDeviceDependentResources(); 59 | } 60 | } 61 | 62 | /// 63 | /// Create any resources that depend on the device or device context 64 | /// 65 | protected virtual void CreateDeviceDependentResources() 66 | { 67 | } 68 | 69 | /// 70 | /// Create any resources that depend upon the size of the render target 71 | /// 72 | protected virtual void CreateSizeDependentResources() 73 | { 74 | } 75 | 76 | /// 77 | /// Render a frame 78 | /// 79 | public void Render() 80 | { 81 | if (Show) 82 | DoRender(); 83 | } 84 | 85 | /// 86 | /// Each descendant of RendererBase performs a frame 87 | /// render within the implementation of DoRender 88 | /// 89 | protected abstract void DoRender(); 90 | 91 | public void Render(SharpDX.Direct3D11.DeviceContext context) 92 | { 93 | if (Show) 94 | DoRender(context); 95 | } 96 | 97 | protected virtual void DoRender(SharpDX.Direct3D11.DeviceContext context) 98 | { 99 | 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/DX11/ScreenAlignedQuadRenderer.cs: -------------------------------------------------------------------------------- 1 | namespace Capture.Hook.DX11 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | using SharpDX; 10 | using SharpDX.DXGI; 11 | using SharpDX.Direct3D11; 12 | using SharpDX.D3DCompiler; 13 | 14 | // Resolve class name conflicts by explicitly stating 15 | // which class they refer to: 16 | using Buffer = SharpDX.Direct3D11.Buffer; 17 | 18 | public class ScreenAlignedQuadRenderer : RendererBase 19 | { 20 | string shaderCodeVertexIn = @"Texture2D Texture0 : register(t0); 21 | SamplerState Sampler : register(s0); 22 | 23 | struct VertexIn 24 | { 25 | float4 Position : SV_Position;// Position - xyzw 26 | }; 27 | 28 | struct PixelIn 29 | { 30 | float4 Position : SV_Position; 31 | float2 UV : TEXCOORD0; 32 | }; 33 | 34 | // Screen-Aligned Quad: vertex shader main function 35 | PixelIn VSMain(VertexIn vertex) 36 | { 37 | PixelIn result = (PixelIn)0; 38 | 39 | // The input quad is expected in device coordinates 40 | // (i.e. 0,0 is center of screen, -1,1 top left, 1,-1 bottom right) 41 | // Therefore no transformation! 42 | result.Position = vertex.Position; 43 | result.Position.w = 1.0f; 44 | 45 | // The UV coordinates are top-left 0,0 bottom-right 1,1 46 | result.UV.x = result.Position.x * 0.5 + 0.5; 47 | result.UV.y = result.Position.y * -0.5 + 0.5; 48 | 49 | return result; 50 | } 51 | 52 | float4 PSMain(PixelIn input) : SV_Target 53 | { 54 | return Texture0.Sample(Sampler, input.UV); 55 | } 56 | "; 57 | 58 | 59 | 60 | string shaderCode = @"Texture2D Texture0 : register(t0); 61 | SamplerState Sampler : register(s0); 62 | 63 | struct PixelIn 64 | { 65 | float4 Position : SV_POSITION; 66 | float2 UV : TEXCOORD0; 67 | }; 68 | 69 | // Vertex shader outputs a full screen quad with UV coords without vertex buffer 70 | PixelIn VSMain(uint vertexId: SV_VertexID) 71 | { 72 | PixelIn result = (PixelIn)0; 73 | 74 | // The input quad is expected in device coordinates 75 | // (i.e. 0,0 is center of screen, -1,1 top left, 1,-1 bottom right) 76 | // Therefore no transformation! 77 | 78 | // The UV coordinates are top-left 0,0, bottom-right 1,1 79 | result.UV = float2((vertexId << 1) & 2, vertexId & 2 ); 80 | result.Position = float4( result.UV * float2( 2.0f, -2.0f ) + float2( -1.0f, 1.0f), 0.0f, 1.0f ); 81 | 82 | return result; 83 | } 84 | 85 | float4 PSMain(PixelIn input) : SV_Target 86 | { 87 | return Texture0.Sample(Sampler, input.UV); 88 | } 89 | "; 90 | 91 | 92 | // The vertex shader 93 | VertexShader vertexShader; 94 | 95 | 96 | // The pixel shader 97 | PixelShader pixelShader; 98 | 99 | SamplerState pointSamplerState; 100 | SamplerState linearSampleState; 101 | 102 | // The vertex layout for the IA 103 | InputLayout vertexLayout; 104 | // The vertex buffer 105 | Buffer vertexBuffer; 106 | // The vertex buffer binding 107 | VertexBufferBinding vertexBinding; 108 | 109 | public bool UseLinearSampling { get; set; } 110 | public ShaderResourceView ShaderResource { get; set; } 111 | public RenderTargetView RenderTargetView { get; set; } 112 | public Texture2D RenderTarget { get; set; } 113 | 114 | public ScreenAlignedQuadRenderer() 115 | { 116 | } 117 | 118 | /// 119 | /// Create any device dependent resources here. 120 | /// This method will be called when the device is first 121 | /// initialized or recreated after being removed or reset. 122 | /// 123 | protected override void CreateDeviceDependentResources() 124 | { 125 | // Ensure that if already set the device resources 126 | // are correctly disposed of before recreating 127 | RemoveAndDispose(ref vertexShader); 128 | RemoveAndDispose(ref pixelShader); 129 | RemoveAndDispose(ref pointSamplerState); 130 | //RemoveAndDispose(ref indexBuffer); 131 | 132 | // Retrieve our SharpDX.Direct3D11.Device1 instance 133 | // Get a reference to the Device1 instance and immediate context 134 | var device = DeviceManager.Direct3DDevice; 135 | var context = DeviceManager.Direct3DContext; 136 | 137 | ShaderFlags shaderFlags = ShaderFlags.None; 138 | #if DEBUG 139 | shaderFlags = ShaderFlags.Debug | ShaderFlags.SkipOptimization; 140 | #endif 141 | // Use our HLSL file include handler to resolve #include directives in the HLSL source 142 | //var includeHandler = new HLSLFileIncludeHandler(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location), "Shaders")); 143 | 144 | // Compile and create the vertex shader 145 | using (var vertexShaderBytecode = ToDispose(ShaderBytecode.Compile(shaderCode, "VSMain", "vs_4_0", shaderFlags, EffectFlags.None, null, null))) 146 | { 147 | vertexShader = ToDispose(new VertexShader(device, vertexShaderBytecode)); 148 | 149 | 150 | //// Layout from VertexShader input signature 151 | //vertexLayout = ToDispose(new InputLayout(device, 152 | // ShaderSignature.GetInputSignature(vertexShaderBytecode), 153 | ////ShaderSignature.GetInputSignature(vertexShaderBytecode), 154 | //new[] 155 | //{ 156 | // // "SV_Position" = vertex coordinate 157 | // new InputElement("SV_Position", 0, Format.R32G32B32_Float, 0, 0), 158 | //})); 159 | 160 | //// Create vertex buffer 161 | //vertexBuffer = ToDispose(Buffer.Create(device, BindFlags.VertexBuffer, new Vector3[] { 162 | // /* Position: float x 3 */ 163 | // new Vector3(-1.0f, -1.0f, -1.0f), 164 | // new Vector3(-1.0f, 1.0f, -1.0f), 165 | // new Vector3(1.0f, -1.0f, -1.0f), 166 | // new Vector3(1.0f, 1.0f, -1.0f), 167 | //})); 168 | //vertexBinding = new VertexBufferBinding(vertexBuffer, Utilities.SizeOf(), 0); 169 | // Triangle strip: 170 | // v1 v3 171 | // |\ | 172 | // | \ B| 173 | // | A\ | 174 | // | \| 175 | // v0 v2 176 | 177 | } 178 | 179 | // Compile and create the pixel shader 180 | using (var bytecode = ToDispose(ShaderBytecode.Compile(shaderCode, "PSMain", "ps_5_0", shaderFlags, EffectFlags.None, null, null))) 181 | pixelShader = ToDispose(new PixelShader(device, bytecode)); 182 | 183 | linearSampleState = ToDispose(new SamplerState(device, new SamplerStateDescription 184 | { 185 | Filter = Filter.MinMagMipLinear, 186 | AddressU = TextureAddressMode.Wrap, 187 | AddressV = TextureAddressMode.Wrap, 188 | AddressW = TextureAddressMode.Wrap, 189 | ComparisonFunction = Comparison.Never, 190 | MinimumLod = 0, 191 | MaximumLod = float.MaxValue 192 | })); 193 | 194 | pointSamplerState = ToDispose(new SamplerState(device, new SamplerStateDescription 195 | { 196 | Filter = Filter.MinMagMipPoint, 197 | AddressU = TextureAddressMode.Wrap, 198 | AddressV = TextureAddressMode.Wrap, 199 | AddressW = TextureAddressMode.Wrap, 200 | ComparisonFunction = Comparison.Never, 201 | MinimumLod = 0, 202 | MaximumLod = float.MaxValue 203 | })); 204 | 205 | context.Rasterizer.State = ToDispose(new RasterizerState(device, new RasterizerStateDescription() 206 | { 207 | CullMode = CullMode.None, 208 | FillMode = FillMode.Solid, 209 | })); 210 | 211 | //// Configure the depth buffer to discard pixels that are 212 | //// further than the current pixel. 213 | //context.OutputMerger.SetDepthStencilState(ToDispose(new DepthStencilState(device, 214 | // new DepthStencilStateDescription() 215 | // { 216 | // IsDepthEnabled = false, // enable depth? 217 | // DepthComparison = Comparison.Less, 218 | // DepthWriteMask = SharpDX.Direct3D11.DepthWriteMask.All, 219 | // IsStencilEnabled = false,// enable stencil? 220 | // StencilReadMask = 0xff, // 0xff (no mask) 221 | // StencilWriteMask = 0xff,// 0xff (no mask) 222 | // // Configure FrontFace depth/stencil operations 223 | // FrontFace = new DepthStencilOperationDescription() 224 | // { 225 | // Comparison = Comparison.Always, 226 | // PassOperation = StencilOperation.Keep, 227 | // FailOperation = StencilOperation.Keep, 228 | // DepthFailOperation = StencilOperation.Increment 229 | // }, 230 | // // Configure BackFace depth/stencil operations 231 | // BackFace = new DepthStencilOperationDescription() 232 | // { 233 | // Comparison = Comparison.Always, 234 | // PassOperation = StencilOperation.Keep, 235 | // FailOperation = StencilOperation.Keep, 236 | // DepthFailOperation = StencilOperation.Decrement 237 | // }, 238 | // }))); 239 | } 240 | 241 | protected override void DoRender() 242 | { 243 | var context = this.DeviceManager.Direct3DContext; 244 | 245 | //context.InputAssembler.InputLayout = vertexLayout; 246 | //context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleStrip; 247 | //context.InputAssembler.SetVertexBuffers(0, vertexBinding); 248 | 249 | 250 | // Retrieve the existing shader and IA settings 251 | //using (var oldVertexLayout = context.InputAssembler.InputLayout) 252 | //using (var oldSampler = context.PixelShader.GetSamplers(0, 1).FirstOrDefault()) 253 | //using (var oldPixelShader = context.PixelShader.Get()) 254 | //using (var oldVertexShader = context.VertexShader.Get()) 255 | //using (var oldRenderTarget = context.OutputMerger.GetRenderTargets(1).FirstOrDefault()) 256 | { 257 | context.ClearRenderTargetView(RenderTargetView, Color.CornflowerBlue); 258 | 259 | // Set sampler 260 | SharpDX.Mathematics.Interop.RawViewportF[] viewportf = { new ViewportF(0, 0, RenderTarget.Description.Width, RenderTarget.Description.Height, 0, 1) }; 261 | context.Rasterizer.SetViewports(viewportf); 262 | context.PixelShader.SetSampler(0, (UseLinearSampling ? linearSampleState : pointSamplerState)); 263 | 264 | // Set shader resource 265 | //bool isMultisampledSRV = false; 266 | if (ShaderResource != null && !ShaderResource.IsDisposed) 267 | { 268 | context.PixelShader.SetShaderResource(0, ShaderResource); 269 | 270 | //if (ShaderResource.Description.Dimension == SharpDX.Direct3D.ShaderResourceViewDimension.Texture2DMultisampled) 271 | //{ 272 | // isMultisampledSRV = true; 273 | //} 274 | } 275 | 276 | // Set pixel shader 277 | //if (isMultisampledSRV) 278 | // context.PixelShader.Set(pixelShaderMS); 279 | //else 280 | context.PixelShader.Set(pixelShader); 281 | 282 | // Set vertex shader 283 | context.VertexShader.Set(vertexShader); 284 | 285 | // Update vertex layout to use 286 | context.InputAssembler.InputLayout = null; 287 | 288 | // Tell the IA we are using a triangle strip 289 | context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleStrip; 290 | // No vertices to pass (note: null as we will use SV_VertexId) 291 | //context.InputAssembler.SetVertexBuffers(0, vertexBuffer); 292 | 293 | // Set the render target 294 | context.OutputMerger.SetTargets(RenderTargetView); 295 | 296 | // Draw the 4 vertices that make up the triangle strip 297 | context.Draw(4, 0); 298 | 299 | // Remove the render target from the pipeline so that we can read from it if necessary 300 | context.OutputMerger.SetTargets((RenderTargetView)null); 301 | 302 | // Restore previous shader and IA settings 303 | //context.PixelShader.SetSampler(0, oldSampler); 304 | //context.PixelShader.Set(oldPixelShader); 305 | //context.VertexShader.Set(oldVertexShader); 306 | //context.InputAssembler.InputLayout = oldVertexLayout; 307 | //context.OutputMerger.SetTargets(oldRenderTarget); 308 | } 309 | } 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/DX9/DXOverlayEngine.cs: -------------------------------------------------------------------------------- 1 | using Capture.Hook.Common; 2 | using SharpDX; 3 | using SharpDX.Direct3D9; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Runtime.InteropServices; 10 | using System.Text; 11 | 12 | namespace Capture.Hook.DX9 13 | { 14 | internal class DXOverlayEngine : Component 15 | { 16 | public List Overlays { get; set; } 17 | 18 | bool _initialised = false; 19 | bool _initialising = false; 20 | 21 | Device _device; 22 | Sprite _sprite; 23 | Dictionary _fontCache = new Dictionary(); 24 | Dictionary _imageCache = new Dictionary(); 25 | 26 | public Device Device { get { return _device; } } 27 | 28 | public DXOverlayEngine() 29 | { 30 | Overlays = new List(); 31 | } 32 | 33 | private void EnsureInitiliased() 34 | { 35 | Debug.Assert(_initialised); 36 | } 37 | 38 | public bool Initialise(Device device) 39 | { 40 | Debug.Assert(!_initialised); 41 | if (_initialising) 42 | return false; 43 | 44 | _initialising = true; 45 | 46 | try 47 | { 48 | 49 | _device = device; 50 | 51 | _sprite = ToDispose(new Sprite(_device)); 52 | 53 | // Initialise any resources required for overlay elements 54 | IntialiseElementResources(); 55 | 56 | _initialised = true; 57 | return true; 58 | } 59 | finally 60 | { 61 | _initialising = false; 62 | } 63 | } 64 | 65 | private void IntialiseElementResources() 66 | { 67 | foreach (var overlay in Overlays) 68 | { 69 | foreach (var element in overlay.Elements) 70 | { 71 | var textElement = element as TextElement; 72 | var imageElement = element as ImageElement; 73 | 74 | if (textElement != null) 75 | { 76 | GetFontForTextElement(textElement); 77 | } 78 | else if (imageElement != null) 79 | { 80 | GetImageForImageElement(imageElement); 81 | } 82 | } 83 | } 84 | } 85 | 86 | private void Begin() 87 | { 88 | _sprite.Begin(SpriteFlags.AlphaBlend); 89 | } 90 | 91 | /// 92 | /// Draw the overlay(s) 93 | /// 94 | public void Draw() 95 | { 96 | EnsureInitiliased(); 97 | 98 | Begin(); 99 | 100 | foreach (var overlay in Overlays) 101 | { 102 | foreach (var element in overlay.Elements) 103 | { 104 | if (element.Hidden) 105 | continue; 106 | 107 | var textElement = element as TextElement; 108 | var imageElement = element as ImageElement; 109 | 110 | if (textElement != null) 111 | { 112 | Font font = GetFontForTextElement(textElement); 113 | if (font != null && !String.IsNullOrEmpty(textElement.Text)) 114 | font.DrawText(_sprite, textElement.Text, textElement.Location.X, textElement.Location.Y, new SharpDX.ColorBGRA(textElement.Color.R, textElement.Color.G, textElement.Color.B, textElement.Color.A)); 115 | } 116 | else if (imageElement != null) 117 | { 118 | //Apply the scaling of the imageElement 119 | var rotation = Matrix.RotationZ(imageElement.Angle); 120 | var scaling = Matrix.Scaling(imageElement.Scale); 121 | _sprite.Transform = rotation * scaling; 122 | 123 | Texture image = GetImageForImageElement(imageElement); 124 | if (image != null) 125 | _sprite.Draw(image, new SharpDX.ColorBGRA(imageElement.Tint.R, imageElement.Tint.G, imageElement.Tint.B, imageElement.Tint.A), null, null, new Vector3(imageElement.Location.X, imageElement.Location.Y, 0)); 126 | 127 | //Reset the transform for other elements 128 | _sprite.Transform = Matrix.Identity; 129 | } 130 | } 131 | } 132 | 133 | End(); 134 | } 135 | 136 | private void End() 137 | { 138 | _sprite.End(); 139 | } 140 | 141 | /// 142 | /// In Direct3D9 it is necessary to call OnLostDevice before any call to device.Reset(...) for certain interfaces found in D3DX (e.g. ID3DXSprite, ID3DXFont, ID3DXLine) - https://msdn.microsoft.com/en-us/library/windows/desktop/bb172979(v=vs.85).aspx 143 | /// 144 | public void BeforeDeviceReset() 145 | { 146 | try 147 | { 148 | foreach (var item in _fontCache) 149 | item.Value.OnLostDevice(); 150 | 151 | if (_sprite != null) 152 | _sprite.OnLostDevice(); 153 | } 154 | catch { } 155 | } 156 | 157 | Font GetFontForTextElement(TextElement element) 158 | { 159 | Font result = null; 160 | 161 | string fontKey = String.Format("{0}{1}{2}{3}", element.Font.Name, element.Font.Size, element.Font.Style, element.AntiAliased); 162 | 163 | if (!_fontCache.TryGetValue(fontKey, out result)) 164 | { 165 | result = ToDispose(new Font(_device, new FontDescription { 166 | FaceName = element.Font.Name, 167 | Italic = (element.Font.Style & System.Drawing.FontStyle.Italic) == System.Drawing.FontStyle.Italic, 168 | Quality = (element.AntiAliased ? FontQuality.Antialiased : FontQuality.Default), 169 | Weight = ((element.Font.Style & System.Drawing.FontStyle.Bold) == System.Drawing.FontStyle.Bold) ? FontWeight.Bold : FontWeight.Normal, 170 | Height = (int)element.Font.SizeInPoints 171 | })); 172 | _fontCache[fontKey] = result; 173 | } 174 | return result; 175 | } 176 | 177 | Texture GetImageForImageElement(ImageElement element) 178 | { 179 | Texture result = null; 180 | 181 | if (!String.IsNullOrEmpty(element.Filename)) 182 | { 183 | if (!_imageCache.TryGetValue(element, out result)) 184 | { 185 | result = ToDispose(SharpDX.Direct3D9.Texture.FromFile(_device, element.Filename)); 186 | 187 | _imageCache[element] = result; 188 | } 189 | } 190 | else if (!_imageCache.TryGetValue(element, out result) && element.Bitmap != null) 191 | { 192 | using (var ms = new MemoryStream()) 193 | { 194 | element.Bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png); 195 | ms.Seek(0, SeekOrigin.Begin); 196 | result = ToDispose(Texture.FromStream(Device, ms)); 197 | } 198 | 199 | _imageCache[element] = result; 200 | } 201 | return result; 202 | } 203 | 204 | /// 205 | /// Releases unmanaged and optionally managed resources 206 | /// 207 | /// true if disposing both unmanaged and managed 208 | protected override void Dispose(bool disposing) 209 | { 210 | if (true) 211 | { 212 | _device = null; 213 | } 214 | } 215 | 216 | void SafeDispose(DisposeBase disposableObj) 217 | { 218 | if (disposableObj != null) 219 | disposableObj.Dispose(); 220 | } 221 | 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/DX9FormatExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Hook 7 | { 8 | public static class DX9FormatExtension 9 | { 10 | 11 | public static int ToPixelDepth(this SharpDX.Direct3D9.Format format) 12 | { 13 | // Only support the DX9 BackBuffer formats: http://msdn.microsoft.com/en-us/library/windows/desktop/bb172558(v=vs.85).aspx 14 | switch (format) 15 | { 16 | case SharpDX.Direct3D9.Format.A2R10G10B10: 17 | case SharpDX.Direct3D9.Format.A8R8G8B8: 18 | case SharpDX.Direct3D9.Format.X8R8G8B8: 19 | return 32; 20 | case SharpDX.Direct3D9.Format.R5G6B5: 21 | case SharpDX.Direct3D9.Format.A1R5G5B5: 22 | case SharpDX.Direct3D9.Format.X1R5G5B5: 23 | return 16; 24 | default: 25 | return -1; 26 | } 27 | } 28 | 29 | public static System.Drawing.Imaging.PixelFormat ToPixelFormat(this SharpDX.Direct3D9.Format format) 30 | { 31 | // Only support the BackBuffer formats: http://msdn.microsoft.com/en-us/library/windows/desktop/bb172558(v=vs.85).aspx 32 | // and of these only those that have a direct mapping to supported PixelFormat's 33 | switch (format) 34 | { 35 | case SharpDX.Direct3D9.Format.A8R8G8B8: 36 | case SharpDX.Direct3D9.Format.X8R8G8B8: 37 | return System.Drawing.Imaging.PixelFormat.Format32bppArgb; 38 | case SharpDX.Direct3D9.Format.R5G6B5: 39 | return System.Drawing.Imaging.PixelFormat.Format16bppRgb565; 40 | case SharpDX.Direct3D9.Format.A1R5G5B5: 41 | case SharpDX.Direct3D9.Format.X1R5G5B5: 42 | return System.Drawing.Imaging.PixelFormat.Format16bppArgb1555; 43 | default: 44 | return System.Drawing.Imaging.PixelFormat.Undefined; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/DXGI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Runtime.InteropServices; 6 | using SharpDX.DXGI; 7 | 8 | namespace Capture.Hook 9 | { 10 | internal static class DXGI 11 | { 12 | public enum DXGISwapChainVTbl : short 13 | { 14 | // IUnknown 15 | QueryInterface = 0, 16 | AddRef = 1, 17 | Release = 2, 18 | 19 | // IDXGIObject 20 | SetPrivateData = 3, 21 | SetPrivateDataInterface = 4, 22 | GetPrivateData = 5, 23 | GetParent = 6, 24 | 25 | // IDXGIDeviceSubObject 26 | GetDevice = 7, 27 | 28 | // IDXGISwapChain 29 | Present = 8, 30 | GetBuffer = 9, 31 | SetFullscreenState = 10, 32 | GetFullscreenState = 11, 33 | GetDesc = 12, 34 | ResizeBuffers = 13, 35 | ResizeTarget = 14, 36 | GetContainingOutput = 15, 37 | GetFrameStatistics = 16, 38 | GetLastPresentCount = 17, 39 | } 40 | 41 | public const int DXGI_SWAPCHAIN_METHOD_COUNT = 18; 42 | 43 | public static SharpDX.DXGI.SwapChainDescription CreateSwapChainDescription(IntPtr windowHandle) 44 | { 45 | return new SharpDX.DXGI.SwapChainDescription 46 | { 47 | BufferCount = 1, 48 | Flags = SharpDX.DXGI.SwapChainFlags.None, 49 | IsWindowed = true, 50 | ModeDescription = new SharpDX.DXGI.ModeDescription(100, 100, new Rational(60, 1), SharpDX.DXGI.Format.R8G8B8A8_UNorm), 51 | OutputHandle = windowHandle, 52 | SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), 53 | SwapEffect = SharpDX.DXGI.SwapEffect.Discard, 54 | Usage = SharpDX.DXGI.Usage.RenderTargetOutput 55 | }; 56 | } 57 | 58 | /* 59 | * 60 | typedef enum DXGI_MODE_SCANLINE_ORDER 61 | { 62 | DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED = 0, 63 | DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE = 1, 64 | DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST = 2, 65 | DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST = 3 66 | } DXGI_MODE_SCANLINE_ORDER; 67 | 68 | typedef enum DXGI_MODE_SCALING 69 | { 70 | DXGI_MODE_SCALING_UNSPECIFIED = 0, 71 | DXGI_MODE_SCALING_CENTERED = 1, 72 | DXGI_MODE_SCALING_STRETCHED = 2 73 | } DXGI_MODE_SCALING; 74 | 75 | typedef enum DXGI_MODE_ROTATION 76 | { 77 | DXGI_MODE_ROTATION_UNSPECIFIED = 0, 78 | DXGI_MODE_ROTATION_IDENTITY = 1, 79 | DXGI_MODE_ROTATION_ROTATE90 = 2, 80 | DXGI_MODE_ROTATION_ROTATE180 = 3, 81 | DXGI_MODE_ROTATION_ROTATE270 = 4 82 | } DXGI_MODE_ROTATION; 83 | 84 | typedef struct DXGI_MODE_DESC 85 | { 86 | UINT Width; 87 | UINT Height; 88 | DXGI_RATIONAL RefreshRate; 89 | DXGI_FORMAT Format; 90 | DXGI_MODE_SCANLINE_ORDER ScanlineOrdering; 91 | DXGI_MODE_SCALING Scaling; 92 | } DXGI_MODE_DESC; 93 | * */ 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/FramesPerSecond.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Hook 7 | { 8 | /// 9 | /// Used to determine the FPS 10 | /// 11 | public class FramesPerSecond 12 | { 13 | int _frames = 0; 14 | int _lastTickCount = 0; 15 | float _lastFrameRate = 0; 16 | 17 | /// 18 | /// Must be called each frame 19 | /// 20 | public void Frame() 21 | { 22 | _frames++; 23 | if (Math.Abs(Environment.TickCount - _lastTickCount) > 1000) 24 | { 25 | _lastFrameRate = (float)_frames * 1000 / Math.Abs(Environment.TickCount - _lastTickCount); 26 | _lastTickCount = Environment.TickCount; 27 | _frames = 0; 28 | } 29 | } 30 | 31 | /// 32 | /// Return the current frames per second 33 | /// 34 | /// 35 | public float GetFPS() 36 | { 37 | return _lastFrameRate; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/Hook.cs: -------------------------------------------------------------------------------- 1 | using EasyHook; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | 8 | namespace Capture.Hook 9 | { 10 | // Thanks to remcoros for the initial version of the following helper classes 11 | 12 | /// 13 | /// Extends with support for accessing the Original method from within a hook delegate 14 | /// 15 | /// A delegate type 16 | public class Hook : Hook 17 | where T: class 18 | { 19 | /// 20 | /// When called from within the delegate this will call the original function at . 21 | /// 22 | public T Original { get; private set; } 23 | 24 | /// 25 | /// Creates a new hook at redirecting to . The hook starts inactive so a call to is required to enable the hook. 26 | /// 27 | /// A pointer to the location to insert the hook 28 | /// The delegate to call from the hooked location 29 | /// The object to assign as the "callback" object within the instance. 30 | public Hook(IntPtr funcToHook, Delegate newFunc, object owner) 31 | : base(funcToHook, newFunc, owner) 32 | { 33 | // Debug assertion that T is a Delegate type 34 | System.Diagnostics.Debug.Assert(typeof(Delegate).IsAssignableFrom(typeof(T))); 35 | 36 | Original = (T)(object)Marshal.GetDelegateForFunctionPointer(funcToHook, typeof(T)); 37 | } 38 | } 39 | 40 | /// 41 | /// Wraps the class with a simplified active/inactive state 42 | /// 43 | public class Hook: IDisposable 44 | { 45 | /// 46 | /// The hooked function location 47 | /// 48 | public IntPtr FuncToHook { get; private set; } 49 | 50 | /// 51 | /// The replacement delegate 52 | /// 53 | public Delegate NewFunc { get; private set; } 54 | 55 | /// 56 | /// The callback object passed to LocalHook constructor 57 | /// 58 | public object Owner { get; private set; } 59 | 60 | /// 61 | /// The instance 62 | /// 63 | public LocalHook LocalHook { get; private set; } 64 | 65 | /// 66 | /// Indicates whether the hook is currently active 67 | /// 68 | public bool IsActive { get; private set; } 69 | 70 | /// 71 | /// Creates a new hook at redirecting to . The hook starts inactive so a call to is required to enable the hook. 72 | /// 73 | /// A pointer to the location to insert the hook 74 | /// The delegate to call from the hooked location 75 | /// The object to assign as the "callback" object within the instance. 76 | public Hook(IntPtr funcToHook, Delegate newFunc, object owner) 77 | { 78 | this.FuncToHook = funcToHook; 79 | this.NewFunc = newFunc; 80 | this.Owner = owner; 81 | 82 | CreateHook(); 83 | } 84 | 85 | ~Hook() 86 | { 87 | Dispose(false); 88 | } 89 | 90 | protected void CreateHook() 91 | { 92 | if (LocalHook != null) return; 93 | 94 | this.LocalHook = LocalHook.Create(FuncToHook, NewFunc, Owner); 95 | } 96 | 97 | protected void UnHook() 98 | { 99 | if (this.IsActive) 100 | Deactivate(); 101 | 102 | if (this.LocalHook != null) 103 | { 104 | this.LocalHook.Dispose(); 105 | this.LocalHook = null; 106 | } 107 | } 108 | 109 | /// 110 | /// Activates the hook 111 | /// 112 | public void Activate() 113 | { 114 | if (this.LocalHook == null) 115 | CreateHook(); 116 | 117 | if (this.IsActive) return; 118 | 119 | this.IsActive = true; 120 | this.LocalHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 }); 121 | } 122 | 123 | /// 124 | /// Deactivates the hook 125 | /// 126 | public void Deactivate() 127 | { 128 | if (!this.IsActive) return; 129 | 130 | this.IsActive = false; 131 | this.LocalHook.ThreadACL.SetInclusiveACL(new Int32[] { 0 }); 132 | } 133 | 134 | 135 | public void Dispose() 136 | { 137 | Dispose(true); 138 | } 139 | 140 | protected virtual void Dispose(bool disposeManagedObjects) 141 | { 142 | // Only clean up managed objects if disposing (i.e. not called from destructor) 143 | if (disposeManagedObjects) 144 | { 145 | UnHook(); 146 | } 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/HookManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Diagnostics; 6 | using EasyHook; 7 | 8 | namespace Capture.Hook 9 | { 10 | public class HookManager 11 | { 12 | static internal List HookedProcesses = new List(); 13 | 14 | /* 15 | * Please note that we have obtained this information with system privileges. 16 | * So if you get client requests with a process ID don't try to open the process 17 | * as this will fail in some cases. Just search the ID in the following list and 18 | * extract information that is already there... 19 | * 20 | * Of course you can change the way this list is implemented and the information 21 | * it contains but you should keep the code semantic. 22 | */ 23 | internal static List ProcessList = new List(); 24 | private static List ActivePIDList = new List(); 25 | 26 | public static void AddHookedProcess(Int32 processId) 27 | { 28 | lock (HookedProcesses) 29 | { 30 | HookedProcesses.Add(processId); 31 | } 32 | } 33 | 34 | public static void RemoveHookedProcess(Int32 processId) 35 | { 36 | lock (HookedProcesses) 37 | { 38 | HookedProcesses.Remove(processId); 39 | } 40 | } 41 | 42 | public static bool IsHooked(Int32 processId) 43 | { 44 | lock (HookedProcesses) 45 | { 46 | return HookedProcesses.Contains(processId); 47 | } 48 | } 49 | 50 | [Serializable] 51 | public class ProcessInfo 52 | { 53 | public String FileName; 54 | public Int32 Id; 55 | public Boolean Is64Bit; 56 | public String User; 57 | } 58 | 59 | public static ProcessInfo[] EnumProcesses() 60 | { 61 | List result = new List(); 62 | Process[] procList = Process.GetProcesses(); 63 | 64 | for (int i = 0; i < procList.Length; i++) 65 | { 66 | Process proc = procList[i]; 67 | 68 | try 69 | { 70 | ProcessInfo info = new ProcessInfo(); 71 | 72 | info.FileName = proc.MainModule.FileName; 73 | info.Id = proc.Id; 74 | info.Is64Bit = RemoteHooking.IsX64Process(proc.Id); 75 | info.User = RemoteHooking.GetProcessIdentity(proc.Id).Name; 76 | 77 | result.Add(info); 78 | } 79 | catch 80 | { 81 | } 82 | } 83 | 84 | return result.ToArray(); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/IDXHook.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Capture.Interface; 6 | 7 | namespace Capture.Hook 8 | { 9 | internal interface IDXHook: IDisposable 10 | { 11 | CaptureInterface Interface 12 | { 13 | get; 14 | set; 15 | } 16 | CaptureConfig Config 17 | { 18 | get; 19 | set; 20 | } 21 | 22 | ScreenshotRequest Request 23 | { 24 | get; 25 | set; 26 | } 27 | 28 | void Hook(); 29 | 30 | void Cleanup(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/SafeHGlobal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | 7 | namespace Capture.Hook 8 | { 9 | /// 10 | /// Provides a safe handle around a block of unmanaged memory. 11 | /// 12 | public class SafeHGlobal : SafeHandle 13 | { 14 | /// 15 | /// When overridden in a derived class, gets a value indicating whether the handle value is invalid. 16 | /// 17 | /// true if the handle value is invalid; otherwise, false. 18 | public override bool IsInvalid 19 | { 20 | get { return handle == IntPtr.Zero; } 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | /// The size of the block of memory to allocate, in bytes. 27 | public SafeHGlobal(int sizeInBytes) 28 | : base(Marshal.AllocHGlobal(sizeInBytes), true) 29 | { 30 | } 31 | 32 | /// 33 | /// When overridden in a derived class, executes the code required to free the handle. 34 | /// 35 | /// 36 | /// true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a releaseHandleFailed MDA Managed Debugging Assistant. 37 | /// 38 | protected override bool ReleaseHandle() 39 | { 40 | Marshal.FreeHGlobal(handle); 41 | return true; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Hook/TextDisplay.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Hook 7 | { 8 | public class TextDisplay 9 | { 10 | long _startTickCount = 0; 11 | 12 | public TextDisplay() 13 | { 14 | _startTickCount = DateTime.Now.Ticks; 15 | Display = true; 16 | } 17 | 18 | /// 19 | /// Must be called each frame 20 | /// 21 | public void Frame() 22 | { 23 | if (Display && Math.Abs(DateTime.Now.Ticks - _startTickCount) > Duration.Ticks) 24 | { 25 | Display = false; 26 | } 27 | } 28 | 29 | public bool Display { get; set; } 30 | public String Text { get; set; } 31 | public TimeSpan Duration { get; set; } 32 | public float Remaining 33 | { 34 | get 35 | { 36 | if (Display) 37 | { 38 | return (float)Math.Abs(DateTime.Now.Ticks - _startTickCount) / (float)Duration.Ticks; 39 | } 40 | else 41 | { 42 | return 0; 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Interface/CaptureConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Reflection; 6 | using System.IO; 7 | 8 | namespace Capture.Interface 9 | { 10 | [Serializable] 11 | public class CaptureConfig 12 | { 13 | public Direct3DVersion Direct3DVersion { get; set; } 14 | public bool ShowOverlay { get; set; } 15 | public int TargetFramesPerSecond { get; set; } 16 | public string TargetFolder { get; set; } 17 | 18 | public CaptureConfig() 19 | { 20 | Direct3DVersion = Direct3DVersion.AutoDetect; 21 | ShowOverlay = false; 22 | TargetFramesPerSecond = 5; 23 | TargetFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Interface/Direct3DVersion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Interface 7 | { 8 | public enum Direct3DVersion 9 | { 10 | Unknown, 11 | AutoDetect, 12 | Direct3D9, 13 | Direct3D10, 14 | Direct3D10_1, 15 | Direct3D11, 16 | Direct3D11_1, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Interface/DisplayTextEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Interface 7 | { 8 | [Serializable] 9 | public class DisplayTextEventArgs: MarshalByRefObject 10 | { 11 | public string Text { get; set; } 12 | public TimeSpan Duration { get; set; } 13 | 14 | public DisplayTextEventArgs(string text, TimeSpan duration) 15 | { 16 | Text = text; 17 | Duration = duration; 18 | } 19 | 20 | public override string ToString() 21 | { 22 | return String.Format("{0}", Text); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Interface/DrawOverlayEventArgs.cs: -------------------------------------------------------------------------------- 1 | using Capture.Hook.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Capture.Interface 9 | { 10 | /// 11 | /// Note: Deliberately not using MarshalByRefObj 12 | /// 13 | [Serializable] 14 | public class DrawOverlayEventArgs 15 | { 16 | public IOverlay Overlay { get; set; } 17 | 18 | public bool IsUpdatePending { get; set; } 19 | 20 | public DrawOverlayEventArgs() 21 | { 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Interface/ImageFormat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Interface 7 | { 8 | public enum ImageFormat 9 | { 10 | Bitmap, 11 | Jpeg, 12 | Png, 13 | PixelData, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Interface/MessageReceivedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Interface 7 | { 8 | [Serializable] 9 | public class MessageReceivedEventArgs: MarshalByRefObject 10 | { 11 | public MessageType MessageType { get; set; } 12 | public string Message { get; set; } 13 | 14 | public MessageReceivedEventArgs(MessageType messageType, string message) 15 | { 16 | MessageType = messageType; 17 | Message = message; 18 | } 19 | 20 | public override string ToString() 21 | { 22 | return String.Format("{0}: {1}", MessageType, Message); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Match3Solver/Capture/Interface/MessageType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Interface 7 | { 8 | public enum MessageType 9 | { 10 | Debug, 11 | Information, 12 | Warning, 13 | Error 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Interface/Screenshot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using System.IO; 7 | using System.Runtime.Remoting; 8 | using System.Security.Permissions; 9 | using System.Runtime.InteropServices; 10 | 11 | namespace Capture.Interface 12 | { 13 | public class Screenshot : MarshalByRefObject, IDisposable 14 | { 15 | Guid _requestId; 16 | public Guid RequestId 17 | { 18 | get 19 | { 20 | return _requestId; 21 | } 22 | } 23 | 24 | public ImageFormat Format { get; set; } 25 | 26 | public System.Drawing.Imaging.PixelFormat PixelFormat { get; set; } 27 | public int Stride { get; set; } 28 | public int Height { get; set; } 29 | public int Width { get; set; } 30 | 31 | byte[] _data; 32 | public byte[] Data 33 | { 34 | get 35 | { 36 | return _data; 37 | } 38 | } 39 | 40 | private bool _disposed; 41 | 42 | public Screenshot(Guid requestId, byte[] data) 43 | { 44 | _requestId = requestId; 45 | _data = data; 46 | } 47 | 48 | ~Screenshot() 49 | { 50 | Dispose(false); 51 | } 52 | 53 | public void Dispose() 54 | { 55 | Dispose(true); 56 | GC.SuppressFinalize(this); 57 | } 58 | 59 | protected virtual void Dispose(bool disposeManagedResources) 60 | { 61 | if (!_disposed) 62 | { 63 | if (disposeManagedResources) 64 | { 65 | Disconnect(); 66 | } 67 | _disposed = true; 68 | } 69 | } 70 | 71 | /// 72 | /// Disconnects the remoting channel(s) of this object and all nested objects. 73 | /// 74 | private void Disconnect() 75 | { 76 | RemotingServices.Disconnect(this); 77 | } 78 | 79 | [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.Infrastructure)] 80 | public override object InitializeLifetimeService() 81 | { 82 | // Returning null designates an infinite non-expiring lease. 83 | // We must therefore ensure that RemotingServices.Disconnect() is called when 84 | // it's no longer needed otherwise there will be a memory leak. 85 | return null; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Interface/ScreenshotExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Text; 8 | 9 | namespace Capture.Interface 10 | { 11 | public static class ScreenshotExtensions 12 | { 13 | public static Bitmap ToBitmap(this byte[] data, int width, int height, int stride, System.Drawing.Imaging.PixelFormat pixelFormat) 14 | { 15 | GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); 16 | try 17 | { 18 | var img = new Bitmap(width, height, stride, pixelFormat, handle.AddrOfPinnedObject()); 19 | return img; 20 | } 21 | finally 22 | { 23 | if (handle.IsAllocated) 24 | handle.Free(); 25 | } 26 | } 27 | 28 | public static Bitmap ToBitmap(this Screenshot screenshot) 29 | { 30 | if (screenshot.Format == ImageFormat.PixelData) 31 | { 32 | return screenshot.Data.ToBitmap(screenshot.Width, screenshot.Height, screenshot.Stride, screenshot.PixelFormat); 33 | } 34 | else 35 | { 36 | return screenshot.Data.ToBitmap(); 37 | } 38 | } 39 | 40 | public static Bitmap ToBitmap(this byte[] imageBytes) 41 | { 42 | // Note: deliberately not disposing of MemoryStream, it doesn't have any unmanaged resources anyway and the GC 43 | // will deal with it. This fixes GitHub issue #19 (https://github.com/spazzarama/Direct3DHook/issues/19). 44 | MemoryStream ms = new MemoryStream(imageBytes); 45 | try 46 | { 47 | Bitmap image = (Bitmap)Image.FromStream(ms); 48 | return image; 49 | } 50 | catch 51 | { 52 | return null; 53 | } 54 | } 55 | 56 | public static byte[] ToByteArray(this Image img, System.Drawing.Imaging.ImageFormat format) 57 | { 58 | using (MemoryStream stream = new MemoryStream()) 59 | { 60 | img.Save(stream, format); 61 | stream.Close(); 62 | return stream.ToArray(); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Interface/ScreenshotReceivedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Capture.Interface 7 | { 8 | [Serializable] 9 | public class ScreenshotReceivedEventArgs: MarshalByRefObject 10 | { 11 | public Int32 ProcessId { get; set; } 12 | public Screenshot Screenshot { get; set; } 13 | 14 | public ScreenshotReceivedEventArgs(Int32 processId, Screenshot screenshot) 15 | { 16 | ProcessId = processId; 17 | Screenshot = screenshot; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Interface/ScreenshotRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using System.Runtime.Remoting; 7 | using System.Security.Permissions; 8 | 9 | namespace Capture.Interface 10 | { 11 | [Serializable] 12 | public class ScreenshotRequest: MarshalByRefObject, IDisposable 13 | { 14 | public Guid RequestId { get; set; } 15 | public Rectangle RegionToCapture { get; set; } 16 | public Size? Resize { get; set; } 17 | public ImageFormat Format { get; set; } 18 | 19 | public ScreenshotRequest(Rectangle region, Size resize) 20 | : this(Guid.NewGuid(), region, resize) 21 | { 22 | } 23 | 24 | public ScreenshotRequest(Rectangle region) 25 | : this(Guid.NewGuid(), region, null) 26 | { 27 | } 28 | 29 | public ScreenshotRequest(Guid requestId, Rectangle region) 30 | : this(requestId, region, null) 31 | { 32 | } 33 | 34 | public ScreenshotRequest(Guid requestId, Rectangle region, Size? resize) 35 | { 36 | RequestId = requestId; 37 | RegionToCapture = region; 38 | Resize = resize; 39 | } 40 | 41 | public ScreenshotRequest Clone() 42 | { 43 | return new ScreenshotRequest(RequestId, RegionToCapture, Resize) 44 | { 45 | Format = Format 46 | }; 47 | } 48 | 49 | ~ScreenshotRequest() 50 | { 51 | Dispose(false); 52 | } 53 | 54 | private bool _disposed; 55 | public void Dispose() 56 | { 57 | Dispose(true); 58 | GC.SuppressFinalize(this); 59 | } 60 | 61 | protected virtual void Dispose(bool disposing) 62 | { 63 | if (!_disposed) 64 | { 65 | if (disposing) 66 | { 67 | Disconnect(); 68 | } 69 | _disposed = true; 70 | } 71 | } 72 | 73 | /// 74 | /// Disconnects the remoting channel(s) of this object and all nested objects. 75 | /// 76 | private void Disconnect() 77 | { 78 | RemotingServices.Disconnect(this); 79 | } 80 | 81 | [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.Infrastructure)] 82 | public override object InitializeLifetimeService() 83 | { 84 | // Returning null designates an infinite non-expiring lease. 85 | // We must therefore ensure that RemotingServices.Disconnect() is called when 86 | // it's no longer needed otherwise there will be a memory leak. 87 | return null; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Match3Solver/Capture/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace Capture 8 | { 9 | [System.Security.SuppressUnmanagedCodeSecurity()] 10 | internal sealed class NativeMethods 11 | { 12 | private NativeMethods() { } 13 | 14 | internal static bool IsWindowInForeground(IntPtr hWnd) 15 | { 16 | return hWnd == GetForegroundWindow(); 17 | } 18 | 19 | #region kernel32 20 | 21 | [DllImport("kernel32.dll")] 22 | public static extern IntPtr GetModuleHandle(string lpModuleName); 23 | 24 | #endregion 25 | 26 | #region user32 27 | 28 | #region ShowWindow 29 | /// Shows a Window 30 | /// 31 | /// To perform certain special effects when showing or hiding a 32 | /// window, use AnimateWindow. 33 | ///The first time an application calls ShowWindow, it should use 34 | ///the WinMain function's nCmdShow parameter as its nCmdShow parameter. 35 | ///Subsequent calls to ShowWindow must use one of the values in the 36 | ///given list, instead of the one specified by the WinMain function's 37 | ///nCmdShow parameter. 38 | ///As noted in the discussion of the nCmdShow parameter, the 39 | ///nCmdShow value is ignored in the first call to ShowWindow if the 40 | ///program that launched the application specifies startup information 41 | ///in the structure. In this case, ShowWindow uses the information 42 | ///specified in the STARTUPINFO structure to show the window. On 43 | ///subsequent calls, the application must call ShowWindow with nCmdShow 44 | ///set to SW_SHOWDEFAULT to use the startup information provided by the 45 | ///program that launched the application. This behavior is designed for 46 | ///the following situations: 47 | /// 48 | /// Applications create their main window by calling CreateWindow 49 | /// with the WS_VISIBLE flag set. 50 | /// Applications create their main window by calling CreateWindow 51 | /// with the WS_VISIBLE flag cleared, and later call ShowWindow with the 52 | /// SW_SHOW flag set to make it visible. 53 | /// 54 | /// Handle to the window. 55 | /// Specifies how the window is to be shown. 56 | /// This parameter is ignored the first time an application calls 57 | /// ShowWindow, if the program that launched the application provides a 58 | /// STARTUPINFO structure. Otherwise, the first time ShowWindow is called, 59 | /// the value should be the value obtained by the WinMain function in its 60 | /// nCmdShow parameter. In subsequent calls, this parameter can be one of 61 | /// the WindowShowStyle members. 62 | /// 63 | /// If the window was previously visible, the return value is nonzero. 64 | /// If the window was previously hidden, the return value is zero. 65 | /// 66 | [DllImport("user32.dll")] 67 | internal static extern bool ShowWindow(IntPtr hWnd, WindowShowStyle nCmdShow); 68 | 69 | /// Enumeration of the different ways of showing a window using 70 | /// ShowWindow 71 | internal enum WindowShowStyle : uint 72 | { 73 | /// Hides the window and activates another window. 74 | /// See SW_HIDE 75 | Hide = 0, 76 | /// Activates and displays a window. If the window is minimized 77 | /// or maximized, the system restores it to its original size and 78 | /// position. An application should specify this flag when displaying 79 | /// the window for the first time. 80 | /// See SW_SHOWNORMAL 81 | ShowNormal = 1, 82 | /// Activates the window and displays it as a minimized window. 83 | /// See SW_SHOWMINIMIZED 84 | ShowMinimized = 2, 85 | /// Activates the window and displays it as a maximized window. 86 | /// See SW_SHOWMAXIMIZED 87 | ShowMaximized = 3, 88 | /// Maximizes the specified window. 89 | /// See SW_MAXIMIZE 90 | Maximize = 3, 91 | /// Displays a window in its most recent size and position. 92 | /// This value is similar to "ShowNormal", except the window is not 93 | /// actived. 94 | /// See SW_SHOWNOACTIVATE 95 | ShowNormalNoActivate = 4, 96 | /// Activates the window and displays it in its current size 97 | /// and position. 98 | /// See SW_SHOW 99 | Show = 5, 100 | /// Minimizes the specified window and activates the next 101 | /// top-level window in the Z order. 102 | /// See SW_MINIMIZE 103 | Minimize = 6, 104 | /// Displays the window as a minimized window. This value is 105 | /// similar to "ShowMinimized", except the window is not activated. 106 | /// See SW_SHOWMINNOACTIVE 107 | ShowMinNoActivate = 7, 108 | /// Displays the window in its current size and position. This 109 | /// value is similar to "Show", except the window is not activated. 110 | /// See SW_SHOWNA 111 | ShowNoActivate = 8, 112 | /// Activates and displays the window. If the window is 113 | /// minimized or maximized, the system restores it to its original size 114 | /// and position. An application should specify this flag when restoring 115 | /// a minimized window. 116 | /// See SW_RESTORE 117 | Restore = 9, 118 | /// Sets the show state based on the SW_ value specified in the 119 | /// STARTUPINFO structure passed to the CreateProcess function by the 120 | /// program that started the application. 121 | /// See SW_SHOWDEFAULT 122 | ShowDefault = 10, 123 | /// Windows 2000/XP: Minimizes a window, even if the thread 124 | /// that owns the window is hung. This flag should only be used when 125 | /// minimizing windows from a different thread. 126 | /// See SW_FORCEMINIMIZE 127 | ForceMinimized = 11 128 | } 129 | #endregion 130 | 131 | /// 132 | /// The GetForegroundWindow function returns a handle to the foreground window. 133 | /// 134 | [DllImport("user32.dll")] 135 | internal static extern IntPtr GetForegroundWindow(); 136 | 137 | [DllImport("user32.dll")] 138 | [return: MarshalAs(UnmanagedType.Bool)] 139 | internal static extern bool SetForegroundWindow(IntPtr hWnd); 140 | 141 | [DllImport("user32.dll")] 142 | [return: MarshalAs(UnmanagedType.Bool)] 143 | internal static extern bool IsIconic(IntPtr hWnd); 144 | 145 | //Get window position 146 | [DllImport("user32.dll")] 147 | public static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle); 148 | 149 | public struct Rect 150 | { 151 | public int Left { get; set; } 152 | public int Top { get; set; } 153 | public int Right { get; set; } 154 | public int Bottom { get; set; } 155 | } 156 | 157 | #endregion 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Capture")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Capture")] 13 | [assembly: AssemblyCopyright("Copyright © Justin Stenning 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("064702fc-aa61-4910-97da-22d71c54c337")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.17929 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Capture.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Capture.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Match3Solver/Capture/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | -------------------------------------------------------------------------------- /Match3Solver/Capture/SharpDX/Component.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace SharpDX 9 | { 10 | 11 | // From SharpDX.Toolkit 12 | 13 | /// 14 | /// A disposable component base class. 15 | /// 16 | public abstract class Component : ComponentBase, IDisposable 17 | { 18 | /// 19 | /// Gets or sets the disposables. 20 | /// 21 | /// The disposables. 22 | protected DisposeCollector DisposeCollector { get; set; } 23 | 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// 27 | protected internal Component() 28 | { 29 | } 30 | 31 | /// 32 | /// Initializes a new instance of the class with an immutable name. 33 | /// 34 | /// The name. 35 | protected Component(string name) : base(name) 36 | { 37 | } 38 | 39 | /// 40 | /// Gets or sets a value indicating whether this instance is attached to a collector. 41 | /// 42 | /// 43 | /// true if this instance is attached to a collector; otherwise, false. 44 | /// 45 | internal bool IsAttached { get; set; } 46 | 47 | /// 48 | /// Gets a value indicating whether this instance is disposed. 49 | /// 50 | /// 51 | /// true if this instance is disposed; otherwise, false. 52 | /// 53 | protected internal bool IsDisposed { get; private set; } 54 | 55 | protected internal bool IsDisposing { get; private set; } 56 | 57 | /// 58 | /// Occurs when when Dispose is called. 59 | /// 60 | public event EventHandler Disposing; 61 | 62 | /// 63 | /// Releases unmanaged and - optionally - managed resources 64 | /// 65 | public void Dispose() 66 | { 67 | if (!IsDisposed) 68 | { 69 | IsDisposing = true; 70 | 71 | // Call the disposing event. 72 | var handler = Disposing; 73 | if (handler != null) 74 | { 75 | handler(this, EventArgs.Empty); 76 | } 77 | 78 | Dispose(true); 79 | IsDisposed = true; 80 | } 81 | } 82 | 83 | /// 84 | /// Disposes of object resources. 85 | /// 86 | /// If true, managed resources should be 87 | /// disposed of in addition to unmanaged resources. 88 | protected virtual void Dispose(bool disposeManagedResources) 89 | { 90 | if (disposeManagedResources) 91 | { 92 | // Dispose all ComObjects 93 | if (DisposeCollector != null) 94 | DisposeCollector.Dispose(); 95 | DisposeCollector = null; 96 | } 97 | } 98 | 99 | /// 100 | /// Adds a disposable object to the list of the objects to dispose. 101 | /// 102 | /// To dispose. 103 | protected internal T ToDispose(T toDisposeArg) 104 | { 105 | if (!ReferenceEquals(toDisposeArg, null)) 106 | { 107 | if (DisposeCollector == null) 108 | DisposeCollector = new DisposeCollector(); 109 | return DisposeCollector.Collect(toDisposeArg); 110 | } 111 | return default(T); 112 | } 113 | 114 | /// 115 | /// Dispose a disposable object and set the reference to null. Removes this object from the ToDispose list. 116 | /// 117 | /// Object to dispose. 118 | protected internal void RemoveAndDispose(ref T objectToDispose) 119 | { 120 | if (!ReferenceEquals(objectToDispose, null) && DisposeCollector != null) 121 | DisposeCollector.RemoveAndDispose(ref objectToDispose); 122 | } 123 | 124 | /// 125 | /// Removes a disposable object to the list of the objects to dispose. 126 | /// 127 | /// 128 | /// To dispose. 129 | protected internal void RemoveToDispose(T toDisposeArg) 130 | { 131 | if (!ReferenceEquals(toDisposeArg, null) && DisposeCollector != null) 132 | DisposeCollector.Remove(toDisposeArg); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /Match3Solver/Capture/SharpDX/ComponentBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace SharpDX 9 | { 10 | // From SharpDX.Toolkit 11 | 12 | /// 13 | /// A lightweight Component base class. 14 | /// 15 | public abstract class ComponentBase : IComponent, INotifyPropertyChanged 16 | { 17 | /// 18 | /// Occurs while this component is disposing and before it is disposed. 19 | /// 20 | //internal event EventHandler Disposing; 21 | private string name; 22 | 23 | /// 24 | /// Gets or sets a value indicating whether the name of this instance is immutable. 25 | /// 26 | /// true if this instance is name immutable; otherwise, false. 27 | private readonly bool isNameImmutable; 28 | 29 | private object tag; 30 | 31 | /// 32 | /// Initializes a new instance of the class with a mutable name. 33 | /// 34 | protected ComponentBase() 35 | { 36 | } 37 | 38 | /// 39 | /// Initializes a new instance of the class with an immutable name. 40 | /// 41 | /// The name. 42 | protected ComponentBase(string name) 43 | { 44 | if (name != null) 45 | { 46 | this.name = name; 47 | this.isNameImmutable = true; 48 | } 49 | } 50 | 51 | /// 52 | /// Gets the name of this component. 53 | /// 54 | /// The name. 55 | [DefaultValue(null)] 56 | public string Name 57 | { 58 | get { return name; } 59 | set 60 | { 61 | if (isNameImmutable) 62 | throw new ArgumentException("Name property is immutable for this instance", "value"); 63 | if (name == value) return; 64 | name = value; 65 | OnPropertyChanged("Name"); 66 | } 67 | } 68 | 69 | /// 70 | /// Gets or sets the tag associated to this object. 71 | /// 72 | /// The tag. 73 | #if !W8CORE 74 | [Browsable(false)] 75 | #endif 76 | [DefaultValue(null)] 77 | public object Tag 78 | { 79 | get 80 | { 81 | return tag; 82 | } 83 | set 84 | { 85 | if (ReferenceEquals(tag, value)) return; 86 | tag = value; 87 | OnPropertyChanged("Tag"); 88 | } 89 | } 90 | 91 | /// 92 | /// Occurs when a property value changes. 93 | /// 94 | public event PropertyChangedEventHandler PropertyChanged; 95 | 96 | protected virtual void OnPropertyChanged(string propertyName) 97 | { 98 | PropertyChangedEventHandler handler = PropertyChanged; 99 | if (handler != null) 100 | { 101 | handler(this, new PropertyChangedEventArgs(propertyName)); 102 | } 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Match3Solver/Capture/SharpDX/IComponent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace SharpDX 8 | { 9 | // From SharpDX.Toolkit 10 | 11 | /// 12 | /// Base interface for a component base. 13 | /// 14 | public interface IComponent 15 | { 16 | /// 17 | /// Gets the name of this component. 18 | /// 19 | /// The name. 20 | string Name { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Match3Solver/CutoffConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Match3Solver 9 | { 10 | public class CutoffConverter : System.Windows.Data.IValueConverter 11 | { 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | return ((int)value) > Cutoff; 15 | } 16 | 17 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | 22 | public int Cutoff { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Match3Solver/EasyHook32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/EasyHook32.dll -------------------------------------------------------------------------------- /Match3Solver/EasyHook32Svc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/EasyHook32Svc.exe -------------------------------------------------------------------------------- /Match3Solver/EasyHook64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/EasyHook64.dll -------------------------------------------------------------------------------- /Match3Solver/EasyHook64Svc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/EasyHook64Svc.exe -------------------------------------------------------------------------------- /Match3Solver/EasyLoad32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/EasyLoad32.dll -------------------------------------------------------------------------------- /Match3Solver/EasyLoad64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/EasyLoad64.dll -------------------------------------------------------------------------------- /Match3Solver/GameHook.cs: -------------------------------------------------------------------------------- 1 | using Capture.Hook; 2 | using Capture; 3 | using System; 4 | using System.Diagnostics; 5 | using Capture.Interface; 6 | using System.Threading; 7 | using System.Windows.Controls; 8 | 9 | using Bitmap = System.Drawing.Bitmap; 10 | using Rectangle = System.Drawing.Rectangle; 11 | using System.Windows.Media; 12 | 13 | namespace Match3Solver 14 | { 15 | public class GameHook 16 | { 17 | int processId = 0; 18 | Process _process; 19 | CaptureProcess _captureProcess; 20 | public Boolean hooked = false; 21 | 22 | TextBlock message; 23 | MainWindow parent; 24 | 25 | private Thread sDX = null; 26 | 27 | public GameHook(TextBlock statusMessage, MainWindow window) 28 | { 29 | this.message = statusMessage; 30 | this.parent = window; 31 | } 32 | 33 | public void AttachProcess() 34 | { 35 | 36 | Process[] processes = Process.GetProcessesByName("HuniePop 2 - Double Date"); 37 | 38 | foreach (Process process in processes) 39 | { 40 | // Simply attach to the first one found. 41 | 42 | // If the process doesn't have a mainwindowhandle yet, skip it (we need to be able to get the hwnd to set foreground etc) 43 | if (process.MainWindowHandle == IntPtr.Zero) 44 | { 45 | continue; 46 | } 47 | 48 | // Skip if the process is already hooked (and we want to hook multiple applications) 49 | if (HookManager.IsHooked(process.Id)) 50 | { 51 | continue; 52 | } 53 | 54 | Direct3DVersion direct3DVersion = Direct3DVersion.AutoDetect; 55 | 56 | CaptureConfig cc = new CaptureConfig() 57 | { 58 | Direct3DVersion = direct3DVersion, 59 | ShowOverlay = true 60 | }; 61 | 62 | processId = process.Id; 63 | _process = process; 64 | 65 | var captureInterface = new CaptureInterface(); 66 | captureInterface.RemoteMessage += new MessageReceivedEvent(CaptureInterface_RemoteMessage); 67 | _captureProcess = new CaptureProcess(process, cc, captureInterface); 68 | 69 | break; 70 | } 71 | Thread.Sleep(10); 72 | 73 | if (_captureProcess == null) 74 | { 75 | this.parent.launcHuniePop2Listener(); 76 | hooked = false; 77 | } 78 | else 79 | { 80 | this.message.Foreground = new SolidColorBrush(Colors.DarkGreen); 81 | this.message.Text = "Attached to game"; 82 | hooked = true; 83 | } 84 | 85 | } 86 | 87 | public Bitmap getScreenshot() 88 | { 89 | _captureProcess.BringProcessWindowToFront(); 90 | return _captureProcess.CaptureInterface.GetScreenshot(Rectangle.Empty, new TimeSpan(0,0,3), null, ImageFormat.Png).ToBitmap(); 91 | } 92 | 93 | public void drawOverlay(Capture.Hook.Common.Overlay items) 94 | { 95 | if (hooked) 96 | { 97 | _captureProcess.CaptureInterface.DrawOverlayInGame(items); 98 | } 99 | } 100 | 101 | /// 102 | /// Display messages from the target process 103 | /// 104 | /// 105 | void CaptureInterface_RemoteMessage(MessageReceivedEventArgs message) 106 | { 107 | Console.WriteLine(message.Message); 108 | } 109 | 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Match3Solver/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/Icon.ico -------------------------------------------------------------------------------- /Match3Solver/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/Icon.png -------------------------------------------------------------------------------- /Match3Solver/Match3Solver.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {1C6187B4-3D0F-4821-A051-BD4A48320838} 8 | WinExe 9 | Match3Solver 10 | Match3Solver 11 | v4.5.1 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | true 17 | publish\ 18 | true 19 | Disk 20 | false 21 | Foreground 22 | 7 23 | Days 24 | false 25 | false 26 | true 27 | 0 28 | 1.0.0.%2a 29 | false 30 | false 31 | true 32 | 33 | 34 | 8.0 35 | 36 | 37 | AnyCPU 38 | true 39 | full 40 | false 41 | bin\Debug\ 42 | DEBUG;TRACE 43 | prompt 44 | 4 45 | true 46 | 47 | 48 | AnyCPU 49 | pdbonly 50 | true 51 | bin\Release\ 52 | TRACE 53 | prompt 54 | 4 55 | true 56 | 57 | 58 | app.manifest 59 | 60 | 61 | Icon.ico 62 | 63 | 64 | 65 | ..\packages\CrashReporter.NET.Official.1.6.0\lib\net40\CrashReporter.NET.dll 66 | 67 | 68 | ..\packages\EasyHook.2.7.7097\lib\net40\EasyHook.dll 69 | 70 | 71 | ..\packages\SharpDX.4.2.0\lib\net45\SharpDX.dll 72 | 73 | 74 | ..\packages\SharpDX.D3DCompiler.4.2.0\lib\net45\SharpDX.D3DCompiler.dll 75 | 76 | 77 | ..\packages\SharpDX.Desktop.4.2.0\lib\net45\SharpDX.Desktop.dll 78 | 79 | 80 | ..\packages\SharpDX.Direct2D1.4.2.0\lib\net45\SharpDX.Direct2D1.dll 81 | 82 | 83 | ..\packages\SharpDX.Direct3D10.4.2.0\lib\net45\SharpDX.Direct3D10.dll 84 | 85 | 86 | ..\packages\SharpDX.Direct3D11.4.2.0\lib\net45\SharpDX.Direct3D11.dll 87 | 88 | 89 | ..\packages\SharpDX.Direct3D11.Effects.4.2.0\lib\net45\SharpDX.Direct3D11.Effects.dll 90 | 91 | 92 | ..\packages\SharpDX.Direct3D9.4.2.0\lib\net45\SharpDX.Direct3D9.dll 93 | 94 | 95 | ..\packages\SharpDX.DXGI.4.2.0\lib\net45\SharpDX.DXGI.dll 96 | 97 | 98 | ..\packages\SharpDX.Mathematics.4.2.0\lib\net45\SharpDX.Mathematics.dll 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 4.0 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | MSBuild:Compile 121 | Designer 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 | MSBuild:Compile 182 | Designer 183 | 184 | 185 | App.xaml 186 | Code 187 | 188 | 189 | MainWindow.xaml 190 | Code 191 | 192 | 193 | 194 | 195 | Code 196 | 197 | 198 | True 199 | True 200 | Resources.resx 201 | 202 | 203 | True 204 | Settings.settings 205 | True 206 | 207 | 208 | 209 | ResXFileCodeGenerator 210 | Resources.Designer.cs 211 | 212 | 213 | 214 | 215 | SettingsSingleFileGenerator 216 | Settings.Designer.cs 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | False 225 | .NET Framework 3.5 SP1 226 | false 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | PreserveNewest 239 | 240 | 241 | PreserveNewest 242 | 243 | 244 | PreserveNewest 245 | 246 | 247 | PreserveNewest 248 | 249 | 250 | PreserveNewest 251 | 252 | 253 | PreserveNewest 254 | 255 | 256 | 257 | 258 | -------------------------------------------------------------------------------- /Match3Solver/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | //[assembly: AssemblyTitle("Match3Solver")] 11 | //[assembly: AssemblyDescription("")] 12 | //[assembly: AssemblyConfiguration("")] 13 | //[assembly: AssemblyCompany("")] 14 | //[assembly: AssemblyProduct("Match3Solver")] 15 | //[assembly: AssemblyCopyright("Copyright © 2021")] 16 | //[assembly: AssemblyTrademark("")] 17 | //[assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | //[assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | //[assembly: AssemblyVersion("1.0.0.0")] 55 | //[assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /Match3Solver/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | 12 | namespace Match3Solver.Properties 13 | { 14 | /// 15 | /// A strongly-typed resource class, for looking up localized strings, etc. 16 | /// 17 | // This class was auto-generated by the StronglyTypedResourceBuilder 18 | // class via a tool like ResGen or Visual Studio. 19 | // To add or remove a member, edit your .ResX file then rerun ResGen 20 | // with the /str option, or rebuild your VS project. 21 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 22 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 23 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 24 | internal class Resources 25 | { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() 33 | { 34 | } 35 | 36 | /// 37 | /// Returns the cached ResourceManager instance used by this class. 38 | /// 39 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 40 | internal static global::System.Resources.ResourceManager ResourceManager 41 | { 42 | get 43 | { 44 | if ((resourceMan == null)) 45 | { 46 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Match3Solver.Properties.Resources", typeof(Resources).Assembly); 47 | resourceMan = temp; 48 | } 49 | return resourceMan; 50 | } 51 | } 52 | 53 | /// 54 | /// Overrides the current thread's CurrentUICulture property for all 55 | /// resource lookups using this strongly typed resource class. 56 | /// 57 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 58 | internal static global::System.Globalization.CultureInfo Culture 59 | { 60 | get 61 | { 62 | return resourceCulture; 63 | } 64 | set 65 | { 66 | resourceCulture = value; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Match3Solver/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /Match3Solver/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | 12 | namespace Match3Solver.Properties 13 | { 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 17 | { 18 | 19 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 20 | 21 | public static Settings Default 22 | { 23 | get 24 | { 25 | return defaultInstance; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Match3Solver/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Match3Solver/Resources/bHeartHeadH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/Resources/bHeartHeadH.png -------------------------------------------------------------------------------- /Match3Solver/Resources/bHeartHeadV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/Resources/bHeartHeadV.png -------------------------------------------------------------------------------- /Match3Solver/Resources/bHeartTailH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/Resources/bHeartTailH.png -------------------------------------------------------------------------------- /Match3Solver/Resources/bHeartTailV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdnpascual/Match3Solver/181a502706e9cfe8825564ac991dee10921b6d0c/Match3Solver/Resources/bHeartTailV.png -------------------------------------------------------------------------------- /Match3Solver/SolverInterface.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Media; 7 | 8 | namespace Match3Solver 9 | { 10 | public interface SolverInterface 11 | { 12 | 13 | public struct Score 14 | { 15 | public int BrokenHeart; 16 | public int Heart; 17 | public int Stamina; 18 | public int Sentiment; 19 | public int Blue; 20 | public int Red; 21 | public int Green; 22 | public int Gold; 23 | public int Bell; 24 | 25 | public int staminaCost; 26 | public int chains; 27 | public Boolean wasChanged; 28 | 29 | public Score(int whyDoINeedThis) 30 | { 31 | this.BrokenHeart = 0; 32 | this.Heart = 0; 33 | this.Stamina = 0; 34 | this.Sentiment = 0; 35 | this.Blue = 0; 36 | this.Red = 0; 37 | this.Green = 0; 38 | this.Gold = 0; 39 | this.Bell = 0; 40 | wasChanged = false; 41 | this.staminaCost = 0; 42 | this.chains = 0; 43 | } 44 | 45 | public void addScoreFromValue(int value) 46 | { 47 | wasChanged = true; 48 | switch (value % 10) 49 | { 50 | case 0: 51 | this.BrokenHeart++; 52 | break; 53 | case 1: 54 | this.Heart++; 55 | break; 56 | case 2: 57 | this.Stamina++; 58 | break; 59 | case 3: 60 | this.Sentiment++; 61 | break; 62 | case 4: 63 | this.Blue++; 64 | break; 65 | case 5: 66 | this.Red++; 67 | break; 68 | case 6: 69 | this.Green++; 70 | break; 71 | case 7: 72 | this.Gold++; 73 | break; 74 | case 8: 75 | this.Bell++; 76 | break; 77 | } 78 | } 79 | 80 | public void resetWasChanged() 81 | { 82 | this.wasChanged = false; 83 | } 84 | 85 | public Boolean hasScore() 86 | { 87 | return (this.BrokenHeart + this.Heart + this.Stamina + this.Sentiment + this.Blue + this.Red + this.Green + this.Gold + this.Bell > 0); 88 | } 89 | 90 | public int getTotal() 91 | { 92 | return this.Heart + this.Stamina + this.Sentiment + this.Blue + this.Red + this.Green + this.Gold + this.Bell - this.BrokenHeart; 93 | } 94 | 95 | public int getTotalNoBroken() 96 | { 97 | return this.Heart + this.Stamina + this.Sentiment + this.Blue + this.Red + this.Green + this.Gold + this.Bell; 98 | } 99 | } 100 | 101 | public struct Movement 102 | { 103 | public int xPos; 104 | public int yPos; 105 | public Boolean isVertical; 106 | public int amount; 107 | public Score score; 108 | public int boardHash; 109 | 110 | public Movement(int xPos, int yPos, Boolean isVertical, int amount, Score score, int boardhash) 111 | { 112 | this.xPos = xPos; 113 | this.yPos = yPos; 114 | this.isVertical = isVertical; 115 | this.amount = amount; 116 | this.score = score; 117 | this.boardHash = boardhash; 118 | } 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Match3Solver/UIFunctions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | using System.Windows.Documents; 7 | using System.Windows.Media; 8 | using System.Windows.Media.Imaging; 9 | using System.Windows.Shapes; 10 | 11 | namespace Match3Solver 12 | { 13 | public class UIFunctions 14 | { 15 | 16 | //0 - Broken heart 17 | //1 - Heart 18 | //2 - Stamina 19 | //3 - Sentiment 20 | //4 - Blue 21 | //5 - Red 22 | //6 - Green 23 | //7 - Gold 24 | //8 - Bell 25 | //9 - Unknown 26 | Dictionary myColors = new Dictionary 27 | { 28 | { 0, Colors.DarkViolet }, 29 | { 1, Colors.HotPink }, 30 | { 2, Colors.LightSlateGray }, 31 | { 3, Colors.Cyan }, 32 | { 4, Colors.Blue }, 33 | { 5, Colors.Red }, 34 | { 6, Colors.Lime }, 35 | { 7, Colors.Goldenrod }, 36 | { 8, Colors.Yellow }, 37 | { 9, Colors.White } 38 | }; 39 | 40 | Dictionary arrowHeadV = new Dictionary(); 41 | Dictionary arrowHeadH = new Dictionary(); 42 | Dictionary arrowTailV = new Dictionary(); 43 | Dictionary arrowTailH = new Dictionary(); 44 | 45 | private MainWindow parent; 46 | 47 | public UIFunctions(MainWindow parent) 48 | { 49 | this.parent = parent; 50 | loadAssets(); 51 | } 52 | 53 | private void loadAssets() 54 | { 55 | System.Drawing.ImageConverter converter = new System.Drawing.ImageConverter(); 56 | arrowHeadV.Add(0, (byte[])converter.ConvertTo(System.Drawing.Image.FromStream(URIImage2Stream(new Uri(@"pack://application:,,,/Resources/bheartheadv.png"))), typeof(byte[]))); 57 | arrowHeadH.Add(0, (byte[])converter.ConvertTo(System.Drawing.Image.FromStream(URIImage2Stream(new Uri(@"pack://application:,,,/Resources/bheartheadh.png"))), typeof(byte[]))); 58 | arrowTailV.Add(0, (byte[])converter.ConvertTo(System.Drawing.Image.FromStream(URIImage2Stream(new Uri(@"pack://application:,,,/Resources/bhearttailv.png"))), typeof(byte[]))); 59 | arrowTailH.Add(0, (byte[])converter.ConvertTo(System.Drawing.Image.FromStream(URIImage2Stream(new Uri(@"pack://application:,,,/Resources/bhearttailh.png"))), typeof(byte[]))); 60 | } 61 | 62 | private MemoryStream URIImage2Stream(Uri path) 63 | { 64 | var bitmapImage = new BitmapImage(path); 65 | 66 | var encoder = new PngBitmapEncoder(); 67 | encoder.Frames.Add(BitmapFrame.Create((BitmapImage)bitmapImage)); 68 | var stream = new MemoryStream(); 69 | encoder.Save(stream); 70 | stream.Flush(); 71 | 72 | return stream; 73 | } 74 | 75 | public Capture.Hook.Common.Overlay parseMovementAndDraw(SolverInterface.Movement command, int cellColor, int height, int width) 76 | { 77 | 78 | System.Drawing.Color tint = new System.Drawing.Color(); 79 | switch (cellColor) 80 | { 81 | case 0: 82 | tint = System.Drawing.Color.DarkMagenta; 83 | break; 84 | case 1: 85 | tint = System.Drawing.Color.Magenta; 86 | break; 87 | case 2: 88 | tint = System.Drawing.Color.Black; 89 | break; 90 | case 3: 91 | tint = System.Drawing.Color.Cyan; 92 | break; 93 | case 4: 94 | tint = System.Drawing.Color.MediumBlue; 95 | break; 96 | case 5: 97 | tint = System.Drawing.Color.Firebrick; 98 | break; 99 | case 6: 100 | tint = System.Drawing.Color.LimeGreen; 101 | break; 102 | case 7: 103 | tint = System.Drawing.Color.DarkOrange; 104 | break; 105 | case 8: 106 | tint = System.Drawing.Color.Yellow; 107 | break; 108 | } 109 | 110 | // CENTER = 1200X35 ON 3840X2160 111 | // PIXEL TO CHECK 1227X364 ON 3840X2160 112 | int startX = (int)(width * 0.2961); 113 | int startY = (int)(height * 0.12686); 114 | int offset = (int)(0.04688 * width); // 180 FOR 4K 115 | 116 | // -30, 0, 60 FOR 4K 117 | int directionOffsetX = command.isVertical ? (int)(-1 * (width * 0.0078125)) : (int)(width * 0.015625); 118 | // 50, 60, -20 FOR 4K 119 | int directionOffsetY = command.isVertical ? ((command.amount > 0) ? (int)(width * 0.01302083) : (int)(width * 0.015625)) : (int)(-1 * (width * 0.0052083)); 120 | 121 | List elem = new List(); 122 | 123 | // TAILS 124 | int i = command.amount > 0 ? command.amount - 1 : command.amount + 1; 125 | while(i != 0) //!= 0 126 | { 127 | int xOffset = command.isVertical ? 0 : (command.amount > 0) ? i-1 : i; 128 | int yOffset = command.isVertical ? (command.amount > 0) ? i - 1 : i : 0; 129 | 130 | elem.Add(new Capture.Hook.Common.ImageElement() { Location = new System.Drawing.Point((startX + (offset * command.xPos)) + (offset * xOffset) + directionOffsetX, (startY + (offset * command.yPos)) + (offset * yOffset) + directionOffsetY), Image = command.isVertical ? arrowTailV[0] : arrowTailH[0], Scale = (float)((float)width / 3840), Tint = tint }); 131 | 132 | if (i >= 0) i--; 133 | else i++; 134 | } 135 | 136 | int finalX = command.isVertical ? command.xPos : command.xPos + command.amount; 137 | int finalY = command.isVertical ? command.yPos + command.amount : command.yPos; 138 | // -190, 7 FOR 4K 139 | int headOffsetX = command.isVertical ? 0 : ((command.amount > 0) ? (int)(-1 * (width * 0.049479167)) : (int)(width * 0.0018229167)); 140 | // -188, 10, 3 FOR 4K 141 | int headOffsetY = command.isVertical ? ((command.amount > 0) ? (int)(-1 * (width * 0.0489584)) : (int)(width * 0.002604167)) : ((command.amount > 0) ? (int)(width * 0.00078125) : 1); 142 | 143 | // HEAD 144 | elem.Add(new Capture.Hook.Common.ImageElement() { Location = new System.Drawing.Point(startX + (offset * finalX) + directionOffsetX + headOffsetX, startY + (offset * finalY) + directionOffsetY + headOffsetY), Image = command.isVertical ? arrowHeadV[0] : arrowHeadH[0], Angle = (command.amount > 0) ? 3.14159f : 0.0f, Scale = (float)((float)width / 3840), Tint = tint }); 145 | 146 | return new Capture.Hook.Common.Overlay 147 | { 148 | Elements = elem, 149 | Hidden = false 150 | }; 151 | } 152 | 153 | public void initBoardDisplay() 154 | { 155 | int xPos = 10; 156 | int yPos = 10; 157 | int x = 0; 158 | int y = 0; 159 | 160 | while (y < parent.length) 161 | { 162 | parent.boardDisplay[y] = new Rectangle[parent.width]; 163 | xPos = 10; 164 | x = 0; 165 | while (x < parent.width) 166 | { 167 | parent.boardDisplay[y][x] = createRectangle(xPos, yPos, myColors[parent.board[y][x] % 10]); 168 | parent.mainGrid.Children.Add(parent.boardDisplay[y][x]); 169 | xPos += parent.boxSize; 170 | x++; 171 | } 172 | yPos += parent.boxSize; 173 | y++; 174 | } 175 | } 176 | 177 | private Rectangle createRectangle(int xPos, int yPos, Color color) 178 | { 179 | Rectangle rect = new Rectangle(); 180 | rect.Fill = new SolidColorBrush(color); 181 | 182 | rect.VerticalAlignment = VerticalAlignment.Top; 183 | rect.HorizontalAlignment = HorizontalAlignment.Left; 184 | 185 | rect.Margin = new Thickness(xPos, yPos, 0, 0); 186 | rect.Stroke = new SolidColorBrush(Colors.Black); 187 | 188 | rect.Height = parent.boxSize; 189 | rect.Width = parent.boxSize; 190 | 191 | return rect; 192 | } 193 | 194 | public void drawBoard(int[][] board) 195 | { 196 | int x = 0; 197 | int y = 0; 198 | while (y < parent.length) 199 | { 200 | x = 0; 201 | while (x < parent.width) 202 | { 203 | parent.boardDisplay[y][x].Fill = new SolidColorBrush(myColors[board[y][x] % 10]); 204 | x++; 205 | } 206 | y++; 207 | } 208 | } 209 | 210 | public void highLightMode(String toSearch, RichTextBox rtb, RichTextBox other) 211 | { 212 | // RESET OTHER RICH TEXT BOX 213 | TextRange text2 = new TextRange(other.Document.ContentStart, other.Document.ContentEnd); 214 | text2.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Normal); 215 | text2.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black); 216 | 217 | // RESET CURRENT RICH TEXT BOX 218 | TextRange text = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd); 219 | TextPointer current = text.Start.GetInsertionPosition(LogicalDirection.Forward); 220 | text.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Normal); 221 | text.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black); 222 | 223 | while (current != null) 224 | { 225 | string textInRun = current.GetTextInRun(LogicalDirection.Forward); 226 | if (!string.IsNullOrWhiteSpace(textInRun)) 227 | { 228 | int index = textInRun.IndexOf(toSearch); 229 | if (index != -1) 230 | { 231 | TextPointer selectionStart = current.GetPositionAtOffset(index, LogicalDirection.Forward); 232 | TextPointer selectionEnd = selectionStart.GetPositionAtOffset(toSearch.Length, LogicalDirection.Forward); 233 | TextRange selection = new TextRange(selectionStart, selectionEnd); 234 | selection.Text = toSearch; 235 | selection.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold); 236 | selection.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red); 237 | rtb.Selection.Select(selection.Start, selection.End); 238 | rtb.Focus(); 239 | } 240 | } 241 | current = current.GetNextContextPosition(LogicalDirection.Forward); 242 | } 243 | } 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /Match3Solver/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Match3Solver/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Match3Solver/resultItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Match3Solver 8 | { 9 | class resultItem 10 | { 11 | public string Position { get; set; } 12 | public int Amount { get; set; } 13 | public string Direction { get; set; } 14 | public int sHeart { get; set; } 15 | public int sStam { get; set; } 16 | public int sSent { get; set; } 17 | public int sBlue { get; set; } 18 | public int sRed { get; set; } 19 | public int sGreen { get; set; } 20 | public int sGold { get; set; } 21 | public int sBell { get; set; } 22 | public int sBHeart { get; set; } 23 | public Boolean isVertical { set; get; } 24 | public int xPos { set; get; } 25 | public int yPos { set; get; } 26 | public int StaminaCost { set; get; } 27 | public int Chain { set; get; } 28 | public int Total { set; get; } 29 | public int TotalWBroken { set; get; } 30 | 31 | public resultItem(SolverInterface.Movement input) 32 | { 33 | Position = "[" + input.yPos + "," + input.xPos + "]"; 34 | Amount = input.amount; 35 | Direction = getDirection(input); 36 | sHeart = input.score.Heart; 37 | sStam = input.score.Stamina; 38 | sSent = input.score.Sentiment; 39 | sBlue = input.score.Blue; 40 | sRed = input.score.Red; 41 | sGreen = input.score.Green; 42 | sGold = input.score.Gold; 43 | sBell = input.score.Bell; 44 | sBHeart = input.score.BrokenHeart; 45 | isVertical = input.isVertical; 46 | xPos = input.xPos; 47 | yPos = input.yPos; 48 | StaminaCost = input.score.staminaCost; 49 | Chain = input.score.chains; 50 | Total = input.score.getTotal(); 51 | TotalWBroken = input.score.getTotalNoBroken() - (2 * input.score.BrokenHeart); 52 | } 53 | 54 | private string getDirection(SolverInterface.Movement input) 55 | { 56 | if (!input.isVertical && input.amount > 0) 57 | { 58 | return "⇒"; 59 | } 60 | else if (!input.isVertical && input.amount < 0) 61 | { 62 | return "⇐"; 63 | } 64 | else if (input.isVertical && input.amount > 0) 65 | { 66 | return "⇓"; 67 | } 68 | else if (input.isVertical && input.amount < 0) 69 | { 70 | return "⇑"; 71 | } 72 | return "?"; 73 | } 74 | 75 | public override string ToString() 76 | { 77 | return Direction; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Match3Solver 2 | 3 | ![WindowScreenshot](https://i.imgur.com/y2bp54S.jpg) 4 | ![Board](https://i.imgur.com/XKdTcJn.jpg) 5 | 6 | Match 3 Solver for HuniePop2 7 | 8 | Features: 9 | - Automatically Injects to the game to be able to screenshot the board state 10 | - Parses and Solve the board state. 11 | - Draw Movements on top of the game 12 | - Various sort modes for results 13 | 14 | Usage: 15 | 1) [Download the Zip](https://github.com/mdnpascual/Match3Solver/releases) 16 | 2) Right click the Zip >> Properties >> Tick Unblock and Click Apply 17 | 3) Extract the zip BUT DO NOT PUT IT ON THE SAME FOLDER WHERE HUNIEPOP2 is located 18 | 4) Run Match3Solver.exe. (It won't run if you Click no when asking for Admin Access) 19 | 5) Run huniepop 20 | 6) Press Ctrl + Alt + C to capture board state and solve. 21 | 22 | Video Demo on How to Use: 23 | 24 | [](https://youtu.be/xW7D1d0Jp6c)https://www.youtube.com/watch?v=xW7D1d0Jp6c 25 | 26 | Known Bugs: 27 | - Random Game crash when alt-tabing 28 | 29 | Unknown Bugs: 30 | - Only Tested on monitors with 16:9 Aspect Ratio (3840x2160, 2560x1440, 1920x1080). Don't know how the gmae behaves on widescreen monitors 31 | 32 | Notes when Building from Source: 33 | Include sharpdx_direct3d11_1_effects_x64.dll in Debug or Release folder. File can be found under Match3Solver\packages\SharpDX.Direct3D11.Effects.4.2.0\runtimes\win7-x64\native 34 | Then add a suffix of "_x64" at the end 35 | --------------------------------------------------------------------------------