Skip to content

Commit

Permalink
IW + WW2 Support, UI, other stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
Scobalula committed Nov 24, 2018
1 parent 41bef25 commit 1252d2e
Show file tree
Hide file tree
Showing 43 changed files with 2,492 additions and 280 deletions.
28 changes: 16 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,25 @@ Husky is a BSP Extractor for Call of Duty. It can rip the raw vertex/face data t

### Supported Games

* Call of Duty: World at War
* Call of Duty: Black Ops
* Call of Duty: Black Ops 2
* Call of Duty: Modern Warfare
* Call of Duty: Modern Warfare 2
* Call of Duty: Modern Warfare 3
* Call of Duty: Advanced Warfare
* Call of Duty: Ghosts
* Call of Duty: Infinite Warfare
* Call of Duty: World at War
* Call of Duty: Black Ops
* Call of Duty: Black Ops 2
* Call of Duty: Advanced Warfare
* Call of DUty: World War 2
* Call of Duty: Modern Warfare Remastered

**Call of Duty: Black Ops 3 will never be supported, for obvious reasons**
**Call of Duty: Black Ops 3 will never be supported, to avoid people ripping custom maps, etc.**

### Downloading/Using Husky

To download Husky, go to the [Releases](https://github.com/Scobalula/Husky/releases) and download the latest build.

To use Husky, simply run the game, load the map you want to extract, and run Husky. In some cases you may need to run Husky as an administator.
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.

Once the map is exported, you will have 3 files for it:

Expand All @@ -28,17 +30,19 @@ Once the map is exported, you will have 3 files for it:
* **mapname**.txt - A search string for Wraith/Greyhound (only contains color maps)
* **mapname**.map - Map file with **static** model locations and rotations

If you wish to use textures (be warned they can result in high RAM usage) then make sure to have the _images folder 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).
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).

### License/Disclaimers

Husky is licensed under the GPL license and it and its source code is free to use and modify under the. Husky comes with NO warranty, any damages caused are solely the responsibility of the user. See the LICENSE file for more information.
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.

All BSP data extracted using Husky is property of the developers, etc. Husky simply parses the data out, what you do with the data is your reponsibility.
**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.

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.

**Husky is currently in alpha, and with that in mind, bugs, errors, you know, the bad stuff.**
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.

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.

## FAQ

Expand All @@ -56,11 +60,11 @@ Some of the exported models can get pretty big. While all have loaded in Maya wi

* Q: Why is there a bunch of geo at the origin?

* 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.
* 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.

## Credits

