├── .gitignore ├── LICENSE ├── README.md └── src └── Husky ├── Husky.sln ├── Husky ├── App.config ├── FileFormats │ ├── IWMap.cs │ └── WavefrontOBJ.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── GameStructures │ ├── GameDefinition.cs │ ├── ModernWarfare4_Offsets.cs │ ├── Shared.cs │ └── Vanguard_Offsets.cs ├── Games │ ├── AdvancedWarfare.cs │ ├── BlackOps.cs │ ├── BlackOps2.cs │ ├── BlackOps3.cs │ ├── Ghosts.cs │ ├── InfiniteWarfare.cs │ ├── ModernWarfare.cs │ ├── ModernWarfare2.cs │ ├── ModernWarfare3.cs │ ├── ModernWarfare4.cs │ ├── ModernWarfareRM.cs │ ├── Vanguard.cs │ ├── WorldAtWar.cs │ └── WorldWarII.cs ├── Husky.csproj ├── HuskyUtil.cs ├── Properties │ └── AssemblyInfo.cs ├── Utility │ ├── FloatToInt.cs │ ├── HalfFloats.cs │ ├── Rotation.cs │ ├── Vectors.cs │ ├── Vertex.cs │ └── VertexNormal.cs ├── icon.ico └── packages.config ├── HuskyUI ├── AboutWindow.xaml ├── AboutWindow.xaml.cs ├── App.config ├── App.xaml ├── App.xaml.cs ├── FodyWeavers.xml ├── HuskyUI.csproj ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── icon.ico ├── icon.png └── packages.config └── PhilLibX ├── ByteUtil.cs ├── Compression └── Oodle.cs ├── Cryptography └── Hash │ ├── CRC32.cs │ ├── DJB.cs │ ├── FNV1a.cs │ └── SDBM.cs ├── IO ├── IOExtensions.cs ├── MemoryUtil.cs ├── ProcessReader.cs └── ProcessWriter.cs ├── Imaging ├── BitmapX.cs └── Texturing.cs ├── Logger.cs ├── MathUtilities.cs ├── NativeMethods.cs ├── PhilLibX.csproj ├── Printer.cs └── Properties └── AssemblyInfo.cs /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Husky 2 | Husky is a BSP Extractor for Call of Duty. It can rip the raw vertex/face data to a file that can be opened in software such as Autodesk Maya (currently only OBJ). It also includes UVs and material names, and in the future, will export other data such as static models, dynamic models, etc. 3 | 4 | ### Supported Games 5 | 6 | * Call of Duty: Modern Warfare 7 | * Call of Duty: Modern Warfare 2 8 | * Call of Duty: Modern Warfare 3 9 | * Call of Duty: Ghosts 10 | * Call of Duty: Infinite Warfare 11 | * Call of Duty: World at War 12 | * Call of Duty: Black Ops 13 | * Call of Duty: Black Ops 2 14 | * Call of Duty: Black Ops 3 15 | * Call of Duty: Advanced Warfare 16 | * Call of Duty: World War 2 17 | * Call of Duty: Modern Warfare Remastered 18 | * Call of Duty: Modern Warfare 2019 (Parasyte) 19 | * Call of Duty: Vanguard (Parasyte) 20 | 21 | ### Downloading/Using Husky 22 | 23 | To download Husky, go to the [Releases](https://github.com/Scobalula/Husky/releases) and download the latest build. 24 | 25 | To use Husky, simply run the game, load the map you want to extract, and run Husky, then click the paper airplane to export the loaded map. In some cases you may need to run Husky as an administator. 26 | 27 | Once the map is exported, you will have 3 files for it: 28 | 29 | * **mapname**.obj - Main 3D Obj File 30 | * **mapname**.mtl - Material Info 31 | * **mapname**.txt - A search string for Wraith/Greyhound (only contains color maps) 32 | * **mapname**.map - Map file with **static** model locations and rotations 33 | 34 | If you wish to use textures (be warned they can result in high RAM usage) then make sure to have the _images folder (use Wraith/Greyhound to export the required images) in the same location as the obj/mtl file and export PNGs (do not ask for other formats, it's staying as PNG, do a find/replace if you want to use other formats). 35 | 36 | ### License/Disclaimers 37 | 38 | Husky is licensed under the GPL license and it and its source code is free to use and modify under the terms of the GPL. Husky comes with NO warranty, any damages caused are solely the responsibility of the user. See the LICENSE file for more information. 39 | 40 | **All** BSP data extracted using Husky is property of the developers, etc. and with this in mind you need to understand the limitation of what you can do with the data. Husky simply parses it out, what you do with it, is your responsibility. 41 | 42 | Some of the exported models can get pretty big. While all have loaded in Maya with no issue, make sure to have available resources available to load and view them. 43 | 44 | Husky is provided ***AS IS***, do not ask how to do XYZ, how to import it into X program, etc. You need to know what you're doing, we can't hold your hand through it. 45 | 46 | Also I've noticed several people asking how to import it into Unity/Unreal, there is a fine line between using the Geo to remake a map in another Call of Duty Game using its own SDK **vs** using the Geo as it is in your game/IP, for example, so ensure you know what you're doing, copyright wise. 47 | 48 | ## FAQ 49 | 50 | * Q: Husky says it cannot find my game? 51 | 52 | * A: Check the above list for a supported game, when searching for a supported game, Husky loops over all processes and stops at the first match, if it's not finding your game and it is supported, your exe is not the same name as what Husky expects or something is blocking .NET from returning its process. 53 | 54 | * Q: Husky says my game is not supported? 55 | 56 | * A: I verify the addresses on legitimate up to date copies of the supported games in the English locale. If you're using a modified executable (Pirated, etc.) I will not support it. 57 | 58 | * Q: The exported OBJ is corrupt when imported? 59 | 60 | * A: Tons of BSPs across all supported games have been verified, if you have find a legitimate instance of a corrupt export, please open an issue with the name of the map, etc. as much info as you can. 61 | 62 | * Q: Why is there a bunch of geo at the origin? 63 | 64 | * A: It appears in all games, script brushmodels are at the origin, and I assume the map_ents assets or some other data is used to tell the game where to move them to on load. This will remain as is. 65 | 66 | # Discord 67 | 68 | ❤️ Join my Discord to receive community help or show off your stuff ❤️ 69 | 70 | [![Join my Discord](https://discordapp.com/api/guilds/719503756810649640/widget.png?style=banner2)](https://discord.gg/RyqyThu) 71 | 72 | ## Credits 73 | 74 | * DTZxPorter - Normal Unpacking Code from Wraith, Half Floats code, Other misc info from Wraith. 75 | * Anna Baker - [Icon](https://thenounproject.com/term/husky/1121992/) ([https://thenounproject.com/anna.baker194/](https://thenounproject.com/anna.baker194/)) -------------------------------------------------------------------------------- /src/Husky/Husky.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2035 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Husky", "Husky\Husky.csproj", "{BBEB0978-D656-4432-80E9-CF2083F53349}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhilLibX", "PhilLibX\PhilLibX.csproj", "{8F5C1BA4-88C1-4177-B91B-DD093DC849B9}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HuskyUI", "HuskyUI\HuskyUI.csproj", "{5BC7C6FE-F65C-4F32-BC26-FAC69926F10E}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {BBEB0978-D656-4432-80E9-CF2083F53349}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {BBEB0978-D656-4432-80E9-CF2083F53349}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {BBEB0978-D656-4432-80E9-CF2083F53349}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {BBEB0978-D656-4432-80E9-CF2083F53349}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {8F5C1BA4-88C1-4177-B91B-DD093DC849B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {8F5C1BA4-88C1-4177-B91B-DD093DC849B9}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {8F5C1BA4-88C1-4177-B91B-DD093DC849B9}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {8F5C1BA4-88C1-4177-B91B-DD093DC849B9}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {5BC7C6FE-F65C-4F32-BC26-FAC69926F10E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {5BC7C6FE-F65C-4F32-BC26-FAC69926F10E}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {5BC7C6FE-F65C-4F32-BC26-FAC69926F10E}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {5BC7C6FE-F65C-4F32-BC26-FAC69926F10E}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {AF6E0EB2-84B0-4787-9E43-AD0E1E27FCAE} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /src/Husky/Husky/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Husky/Husky/FileFormats/IWMap.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // Husky - Call of Duty BSP Extractor 3 | // Copyright (C) 2018 Philip/Scobalula 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // ------------------------------------------------------------------------ 18 | using System; 19 | using System.Collections.Generic; 20 | using System.IO; 21 | 22 | namespace Husky 23 | { 24 | /// 25 | /// A class to hold IWMap Info and Logic 26 | /// 27 | public class IWMap 28 | { 29 | /// 30 | /// A class to hold a .MAP Entity 31 | /// 32 | public class Entity 33 | { 34 | /// 35 | /// Entity KVPs 36 | /// 37 | public Dictionary KeyValuePairs = new Dictionary(); 38 | 39 | /// 40 | /// Initializes an entity with a Classname 41 | /// 42 | public Entity(string className) 43 | { 44 | KeyValuePairs["classname"] = className; 45 | } 46 | 47 | /// 48 | /// Creates a Misc/Prop Model 49 | /// 50 | /// Name of the Model Asset 51 | /// XYZ Origin 52 | /// XYZ Angles 53 | /// Model Scale 54 | /// Resulting entity 55 | public static Entity CreateMiscModel(string modelName, Vector3 origin, Vector3 angles, float modelScale) 56 | { 57 | // Create new entity 58 | var result = new Entity("misc_model"); 59 | // Add properties 60 | result.KeyValuePairs["model"] = modelName; 61 | result.KeyValuePairs["origin"] = String.Format("{0:0.0000} {1:0.0000} {2:0.0000}", origin.X, origin.Y, origin.Z); 62 | result.KeyValuePairs["angles"] = String.Format("{1:0.0000} {2:0.0000} {0:0.0000}", angles.X, angles.Y, angles.Z); 63 | result.KeyValuePairs["modelscale"] = modelScale.ToString(); 64 | // Ship her back 65 | return result; 66 | } 67 | } 68 | 69 | /// 70 | /// Map entities 71 | /// 72 | public List Entities = new List(); 73 | 74 | /// 75 | /// Initializes an IW Map with a Basic Worldspawn Entity 76 | /// 77 | public IWMap() 78 | { 79 | // Create Worldspawn Entity 80 | var worldspawn = new Entity("worldspawn"); 81 | // Set properties 82 | worldspawn.KeyValuePairs["fsi"] = "default"; 83 | worldspawn.KeyValuePairs["gravity"] = "800"; 84 | worldspawn.KeyValuePairs["lodbias"] = "default"; 85 | worldspawn.KeyValuePairs["lutmaterial"] = "luts_t7_default"; 86 | worldspawn.KeyValuePairs["numOmniShadowSlices"] = "24"; 87 | worldspawn.KeyValuePairs["numSpotShadowSlices"] = "64"; 88 | worldspawn.KeyValuePairs["sky_intensity_factor0"] = "1"; 89 | worldspawn.KeyValuePairs["sky_intensity_factor1"] = "1"; 90 | worldspawn.KeyValuePairs["state_alias_1"] = "State 1"; 91 | worldspawn.KeyValuePairs["state_alias_2"] = "State 2"; 92 | worldspawn.KeyValuePairs["state_alias_3"] = "State 3"; 93 | worldspawn.KeyValuePairs["state_alias_4"] = "State 4"; 94 | // Add it 95 | Entities.Add(worldspawn); 96 | } 97 | 98 | /// 99 | /// Dumps whatever we can to a .MAP file 100 | /// 101 | /// File Name 102 | public void DumpToMap(string fileName) 103 | { 104 | // Create output stream 105 | using (var writer = new StreamWriter(fileName)) 106 | { 107 | // Write basic header 108 | writer.WriteLine("iwmap 4"); 109 | writer.WriteLine("\"script_startingnumber\" 0"); 110 | writer.WriteLine("\"000_Global\" flags active"); 111 | writer.WriteLine("\"The Map\" flags expanded "); 112 | 113 | // Write entitys 114 | for (int i = 0; i < Entities.Count; i++) 115 | { 116 | // Write Index Comment 117 | writer.WriteLine("// entity {0}", i); 118 | // Write initial bracket 119 | writer.WriteLine("{"); 120 | // Write KVPs 121 | foreach (var kvp in Entities[i].KeyValuePairs) 122 | writer.WriteLine("\"{0}\" \"{1}\"", kvp.Key, kvp.Value); 123 | // Write end bvracket 124 | writer.WriteLine("}"); 125 | } 126 | } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/Husky/Husky/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Husky/Husky/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 'true' to run assembly verification on the target assembly after all weavers have been finished. 12 | 13 | 14 | 15 | 16 | A comma separated list of error codes that can be safely ignored in assembly verification. 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Husky/Husky/GameStructures/GameDefinition.cs: -------------------------------------------------------------------------------- 1 | using PhilLibX.IO; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Husky 11 | { 12 | public class GameDefinition 13 | { 14 | public long AssetDBAddress { get; set; } 15 | public long AssetSizesAddress { get; set; } 16 | public string GameType { get; set; } 17 | public string GamePath { get; set; } 18 | public Action> ExportMethod { get; set; } 19 | 20 | 21 | public GameDefinition( 22 | long assetDBAddress, 23 | long assetSizesAddress, 24 | string gameType, 25 | Action> exportMethod) 26 | { 27 | AssetDBAddress = assetDBAddress; 28 | AssetSizesAddress = assetSizesAddress; 29 | GameType = gameType; 30 | ExportMethod = exportMethod; 31 | } 32 | 33 | public void ParseParasyteDB(Process proces, Action printCallback) 34 | { 35 | string dbPath = Path.Combine( 36 | Path.GetDirectoryName(proces.MainModule.FileName), 37 | "Data/CurrentHandler.parasyte_state_info"); 38 | if (!File.Exists(dbPath)) 39 | { 40 | printCallback?.Invoke("Parasyte Database not found"); 41 | return; 42 | } 43 | 44 | using (BinaryReader dbReader = new BinaryReader(File.OpenRead(dbPath))) 45 | { 46 | // Validate supported game 47 | var GameID = dbReader.ReadUInt64(); 48 | switch (GameID) 49 | { 50 | // Modern Warfare 2019 51 | case 0x3931524157444f4d: 52 | ExportMethod = ModernWarfare4.ExportBSPData; 53 | break; 54 | 55 | case 0x44524155474e4156: 56 | ExportMethod = Vanguard.ExportBSPData; 57 | break; 58 | 59 | default: 60 | printCallback?.Invoke("Parasyte game handler found but is not supported."); 61 | return; 62 | } 63 | 64 | // Parse necessary offsets and paths 65 | AssetDBAddress = dbReader.ReadInt64(); 66 | // StringTableAddress - we skip it 67 | dbReader.BaseStream.Position += 8; 68 | // Game directory 69 | int pathLength = dbReader.ReadInt32(); 70 | GamePath = Encoding.UTF8.GetString(dbReader.ReadBytes(pathLength)); 71 | } 72 | } 73 | public void Export(ProcessReader reader, Action printCallback) 74 | { 75 | ExportMethod(reader, AssetDBAddress, AssetSizesAddress, GameType, printCallback); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Husky/Husky/GameStructures/ModernWarfare4_Offsets.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Numerics; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Husky 10 | { 11 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 12 | public unsafe struct MW4XAssetPoolData 13 | { 14 | // Pool pointer 15 | public long PoolPtr { get; set; } 16 | 17 | // A pointer to the closest free header 18 | public long PoolFreeHeadPtr { get; set; } 19 | 20 | // The maximum pool size 21 | public int PoolSize { get; set; } 22 | 23 | // The beginning of the pool 24 | public int AssetSize { get; set; } 25 | 26 | }; 27 | /// 28 | /// MW4 GfxMap Asset 29 | /// 30 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 31 | public unsafe struct MW4GfxMap 32 | { 33 | public long NamePointer; 34 | public long MapNamePointer; 35 | public fixed byte UnknownValues01[184]; 36 | public int SurfaceCount; 37 | public int SurfaceDataCount; 38 | public fixed byte UnknownValues02[48]; 39 | public long SurfacesPointer; 40 | public fixed byte UnknownValues03[64]; 41 | public long SurfaceDataPointer; 42 | public fixed byte UnknownValues04[68]; 43 | public int UniqueModelCount; 44 | public int ModelInstDataCount; 45 | public fixed byte UnknownValues06[4]; 46 | public int ModelInstCount; 47 | public fixed byte UnknownValues07[44]; 48 | public long UniqueModelsPtr; 49 | public long Padding; 50 | public long ModelInstDataPtr; 51 | public fixed byte UnknownValues08[248]; 52 | public long ModelInstPtr; 53 | public fixed byte UnknownValues09[1348]; 54 | public int TrZoneCount; 55 | public long TrZonePtr; 56 | } 57 | /// 58 | /// Contains data for each xmodel instances 59 | /// 60 | [StructLayout(LayoutKind.Sequential)] 61 | public unsafe struct MW4ModelInstData 62 | { 63 | public int firstInstance; 64 | public int instanceCount; 65 | public ushort uniqueModelIndex; 66 | public fixed byte Padding[6]; 67 | } 68 | 69 | [StructLayout(LayoutKind.Sequential)] 70 | public unsafe struct MW4GfxStaticModel 71 | { 72 | public long XModelPointer; 73 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] 74 | public uint[] Flags; 75 | } 76 | 77 | /// 78 | /// Surface Data - points to surface data in TRZone 79 | /// 80 | [StructLayout(LayoutKind.Sequential)] 81 | public unsafe struct MW4GfxSurfaceData 82 | { 83 | public int TransientZone; // Zone Index 84 | public int LayerCount; 85 | public int PositionsPosition; 86 | public int NormalQuatPosition; 87 | public int Unk01; 88 | public int ColorsPosition; 89 | public int UVsPosition; 90 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)] 91 | public uint[] UnkOffsets; // Don't know 92 | }; 93 | 94 | /// 95 | /// Modern Warfare 2019 World TRZone 96 | /// 97 | [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 336)] 98 | public unsafe struct MW4GfxWorldTRZone 99 | { 100 | public long NamePointer; 101 | public int Index; 102 | public int Padding; 103 | public int PositionsBufferSize; 104 | public int DrawDataBufferSize; 105 | public long PositionsBufferPointer; 106 | public long DrawDataBufferPointer; 107 | public fixed byte UnknownData01[128]; 108 | public int FaceIndicesBufferSize; 109 | public long FaceIndicesBufferPointer; 110 | public fixed byte UnknownData02[32]; 111 | } 112 | 113 | /// 114 | /// Modern Warfare 2019 BSP Surface Structure 115 | /// 116 | [StructLayout(LayoutKind.Sequential)] 117 | public unsafe struct MW4GfxMapSurface 118 | { 119 | public int BufferOffset; 120 | public int UnknownFloat01; 121 | public ushort VertexCount; 122 | public ushort FaceCount; 123 | public int FaceIndex; 124 | public long MaterialPointer; 125 | public int DataIndex; 126 | public ushort TransientIndex; 127 | public byte LightmapIndex; 128 | public long UnknownValue01; 129 | } 130 | 131 | /// 132 | /// Modern Warfare 2019 Static Model Placement 133 | /// 134 | [StructLayout(LayoutKind.Sequential)] 135 | public unsafe struct MW4GfxStaticModelPlacement 136 | { 137 | /// 138 | /// 12 bytes Packed Position 139 | /// 140 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] 141 | public int[] PackedPosition; 142 | /// 143 | /// Quaternion Rotation packed into 4 ushorts 144 | /// 145 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] 146 | public ushort[] PackedQuat; 147 | /// 148 | /// Model Scale 149 | /// 150 | public float Scale; 151 | } 152 | 153 | /// 154 | /// Material Asset Info 155 | /// 156 | public unsafe struct MW4Material 157 | { 158 | /// 159 | /// A pointer to the name of this material 160 | /// 161 | public long NamePointer { get; set; } 162 | 163 | /// 164 | /// Unknown Bytes (Flags, settings, etc.) 165 | /// 166 | public fixed byte UnknownBytes[20]; 167 | 168 | /// 169 | /// Number of Images this Material has 170 | /// 171 | public byte ImageCount { get; set; } 172 | 173 | public byte ConstantCount { get; set; } 174 | 175 | /// 176 | /// Unknown Bytes (Flags, settings, etc.) 177 | /// 178 | public fixed byte UnknownBytes1[34]; 179 | 180 | /// 181 | /// A pointer to the Tech Set this Material uses 182 | /// 183 | public long TechniqueSetPointer { get; set; } 184 | 185 | /// 186 | /// A pointer to this Material's Image table 187 | /// 188 | public long ImageTablePointer { get; set; } 189 | 190 | /// 191 | /// Unknown Bytes (Flags, settings, etc.) 192 | /// 193 | public fixed byte UnknownBytes2[40]; 194 | } 195 | } -------------------------------------------------------------------------------- /src/Husky/Husky/GameStructures/Shared.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // Husky - Call of Duty BSP Extractor 3 | // Copyright (C) 2018 Philip/Scobalula 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // ------------------------------------------------------------------------ 18 | using System.Runtime.InteropServices; 19 | 20 | namespace Husky 21 | { 22 | /// 23 | /// Gfx Color 24 | /// 25 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 26 | public unsafe struct GfxColor 27 | { 28 | /// 29 | /// Red Value 30 | /// 31 | public byte R { get; set; } 32 | 33 | /// 34 | /// Red Value 35 | /// 36 | public byte G { get; set; } 37 | 38 | /// 39 | /// Red Value 40 | /// 41 | public byte B { get; set; } 42 | 43 | /// 44 | /// Red Value 45 | /// 46 | public byte A { get; set; } 47 | } 48 | 49 | /// 50 | /// Gfx Vertex 51 | /// 52 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 53 | public unsafe struct GfxVertex 54 | { 55 | /// 56 | /// X Position 57 | /// 58 | public float X { get; set; } 59 | 60 | /// 61 | /// Y Position 62 | /// 63 | public float Y { get; set; } 64 | 65 | /// 66 | /// Z Position 67 | /// 68 | public float Z { get; set; } 69 | 70 | /// 71 | /// Bi Normal 72 | /// 73 | public float BiNormal { get; set; } 74 | 75 | /// 76 | /// RGBA Color 77 | /// 78 | public GfxColor Color { get; set; } 79 | 80 | /// 81 | /// U Texture Position 82 | /// 83 | public float U { get; set; } 84 | 85 | /// 86 | /// V Texture Position 87 | /// 88 | public float V { get; set; } 89 | 90 | /// 91 | /// Unknown Bytes (Possibly tangent, etc.) 92 | /// 93 | public long Padding { get; set; } 94 | 95 | /// 96 | /// Packed Vertex Normal (same as XModels) 97 | /// 98 | public PackedUnitVector Normal { get; set; } 99 | 100 | /// 101 | /// Unknown Bytes (2 shorts?) 102 | /// 103 | public int Padding2 { get; set; } 104 | } 105 | 106 | /// 107 | /// Packed Unit Vector as 4 bytes 108 | /// 109 | [StructLayout(LayoutKind.Explicit)] 110 | public struct PackedUnitVector 111 | { 112 | /// 113 | /// Packed Value 114 | /// 115 | [FieldOffset(0)] 116 | public int Value; 117 | 118 | /// 119 | /// First Byte 120 | /// 121 | [FieldOffset(0)] 122 | public byte Byte1; 123 | 124 | /// 125 | /// Second Byte 126 | /// 127 | [FieldOffset(1)] 128 | public byte Byte2; 129 | 130 | /// 131 | /// Third Byte 132 | /// 133 | [FieldOffset(2)] 134 | public byte Byte3; 135 | 136 | /// 137 | /// Fourth Byte 138 | /// 139 | [FieldOffset(3)] 140 | public byte Byte4; 141 | } 142 | 143 | /// 144 | /// Material Image for: WaW 145 | /// 146 | public unsafe struct MaterialImage32A 147 | { 148 | /// 149 | /// Semantic Hash/Usage 150 | /// 151 | public uint SemanticHash { get; set; } 152 | 153 | /// 154 | /// Unknown Int 155 | /// 156 | public uint UnknownInt { get; set; } 157 | 158 | /// 159 | /// Null Padding 160 | /// 161 | public int Padding { get; set; } 162 | 163 | /// 164 | /// Pointer to the Image Asset 165 | /// 166 | public int ImagePointer { get; set; } 167 | } 168 | 169 | /// 170 | /// Material Image for: MW2, MW3 171 | /// 172 | public unsafe struct MaterialImage32B 173 | { 174 | /// 175 | /// Semantic Hash/Usage 176 | /// 177 | public uint SemanticHash { get; set; } 178 | 179 | /// 180 | /// Unknown Int 181 | /// 182 | public uint UnknownInt { get; set; } 183 | 184 | /// 185 | /// Pointer to the Image Asset 186 | /// 187 | public int ImagePointer { get; set; } 188 | } 189 | 190 | /// 191 | /// Material Image for: Ghosts, AW, MWR 192 | /// 193 | public unsafe struct MaterialImage64A 194 | { 195 | /// 196 | /// Semantic Hash/Usage 197 | /// 198 | public uint SemanticHash { get; set; } 199 | 200 | /// 201 | /// Unknown Int (It's possible the semantic hash is actually 64bit, and this is apart of the actual hash) 202 | /// 203 | public uint UnknownInt { get; set; } 204 | 205 | /// 206 | /// Pointer to the Image Asset 207 | /// 208 | public long ImagePointer { get; set; } 209 | } 210 | 211 | /// 212 | /// Bo3 Material Image Struct 213 | /// 214 | public unsafe struct MaterialImage64B 215 | { 216 | /// 217 | /// A pointer to the image asset 218 | /// 219 | public long ImagePointer { get; set; } 220 | 221 | /// 222 | /// Semantic Hash (i.e. colorMap, colorMap00, etc.) Varies from MTL type, base ones like colorMap are always the same 223 | /// 224 | public uint SemanticHash { get; set; } 225 | 226 | /// 227 | /// End Bytes (Usage, etc.) 228 | /// 229 | public fixed byte Padding[0x14]; 230 | } 231 | 232 | /// 233 | /// 3Float Vertex Position 234 | /// 235 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 236 | public unsafe struct GfxVertexPosition 237 | { 238 | public float X { get; set; } 239 | public float Y { get; set; } 240 | public float Z { get; set; } 241 | 242 | public Vector3 ToCentimeter() 243 | { 244 | return new Vector3(X * 2.54, Y * 2.54, Z * 2.54); 245 | } 246 | } 247 | 248 | /// 249 | /// 2Float Vertex UVs 250 | /// 251 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 252 | public unsafe struct GfxVertexUV 253 | { 254 | /// 255 | /// U Texture Position 256 | /// 257 | public float U { get; set; } 258 | 259 | /// 260 | /// V Texture Position 261 | /// 262 | public float V { get; set; } 263 | } 264 | 265 | /// 266 | /// Parasytes XAsset Structure. 267 | /// 268 | [StructLayout(LayoutKind.Sequential)] 269 | public struct ParasyteXAsset64 270 | { 271 | /// 272 | /// The xasset type depending on the game it is from. 273 | /// 274 | public int Type; 275 | 276 | /// 277 | /// The xasset size. 278 | /// 279 | public int HeaderSize; 280 | 281 | /// 282 | /// The xasset ID. 283 | /// 284 | public long ID; 285 | 286 | /// 287 | /// The xasset Name. 288 | /// 289 | public long Name; 290 | 291 | /// 292 | /// Whether or not this asset is a tempt slot. 293 | /// 294 | public int Temp; 295 | 296 | /// 297 | /// Header Memory. 298 | /// 299 | public long HeaderMemory; 300 | 301 | /// 302 | /// The fast file that owns this asset. 303 | /// 304 | public long Owner; 305 | 306 | /// 307 | /// The previous xasset in the list. 308 | /// 309 | public long Previous; 310 | 311 | /// 312 | /// The next xasset in the list. 313 | /// 314 | public long Next; 315 | 316 | /// 317 | /// First child asset we have overriden. 318 | /// 319 | public long FirstChild; 320 | 321 | /// 322 | /// Last child asset we have overriden. 323 | /// 324 | public long LastChild; 325 | 326 | /// 327 | /// The asset header. 328 | /// 329 | public long Header; 330 | /// 331 | /// The size of the extended data. 332 | /// 333 | public long ExtendedDataSize; 334 | 335 | /// 336 | /// The extended data, if any. 337 | /// 338 | public long ExtendedData; 339 | 340 | /// 341 | /// The pointer that points to the extended data. 342 | /// 343 | public long ExtendedDataPtrOffset; 344 | }; 345 | 346 | /// 347 | /// Parasytes XAsset Pool Structure. 348 | /// 349 | [StructLayout(LayoutKind.Sequential)] 350 | public struct ParasyteXAssetPool64 351 | { 352 | /// 353 | /// The start of the asset chain. 354 | /// 355 | public long FirstXAsset; 356 | 357 | /// 358 | /// The end of the asset chain. 359 | /// 360 | public long LastXAsset; 361 | 362 | /// 363 | /// The asset hash table for this pool. 364 | /// 365 | public long LookupTable; 366 | 367 | /// 368 | /// Storage for asset headers for this pool. 369 | /// 370 | public long HeaderMemory; 371 | }; 372 | } 373 | -------------------------------------------------------------------------------- /src/Husky/Husky/GameStructures/Vanguard_Offsets.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Numerics; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Husky 10 | { 11 | /// 12 | /// Vanguard GfxWorldTRZone 13 | /// 14 | [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 136)] 15 | public unsafe struct VGGfxWorldTRZone 16 | { 17 | public long NamePointer; 18 | public long UnknownPtr; 19 | public int Index; 20 | public int Unknown; 21 | public int VertexBufferSize; // 0x18 22 | public int IndexCount; // 0x1C 23 | public int UnknownCount2; // 0x20 24 | public int UnknownValue; // Don't know 25 | public long VertexBufferPointer; // 0x28 26 | public long IndicesBufferPointer; // 0x30 -- size is IndexCount * 2 27 | public long UnknownBuffer2; // 0x38 -- size is UnknownCount2 * 28 28 | public long Unknown2; // Don't know 29 | public long UnknownBuffer3; // 0x48 30 | public long UnknownSize4; // 0x50 31 | public long UnknownBuffer4; // 0x58 -- size is UnknownSize4 << 6 32 | public fixed byte Padding[32]; 33 | } 34 | /// 35 | /// Vanguard GfxWorld 36 | /// 37 | [StructLayout(LayoutKind.Sequential, Pack = 8)] 38 | public unsafe struct VGGfxMap 39 | { 40 | public long NamePointer; // 0x0 41 | public long MapNamePointer; // 0x8 42 | public fixed byte Unknown01[120]; 43 | public int surfaceCount; // 0x88 44 | public int surfaceDataCount; // 0x8C 45 | public int materialCount; // 0x90 46 | public fixed byte Unknown02[76]; 47 | public long surfacesPtr; // 0xE0 48 | public fixed byte Unknown03[72]; 49 | public long surfaceBoundsPtr; // 0x130 // size is surfaceCount * 6 50 | public fixed byte Unknown04[64]; 51 | public long materialsPtr; // 0x178 -- size is materialCount * 8 52 | public long unknownPtr1; // 0x180 -- size is materialCount * 4 53 | public long surfaceDataPtr; // 0x188 -- size is surfaceDataCount * 128 / surfaceDataCount << 7 54 | public long surfaceOffsetsPtr; // 0x190 -- size is surfaceDataCount * 16 (same as first 16 bytes of surfaceData) 55 | public long unknownPtr4; // 0x198 -- size is surfaceDataCount << 7 56 | public fixed byte Unknown05[420]; 57 | public int UniqueModelCount; // 0x344 58 | public int ModelInstDataCount; // 0x348 59 | public int UnknownValue; // 0x34C 60 | public int ModelInstCount; // 0x350 61 | public fixed byte Unknown06[84]; 62 | public long UniqueModelsPtr; // 0x3A8 63 | public long Padding; 64 | public long ModelInstDataPtr; // 0x3B8 65 | public fixed byte Unknown07[248]; 66 | public long ModelInstPtr; // 0x4B8 67 | public fixed byte Unknown08[328]; 68 | public long UnknownModelPtr; // 0x608 -- size is uniqueModelCount * 72 69 | } 70 | 71 | /// 72 | /// Vanguard Surface Data Structure 73 | /// 74 | [StructLayout(LayoutKind.Sequential)] 75 | public unsafe struct VGGfxSurfaceData 76 | { 77 | public float Scale; 78 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] 79 | public float[] Offsets; 80 | public int ZoneIndex; // Transient Index probably here? 81 | public int Unknown01; 82 | public int Unknown02; 83 | public int LayerCount; 84 | /* VERTEX OFFSETS 85 | * 1 - Vertex Positions 86 | * 2 - Normals 87 | * 4 - Colors 88 | * 5 - UVs */ 89 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 90 | public int[] VertexOffsets; 91 | public float UnknownValue; 92 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)] 93 | public int[] Unknown03; 94 | } 95 | 96 | /// 97 | /// Vanguard Surface Structure 98 | /// 99 | [StructLayout(LayoutKind.Sequential)] 100 | public unsafe struct VGGfxMapSurface 101 | { 102 | public int BufferOffset; 103 | public int FaceIndex; 104 | public int UnknownValue01; 105 | public ushort FaceCount; 106 | public ushort VertexCount; 107 | public int DataIndex; 108 | public int MaterialIndex; 109 | public int UnknownValue02; 110 | public int UnknownValue03; 111 | } 112 | 113 | /// 114 | /// Vanguard Material Asset 115 | /// 116 | public unsafe struct VGMaterial 117 | { 118 | /// 119 | /// A pointer to the name of this material 120 | /// 121 | public long NamePointer { get; set; } 122 | 123 | /// 124 | /// Unknown Bytes (Flags, settings, etc.) 125 | /// 126 | public fixed byte UnknownBytes[20]; 127 | 128 | /// 129 | /// Number of Images this Material has 130 | /// 131 | public byte ImageCount { get; set; } 132 | 133 | public byte ConstantCount { get; set; } 134 | 135 | /// 136 | /// Unknown Bytes (Flags, settings, etc.) 137 | /// 138 | public fixed byte UnknownBytes1[18]; 139 | 140 | /// 141 | /// A pointer to the Tech Set this Material uses 142 | /// 143 | public long TechniqueSetPointer { get; set; } 144 | 145 | /// 146 | /// A pointer to this Material's Image table 147 | /// 148 | public long ImageTablePointer { get; set; } 149 | 150 | public long Padding { get; set; } // Constant Table? 151 | 152 | /// 153 | /// Unknown Bytes (Flags, settings, etc.) 154 | /// 155 | public fixed byte UnknownBytes2[56]; 156 | } 157 | } -------------------------------------------------------------------------------- /src/Husky/Husky/Husky.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | {BBEB0978-D656-4432-80E9-CF2083F53349} 9 | Library 10 | Husky 11 | HuskyLib 12 | v4.8 13 | 512 14 | true 15 | 16 | 17 | 18 | 19 | 20 | x64 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | true 29 | 30 | 31 | x64 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE 36 | prompt 37 | 4 38 | true 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | ..\packages\Costura.Fody.3.1.6\lib\net46\Costura.dll 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 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 | {8f5c1ba4-88c1-4177-b91b-dd093dc849b9} 99 | PhilLibX 100 | 101 | 102 | 103 | 104 | 105 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /src/Husky/Husky/HuskyUtil.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // Husky - Call of Duty BSP Extractor 3 | // Copyright (C) 2018 Philip/Scobalula 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // ------------------------------------------------------------------------ 18 | // TODO: Write converters for other formats (like SEModel) for now we're just writing OBJ 19 | using System; 20 | using System.Collections.Generic; 21 | using System.Diagnostics; 22 | using System.IO; 23 | using System.Reflection; 24 | using PhilLibX; 25 | using PhilLibX.IO; 26 | 27 | namespace Husky 28 | { 29 | 30 | /// 31 | /// Main Program Class 32 | /// 33 | public class HuskyUtil 34 | { 35 | /// 36 | /// Game Addresses & Methods (Asset DB and Asset Pool Sizes) (Some are relative due to ASLR) 37 | /// 38 | static Dictionary Games = new Dictionary() 39 | { 40 | // Call of Duty: World At War 41 | { "CoDWaWmp", new GameDefinition(0x8D0958, 0x8D06E8, "mp", WorldatWar.ExportBSPData) }, 42 | { "CoDWaW", new GameDefinition(0x8DC828, 0x8DC5D0, "sp", WorldatWar.ExportBSPData) }, 43 | // Call of Duty: Modern Warfare 44 | { "iw3mp", new GameDefinition(0x7265E0, 0x7263A0, "mp", ModernWarfare.ExportBSPData) }, 45 | { "iw3sp", new GameDefinition(0x7307F8, 0x730510, "sp", ModernWarfare.ExportBSPData) }, 46 | // Call of Duty: Modern Warfare 2 47 | { "iw4mp", new GameDefinition(0x6F81D0, 0x6F7F08, "mp", ModernWarfare2.ExportBSPData) }, 48 | { "iw4sp", new GameDefinition(0x7307F8, 0x730510, "sp", ModernWarfare2.ExportBSPData) }, 49 | // Call of Duty: Modern Warfare 3 50 | { "iw5mp", new GameDefinition(0x8AB258, 0x8AAF78, "mp", ModernWarfare3.ExportBSPData) }, 51 | { "iw5sp", new GameDefinition(0x92AD20, 0x92AA40, "sp", ModernWarfare3.ExportBSPData) }, 52 | // Call of Duty: Black Ops 53 | { "BlackOps", new GameDefinition(0xB741B8, 0xB73EF8, "sp", BlackOps.ExportBSPData) }, 54 | { "BlackOpsMP", new GameDefinition(0xBF2C30, 0xBF2970, "mp", BlackOps.ExportBSPData) }, 55 | // Call of Duty: Black Ops 2 56 | { "t6zm", new GameDefinition(0xD41240, 0xD40E80, "zm", BlackOps2.ExportBSPData) }, 57 | { "t6mp", new GameDefinition(0xD4B340, 0xD4AF80, "mp", BlackOps2.ExportBSPData) }, 58 | { "t6sp", new GameDefinition(0xBD46B8, 0xBD42F8, "sp", BlackOps2.ExportBSPData) }, 59 | // Call of Duty: Black Ops III 60 | { "BlackOps3", new GameDefinition(0x94093F0, 0, "core", BlackOps3.ExportBSPData) }, 61 | // Call of Duty: Ghosts 62 | { "iw6mp64_ship", new GameDefinition(0x1409E4F20, 0x1409E4E20, "mp", Ghosts.ExportBSPData) }, 63 | { "iw6sp64_ship", new GameDefinition(0x14086DCB0, 0x14086DBB0, "sp", Ghosts.ExportBSPData) }, 64 | // Call of Duty: Infinite Warfare 65 | { "iw7_ship", new GameDefinition(0x1414663D0, 0x141466290, "core", InfiniteWarfare.ExportBSPData) }, 66 | // Parasyte (We use MW2019 as base) 67 | { "Parasyte.CLI", new GameDefinition(0, 0, "core", ModernWarfare4.ExportBSPData) }, 68 | // Call of Duty: Advanced Warfare 69 | { "s1_mp64_ship", new GameDefinition(0x1409B40D0, 0x1409B4B90, "mp", AdvancedWarfare.ExportBSPData) }, 70 | { "s1_sp64_ship", new GameDefinition(0x140804690, 0x140804140, "sp", AdvancedWarfare.ExportBSPData) }, 71 | // Call of Duty: World War II 72 | { "s2_mp64_ship", new GameDefinition(0xC08470, 0xEB0C30, "mp", WorldWarII.ExportBSPData) }, 73 | { "s2_sp64_ship", new GameDefinition(0x94FD10, 0xBD65E0, "sp", WorldWarII.ExportBSPData) }, 74 | // Call of Duty: Modern Warfare Remastered 75 | { "h1_mp64_ship", new GameDefinition(0x10B4460, 0x10B3C80, "mp", ModernWarfareRM.ExportBSPData) }, 76 | { "h1_sp64_ship", new GameDefinition(0xEC9FB0, 0xEC97D0, "sp", ModernWarfareRM.ExportBSPData) }, 77 | }; 78 | 79 | /// 80 | /// Looks for matching game and loads BSP from it 81 | /// 82 | public static void LoadGame(Action printCallback = null) 83 | { 84 | try 85 | { 86 | // Get all processes 87 | var processes = Process.GetProcesses(); 88 | 89 | // Loop through them, find match 90 | foreach (var process in processes) 91 | { 92 | // Check for it in dictionary 93 | if (Games.TryGetValue(process.ProcessName, out var game)) 94 | { 95 | // If process is Parasyte, parse DB first 96 | if (process.ProcessName == "Parasyte.CLI") 97 | game.ParseParasyteDB(process, printCallback); 98 | 99 | // Check for valid AssetPool Address 100 | if (game.AssetDBAddress != 0) 101 | // Export it 102 | game.Export(new ProcessReader(process), printCallback); 103 | 104 | // Done 105 | return; 106 | } 107 | } 108 | 109 | // Failed 110 | printCallback?.Invoke("Failed to find a supported game, please ensure one of them is running."); 111 | } 112 | catch(Exception e) 113 | { 114 | printCallback?.Invoke("An unhandled exception has occured:"); 115 | printCallback?.Invoke(e); 116 | } 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Husky/Husky/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("Husky - Call of Duty BSP Extractor")] 8 | [assembly: AssemblyDescription("Extracts BSP Data from Call of Duty")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Scobalula")] 11 | [assembly: AssemblyProduct("Husky")] 12 | [assembly: AssemblyCopyright("Copyright © Scobalula 2018")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("bbeb0978-d656-4432-80e9-cf2083f53349")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("0.5.0.0")] 35 | [assembly: AssemblyFileVersion("0.5.0.0")] 36 | -------------------------------------------------------------------------------- /src/Husky/Husky/Utility/FloatToInt.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // Husky - Call of Duty BSP Extractor 3 | // Copyright (C) 2018 Philip/Scobalula 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // ------------------------------------------------------------------------ 18 | using System.Runtime.InteropServices; 19 | 20 | namespace Husky 21 | { 22 | /// 23 | /// A class that contains both a float and an int in the same bytes, to mimick C++ Unions 24 | /// 25 | [StructLayout(LayoutKind.Explicit)] 26 | class FloatToInt 27 | { 28 | /// 29 | /// Integer Value 30 | /// 31 | [FieldOffset(0)] 32 | public uint Integer; 33 | 34 | /// 35 | /// Floating Point Value 36 | /// 37 | [FieldOffset(0)] 38 | public float Float; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Husky/Husky/Utility/HalfFloats.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // Husky - Call of Duty BSP Extractor 3 | // Copyright (C) 2018 Philip/Scobalula 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // ------------------------------------------------------------------------ 18 | using System.Runtime.InteropServices; 19 | 20 | namespace Husky 21 | { 22 | class HalfFloats 23 | { 24 | /// 25 | /// Shift value 26 | /// 27 | const int Shift = 13; 28 | 29 | /// 30 | /// Sign used to shift 31 | /// 32 | const int ShiftSign = 16; 33 | 34 | /// 35 | /// Infinity of a float 36 | /// 37 | const int FloatInfinity = 0x7F800000; 38 | 39 | /// 40 | /// Maximum value of a half float 41 | /// 42 | const int MaxValue = 0x477FE000; 43 | 44 | /// 45 | /// Minimum value of a half float 46 | /// 47 | const int MinValue = 0x38800000; 48 | 49 | /// 50 | /// Sign bit of a float 51 | /// 52 | const uint SignBit = 0x80000000; 53 | 54 | /// 55 | /// Precalculated properties of a half float 56 | /// 57 | const int InfC = FloatInfinity >> Shift; 58 | const int NaNN = (InfC + 1) << Shift; 59 | const int MaxC = MaxValue >> Shift; 60 | const int MinC = MinValue >> Shift; 61 | const int SignC = (int)(SignBit >> ShiftSign); 62 | 63 | /// 64 | /// Precalculated (1 << 23) / minN 65 | /// 66 | const int MulN = 0x52000000; 67 | 68 | /// 69 | /// Precalculated minN / (1 << (23 - shift)) 70 | /// 71 | const int MulC = 0x33800000; 72 | 73 | /// 74 | /// Max float subnormal down shifted 75 | /// 76 | const int SubC = 0x003FF; 77 | 78 | /// 79 | /// Min float normal down shifted 80 | /// 81 | const int NorC = 0x00400; 82 | 83 | /// 84 | /// Precalculated min and max decimals 85 | /// 86 | const int MaxD = InfC - MaxC - 1; 87 | const int MinD = MinC - SubC - 1; 88 | 89 | /// 90 | /// A struct to hold different data types in 1 set of bytes 91 | /// 92 | [StructLayout(LayoutKind.Explicit)] 93 | public struct FloatBits 94 | { 95 | /// 96 | /// Floating Point Value 97 | /// 98 | [FieldOffset(0)] 99 | public float Float; 100 | 101 | /// 102 | /// Unsigned Integer Value 103 | /// 104 | [FieldOffset(0)] 105 | public uint UnsignedInteger; 106 | 107 | /// 108 | /// Signed Integer Value 109 | /// 110 | [FieldOffset(0)] 111 | public int SignedInteger; 112 | } 113 | 114 | /// 115 | /// Converts a half precision floating point number to a single precision floating point number 116 | /// 117 | /// 16bit Int representation of the float 118 | /// Resulting Float 119 | public static float ToFloat(ushort value) 120 | { 121 | // Define bit values 122 | FloatBits v, s = new FloatBits(); 123 | // Set the initial values (if we don't do this, .NET considers them unassigned) 124 | v.SignedInteger = 0; 125 | v.UnsignedInteger = 0; 126 | v.Float = 0; 127 | s.SignedInteger = 0; 128 | s.UnsignedInteger = 0; 129 | s.Float = 0; 130 | // Assign the initial value given 131 | v.UnsignedInteger = value; 132 | // Calculate sign 133 | int sign = v.SignedInteger & SignC; 134 | v.SignedInteger ^= sign; 135 | sign <<= ShiftSign; 136 | v.SignedInteger ^= ((v.SignedInteger + MinD) ^ v.SignedInteger) & -(v.SignedInteger > SubC ? 1 : 0); 137 | v.SignedInteger ^= ((v.SignedInteger + MaxD) ^ v.SignedInteger) & -(v.SignedInteger > MaxC ? 1 : 0); 138 | // Inverse Subnormals 139 | s.SignedInteger = MulC; 140 | s.Float *= v.SignedInteger; 141 | int mask = -(NorC > v.SignedInteger ? 1 : 0); 142 | v.SignedInteger <<= Shift; 143 | v.SignedInteger ^= (s.SignedInteger ^ v.SignedInteger) & mask; 144 | v.SignedInteger |= sign; 145 | // Return the expanded result 146 | return v.Float; 147 | 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/Husky/Husky/Utility/Rotation.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // Husky - Call of Duty BSP Extractor 3 | // Copyright (C) 2018 Philip/Scobalula 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // ------------------------------------------------------------------------ 18 | using System; 19 | 20 | namespace Husky 21 | { 22 | /// 23 | /// Rotation Utilities 24 | /// 25 | public class Rotation 26 | { 27 | /// 28 | /// Class to hold a 4x4 Matrix 29 | /// 30 | public class Matrix 31 | { 32 | /// 33 | /// Values 34 | /// 35 | public double[] Values = new double[16]; 36 | 37 | /// 38 | /// Converts a Matrix to a Quaternion 39 | /// 40 | /// Resulting Quaternion 41 | public Vector4 ToQuaternion() 42 | { 43 | Vector4 result = new Vector4(0, 0, 0, 1.0); 44 | 45 | double divisor; 46 | 47 | double transRemain = Values[0] + Values[5] + Values[10]; 48 | 49 | if (transRemain > 0) 50 | { 51 | divisor = Math.Sqrt(transRemain + 1.0) * 2.0; 52 | result.W = 0.25 * divisor; 53 | result.X = (Values[6] - Values[9]) / divisor; 54 | result.Y = (Values[8] - Values[2]) / divisor; 55 | result.Z = (Values[1] - Values[4]) / divisor; 56 | } 57 | else if ((Values[0] > Values[5]) && (Values[0] > Values[10])) 58 | { 59 | divisor = Math.Sqrt( 60 | 1.0 + Values[0] - Values[5] - Values[10]) * 2.0; 61 | result.W = (Values[6] - Values[9]) / divisor; 62 | result.X = 0.25 * divisor; 63 | result.Y = (Values[4] + Values[1]) / divisor; 64 | result.Z = (Values[8] + Values[2]) / divisor; 65 | } 66 | else if (Values[5] > Values[10]) 67 | { 68 | divisor = Math.Sqrt( 69 | 1.0 + Values[5] - Values[0] - Values[10]) * 2.0; 70 | result.W = (Values[8] - Values[2]) / divisor; 71 | result.X = (Values[4] + Values[1]) / divisor; 72 | result.Y = 0.25 * divisor; 73 | result.Z = (Values[9] + Values[6]) / divisor; 74 | } 75 | else 76 | { 77 | divisor = Math.Sqrt( 78 | 1.0 + Values[10] - Values[0] - Values[5]) * 2.0; 79 | result.W = (Values[1] - Values[4]) / divisor; 80 | result.X = (Values[8] + Values[2]) / divisor; 81 | result.Y = (Values[9] + Values[6]) / divisor; 82 | result.Z = 0.25 * divisor; 83 | } 84 | 85 | // Return resulting vector 86 | return result; 87 | } 88 | 89 | /// 90 | /// Converts a Matrix to Euler Angles 91 | /// 92 | /// Resulting Euler Vector 93 | public Vector3 ToEuler() 94 | { 95 | // I need to switch this back from Mat -> Quat -> Euler to straight Mat -> Euler 96 | // I thought none the calculations were working, NO, the bastards 97 | // in the .MAP files store them as YXZ or some crap like that 98 | var quaternion = ToQuaternion(); 99 | 100 | Vector3 result = new Vector3(); 101 | 102 | double t0 = 2.0 * (quaternion.W * quaternion.X + quaternion.Y * quaternion.Z); 103 | double t1 = 1.0 - 2.0 * (quaternion.X * quaternion.X + quaternion.Y * quaternion.Y); 104 | 105 | result.X = Math.Atan2(t0, t1); 106 | 107 | 108 | double t2 = 2.0 * (quaternion.W * quaternion.Y - quaternion.Z * quaternion.X); 109 | 110 | t2 = t2 > 1.0 ? 1.0 : t2; 111 | t2 = t2 < -1.0 ? -1.0 : t2; 112 | result.Y = Math.Asin(t2); 113 | 114 | 115 | double t3 = +2.0 * (quaternion.W * quaternion.Z + quaternion.X * quaternion.Y); 116 | double t4 = +1.0 - 2.0 * (quaternion.Y * quaternion.Y + quaternion.Z * quaternion.Z); 117 | 118 | result.Z = Math.Atan2(t3, t4); 119 | 120 | return result; 121 | } 122 | } 123 | 124 | /// 125 | /// Converts Euler value to degrees 126 | /// 127 | /// Value to convert 128 | /// Value in degrees 129 | public static double ToDegrees(double value) 130 | { 131 | return (value / (2 * Math.PI)) * 360; 132 | } 133 | 134 | /// 135 | /// Converts Euler value to degrees 136 | /// 137 | /// Value to convert 138 | /// Value in degrees 139 | public static Vector3 ToDegrees(Vector3 value) 140 | { 141 | // Return new vector 142 | return new Vector3( 143 | ToDegrees(value.X), 144 | ToDegrees(value.Y), 145 | ToDegrees(value.Z) 146 | ); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/Husky/Husky/Utility/Vectors.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // Husky - Call of Duty BSP Extractor 3 | // Copyright (C) 2018 Philip/Scobalula 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // ------------------------------------------------------------------------ 18 | 19 | using System; 20 | 21 | namespace Husky 22 | { 23 | /// 24 | /// A class to hold a 2-D Vector 25 | /// 26 | public class Vector2 27 | { 28 | /// 29 | /// X Value 30 | /// 31 | public double X { get; set; } 32 | 33 | /// 34 | /// Y Value 35 | /// 36 | public double Y { get; set; } 37 | 38 | /// 39 | /// Initializes a 2-D Vector at 0 40 | /// 41 | public Vector2() 42 | { 43 | X = 0.0; 44 | Y = 0.0; 45 | } 46 | 47 | /// 48 | /// Initializes a 2-D Vector with the given values 49 | /// 50 | /// X Value 51 | /// Y Value 52 | public Vector2(double x, double y) 53 | { 54 | X = x; 55 | Y = y; 56 | } 57 | } 58 | 59 | /// 60 | /// A class to hold a 3-D Vector 61 | /// 62 | public class Vector3 : Vector2 63 | { 64 | /// 65 | /// Z Value 66 | /// 67 | public double Z { get; set; } 68 | 69 | /// 70 | /// Initializes a 3-D Vector at 0 71 | /// 72 | public Vector3() 73 | { 74 | X = 0.0; 75 | Y = 0.0; 76 | Z = 0.0; 77 | } 78 | 79 | /// 80 | /// Initializes a 3-D Vector with the given values 81 | /// 82 | /// X Value 83 | /// Y Value 84 | /// Z Value 85 | public Vector3(double x, double y, double z) 86 | { 87 | X = x; 88 | Y = y; 89 | Z = z; 90 | } 91 | public static Vector3 Cross(Vector3 left, Vector3 right) 92 | { 93 | Vector3 returnValue = new Vector3(); 94 | 95 | returnValue.X = left.Y * right.Z - left.Z * right.Y; 96 | returnValue.Y = left.Z * right.X - left.X * right.Z; 97 | returnValue.Z = left.X * right.Y - left.Y * right.X; 98 | 99 | return returnValue; 100 | } 101 | } 102 | 103 | /// 104 | /// A class to hold a 4-D Vector 105 | /// 106 | public class Vector4 : Vector3 107 | { 108 | /// 109 | /// W Value 110 | /// 111 | public double W { get; set; } 112 | 113 | /// 114 | /// Initializes a 4-D Vector at 0 115 | /// 116 | public Vector4() 117 | { 118 | X = 0.0; 119 | Y = 0.0; 120 | Z = 0.0; 121 | W = 0.0; 122 | } 123 | 124 | /// 125 | /// Initializes a 4-D Vector with the given values 126 | /// 127 | /// X Value 128 | /// Y Value 129 | /// Z Value 130 | /// W Value 131 | public Vector4(double x, double y, double z, double w) 132 | { 133 | X = x; 134 | Y = y; 135 | Z = z; 136 | W = w; 137 | } 138 | 139 | public Vector3 ToEuler() 140 | { 141 | var result = new Vector3(); 142 | 143 | double t0 = 2.0 * (W * X + Y * Z); 144 | double t1 = 1.0 - 2.0 * (X * X + Y * Y); 145 | 146 | result.X = Math.Atan2(t0, t1); 147 | 148 | 149 | double t2 = 2.0 * (W * Y - Z * X); 150 | 151 | t2 = t2 > 1.0 ? 1.0 : t2; 152 | t2 = t2 < -1.0 ? -1.0 : t2; 153 | result.Y = Math.Asin(t2); 154 | 155 | 156 | double t3 = +2.0 * (W * Z + X * Y); 157 | double t4 = +1.0 - 2.0 * (Y * Y + Z * Z); 158 | 159 | result.Z = Math.Atan2(t3, t4); 160 | 161 | return result; 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/Husky/Husky/Utility/Vertex.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // Husky - Call of Duty BSP Extractor 3 | // Copyright (C) 2018 Philip/Scobalula 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // ------------------------------------------------------------------------ 18 | 19 | namespace Husky 20 | { 21 | /// 22 | /// Vertex Class (Position, Offset, etc.) 23 | /// 24 | public class Vertex 25 | { 26 | /// 27 | /// Vertex Position 28 | /// 29 | public Vector3 Position { get; set; } 30 | 31 | /// 32 | /// Vertex Normal 33 | /// 34 | public Vector3 Normal { get; set; } 35 | 36 | /// 37 | /// Vertex UV/Texture Coordinates 38 | /// 39 | public Vector2 UV { get; set; } 40 | 41 | public static Vector3 UnpackVGVertex(ulong PackedPosition, float scale, float[] midPoint) 42 | { 43 | return new Vector3( 44 | ((((PackedPosition >> 0) & 0x1FFFFF) * scale) + midPoint[0]) * 2.54, 45 | ((((PackedPosition >> 21) & 0x1FFFFF) * scale) + midPoint[1]) * 2.54, 46 | ((((PackedPosition >> 42) & 0x1FFFFF) * scale) + midPoint[2]) * 2.54); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Husky/Husky/Utility/VertexNormal.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // Husky - Call of Duty BSP Extractor 3 | // Copyright (C) 2018 Philip/Scobalula 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // ------------------------------------------------------------------------ 18 | 19 | using System; 20 | 21 | namespace Husky 22 | { 23 | /// 24 | /// Vertex Normal Unpacking Methods 25 | /// 26 | class VertexNormalUnpacking 27 | { 28 | /// 29 | /// Unpacks a Vertex Normal from: WaW, MW2, MW3, Bo1 30 | /// 31 | /// Packed 4 byte Vertex Normal 32 | /// Resulting Vertex Normal 33 | public static Vector3 MethodA(PackedUnitVector packedNormal) 34 | { 35 | // Decode the scale of the vector 36 | float decodeScale = ((float)(packedNormal.Byte4 - -192.0) / 32385.0f); 37 | 38 | // Return decoded vector 39 | return new Vector3( 40 | (float)(packedNormal.Byte1 - 127.0) * decodeScale, 41 | (float)(packedNormal.Byte2 - 127.0) * decodeScale, 42 | (float)(packedNormal.Byte3 - 127.0) * decodeScale); 43 | } 44 | 45 | /// 46 | /// Unpacks a Vertex Normal from: Ghosts, AW, MWR 47 | /// 48 | /// Packed 4 byte Vertex Normal 49 | /// Resulting Vertex Normal 50 | public static Vector3 MethodB(PackedUnitVector packedNormal) 51 | { 52 | // Return decoded vector 53 | return new Vector3( 54 | (float)(((packedNormal.Value & 0x3FF) / 1023.0) * 2.0 - 1.0), 55 | (float)((((packedNormal.Value >> 10) & 0x3FF) / 1023.0) * 2.0 - 1.0), 56 | (float)((((packedNormal.Value >> 20) & 0x3FF) / 1023.0) * 2.0 - 1.0)); 57 | } 58 | 59 | /// 60 | /// Unpacks a Vertex Normal from: Bo2 61 | /// 62 | /// Packed 4 byte Vertex Normal 63 | /// Resulting Vertex Normal 64 | public static Vector3 MethodC(PackedUnitVector packedNormal) 65 | { 66 | // Resulting values 67 | var builtX = new FloatToInt { Integer = (uint)((packedNormal.Value & 0x3FF) - 2 * (packedNormal.Value & 0x200) + 0x40400000) }; 68 | var builtY = new FloatToInt { Integer = (uint)((((packedNormal.Value >> 10) & 0x3FF) - 2 * ((packedNormal.Value >> 10) & 0x200) + 0x40400000)) }; 69 | var builtZ = new FloatToInt { Integer = (uint)((((packedNormal.Value >> 20) & 0x3FF) - 2 * ((packedNormal.Value >> 20) & 0x200) + 0x40400000)) }; 70 | 71 | // Return decoded vector 72 | return new Vector3( 73 | (builtX.Float - 3.0) * 8208.0312f, 74 | (builtY.Float - 3.0) * 8208.0312f, 75 | (builtZ.Float - 3.0) * 8208.0312f); 76 | } 77 | 78 | /// 79 | /// Unpacks a Vertex Normal from: Bo3 80 | /// 81 | /// Packed 4 byte Vertex Normal 82 | /// Resulting Vertex Normal 83 | public static Vector3 MethodD(PackedUnitVector packedNormal) 84 | { 85 | // Unpack normal 86 | int packedX = (((packedNormal.Value >> 0) & ((1 << 10) - 1)) - 512); 87 | int packedY = (((packedNormal.Value >> 10) & ((1 << 10) - 1)) - 512); 88 | int packedZ = (((packedNormal.Value >> 20) & ((1 << 10) - 1)) - 512); 89 | 90 | // Return decoded vector 91 | return new Vector3( 92 | packedX / 511.0, 93 | packedY / 511.0, 94 | packedZ / 511.0); 95 | 96 | } 97 | 98 | public static (Vector3, Vector3, Vector3) UnpackTangentFrame(uint packedQuat) 99 | { 100 | // https://dev.theomader.com/qtangents/ 101 | var idx = packedQuat >> 30; 102 | 103 | var tx = ((((packedQuat >> 00) & 0x3FF) / 511.5f) - 1.0f) / 1.4142135f; 104 | var ty = ((((packedQuat >> 10) & 0x3FF) / 511.5f) - 1.0f) / 1.4142135f; 105 | var tz = ((((packedQuat >> 20) & 0x1FF) / 255.5f) - 1.0f) / 1.4142135f; 106 | var tw = 0.0f; 107 | 108 | var sum = (tx * tx) + (ty * ty) + (tz * tz); 109 | 110 | if (sum <= 1.0f) 111 | tw = (float)Math.Sqrt(1.0f - sum); 112 | 113 | var q = new Vector4(); 114 | 115 | switch (idx) 116 | { 117 | case 0: 118 | q.X = tw; 119 | q.Y = tx; 120 | q.Z = ty; 121 | q.W = tz; 122 | break; 123 | case 1: 124 | q.X = tx; 125 | q.Y = tw; 126 | q.Z = ty; 127 | q.W = tz; 128 | break; 129 | case 2: 130 | q.X = tx; 131 | q.Y = ty; 132 | q.Z = tw; 133 | q.W = tz; 134 | break; 135 | case 3: 136 | q.X = tx; 137 | q.Y = ty; 138 | q.Z = tz; 139 | q.W = tw; 140 | break; 141 | } 142 | 143 | var tangent = new Vector3( 144 | 1 - 2 * (q.Y * q.Y + q.Z * q.Z), 145 | 2 * (q.X * q.Y + q.W * q.Z), 146 | 2 * (q.X * q.Z - q.W * q.Y)); 147 | var bitangent = new Vector3( 148 | 2 * (q.X * q.Y - q.W * q.Z), 149 | 1 - 2 * (q.X * q.X + q.Z * q.Z), 150 | 2 * (q.Y * q.Z + q.W * q.X)); 151 | var normal = Vector3.Cross(tangent, bitangent); 152 | 153 | return (tangent, bitangent, normal); 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/Husky/Husky/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scobalula/Husky/ce1f82df7fb125b57e85c9e9ade49ceaf0e24428/src/Husky/Husky/icon.ico -------------------------------------------------------------------------------- /src/Husky/Husky/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/Husky/HuskyUI/AboutWindow.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 140 | 141 | -------------------------------------------------------------------------------- /src/Husky/HuskyUI/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // Husky - Call of Duty BSP Extractor 3 | // Copyright (C) 2018 Philip/Scobalula 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // ------------------------------------------------------------------------ 18 | using System; 19 | using System.Windows; 20 | using System.Threading; 21 | using System.Windows.Shell; 22 | using Husky; 23 | using System.Reflection; 24 | 25 | namespace HuskyUI 26 | { 27 | /// 28 | /// Interaction logic for MainWindow.xaml 29 | /// 30 | public partial class MainWindow : Window 31 | { 32 | /// 33 | /// Whether or not a thread is active 34 | /// 35 | public bool ThreadActive = false; 36 | 37 | /// 38 | /// Initializes MainWindow 39 | /// 40 | public MainWindow() 41 | { 42 | InitializeComponent(); 43 | // Set title 44 | Title = String.Format("Husky - Version {0}", Assembly.GetExecutingAssembly().GetName().Version); 45 | // Initial Print 46 | PrintLine("Load a supported CoD Game, then click the paper plane to export loaded BSP data."); 47 | PrintLine(""); 48 | } 49 | 50 | private void ExportClick(object sender, RoutedEventArgs e) 51 | { 52 | // Check is a thread already active 53 | if (ThreadActive) 54 | return; 55 | // Create new thread and export 56 | new Thread(delegate () 57 | { 58 | UpdateProgressState(TaskbarItemProgressState.Indeterminate); 59 | ThreadActive = true; 60 | HuskyUtil.LoadGame(PrintLine); 61 | PrintLine(""); 62 | ThreadActive = false; 63 | UpdateProgressState(TaskbarItemProgressState.Normal); 64 | }).Start(); 65 | } 66 | 67 | /// 68 | /// Prints to the ConsoleBox 69 | /// 70 | /// Value to print 71 | private void PrintLine(object value) 72 | { 73 | Dispatcher.BeginInvoke(new Action(() => ConsoleBox.AppendText(value.ToString() + Environment.NewLine))); 74 | } 75 | 76 | /// 77 | /// Updates Progress State 78 | /// 79 | /// State to set 80 | private void UpdateProgressState(TaskbarItemProgressState state) 81 | { 82 | Dispatcher.BeginInvoke(new Action(() => TaskBarProgress.ProgressState = state)); 83 | } 84 | 85 | /// 86 | /// Shows the About Window and Dims the Main Window 87 | /// 88 | private void AboutClick(object sender, RoutedEventArgs e) 89 | { 90 | AboutWindow aboutWindow = new AboutWindow() 91 | { 92 | Owner = this 93 | }; 94 | aboutWindow.VersionLabel.Content = String.Format("Version: {0}", Assembly.GetExecutingAssembly().GetName().Version); 95 | DimBox.Visibility = Visibility.Visible; 96 | aboutWindow.ShowDialog(); 97 | DimBox.Visibility = Visibility.Hidden; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Husky/HuskyUI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 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("Husky - Call of Duty BSP Extractor")] 9 | [assembly: AssemblyDescription("Call of Duty BSP Extractor")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Philip/Scobalula")] 12 | [assembly: AssemblyProduct("HuskyUI")] 13 | [assembly: AssemblyCopyright("Copyright © Scobalula 2018")] 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 | //In order to begin building localizable applications, set 23 | //CultureYouAreCodingWith in your .csproj file 24 | //inside a . For example, if you are using US english 25 | //in your source files, set the to en-US. Then uncomment 26 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 27 | //the line below to match the UICulture setting in the project file. 28 | 29 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 30 | 31 | 32 | [assembly: ThemeInfo( 33 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 34 | //(used if a resource is not found in the page, 35 | // or application resource dictionaries) 36 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 37 | //(used if a resource is not found in the page, 38 | // app, or any theme specific resource dictionaries) 39 | )] 40 | 41 | 42 | // Version information for an assembly consists of the following four values: 43 | // 44 | // Major Version 45 | // Minor Version 46 | // Build Number 47 | // Revision 48 | // 49 | // You can specify all the values or you can default the Build and Revision Numbers 50 | // by using the '*' as shown below: 51 | // [assembly: AssemblyVersion("1.0.*")] 52 | [assembly: AssemblyVersion("0.8.0.0")] 53 | [assembly: AssemblyFileVersion("0.8.0.0")] 54 | -------------------------------------------------------------------------------- /src/Husky/HuskyUI/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 | namespace HuskyUI.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", "16.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("HuskyUI.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 | -------------------------------------------------------------------------------- /src/Husky/HuskyUI/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 | -------------------------------------------------------------------------------- /src/Husky/HuskyUI/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 | namespace HuskyUI.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Husky/HuskyUI/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Husky/HuskyUI/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scobalula/Husky/ce1f82df7fb125b57e85c9e9ade49ceaf0e24428/src/Husky/HuskyUI/icon.ico -------------------------------------------------------------------------------- /src/Husky/HuskyUI/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scobalula/Husky/ce1f82df7fb125b57e85c9e9ade49ceaf0e24428/src/Husky/HuskyUI/icon.png -------------------------------------------------------------------------------- /src/Husky/HuskyUI/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/ByteUtil.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: ByteUtil.cs 24 | // Author: Philip/Scobalula 25 | // Description: Utilities for working with Bytes and Bits 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Runtime.InteropServices; 29 | using System.Text; 30 | 31 | namespace PhilLibX 32 | { 33 | /// 34 | /// Utilities for working with Bytes and Bits 35 | /// 36 | public class ByteUtil 37 | { 38 | /// 39 | /// Reads a null terminated string from a byte array 40 | /// 41 | /// Byte Array input 42 | /// Start Index 43 | /// Resulting string 44 | public static string ReadNullTerminatedString(byte[] input, int startIndex) 45 | { 46 | List result = new List(); 47 | 48 | for (int i = startIndex; i < input.Length && input[i] != 0; i++) 49 | result.Add(input[i]); 50 | 51 | return Encoding.ASCII.GetString(result.ToArray()); 52 | } 53 | 54 | /// 55 | /// Returns the value of the bit in the given integer 56 | /// 57 | /// Integer Input 58 | /// Position 59 | /// Result 60 | public static byte GetBit(long input, int bit) 61 | { 62 | return (byte)((input >> bit) & 1); 63 | } 64 | 65 | public static T BytesToStruct(byte[] data, int startIndex) 66 | { 67 | // Size of Struct 68 | int size = Marshal.SizeOf(); 69 | // Create new byte array 70 | byte[] buffer = new byte[size]; 71 | // Copy it 72 | Buffer.BlockCopy(data, startIndex, buffer, 0, size); 73 | // Return result 74 | return BytesToStruct(buffer); 75 | } 76 | 77 | public static T BytesToStruct(byte[] data) 78 | { 79 | GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); 80 | T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); 81 | handle.Free(); 82 | return theStructure; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/Compression/Oodle.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: Compression/Oodle.cs 24 | // Author: Philip/Scobalula 25 | // Description: Basic Oodle64 Compression Wrapper, currently supports decompression. 26 | // Credits: 27 | // - DTZxPorter - SirenLib (for OodleLZ_Decompress parameters) 28 | // Other notes: 29 | // - Tested on Oodle V5 and V6 30 | 31 | namespace PhilLibX.Compression 32 | { 33 | /// 34 | /// Oodle Compression Utils 35 | /// 36 | public class Oodle 37 | { 38 | /// 39 | /// Decompresses a byte array of Oodle Compressed Data (Requires Oodle DLL) 40 | /// 41 | /// Input Compressed Data 42 | /// Decompressed Size 43 | /// Resulting Array if success, otherwise null. 44 | public static byte[] Decompress(byte[] input, long decompressedLength) 45 | { 46 | // Resulting decompressed Data 47 | byte[] result = new byte[decompressedLength]; 48 | // Decode the data (other parameters such as callbacks not required) 49 | long decodedSize = NativeMethods.OodleLZ_Decompress(input, input.Length, result, decompressedLength, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3); 50 | // Check did we fail 51 | if (decodedSize == 0) return null; 52 | // Return Result 53 | return result; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/Cryptography/Hash/CRC32.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: Cryptograhpy/Hash/CRC32.cs 24 | // Author: Philip/Scobalula 25 | // Description: Class to handle calculating CRC32 (While not exactly a "hash" algorithm, I have left it in here) 26 | using System.Text; 27 | 28 | namespace PhilLibX.Cryptography.Hash 29 | { 30 | /// 31 | /// Class to handle calculating CRC32 32 | /// 33 | public class CRC32 34 | { 35 | /// 36 | /// CRC32 Table 37 | /// 38 | private static readonly uint[] CRC32Table = { 39 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 40 | 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 41 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 42 | 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 43 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 44 | 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 45 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 46 | 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 47 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 48 | 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 49 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 50 | 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 51 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 52 | 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 53 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 54 | 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 55 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 56 | 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 57 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 58 | 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 59 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 60 | 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 61 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 62 | 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 63 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 64 | 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 65 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 66 | 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 67 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 68 | 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 69 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 70 | 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 71 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 72 | 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 73 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 74 | 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 75 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 76 | 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 77 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 78 | 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 79 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 80 | 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 81 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; 82 | 83 | /// 84 | /// Calculates CRC32 for a given string. 85 | /// 86 | /// String to generate a hash from 87 | /// Resulting Unsigned CRC32 Value 88 | public static uint Calculate(string value) 89 | { 90 | return Calculate(Encoding.ASCII.GetBytes(value)); 91 | } 92 | 93 | /// 94 | /// Calculates CRC32 for a sequence of bytes. 95 | /// 96 | /// Bytes to generate a hash from 97 | /// Resulting Unsigned CRC32 Value 98 | public static uint Calculate(byte[] value) 99 | { 100 | // Resulting CRC32 101 | uint result = 0xFFFFFFFF; 102 | 103 | // Loop Bytes 104 | for(int i = 0; i < value.Length; i++) 105 | result = CRC32Table[(result ^ value[i]) & 0xff] ^ ((result) >> 8); 106 | 107 | // Return 108 | return ~result; 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/Cryptography/Hash/DJB.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: Cryptograhpy/Hash/DJB.cs 24 | // Author: Philip/Scobalula 25 | // Description: Class to handle calculating DJB Hash 26 | using System.Text; 27 | 28 | namespace PhilLibX.Cryptography.Hash 29 | { 30 | /// 31 | /// Class to handle calculating DJB Hash 32 | /// 33 | public class DJB 34 | { 35 | /// 36 | /// Calculates DJB Hash for the given string. 37 | /// 38 | /// String to generate a hash from 39 | /// Initial Hash Value (Defaults to 0x1505/5381) 40 | /// Resulting Unsigned Hash Value 41 | public static uint Calculate(string value, uint initial = 0x1505) 42 | { 43 | return Calculate(Encoding.ASCII.GetBytes(value), initial); 44 | } 45 | 46 | /// 47 | /// Calculates DJB Hash for a sequence of bytes. 48 | /// 49 | /// Bytes to generate a hash from 50 | /// Initial Hash Value (Defaults to 0x1505/5381) 51 | /// Resulting Unsigned Hash Value 52 | public static uint Calculate(byte[] value, uint initial = 0x1505) 53 | { 54 | // Set INitial Value 55 | uint hash = initial; 56 | 57 | // Loop Bytes 58 | for (int i = 0; i < value.Length; i++) 59 | hash = ((hash << 5) + hash) + value[i]; 60 | 61 | // Result 62 | return hash; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/Cryptography/Hash/FNV1a.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: Cryptograhpy/Hash/FNV1a.cs 24 | // Author: Philip/Scobalula 25 | // Description: Class to handle calculating FNV1a 26 | using System.Text; 27 | 28 | namespace PhilLibX.Cryptography.Hash 29 | { 30 | public class FNV1a 31 | { 32 | /// 33 | /// Offset Basis for calculating 32bit FNV1a Hashes 34 | /// 35 | public const uint OffsetBasis32 = 0x811C9DC5; 36 | 37 | /// 38 | /// Offset Basis for calculating 64bit FNV1a Hashes 39 | /// 40 | public const ulong OffsetBasis64 = 0xCBF29CE484222325; 41 | 42 | 43 | /// 44 | /// Calculates 32Bit FNV1a Hash for a given string 45 | /// 46 | /// String to generate a hash from 47 | /// Initial Hash Value (Defaults to OffsetBasis32)) 48 | /// Resulting Unsigned Hash Value 49 | public static uint Calculate32(string value, uint initial = OffsetBasis32) 50 | { 51 | return Calculate32(Encoding.ASCII.GetBytes(value), initial); 52 | } 53 | 54 | /// 55 | /// Calculates 32Bit FNV1a Hash for a given string 56 | /// 57 | /// String to generate a hash from 58 | /// Initial Hash Value (Defaults to OffsetBasis32)) 59 | /// Resulting Unsigned Hash Value 60 | public static ulong Calculate64(string value, ulong initial = OffsetBasis64) 61 | { 62 | return Calculate64(Encoding.ASCII.GetBytes(value), initial); 63 | } 64 | 65 | /// 66 | /// Calculates 32Bit FNV1a Hash for a sequence of bytes. 67 | /// 68 | /// Bytes to generate a hash from 69 | /// Initial Hash Value (Defaults to OffsetBasis32)) 70 | /// Resulting Unsigned Hash Value 71 | public static uint Calculate32(byte[] value, uint initial = 0) 72 | { 73 | // Set Initial Value 74 | uint hash = initial; 75 | 76 | // Loop Bytes 77 | for (int i = 0; i < value.Length; i++) 78 | { 79 | hash ^= value[i]; 80 | hash *= 0x1000193; 81 | } 82 | 83 | // Return 84 | return hash; 85 | } 86 | 87 | /// 88 | /// Calculates 64Bit FNV1a Hash for a sequence of bytes. 89 | /// 90 | /// Bytes to generate a hash from 91 | /// Initial Hash Value (Defaults to OffsetBasis64)) 92 | /// Resulting Unsigned Hash Value 93 | public static ulong Calculate64(byte[] value, ulong initial = OffsetBasis64) 94 | { 95 | // Set Initial Value 96 | ulong hash = initial; 97 | 98 | // Loop Bytes 99 | for (int i = 0; i < value.Length; i++) 100 | { 101 | hash ^= value[i]; 102 | hash *= 0x100000001B3; 103 | } 104 | 105 | // Return 106 | return hash; 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/Cryptography/Hash/SDBM.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: Cryptograhpy/Hash/SDBM.cs 24 | // Author: Philip/Scobalula 25 | // Description: Class to handle calculating SDBM Hash 26 | using System.Text; 27 | 28 | namespace PhilLibX.Cryptography.Hash 29 | { 30 | /// 31 | /// Class to handle calculating SDBM Hash 32 | /// 33 | public class SDBM 34 | { 35 | /// 36 | /// Calculates SDBM Hash for the given string. 37 | /// 38 | /// String to generate a hash from 39 | /// Initial Hash Value (0) 40 | /// Resulting Unsigned Hash Value 41 | public static uint Calculate(string value, uint initial = 0) 42 | { 43 | return Calculate(Encoding.ASCII.GetBytes(value), initial); 44 | } 45 | 46 | /// 47 | /// Calculates SDBM Hash for a sequence of bytes. 48 | /// 49 | /// Bytes to generate a hash from 50 | /// Initial Hash Value (Defaults to 0)) 51 | /// Resulting Unsigned Hash Value 52 | public static uint Calculate(byte[] value, uint initial = 0) 53 | { 54 | // Set INitial Value 55 | uint hash = initial; 56 | 57 | // Loop Bytes 58 | for (int i = 0; i < value.Length; i++) 59 | hash = value[i] + (hash << 6) + (hash << 16) - hash; 60 | 61 | // Return 62 | return hash; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/IO/IOExtensions.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: IO/IOExtensions.cs 24 | // Author: Philip/Scobalula 25 | // Description: IO Utilities/Extensions for reading null terminated strings, scanning files, etc. 26 | using System; 27 | using System.Collections.Generic; 28 | using System.IO; 29 | using System.Runtime.InteropServices; 30 | using System.Text; 31 | 32 | namespace PhilLibX.IO 33 | { 34 | /// 35 | /// IO Utilities/Extensions 36 | /// 37 | public static class IOExtensions 38 | { 39 | /// 40 | /// Reads a string terminated by a null byte 41 | /// 42 | /// Read String 43 | public static string ReadNullTerminatedString(this BinaryReader br, int maxSize = -1) 44 | { 45 | // Create String Builder 46 | StringBuilder str = new StringBuilder(); 47 | // Current Byte Read 48 | int byteRead; 49 | // Size of String 50 | int size = 0; 51 | // Loop Until we hit terminating null character 52 | while ((byteRead = br.BaseStream.ReadByte()) != 0x0 && size++ != maxSize) 53 | str.Append(Convert.ToChar(byteRead)); 54 | // Ship back Result 55 | return str.ToString(); 56 | } 57 | 58 | /// 59 | /// Reads a string of fixed size 60 | /// 61 | /// Size of string in bytes 62 | /// Read String 63 | public static string ReadFixedString(this BinaryReader br, int numBytes) 64 | { 65 | // Purge Null Bytes and Return 66 | return Encoding.ASCII.GetString(br.ReadBytes(numBytes)).TrimEnd('\0'); 67 | } 68 | 69 | public static T ReadStruct(this BinaryReader br) 70 | { 71 | byte[] data = br.ReadBytes(Marshal.SizeOf()); 72 | GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); 73 | T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); 74 | handle.Free(); 75 | return theStructure; 76 | } 77 | 78 | /// 79 | /// Sets the position of the Base Stream 80 | /// 81 | /// 82 | /// Offset to seek to. 83 | /// Seek Origin 84 | public static void Seek(this BinaryReader br, long offset, SeekOrigin seekOrigin) 85 | { 86 | // Set stream position 87 | br.BaseStream.Seek(offset, seekOrigin); 88 | } 89 | 90 | /// 91 | /// Finds occurences of a string in the stream 92 | /// 93 | /// Reader to use for scanning 94 | /// String Needle to search for 95 | /// Stops at first result 96 | /// Resulting offsets 97 | public static long[] FindString(this BinaryReader br, string needle, bool firstOccurence = false) 98 | { 99 | // Convert to bytes and scan 100 | return br.FindBytes(Encoding.ASCII.GetBytes(needle), firstOccurence); 101 | } 102 | 103 | /// 104 | /// Finds occurences of bytes in the stream 105 | /// 106 | /// Reader to use for scanning 107 | /// Byte Array Needle to search for 108 | /// Stops at first result 109 | /// Resulting offsets 110 | public static long[] FindBytes(this BinaryReader br, byte[] needle, bool firstOccurence = false) 111 | { 112 | // List of offsets in file. 113 | List offsets = new List(); 114 | 115 | // Buffer 116 | byte[] buffer = new byte[1048576]; 117 | 118 | // Bytes Read 119 | int bytesRead = 0; 120 | 121 | // Starting Offset 122 | long readBegin = br.BaseStream.Position; 123 | 124 | // Needle Index 125 | int needleIndex = 0; 126 | 127 | // Byte Array Index 128 | int bufferIndex = 0; 129 | 130 | // Read chunk of file 131 | while ((bytesRead = br.BaseStream.Read(buffer, 0, buffer.Length)) != 0) 132 | { 133 | // Loop through byte array 134 | for (bufferIndex = 0; bufferIndex < bytesRead; bufferIndex++) 135 | { 136 | // Check if current bytes match 137 | if (needle[needleIndex] == buffer[bufferIndex]) 138 | { 139 | // Increment 140 | needleIndex++; 141 | 142 | // Check if we have a match 143 | if (needleIndex == needle.Length) 144 | { 145 | // Add Offset 146 | offsets.Add(readBegin + bufferIndex + 1 - needle.Length); 147 | 148 | // Reset Index 149 | needleIndex = 0; 150 | 151 | // If only first occurence, end search 152 | if (firstOccurence) 153 | return offsets.ToArray(); 154 | } 155 | } 156 | else 157 | { 158 | // Reset Index 159 | needleIndex = 0; 160 | } 161 | } 162 | // Set next offset 163 | readBegin += bytesRead; 164 | } 165 | // Return offsets as an array 166 | return offsets.ToArray(); 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/IO/MemoryUtil.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: IO/MemoryUtil.cs 24 | // Author: Philip/Scobalula 25 | // Description: Utilities for Reading Process Memory 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Runtime.InteropServices; 29 | using System.Text; 30 | 31 | namespace PhilLibX.IO 32 | { 33 | /// 34 | /// Utilities for Reading Process Memory 35 | /// 36 | public class MemoryUtil 37 | { 38 | /// 39 | /// Required to read memory in a process using ReadProcessMemory. 40 | /// 41 | public const int ProcessVMRead = 0x0010; 42 | 43 | /// 44 | /// Required to write to memory in a process using WriteProcessMemory. 45 | /// 46 | public const int ProcessVMWrite = 0x0020; 47 | 48 | /// 49 | /// Required to perform an operation on the address space of a process 50 | /// 51 | public const int ProcessVMOperation = 0x0008; 52 | 53 | /// 54 | /// Reads bytes from a Processes Memory and returns a byte array of read data. 55 | /// 56 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 57 | /// The address of the data to be read. 58 | /// The number of bytes to be read from the specified process. 59 | /// Bytes read 60 | public static byte[] ReadBytes(IntPtr processHandle, long address, int numBytes) 61 | { 62 | // Resulting buffer 63 | byte[] buffer = new byte[numBytes]; 64 | // Request ReadProcessMemory 65 | NativeMethods.ReadProcessMemory((int)processHandle, address, buffer, buffer.Length, out int bytesRead); 66 | // Return result 67 | return buffer; 68 | } 69 | 70 | /// 71 | /// Reads a 64Bit Integer from a Processes Memory 72 | /// 73 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 74 | /// The address of the data to be read. 75 | /// Resulting Data 76 | public static long ReadInt64(IntPtr processHandle, long address) 77 | { 78 | return BitConverter.ToInt64(ReadBytes(processHandle, address, 8), 0); 79 | } 80 | 81 | /// 82 | /// Reads an unsigned 64Bit Integer from a Processes Memory 83 | /// 84 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 85 | /// The address of the data to be read. 86 | /// Resulting Data 87 | public static ulong ReadUInt64(IntPtr processHandle, long address) 88 | { 89 | return BitConverter.ToUInt64(ReadBytes(processHandle, address, 8), 0); 90 | } 91 | 92 | /// 93 | /// Reads a 32Bit Integer from a Processes Memory 94 | /// 95 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 96 | /// The address of the data to be read. 97 | /// Resulting Data 98 | public static int ReadInt32(IntPtr processHandle, long address) 99 | { 100 | return BitConverter.ToInt32(ReadBytes(processHandle, address, 4), 0); 101 | } 102 | 103 | /// 104 | /// Reads an unsigned 32Bit Integer from a Processes Memory 105 | /// 106 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 107 | /// The address of the data to be read. 108 | /// Resulting Data 109 | public static uint ReadUInt32(IntPtr processHandle, long address) 110 | { 111 | return BitConverter.ToUInt32(ReadBytes(processHandle, address, 4), 0); 112 | } 113 | 114 | /// 115 | /// Reads a 16Bit Integer from a Processes Memory 116 | /// 117 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 118 | /// The address of the data to be read. 119 | /// Resulting Data 120 | public static short ReadInt16(IntPtr processHandle, long address) 121 | { 122 | return BitConverter.ToInt16(ReadBytes(processHandle, address, 4), 0); 123 | } 124 | 125 | /// 126 | /// Reads an unsigned 16Bit Integer from a Processes Memory 127 | /// 128 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 129 | /// The address of the data to be read. 130 | /// Resulting Data 131 | public static ushort ReadUInt16(IntPtr processHandle, long address) 132 | { 133 | return BitConverter.ToUInt16(ReadBytes(processHandle, address, 2), 0); 134 | } 135 | 136 | /// 137 | /// Reads a 4 byte single precision floating point number from a Processes Memory 138 | /// 139 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 140 | /// The address of the data to be read. 141 | /// Resulting Data 142 | public static float ReadSingle(IntPtr processHandle, long address) 143 | { 144 | return BitConverter.ToSingle(ReadBytes(processHandle, address, 2), 0); 145 | } 146 | 147 | /// 148 | /// Reads an 8 byte double precision floating point number from a Processes Memory 149 | /// 150 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 151 | /// The address of the data to be read. 152 | /// Resulting Data 153 | public static double ReadDouble(IntPtr processHandle, long address) 154 | { 155 | return BitConverter.ToDouble(ReadBytes(processHandle, address, 8), 0); 156 | } 157 | 158 | /// 159 | /// Reads a string from a processes' memory terminated by a null byte. 160 | /// 161 | /// Process Handle Pointer 162 | /// Memory Address 163 | /// Buffer Read Size 164 | /// Resulting String 165 | public static string ReadNullTerminatedString(IntPtr processHandle, long address, int bufferSize = 0xFF) 166 | { 167 | List result = new List(); 168 | 169 | byte[] buffer = ReadBytes(processHandle, address, bufferSize); 170 | 171 | while (true) 172 | { 173 | for (int i = 0; i < buffer.Length; i++) 174 | { 175 | if (buffer[i] == 0x0) 176 | return Encoding.ASCII.GetString(result.ToArray()); 177 | 178 | result.Add(buffer[i]); 179 | } 180 | 181 | buffer = ReadBytes(processHandle, address += bufferSize, bufferSize); 182 | } 183 | } 184 | 185 | /// 186 | /// Reads a struct from a Processes Memory 187 | /// 188 | /// Struct Type 189 | /// Process Handle Pointer 190 | /// Memory Address 191 | /// Resulting Struct 192 | public static T ReadStruct(IntPtr processHandle, long address) 193 | { 194 | byte[] data = ReadBytes(processHandle, address, Marshal.SizeOf()); 195 | GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); 196 | T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); 197 | handle.Free(); 198 | return theStructure; 199 | } 200 | 201 | /// 202 | /// Searches for bytes in a processes memory. 203 | /// 204 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 205 | /// Byte Sequence to scan for. 206 | /// Address to start the search at. 207 | /// Address to end the search at. 208 | /// Byte Buffer Size 209 | /// If we should stop the search at the first result. 210 | /// 211 | public static long[] FindBytes(IntPtr processHandle, byte?[] needle, long startAddress, long endAddress, bool firstMatch = false, int bufferSize = 0xFFFF) 212 | { 213 | List results = new List(); 214 | long searchAddress = startAddress; 215 | 216 | int needleIndex = 0; 217 | int bufferIndex = 0; 218 | 219 | while (true) 220 | { 221 | try 222 | { 223 | byte[] buffer = ReadBytes(processHandle, searchAddress, bufferSize); 224 | 225 | for (bufferIndex = 0; bufferIndex < buffer.Length; bufferIndex++) 226 | { 227 | if (needle[needleIndex] == null) 228 | { 229 | needleIndex++; 230 | continue; 231 | } 232 | 233 | if (needle[needleIndex] == buffer[bufferIndex]) 234 | { 235 | needleIndex++; 236 | 237 | if (needleIndex == needle.Length) 238 | { 239 | results.Add(searchAddress + bufferIndex - needle.Length + 1); 240 | 241 | if (firstMatch) 242 | return results.ToArray(); 243 | 244 | needleIndex = 0; 245 | } 246 | } 247 | else 248 | { 249 | needleIndex = 0; 250 | } 251 | } 252 | } 253 | catch 254 | { 255 | break; 256 | } 257 | 258 | searchAddress += bufferSize; 259 | 260 | if (searchAddress > endAddress) 261 | break; 262 | } 263 | 264 | return results.ToArray(); 265 | } 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/IO/ProcessReader.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: IO/ProcessReader.cs 24 | // Author: Philip/Scobalula 25 | // Description: A class to help with reading the memory of other processes. 26 | using System; 27 | using System.Diagnostics; 28 | using System.Runtime.InteropServices; 29 | 30 | namespace PhilLibX.IO 31 | { 32 | /// 33 | /// A class to help with reading the memory of other processes. 34 | /// 35 | public class ProcessReader 36 | { 37 | /// 38 | /// Internal Process Property 39 | /// 40 | private Process _Process { get; set; } 41 | 42 | /// 43 | /// Internal Handle Property 44 | /// 45 | private IntPtr _Handle { get; set; } 46 | 47 | /// 48 | /// Active Process 49 | /// 50 | public Process ActiveProcess 51 | { 52 | get { return _Process; } 53 | set 54 | { 55 | _Process = value; 56 | _Handle = NativeMethods.OpenProcess(MemoryUtil.ProcessVMRead, false, _Process.Id); 57 | } 58 | } 59 | 60 | /// 61 | /// Active Process Handle 62 | /// 63 | public IntPtr Handle { get { return _Handle; } } 64 | 65 | /// 66 | /// Initalizes a Process Reader with a Process 67 | /// 68 | public ProcessReader(Process process) 69 | { 70 | ActiveProcess = process; 71 | } 72 | 73 | /// 74 | /// Reads bytes from the Processes Memory 75 | /// 76 | /// The address of the data to be read. 77 | /// The number of bytes to be read. 78 | /// Bytes read 79 | public byte[] ReadBytes(long address, int numBytes) 80 | { 81 | return MemoryUtil.ReadBytes(Handle, address, numBytes); 82 | } 83 | 84 | /// 85 | /// Reads 64Bit Integer from the Processes Memory 86 | /// 87 | /// The address of the data to be read. 88 | /// Resulting Data 89 | public long ReadInt64(long address) 90 | { 91 | return MemoryUtil.ReadInt64(Handle, address); 92 | } 93 | 94 | /// 95 | /// Reads an unsigned 64Bit Integer from the Processes Memory 96 | /// 97 | /// The address of the data to be read. 98 | /// Resulting Data 99 | public ulong ReadUInt64(long address) 100 | { 101 | return MemoryUtil.ReadUInt64(Handle, address); 102 | } 103 | 104 | /// 105 | /// Reads 32Bit Integer from the Processes Memory 106 | /// 107 | /// The address of the data to be read. 108 | /// Resulting Data 109 | public int ReadInt32(long address) 110 | { 111 | return MemoryUtil.ReadInt32(Handle, address); 112 | } 113 | 114 | /// 115 | /// Reads 32Bit Integer from the Processes Memory 116 | /// 117 | /// The address of the data to be read. 118 | /// Resulting Data 119 | public uint ReadUInt32(long address) 120 | { 121 | return MemoryUtil.ReadUInt32(Handle, address); 122 | } 123 | 124 | /// 125 | /// Reads a 16Bit Integer from the Processes Memory 126 | /// 127 | /// The address of the data to be read. 128 | /// Resulting Data 129 | public short ReadInt16(long address) 130 | { 131 | return MemoryUtil.ReadInt16(Handle, address); 132 | } 133 | 134 | /// 135 | /// Reads an unsigned 16Bit Integer from the Processes Memory 136 | /// 137 | /// The address of the data to be read. 138 | /// Resulting Data 139 | public ushort ReadUInt16(long address) 140 | { 141 | return MemoryUtil.ReadUInt16(Handle, address); 142 | } 143 | 144 | /// 145 | /// Reads a 4 byte single precision floating point number from the Processes Memory 146 | /// 147 | /// The address of the data to be read. 148 | /// Resulting Data 149 | public float ReadSingle(long address) 150 | { 151 | return MemoryUtil.ReadSingle(Handle, address); 152 | } 153 | 154 | /// 155 | /// Reads an 8 byte double precision floating point number from the Processes Memory 156 | /// 157 | /// The address of the data to be read. 158 | /// Resulting Data 159 | public double ReadDouble(long address) 160 | { 161 | return MemoryUtil.ReadDouble(Handle, address); 162 | } 163 | 164 | /// 165 | /// Reads a string from the processes' memory terminated by a null byte. 166 | /// 167 | /// Memory Address 168 | /// Buffer Read Size 169 | /// Resulting String 170 | public string ReadNullTerminatedString(long address, int bufferSize = 0xFF) 171 | { 172 | return MemoryUtil.ReadNullTerminatedString(Handle, address, bufferSize); 173 | } 174 | 175 | /// 176 | /// Reads a struct from the Processes Memory 177 | /// 178 | /// Struct Type 179 | /// Memory Address 180 | /// Resulting Struct 181 | public T ReadStruct(long address) 182 | { 183 | return MemoryUtil.ReadStruct(Handle, address); 184 | } 185 | 186 | /// 187 | /// Reads a struct multiple times from the Processes Memory 188 | /// 189 | /// Struct Type 190 | /// Memory Address 191 | /// Amount of times the struct is read 192 | /// Struct Size 193 | /// Array of Struct Type 194 | public T[] ReadStructArray(long address, int count) 195 | { 196 | T[] buffer = new T[count]; 197 | for (int i = 0; i < count; i++) 198 | { 199 | buffer[i] = ReadStruct(address + i * Marshal.SizeOf(typeof(T))); 200 | } 201 | return buffer; 202 | } 203 | /// 204 | /// Searches for bytes in the Processes Memory 205 | /// 206 | /// Byte Sequence to scan for. 207 | /// Address to start the search at. 208 | /// Address to end the search at. 209 | /// If we should stop the search at the first result. 210 | /// Byte Buffer Size 211 | /// Results 212 | public long[] FindBytes(byte?[] needle, long startAddress, long endAddress, bool firstMatch = false, int bufferSize = 0xFFFF) 213 | { 214 | return MemoryUtil.FindBytes(Handle, needle, startAddress, endAddress, firstMatch, bufferSize); 215 | } 216 | 217 | /// 218 | /// Gets the Active Processes' Base Address 219 | /// 220 | /// Base Address of the Active Process 221 | public long GetBaseAddress() 222 | { 223 | return (long)ActiveProcess?.MainModule.BaseAddress; 224 | } 225 | 226 | /// 227 | /// Gets the size of the Main Module Size 228 | /// 229 | /// Main Module Size 230 | public long GetModuleMemorySize() 231 | { 232 | return (long)ActiveProcess?.MainModule.ModuleMemorySize; 233 | } 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/IO/ProcessWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Diagnostics; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace PhilLibX.IO 7 | { 8 | public class ProcessWriter 9 | { 10 | /// 11 | /// Internal Process Property 12 | /// 13 | private Process _Process { get; set; } 14 | 15 | /// 16 | /// Internal Handle Property 17 | /// 18 | private IntPtr _Handle { get; set; } 19 | 20 | /// 21 | /// Active Process 22 | /// 23 | public Process ActiveProcess 24 | { 25 | get { return _Process; } 26 | set 27 | { 28 | _Process = value; 29 | _Handle = NativeMethods.OpenProcess(MemoryUtil.ProcessVMOperation | MemoryUtil.ProcessVMWrite, false, _Process.Id); 30 | } 31 | } 32 | 33 | /// 34 | /// Active Process Handle 35 | /// 36 | public IntPtr Handle { get { return _Handle; } } 37 | 38 | /// 39 | /// Initalizes a Process Reader with a Process 40 | /// 41 | public ProcessWriter(Process process) 42 | { 43 | ActiveProcess = process; 44 | } 45 | 46 | /// 47 | /// Writes bytes to the processes' memory 48 | /// 49 | /// 50 | /// 51 | public void WriteBytes(long address, byte[] buffer) 52 | { 53 | if(!NativeMethods.WriteProcessMemory((int)Handle, address, buffer, buffer.Length, out int bytesRead)) 54 | { 55 | throw new ArgumentException(new Win32Exception(Marshal.GetLastWin32Error()).Message); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/Imaging/BitmapX.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: Imaging/BitmapX.cs 24 | // Author: Philip/Scobalula 25 | // Description: Faster Bitmap Processing 26 | using System; 27 | using System.Drawing; 28 | using System.Drawing.Imaging; 29 | using System.IO; 30 | using System.Linq; 31 | using System.Runtime.InteropServices; 32 | 33 | namespace PhilLibX.Imaging 34 | { 35 | /// 36 | /// Faster Bitmap Processing 37 | /// 38 | public class BitmapX : IDisposable 39 | { 40 | /// 41 | /// Accepted Bits Per Pixel (for now we only support 24 and 32bpp 42 | /// 43 | public static readonly int[] AcceptedBitsPerPixel = 44 | { 45 | 24, 46 | 32, 47 | }; 48 | 49 | /// 50 | /// Pixel Data Pointer 51 | /// 52 | private IntPtr PixelDataPointer { get; set; } 53 | 54 | /// 55 | /// Raw Pixel Data 56 | /// 57 | private byte[] Pixels { get; set; } 58 | 59 | /// 60 | /// Source Bitmap Object 61 | /// 62 | private Bitmap BitmapSource { get; set; } 63 | 64 | /// 65 | /// Source Bitmap Data Object 66 | /// 67 | private BitmapData BitmapDataSource { get; set; } 68 | 69 | /// 70 | /// Internal Bits Per Pizel Value 71 | /// 72 | private int _BitsPerPixel { get; set; } 73 | 74 | /// 75 | /// Internal Bitmap Width Value 76 | /// 77 | private int _Width { get; set; } 78 | 79 | /// 80 | /// Internal Bitmap Height Value 81 | /// 82 | private int _Height { get; set; } 83 | 84 | /// 85 | /// Bitmap Width 86 | /// 87 | public int Width { get { return _Width; } } 88 | 89 | /// 90 | /// Bitmap Height 91 | /// 92 | public int Height { get { return _Height; } } 93 | 94 | /// 95 | /// Number of bits per pixel. (24, 96 | /// 97 | public int BitsPerPixel { get { return _BitsPerPixel; } } 98 | 99 | /// 100 | /// Number of bits per pixel. (24, 101 | /// 102 | public int BytesPerPixel { get { return BitsPerPixel / 8; } } 103 | 104 | /// 105 | /// Pixel Count 106 | /// 107 | public int PixelCount { get { return Width * Height; } } 108 | 109 | /// 110 | /// Initializes BitmapX with a new Bitmap 111 | /// 112 | /// Pixel Width 113 | /// Pixel Height 114 | /// Pixel Format (32bpp ARGB by Default) 115 | public BitmapX(int width, int height, PixelFormat pixelFormat = PixelFormat.Format32bppArgb) 116 | { 117 | LoadBitmap(new Bitmap(width, height, pixelFormat)); 118 | } 119 | 120 | /// 121 | /// Initializes BitmapX with a file 122 | /// 123 | /// Path to image file 124 | public BitmapX(string fileName) 125 | { 126 | LoadBitmap(new Bitmap(fileName)); 127 | } 128 | 129 | /// 130 | /// Initializes BitmapX with an Image 131 | /// 132 | /// Existing Image Object 133 | public BitmapX(Image image) 134 | { 135 | LoadBitmap(new Bitmap(image)); 136 | } 137 | 138 | /// 139 | /// Initializes BitmapX with a Stream 140 | /// 141 | /// Stream with Image data 142 | public BitmapX(Stream stream) 143 | { 144 | LoadBitmap(new Bitmap(stream)); 145 | } 146 | 147 | /// 148 | /// Initializes BitmapX with a Bitmap 149 | /// 150 | /// Bitmap Source 151 | public BitmapX(Bitmap bitmap) 152 | { 153 | LoadBitmap(bitmap); 154 | } 155 | 156 | /// 157 | /// Loads a Bitmap into the BitmapX 158 | /// 159 | /// Bitmap Source 160 | public void LoadBitmap(Bitmap bitmap) 161 | { 162 | // Dispose the Original if exists 163 | BitmapSource?.Dispose(); 164 | 165 | // Get Bpp 166 | _BitsPerPixel = Image.GetPixelFormatSize(bitmap.PixelFormat); 167 | 168 | // Check for supported Bpp 169 | if (!AcceptedBitsPerPixel.Contains(BitsPerPixel)) 170 | throw new ArgumentException("Unsupported Bitmap Pixel Size: " + BitsPerPixel.ToString()); 171 | 172 | // Set Bitmap 173 | BitmapSource = bitmap; 174 | 175 | // Set Width + Height 176 | _Width = BitmapSource.Width; 177 | _Height = BitmapSource.Height; 178 | 179 | LockBits(); 180 | } 181 | 182 | /// 183 | /// Locks the Bits of the Source Bitmap 184 | /// 185 | public void LockBits() 186 | { 187 | // Lock the Bits 188 | BitmapDataSource = BitmapSource.LockBits( 189 | new Rectangle(0, 0, BitmapSource.Width, BitmapSource.Height), 190 | ImageLockMode.ReadWrite, 191 | BitmapSource.PixelFormat); 192 | 193 | // Set Pixel Array 194 | Pixels = new byte[PixelCount * BytesPerPixel]; 195 | 196 | // Set Pixel Pointer 197 | PixelDataPointer = BitmapDataSource.Scan0; 198 | 199 | // Copy the Data, maintain safe code using Marshal instead of accessing the raw pointer 200 | Marshal.Copy(PixelDataPointer, Pixels, 0, Pixels.Length); 201 | } 202 | 203 | /// 204 | /// Unlocks the Bits of the Source Image 205 | /// 206 | public void UnlockBits() 207 | { 208 | // Copy the Data, maintain safe code using Marshal instead of accessing the raw pointer 209 | Marshal.Copy(Pixels, 0, PixelDataPointer, Pixels.Length); 210 | 211 | // Unlock bitmap data 212 | BitmapSource.UnlockBits(BitmapDataSource); 213 | } 214 | 215 | /// 216 | /// Gets Color at the given Pixel 217 | /// 218 | /// X Coordinate 219 | /// Y Coordinate 220 | /// Resulting Color 221 | public Color GetPixel(int x, int y) 222 | { 223 | // Get Position of the Pixe, based off Bpp 224 | int pixelIndex = ((y * Width) + x) * BytesPerPixel; 225 | 226 | // Convert to Color, only take Alpha if we're 32Bpp 227 | Color result = Color.FromArgb( 228 | // Alpha 229 | BitsPerPixel == 32 ? Pixels[pixelIndex + 3] : 255, 230 | // Red 231 | Pixels[pixelIndex + 2], 232 | // Green 233 | Pixels[pixelIndex + 1], 234 | // Blue 235 | Pixels[pixelIndex]); 236 | 237 | // Ship back the result 238 | return result; 239 | } 240 | 241 | /// 242 | /// Sets Color at the given Pixel 243 | /// 244 | /// X Coordinate 245 | /// Y Coordinate 246 | /// Color to set 247 | public void SetPixel(int x, int y, Color color) 248 | { 249 | // Get Position of the Pixe, based off Bpp 250 | int pixelIndex = ((y * Width) + x) * BytesPerPixel; 251 | 252 | // Set Pixel Data 253 | // Blue 254 | Pixels[pixelIndex] = color.B; 255 | // Green 256 | Pixels[pixelIndex + 1] = color.G; 257 | // Red 258 | Pixels[pixelIndex + 2] = color.R; 259 | 260 | // Set Alpha only if we're 32Bpp 261 | if (BitsPerPixel == 32) 262 | Pixels[pixelIndex + 3] = color.A; 263 | } 264 | 265 | public void Save(string filePath, bool relockBits = true) 266 | { 267 | // Unlock the Bits 268 | UnlockBits(); 269 | 270 | 271 | // Save the Bitmap 272 | BitmapSource.Save(filePath); 273 | 274 | 275 | // Check if we must relock the bits 276 | if (relockBits) LockBits(); 277 | } 278 | 279 | /// 280 | /// Checks if this image is 1 color 281 | /// 282 | /// False if has pixel differences, otherwise True 283 | public bool IsSingleColor() 284 | { 285 | // Color trackers 286 | int previousColor = 0; 287 | int pixel; 288 | 289 | // Get initial pixel 290 | for (int i = 0; i < BytesPerPixel; i++) 291 | previousColor += Pixels[i]; 292 | 293 | // Loop pixels 294 | for (int i = 0; i < PixelCount; i += BytesPerPixel) 295 | { 296 | // Initial Value 297 | pixel = 0; 298 | 299 | // Sum values 300 | for (int j = 0; j < BytesPerPixel; j++) 301 | pixel += Pixels[i + j]; 302 | 303 | // Compare 304 | if (previousColor != pixel) 305 | return false; 306 | 307 | // Set for next comparison 308 | previousColor = pixel; 309 | } 310 | 311 | // All 1 color if we got here 312 | return true; 313 | } 314 | 315 | /// 316 | /// Checks if this image has colors greater than the given values 317 | /// 318 | /// 319 | /// 320 | /// 321 | /// 322 | public bool HasColorsGreaterThan(int rValue, int bValue, int gValue) 323 | { 324 | // Color Values to compare 325 | int[] colorCheck = 326 | { 327 | rValue, 328 | bValue, 329 | gValue 330 | }; 331 | 332 | // Loop pixels 333 | for (int i = 0; i < PixelCount; i += BytesPerPixel) 334 | for (int j = 0; j < 3; j++) 335 | if (Pixels[i + j] >= colorCheck[j]) 336 | return false; 337 | 338 | // All 1 color if we got here 339 | return true; 340 | } 341 | 342 | /// 343 | /// Checks if this image is monochrome 344 | /// 345 | /// False if has pixel differences, otherwise True 346 | public bool IsMonochrome() 347 | { 348 | // Loop pixels 349 | for (int i = 0; i < PixelCount; i += BytesPerPixel) 350 | { 351 | // We only care about actual color values 352 | if ( 353 | Pixels[i] != Pixels[i + 1] || 354 | Pixels[i] != Pixels[i + 2] || 355 | Pixels[i + 1] != Pixels[i + 2]) 356 | return false; 357 | } 358 | 359 | // All 1 color if we got here 360 | return true; 361 | } 362 | 363 | /// 364 | /// Disposes of the BitmapX Object 365 | /// 366 | public void Dispose() 367 | { 368 | // Dispose the Bitmap 369 | BitmapSource?.Dispose(); 370 | } 371 | } 372 | } 373 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/Logger.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: Logger.cs 24 | // Author: Philip/Scobalula 25 | // Description: Basic Logging Utilities 26 | using System; 27 | using System.IO; 28 | 29 | namespace PhilLibX 30 | { 31 | /// 32 | /// Basic Logging Class 33 | /// 34 | public class Logger : IDisposable 35 | { 36 | /// 37 | /// Message Types for logging 38 | /// 39 | public enum MessageType 40 | { 41 | INFO, 42 | WARNING, 43 | ERROR, 44 | } 45 | 46 | /// 47 | /// Log File Name 48 | /// 49 | public string LogFile { get; set; } 50 | 51 | /// 52 | /// Current Log Name 53 | /// 54 | private string LogName { get; set; } 55 | 56 | /// 57 | /// Active Stream 58 | /// 59 | private StreamWriter ActiveStream { get; set; } 60 | 61 | /// 62 | /// Initiate Logger 63 | /// 64 | /// Log Name 65 | /// Log File Name 66 | public Logger(string logName, string fileName) 67 | { 68 | // Set properties 69 | LogFile = fileName; 70 | LogName = logName; 71 | 72 | // Write Initial 73 | Write(LogName, MessageType.INFO); 74 | 75 | // Close 76 | Close(); 77 | } 78 | 79 | /// 80 | /// Writes a message to the log 81 | /// 82 | /// 83 | /// 84 | public void Write(string message, MessageType messageType) 85 | { 86 | /* 87 | // Re-open stream if closed/null 88 | if ((ActiveStream == null) || (ActiveStream.BaseStream == null)) 89 | ActiveStream = new StreamWriter(LogFile, true); 90 | 91 | // Write to file 92 | ActiveStream.WriteLine("{0} [ {1} ] {2}", DateTime.Now.ToString("dd-MM-yyyy - HH:mm:ss"), messageType, message); 93 | */ 94 | } 95 | 96 | /// 97 | /// Closes current Streamwriter 98 | /// 99 | public void Close() 100 | { 101 | // Close it and clear it 102 | ActiveStream?.Close(); 103 | ActiveStream = null; 104 | } 105 | 106 | /// 107 | /// Disposes of the Logger and its Streamwriter 108 | /// 109 | public void Dispose() 110 | { 111 | // Close stream 112 | Close(); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/MathUtilities.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: MathUtilities.cs 24 | // Author: Philip/Scobalula 25 | // Description: Mathematic Utilities 26 | using System; 27 | 28 | namespace PhilLibX 29 | { 30 | /// 31 | /// Mathematic Utilities 32 | /// 33 | public class MathUtilities 34 | { 35 | /// 36 | /// Clamps Value to a range. 37 | /// 38 | /// Value to Clamp 39 | /// Max value 40 | /// Min value 41 | /// Clamped Value 42 | public static T Clamp(T value, T max, T min) where T : IComparable 43 | { 44 | return value.CompareTo(min) < 0 ? min : value.CompareTo(max) > 0 ? max : value; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: NativeMethods.cs 24 | // Author: Philip/Scobalula 25 | // Description: Native/Unmanaged Methods (DLLs required for certain components) 26 | using System; 27 | using System.Runtime.InteropServices; 28 | 29 | namespace PhilLibX 30 | { 31 | /// 32 | /// Description: Native/Unmanaged Methods (DLLs required for certain components) 33 | /// 34 | internal class NativeMethods 35 | { 36 | /// 37 | /// Oodle Library Path 38 | /// 39 | private const string OodleLibraryPath = "oo2core_6_win64"; 40 | 41 | 42 | /// 43 | /// Reads data from an area of memory in a specified process. The entire area to be read must be accessible or the operation fails. 44 | /// 45 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 46 | /// A pointer to the base address in the specified process from which to read. Before any data transfer occurs, the system verifies that all data in the base address and memory of the specified size is accessible for read access, and if it is not accessible the function fails. 47 | /// A pointer to a buffer that receives the contents from the address space of the specified process. 48 | /// The number of bytes to be read from the specified process. 49 | /// A pointer to a variable that receives the number of bytes transferred into the specified buffer. 50 | /// 51 | [DllImport("kernel32.dll", SetLastError = true)] 52 | public static extern bool ReadProcessMemory 53 | ( 54 | int hProcess, 55 | long lpBaseAddress, 56 | byte[] lpBuffer, 57 | int nSize, 58 | out int lpNumberOfBytesRead 59 | ); 60 | 61 | /// 62 | /// Reads data from an area of memory in a specified process. The entire area to be read must be accessible or the operation fails. 63 | /// 64 | /// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process. 65 | /// A pointer to the base address in the specified process from which to read. Before any data transfer occurs, the system verifies that all data in the base address and memory of the specified size is accessible for read access, and if it is not accessible the function fails. 66 | /// A pointer to a buffer that receives the contents from the address space of the specified process. 67 | /// The number of bytes to be read from the specified process. 68 | /// A pointer to a variable that receives the number of bytes transferred into the specified buffer. 69 | /// 70 | [DllImport("kernel32.dll", SetLastError = true)] 71 | public static extern bool WriteProcessMemory 72 | ( 73 | int hProcess, 74 | long lpBaseAddress, 75 | byte[] lpBuffer, 76 | int nSize, 77 | out int lpNumberOfBytesRead 78 | ); 79 | 80 | /// 81 | /// Opens an existing local process object. 82 | /// 83 | /// The access to the process object. This access right is checked against the security descriptor for the process. This parameter can be one or more of the process access rights. If the caller has enabled the SeDebugPrivilege privilege, the requested access is granted regardless of the contents of the security descriptor. 84 | /// If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle. 85 | /// The identifier of the local process to be opened. 86 | /// 87 | [DllImport("kernel32.dll")] 88 | public static extern IntPtr OpenProcess 89 | ( 90 | int dwDesiredAccess, 91 | bool bInheritHandle, 92 | int dwProcessId 93 | ); 94 | 95 | /// 96 | /// Oodle64 Decompression Method 97 | /// 98 | [DllImport(OodleLibraryPath, CallingConvention = CallingConvention.Cdecl)] 99 | public static extern long OodleLZ_Decompress(byte[] buffer, long bufferSize, byte[] result, long outputBufferSize, int a, int b, int c, long d, long e, long f, long g, long h, long i, int ThreadModule); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/PhilLibX.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8F5C1BA4-88C1-4177-B91B-DD093DC849B9} 8 | Library 9 | Properties 10 | PhilLibX 11 | PhilLibX 12 | v4.8 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | x64 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/Printer.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // PhilLibX - My Utility Library 3 | // Copyright(c) 2018 Philip/Scobalula 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // ------------------------------------------------------------------------ 23 | // File: Printer.cs 24 | // Author: Philip/Scobalula 25 | // Description: Class to Print stuff to the Console with more swag 🖨️ 26 | using System; 27 | using System.Diagnostics; 28 | using System.IO; 29 | 30 | namespace PhilLibX 31 | { 32 | /// 33 | /// Class to Print stuff to the Console with more swag 🖨️ 34 | /// 35 | public class Printer 36 | { 37 | /// 38 | /// Prefix Padding 39 | /// 40 | private static int PrefixPadding = 12; 41 | 42 | /// 43 | /// Prefix Color 44 | /// 45 | private static ConsoleColor PrefixColor = ConsoleColor.DarkBlue; 46 | 47 | /// 48 | /// Sets Prefix Padding 49 | /// 50 | /// Padding Size 51 | public static void SetPrefixPadding(int padding) 52 | { 53 | PrefixPadding = padding; 54 | } 55 | 56 | /// 57 | /// Sets the Console Prefix Color 58 | /// 59 | /// Background Color for Prefix 60 | public static void SetPrefixBackgroundColor(ConsoleColor color) 61 | { 62 | PrefixColor = color; 63 | } 64 | 65 | /// 66 | /// Writes a line to the console with optional BackGround 67 | /// 68 | /// Value to print 69 | /// Value to prefix 70 | /// Prefix Padding 71 | /// Background Color 72 | /// Prefix Background Color 73 | public static void WriteLine(object prefix = null, object value = null, ConsoleColor backgroundColor = ConsoleColor.Black) 74 | { 75 | // Check if we even have a prefix, if not just do a normal print 76 | if(prefix != null) 77 | { 78 | Console.BackgroundColor = PrefixColor; 79 | Console.Write(" {0}", prefix.ToString().PadRight(PrefixPadding)); 80 | Console.ResetColor(); 81 | Console.Write("│ "); 82 | } 83 | Console.BackgroundColor = backgroundColor; 84 | Console.WriteLine("{0}", value); 85 | Console.ResetColor(); 86 | } 87 | 88 | /// 89 | /// Writes a line to the console with optional BackGround 90 | /// 91 | /// Value to print 92 | /// Value to prefix 93 | /// Prefix Padding 94 | /// Background Color 95 | /// Prefix Background Color 96 | public static void WriteException(Exception exception, object prefix = null, object value = null, ConsoleColor backgroundColor = ConsoleColor.DarkRed) 97 | { 98 | // Write Initial Value 99 | WriteLine(prefix, value, backgroundColor); 100 | 101 | // Grab stack trace and recent frame 102 | var stackTrace = new StackTrace(exception, true); 103 | var stackFrame = stackTrace.GetFrame(0); 104 | 105 | // Write Formatted Exception 106 | WriteLine(prefix, exception.Message, backgroundColor); 107 | WriteLine(prefix, String.Format("{0}::{1}.{2}(...)::Line::{3}:{4}", 108 | Path.GetFileName(stackFrame.GetFileName()), 109 | stackFrame.GetMethod().ReflectedType.Name, 110 | stackFrame.GetMethod().Name, 111 | stackFrame.GetFileLineNumber(), 112 | stackFrame.GetFileColumnNumber()), backgroundColor); 113 | 114 | Console.ResetColor(); 115 | } 116 | 117 | /// 118 | /// Writes to the console with optional BackGround 119 | /// 120 | /// Value to print 121 | /// Value to prefix 122 | /// Prefix Padding 123 | /// Background Color 124 | /// Prefix Background Color 125 | public static void Write(object prefix = null, object value = null, ConsoleColor backgroundColor = ConsoleColor.Black) 126 | { 127 | // Check if we even have a prefix, if not just do a normal print 128 | if (prefix != null) 129 | { 130 | Console.BackgroundColor = ConsoleColor.DarkBlue; 131 | Console.Write(" {0}", prefix.ToString().PadRight(PrefixPadding)); 132 | Console.ResetColor(); 133 | Console.Write("│ "); 134 | } 135 | Console.BackgroundColor = backgroundColor; 136 | Console.Write("{0}", value); 137 | Console.ResetColor(); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/Husky/PhilLibX/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("PhilLibX")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("PhilLibX")] 12 | [assembly: AssemblyCopyright("Copyright © 2018")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("8f5c1ba4-88c1-4177-b91b-dd093dc849b9")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | --------------------------------------------------------------------------------