* DTZxPorter - Normal Unpacking Code from Wraith + Other misc info from Wraith, SELib
* DTZxPorter - Normal Unpacking Code from Wraith, Half Floats code, Other misc info from Wraith.
* Anna Baker - [Icon](https://thenounproject.com/term/husky/1121992/) ([https://thenounproject.com/anna.baker194/](https://thenounproject.com/anna.baker194/))

## Support Me
Expand Down
6 changes: 6 additions & 0 deletions src/Husky/Husky.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Husky", "Husky\Husky.csproj
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhilLibX", "PhilLibX\PhilLibX.csproj", "{8F5C1BA4-88C1-4177-B91B-DD093DC849B9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HuskyUI", "HuskyUI\HuskyUI.csproj", "{5BC7C6FE-F65C-4F32-BC26-FAC69926F10E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -21,6 +23,10 @@ Global
{8F5C1BA4-88C1-4177-B91B-DD093DC849B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8F5C1BA4-88C1-4177-B91B-DD093DC849B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8F5C1BA4-88C1-4177-B91B-DD093DC849B9}.Release|Any CPU.Build.0 = Release|Any CPU
{5BC7C6FE-F65C-4F32-BC26-FAC69926F10E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5BC7C6FE-F65C-4F32-BC26-FAC69926F10E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5BC7C6FE-F65C-4F32-BC26-FAC69926F10E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5BC7C6FE-F65C-4F32-BC26-FAC69926F10E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
20 changes: 19 additions & 1 deletion src/Husky/Husky/FileFormats/IWMap.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
using System;
// ------------------------------------------------------------------------
// Husky - Call of Duty BSP Extractor
// Copyright (C) 2018 Philip/Scobalula
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.IO;

namespace Husky
{
/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions src/Husky/Husky/FodyWeavers.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
<Costura/>
<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Costura />
</Weavers>
21 changes: 21 additions & 0 deletions src/Husky/Husky/FodyWeavers.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuild. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="Costura" minOccurs="0" maxOccurs="1" type="xs:anyType" />
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification on the target assembly after all weavers have been finished.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
19 changes: 18 additions & 1 deletion src/Husky/Husky/GameStructures/Shared.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
using System.Runtime.InteropServices;
// ------------------------------------------------------------------------
// Husky - Call of Duty BSP Extractor
// Copyright (C) 2018 Philip/Scobalula
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ------------------------------------------------------------------------
using System.Runtime.InteropServices;

namespace Husky
{
Expand Down
38 changes: 19 additions & 19 deletions src/Husky/Husky/Games/AdvancedWarfare.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,10 @@ public unsafe struct GfxStaticModel
/// <summary>
/// Reads BSP Data
/// </summary>
public static void ExportBSPData(ProcessReader reader, long assetPoolsAddress, long assetSizesAddress, string gameType)
public static void ExportBSPData(ProcessReader reader, long assetPoolsAddress, long assetSizesAddress, string gameType, Action<object> printCallback = null)
{
// Found her
Printer.WriteLine("INFO", "Found supported game: Call of Duty: Advanced Warfare");
printCallback?.Invoke("Found supported game: Call of Duty: Advanced Warfare");

// Validate by XModel Name
if (reader.ReadNullTerminatedString(reader.ReadInt64(reader.ReadInt64(assetPoolsAddress + 0x38) + 8)) == "fx")
Expand All @@ -288,19 +288,19 @@ public static void ExportBSPData(ProcessReader reader, long assetPoolsAddress, l
// Verify a BSP is actually loaded (if in base menu, etc, no map is loaded)
if (String.IsNullOrWhiteSpace(gfxMapName))
{
Printer.WriteLine("ERROR", "No BSP loaded. Enter Main Menu or a Map to load in the required assets.", ConsoleColor.DarkRed);
printCallback?.Invoke("No BSP loaded. Enter Main Menu or a Map to load in the required assets.");
}
else
{
// New IW Map
var mapFile = new IWMap();
// Print Info
Printer.WriteLine("INFO", String.Format("Loaded Gfx Map - {0}", gfxMapName));
Printer.WriteLine("INFO", String.Format("Loaded Map - {0}", mapName));
Printer.WriteLine("INFO", String.Format("Vertex Count - {0}", gfxMapAsset.GfxVertexCount));
Printer.WriteLine("INFO", String.Format("Indices Count - {0}", gfxMapAsset.GfxIndicesCount));
Printer.WriteLine("INFO", String.Format("Surface Count - {0}", gfxMapAsset.SurfaceCount));
Printer.WriteLine("INFO", String.Format("Model Count - {0}", gfxMapAsset.GfxStaticModelsCount));
printCallback?.Invoke(String.Format("Loaded Gfx Map - {0}", gfxMapName));
printCallback?.Invoke(String.Format("Loaded Map - {0}", mapName));
printCallback?.Invoke(String.Format("Vertex Count - {0}", gfxMapAsset.GfxVertexCount));
printCallback?.Invoke(String.Format("Indices Count - {0}", gfxMapAsset.GfxIndicesCount));
printCallback?.Invoke(String.Format("Surface Count - {0}", gfxMapAsset.SurfaceCount));
printCallback?.Invoke(String.Format("Model Count - {0}", gfxMapAsset.GfxStaticModelsCount));

// Build output Folder
string outputName = Path.Combine("exported_maps", "advanced_warfare", gameType, mapName, mapName);
Expand All @@ -310,31 +310,31 @@ public static void ExportBSPData(ProcessReader reader, long assetPoolsAddress, l
var stopWatch = Stopwatch.StartNew();

// Read Vertices
Printer.WriteLine("INFO", "Parsing vertex data....");
printCallback?.Invoke("Parsing vertex data....");
var vertices = ReadGfxVertices(reader, gfxMapAsset.GfxVerticesPointer, (int)gfxMapAsset.GfxVertexCount);
Printer.WriteLine("INFO", String.Format("Parsed vertex data in {0:0.00} seconds.", stopWatch.ElapsedMilliseconds / 1000.0));
printCallback?.Invoke(String.Format("Parsed vertex data in {0:0.00} seconds.", stopWatch.ElapsedMilliseconds / 1000.0));

// Reset timer
stopWatch.Restart();

// Read Indices
Printer.WriteLine("INFO", "Parsing surface indices....");
printCallback?.Invoke("Parsing surface indices....");
var indices = ReadGfxIndices(reader, gfxMapAsset.GfxIndicesPointer, (int)gfxMapAsset.GfxIndicesCount);
Printer.WriteLine("INFO", String.Format("Parsed indices in {0:0.00} seconds.", stopWatch.ElapsedMilliseconds / 1000.0));
printCallback?.Invoke(String.Format("Parsed indices in {0:0.00} seconds.", stopWatch.ElapsedMilliseconds / 1000.0));

// Reset timer
stopWatch.Restart();

// Read Indices
Printer.WriteLine("INFO", "Parsing surfaces....");
printCallback?.Invoke("Parsing surfaces....");
var surfaces = ReadGfxSufaces(reader, gfxMapAsset.GfxSurfacesPointer, gfxMapAsset.SurfaceCount);
Printer.WriteLine("INFO", String.Format("Parsed surfaces in {0:0.00} seconds.", stopWatch.ElapsedMilliseconds / 1000.0));
printCallback?.Invoke(String.Format("Parsed surfaces in {0:0.00} seconds.", stopWatch.ElapsedMilliseconds / 1000.0));

// Reset timer
stopWatch.Restart();

// Write OBJ
Printer.WriteLine("INFO", "Converting to OBJ....");
printCallback?.Invoke("Converting to OBJ....");

// Create new OBJ
var obj = new WavefrontOBJ();
Expand Down Expand Up @@ -402,13 +402,13 @@ public static void ExportBSPData(ProcessReader reader, long assetPoolsAddress, l
mapFile.DumpToMap(outputName + ".map");

// Done
Printer.WriteLine("INFO", String.Format("Converted to OBJ in {0:0.00} seconds.", stopWatch.ElapsedMilliseconds / 1000.0));
printCallback?.Invoke(String.Format("Converted to OBJ in {0:0.00} seconds.", stopWatch.ElapsedMilliseconds / 1000.0));
}

}
else
{
Printer.WriteLine("ERROR", "Call of Duty: Advanced Warfare is supported, but this EXE is not.", ConsoleColor.DarkRed);
printCallback?.Invoke("Call of Duty: Advanced Warfare is supported, but this EXE is not.");
}
}

Expand Down Expand Up @@ -469,7 +469,7 @@ public static Vertex[] ReadGfxVertices(ProcessReader reader, long address, int c
gfxVertex.Y * 2.54,
gfxVertex.Z * 2.54),
// Decode and set normal (from DTZxPorter - Wraith, same as XModels)
Normal = VertexNormal.UnpackB(gfxVertex.Normal),
Normal = VertexNormalUnpacking.MethodB(gfxVertex.Normal),
// Set UV
UV = new Vector2(gfxVertex.U, 1 - gfxVertex.V)
};
Expand Down
Loading

0 comments on commit 1252d2e

Please sign in to comment.