From 94ebe5b707a0cd90b1ef425c0580f4509b4a8610 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sun, 25 Dec 2022 23:33:52 -0800 Subject: [PATCH] Add NCF wrapper --- BurnOutSharp.Builders/GCF.cs | 5 +- BurnOutSharp.Builders/NCF.cs | 69 ++- BurnOutSharp.Models/NCF/DirectoryEntry.cs | 5 + BurnOutSharp.Models/NCF/File.cs | 4 +- BurnOutSharp.Models/NCF/Header.cs | 6 +- BurnOutSharp.Wrappers/NCF.cs | 564 ++++++++++++++++++++++ BurnOutSharp/Tools/Utilities.cs | 1 - Test/Program.cs | 31 ++ 8 files changed, 669 insertions(+), 16 deletions(-) create mode 100644 BurnOutSharp.Wrappers/NCF.cs diff --git a/BurnOutSharp.Builders/GCF.cs b/BurnOutSharp.Builders/GCF.cs index 4ad58ff0..13b4ac2a 100644 --- a/BurnOutSharp.Builders/GCF.cs +++ b/BurnOutSharp.Builders/GCF.cs @@ -237,7 +237,10 @@ namespace BurnOutSharp.Builders { data.Seek(-directoryName.Length, SeekOrigin.Current); byte[] endingData = data.ReadBytes((int)(directoryNamesEnd - data.Position)); - directoryName = Encoding.ASCII.GetString(endingData); + if (endingData != null) + directoryName = Encoding.ASCII.GetString(endingData); + else + directoryName = null; } file.DirectoryNames[nameOffset] = directoryName; diff --git a/BurnOutSharp.Builders/NCF.cs b/BurnOutSharp.Builders/NCF.cs index 2f00ccc3..8e9ebfe4 100644 --- a/BurnOutSharp.Builders/NCF.cs +++ b/BurnOutSharp.Builders/NCF.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.IO; using System.Text; using BurnOutSharp.Models.NCF; @@ -127,9 +128,41 @@ namespace BurnOutSharp.Builders #region Directory Names - // Read the directory names as a single string - byte[] directoryNames = data.ReadBytes((int)directoryHeader.NameSize); - file.DirectoryNames = Encoding.ASCII.GetString(directoryNames); + if (directoryHeader.NameSize > 0) + { + // Get the current offset for adjustment + long directoryNamesStart = data.Position; + + // Get the ending offset + long directoryNamesEnd = data.Position + directoryHeader.NameSize; + + // Create the string dictionary + file.DirectoryNames = new Dictionary(); + + // Loop and read the null-terminated strings + while (data.Position < directoryNamesEnd) + { + long nameOffset = data.Position - directoryNamesStart; + string directoryName = data.ReadString(Encoding.ASCII); + if (data.Position > directoryNamesEnd) + { + data.Seek(-directoryName.Length, SeekOrigin.Current); + byte[] endingData = data.ReadBytes((int)(directoryNamesEnd - data.Position)); + if (endingData != null) + directoryName = Encoding.ASCII.GetString(endingData); + else + directoryName = null; + } + + file.DirectoryNames[nameOffset] = directoryName; + } + + // Loop and assign to entries + foreach (var directoryEntry in file.DirectoryEntries) + { + directoryEntry.Name = file.DirectoryNames[directoryEntry.NameOffset]; + } + } #endregion @@ -204,7 +237,7 @@ namespace BurnOutSharp.Builders #endregion - #region Directory Map Entries + #region Unknown Entries // Create the unknown entry array file.UnknownEntries = new UnknownEntry[directoryHeader.ItemCount]; @@ -290,8 +323,11 @@ namespace BurnOutSharp.Builders Header header = new Header(); header.Dummy0 = data.ReadUInt32(); + if (header.Dummy0 != 0x00000001) + return null; + header.MajorVersion = data.ReadUInt32(); - if (header.MajorVersion != 2) + if (header.MajorVersion != 0x00000002) return null; header.MinorVersion = data.ReadUInt32(); @@ -300,12 +336,12 @@ namespace BurnOutSharp.Builders header.CacheID = data.ReadUInt32(); header.LastVersionPlayed = data.ReadUInt32(); - header.Dummy3 = data.ReadUInt32(); - header.Dummy4 = data.ReadUInt32(); + header.Dummy1 = data.ReadUInt32(); + header.Dummy2 = data.ReadUInt32(); header.FileSize = data.ReadUInt32(); header.BlockSize = data.ReadUInt32(); header.BlockCount = data.ReadUInt32(); - header.Dummy5 = data.ReadUInt32(); + header.Dummy3 = data.ReadUInt32(); return header; } @@ -321,16 +357,20 @@ namespace BurnOutSharp.Builders DirectoryHeader directoryHeader = new DirectoryHeader(); directoryHeader.Dummy0 = data.ReadUInt32(); + if (directoryHeader.Dummy0 != 0x00000004) + return null; + directoryHeader.CacheID = data.ReadUInt32(); directoryHeader.LastVersionPlayed = data.ReadUInt32(); directoryHeader.ItemCount = data.ReadUInt32(); directoryHeader.FileCount = data.ReadUInt32(); - directoryHeader.Dummy1 = data.ReadUInt32(); + directoryHeader.ChecksumDataLength = data.ReadUInt32(); directoryHeader.DirectorySize = data.ReadUInt32(); directoryHeader.NameSize = data.ReadUInt32(); directoryHeader.Info1Count = data.ReadUInt32(); directoryHeader.CopyCount = data.ReadUInt32(); directoryHeader.LocalCount = data.ReadUInt32(); + directoryHeader.Dummy1 = data.ReadUInt32(); directoryHeader.Dummy2 = data.ReadUInt32(); directoryHeader.Checksum = data.ReadUInt32(); @@ -433,7 +473,7 @@ namespace BurnOutSharp.Builders return null; unknownHeader.Dummy1 = data.ReadUInt32(); - if (unknownHeader.Dummy0 != 0x00000000) + if (unknownHeader.Dummy1 != 0x00000000) return null; return unknownHeader; @@ -465,6 +505,9 @@ namespace BurnOutSharp.Builders ChecksumHeader checksumHeader = new ChecksumHeader(); checksumHeader.Dummy0 = data.ReadUInt32(); + if (checksumHeader.Dummy0 != 0x00000001) + return null; + checksumHeader.ChecksumSize = data.ReadUInt32(); return checksumHeader; @@ -481,7 +524,13 @@ namespace BurnOutSharp.Builders ChecksumMapHeader checksumMapHeader = new ChecksumMapHeader(); checksumMapHeader.Dummy0 = data.ReadUInt32(); + if (checksumMapHeader.Dummy0 != 0x14893721) + return null; + checksumMapHeader.Dummy1 = data.ReadUInt32(); + if (checksumMapHeader.Dummy1 != 0x00000001) + return null; + checksumMapHeader.ItemCount = data.ReadUInt32(); checksumMapHeader.ChecksumCount = data.ReadUInt32(); diff --git a/BurnOutSharp.Models/NCF/DirectoryEntry.cs b/BurnOutSharp.Models/NCF/DirectoryEntry.cs index 5bb4232d..4f14273c 100644 --- a/BurnOutSharp.Models/NCF/DirectoryEntry.cs +++ b/BurnOutSharp.Models/NCF/DirectoryEntry.cs @@ -8,6 +8,11 @@ namespace BurnOutSharp.Models.NCF /// public uint NameOffset; + /// + /// Directory item name from the end of the directory items. + /// + public string Name; + /// /// Size of the item. (If file, file size. If folder, num items.) /// diff --git a/BurnOutSharp.Models/NCF/File.cs b/BurnOutSharp.Models/NCF/File.cs index 552e6f18..944d45f6 100644 --- a/BurnOutSharp.Models/NCF/File.cs +++ b/BurnOutSharp.Models/NCF/File.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; + namespace BurnOutSharp.Models.NCF { /// @@ -24,7 +26,7 @@ namespace BurnOutSharp.Models.NCF /// /// Directory names data /// - public string DirectoryNames { get; set; } + public Dictionary DirectoryNames { get; set; } /// /// Directory info 1 entries data diff --git a/BurnOutSharp.Models/NCF/Header.cs b/BurnOutSharp.Models/NCF/Header.cs index 2f795c3f..c8c86dac 100644 --- a/BurnOutSharp.Models/NCF/Header.cs +++ b/BurnOutSharp.Models/NCF/Header.cs @@ -31,12 +31,12 @@ namespace BurnOutSharp.Models.NCF /// /// Reserved /// - public uint Dummy3; + public uint Dummy1; /// /// Reserved /// - public uint Dummy4; + public uint Dummy2; /// /// Total size of NCF file in bytes. @@ -56,6 +56,6 @@ namespace BurnOutSharp.Models.NCF /// /// Reserved /// - public uint Dummy5; + public uint Dummy3; } } diff --git a/BurnOutSharp.Wrappers/NCF.cs b/BurnOutSharp.Wrappers/NCF.cs new file mode 100644 index 00000000..0562d7fb --- /dev/null +++ b/BurnOutSharp.Wrappers/NCF.cs @@ -0,0 +1,564 @@ +using System; +using System.IO; + +namespace BurnOutSharp.Wrappers +{ + public class NCF : WrapperBase + { + #region Pass-Through Properties + + #region Header + + /// + public uint Dummy0 => _file.Header.Dummy0; + + /// + public uint MajorVersion => _file.Header.MajorVersion; + + /// + public uint MinorVersion => _file.Header.MinorVersion; + + /// + public uint CacheID => _file.Header.CacheID; + + /// + public uint LastVersionPlayed => _file.Header.LastVersionPlayed; + + /// + public uint Dummy1 => _file.Header.Dummy1; + + /// + public uint Dummy2 => _file.Header.Dummy2; + + /// + public uint FileSize => _file.Header.FileSize; + + /// + public uint BlockSize => _file.Header.BlockSize; + + /// + public uint BlockCount => _file.Header.BlockCount; + + /// + public uint Dummy3 => _file.Header.Dummy3; + + #endregion + + #region Directory Header + + /// + public uint DH_Dummy0 => _file.DirectoryHeader.Dummy0; + + /// + public uint DH_CacheID => _file.DirectoryHeader.CacheID; + + /// + public uint DH_LastVersionPlayed => _file.DirectoryHeader.LastVersionPlayed; + + /// + public uint DH_ItemCount => _file.DirectoryHeader.ItemCount; + + /// + public uint DH_FileCount => _file.DirectoryHeader.FileCount; + + /// + public uint DH_ChecksumDataLength => _file.DirectoryHeader.ChecksumDataLength; + + /// + public uint DH_DirectorySize => _file.DirectoryHeader.DirectorySize; + + /// + public uint DH_NameSize => _file.DirectoryHeader.NameSize; + + /// + public uint DH_Info1Count => _file.DirectoryHeader.Info1Count; + + /// + public uint DH_CopyCount => _file.DirectoryHeader.CopyCount; + + /// + public uint DH_LocalCount => _file.DirectoryHeader.LocalCount; + + /// + public uint DH_Dummy1 => _file.DirectoryHeader.Dummy1; + + /// + public uint DH_Dummy2 => _file.DirectoryHeader.Dummy2; + + /// + public uint DH_Checksum => _file.DirectoryHeader.Checksum; + + #endregion + + #region Directory Entries + + /// + public Models.NCF.DirectoryEntry[] DirectoryEntries => _file.DirectoryEntries; + + #endregion + + #region Directory Names + + /// + public System.Collections.Generic.Dictionary DirectoryNames => _file.DirectoryNames; + + #endregion + + #region Directory Info 1 Entries + + /// + public Models.NCF.DirectoryInfo1Entry[] DirectoryInfo1Entries => _file.DirectoryInfo1Entries; + + #endregion + + #region Directory Info 2 Entries + + /// + public Models.NCF.DirectoryInfo2Entry[] DirectoryInfo2Entries => _file.DirectoryInfo2Entries; + + #endregion + + #region Directory Copy Entries + + /// + public Models.NCF.DirectoryCopyEntry[] DirectoryCopyEntries => _file.DirectoryCopyEntries; + + #endregion + + #region Directory Local Entries + + /// + public Models.NCF.DirectoryLocalEntry[] DirectoryLocalEntries => _file.DirectoryLocalEntries; + + #endregion + + #region Unknown Header + + /// + public uint UH_Dummy0 => _file.UnknownHeader.Dummy0; + + /// + public uint UH_Dummy1 => _file.UnknownHeader.Dummy1; + + #endregion + + #region Unknown Entries + + /// + public Models.NCF.UnknownEntry[] UnknownEntries => _file.UnknownEntries; + + #endregion + + #region Checksum Header + + /// + public uint CH_Dummy0 => _file.ChecksumHeader.Dummy0; + + /// + public uint CH_ChecksumSize => _file.ChecksumHeader.ChecksumSize; + + #endregion + + #region Checksum Map Header + + /// + public uint CMH_Dummy0 => _file.ChecksumMapHeader.Dummy0; + + /// + public uint CMH_Dummy1 => _file.ChecksumMapHeader.Dummy1; + + /// + public uint CMH_ItemCount => _file.ChecksumMapHeader.ItemCount; + + /// + public uint CMH_ChecksumCount => _file.ChecksumMapHeader.ChecksumCount; + + #endregion + + #region Checksum Map Entries + + /// + public Models.NCF.ChecksumMapEntry[] ChecksumMapEntries => _file.ChecksumMapEntries; + + #endregion + + #region Checksum Entries + + /// + public Models.NCF.ChecksumEntry[] ChecksumEntries => _file.ChecksumEntries; + + #endregion + + #endregion + + #region Instance Variables + + /// + /// Internal representation of the NCF + /// + private Models.NCF.File _file; + + #endregion + + #region Constructors + + /// + /// Private constructor + /// + private NCF() { } + + /// + /// Create an NCF from a byte array and offset + /// + /// Byte array representing the NCF + /// Offset within the array to parse + /// An NCF wrapper on success, null on failure + public static NCF Create(byte[] data, int offset) + { + // If the data is invalid + if (data == null) + return null; + + // If the offset is out of bounds + if (offset < 0 || offset >= data.Length) + return null; + + // Create a memory stream and use that + MemoryStream dataStream = new MemoryStream(data, offset, data.Length - offset); + return Create(dataStream); + } + + /// + /// Create a NCF from a Stream + /// + /// Stream representing the NCF + /// An NCF wrapper on success, null on failure + public static NCF Create(Stream data) + { + // If the data is invalid + if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) + return null; + + var file = Builders.NCF.ParseFile(data); + if (file == null) + return null; + + var wrapper = new NCF + { + _file = file, + _dataSource = DataSource.Stream, + _streamData = data, + }; + return wrapper; + } + + #endregion + + #region Printing + + /// + public override void Print() + { + Console.WriteLine("NCF Information:"); + Console.WriteLine("-------------------------"); + Console.WriteLine(); + + // Header + PrintHeader(); + + // Directory and Directory Maps + PrintDirectoryHeader(); + PrintDirectoryEntries(); + // TODO: Should we print out the entire string table? + PrintDirectoryInfo1Entries(); + PrintDirectoryInfo2Entries(); + PrintDirectoryCopyEntries(); + PrintDirectoryLocalEntries(); + PrintUnknownHeader(); + PrintUnknownEntries(); + + // Checksums and Checksum Maps + PrintChecksumHeader(); + PrintChecksumMapHeader(); + PrintChecksumMapEntries(); + PrintChecksumEntries(); + } + + /// + /// Print header information + /// + private void PrintHeader() + { + Console.WriteLine(" Header Information:"); + Console.WriteLine(" -------------------------"); + Console.WriteLine($" Dummy 0: {Dummy0}"); + Console.WriteLine($" Major version: {MajorVersion}"); + Console.WriteLine($" Minor version: {MinorVersion}"); + Console.WriteLine($" Cache ID: {CacheID}"); + Console.WriteLine($" Last version played: {LastVersionPlayed}"); + Console.WriteLine($" Dummy 1: {Dummy1}"); + Console.WriteLine($" Dummy 2: {Dummy2}"); + Console.WriteLine($" File size: {FileSize}"); + Console.WriteLine($" Block size: {BlockSize}"); + Console.WriteLine($" Block count: {BlockCount}"); + Console.WriteLine($" Dummy 3: {Dummy3}"); + Console.WriteLine(); + } + + /// + /// Print directory header information + /// + private void PrintDirectoryHeader() + { + Console.WriteLine(" Directory Header Information:"); + Console.WriteLine(" -------------------------"); + Console.WriteLine($" Dummy 0: {DH_Dummy0}"); + Console.WriteLine($" Cache ID: {DH_CacheID}"); + Console.WriteLine($" Last version played: {DH_LastVersionPlayed}"); + Console.WriteLine($" Item count: {DH_ItemCount}"); + Console.WriteLine($" File count: {DH_FileCount}"); + Console.WriteLine($" Checksum data length: {DH_ChecksumDataLength}"); + Console.WriteLine($" Directory size: {DH_DirectorySize}"); + Console.WriteLine($" Name size: {DH_NameSize}"); + Console.WriteLine($" Info 1 count: {DH_Info1Count}"); + Console.WriteLine($" Copy count: {DH_CopyCount}"); + Console.WriteLine($" Local count: {DH_LocalCount}"); + Console.WriteLine($" Dummy 1: {DH_Dummy1}"); + Console.WriteLine($" Dummy 2: {DH_Dummy2}"); + Console.WriteLine($" Checksum: {DH_Checksum}"); + Console.WriteLine(); + } + + /// + /// Print directory entries information + /// + private void PrintDirectoryEntries() + { + Console.WriteLine(" Directory Entries Information:"); + Console.WriteLine(" -------------------------"); + if (DirectoryEntries == null || DirectoryEntries.Length == 0) + { + Console.WriteLine(" No directory entries"); + } + else + { + for (int i = 0; i < DirectoryEntries.Length; i++) + { + var directoryEntry = DirectoryEntries[i]; + Console.WriteLine($" Directory Entry {i}"); + Console.WriteLine($" Name offset: {directoryEntry.NameOffset}"); + Console.WriteLine($" Name: {directoryEntry.Name}"); + Console.WriteLine($" Item size: {directoryEntry.ItemSize}"); + Console.WriteLine($" Checksum index: {directoryEntry.ChecksumIndex}"); + Console.WriteLine($" Directory flags: {directoryEntry.DirectoryFlags}"); + Console.WriteLine($" Parent index: {directoryEntry.ParentIndex}"); + Console.WriteLine($" Next index: {directoryEntry.NextIndex}"); + Console.WriteLine($" First index: {directoryEntry.FirstIndex}"); + } + } + Console.WriteLine(); + } + + /// + /// Print directory info 1 entries information + /// + private void PrintDirectoryInfo1Entries() + { + Console.WriteLine(" Directory Info 1 Entries Information:"); + Console.WriteLine(" -------------------------"); + if (DirectoryInfo1Entries == null || DirectoryInfo1Entries.Length == 0) + { + Console.WriteLine(" No directory info 1 entries"); + } + else + { + for (int i = 0; i < DirectoryInfo1Entries.Length; i++) + { + var directoryInfoEntry = DirectoryInfo1Entries[i]; + Console.WriteLine($" Directory Info 1 Entry {i}"); + Console.WriteLine($" Dummy 0: {directoryInfoEntry.Dummy0}"); + } + } + Console.WriteLine(); + } + + /// + /// Print directory info 2 entries information + /// + private void PrintDirectoryInfo2Entries() + { + Console.WriteLine(" Directory Info 2 Entries Information:"); + Console.WriteLine(" -------------------------"); + if (DirectoryInfo2Entries == null || DirectoryInfo2Entries.Length == 0) + { + Console.WriteLine(" No directory info 2 entries"); + } + else + { + for (int i = 0; i < DirectoryInfo2Entries.Length; i++) + { + var directoryInfoEntry = DirectoryInfo2Entries[i]; + Console.WriteLine($" Directory Info 2 Entry {i}"); + Console.WriteLine($" Dummy 0: {directoryInfoEntry.Dummy0}"); + } + } + Console.WriteLine(); + } + + /// + /// Print directory copy entries information + /// + private void PrintDirectoryCopyEntries() + { + Console.WriteLine(" Directory Copy Entries Information:"); + Console.WriteLine(value: " -------------------------"); + if (DirectoryCopyEntries == null || DirectoryCopyEntries.Length == 0) + { + Console.WriteLine(" No directory copy entries"); + } + else + { + for (int i = 0; i < DirectoryCopyEntries.Length; i++) + { + var directoryCopyEntry = DirectoryCopyEntries[i]; + Console.WriteLine($" Directory Copy Entry {i}"); + Console.WriteLine($" Directory index: {directoryCopyEntry.DirectoryIndex}"); + } + } + Console.WriteLine(); + } + + /// + /// Print directory local entries information + /// + private void PrintDirectoryLocalEntries() + { + Console.WriteLine(" Directory Local Entries Information:"); + Console.WriteLine(value: " -------------------------"); + if (DirectoryLocalEntries == null || DirectoryLocalEntries.Length == 0) + { + Console.WriteLine(" No directory local entries"); + } + else + { + for (int i = 0; i < DirectoryLocalEntries.Length; i++) + { + var directoryLocalEntry = DirectoryLocalEntries[i]; + Console.WriteLine($" Directory Local Entry {i}"); + Console.WriteLine($" Directory index: {directoryLocalEntry.DirectoryIndex}"); + } + } + Console.WriteLine(); + } + + /// + /// Print unknown header information + /// + private void PrintUnknownHeader() + { + Console.WriteLine(" Unknown Header Information:"); + Console.WriteLine(" -------------------------"); + Console.WriteLine($" Dummy 0: {UH_Dummy0}"); + Console.WriteLine($" Dummy 1: {UH_Dummy1}"); + Console.WriteLine(); + } + + /// + /// Print unknown entries information + /// + private void PrintUnknownEntries() + { + Console.WriteLine(" Unknown Entries Information:"); + Console.WriteLine(value: " -------------------------"); + if (UnknownEntries == null || UnknownEntries.Length == 0) + { + Console.WriteLine(" No unknown entries"); + } + else + { + for (int i = 0; i < UnknownEntries.Length; i++) + { + var unknownEntry = UnknownEntries[i]; + Console.WriteLine($" Unknown Entry {i}"); + Console.WriteLine($" Dummy 0: {unknownEntry.Dummy0}"); + } + } + Console.WriteLine(); + } + + /// + /// Print checksum header information + /// + private void PrintChecksumHeader() + { + Console.WriteLine(" Checksum Header Information:"); + Console.WriteLine(" -------------------------"); + Console.WriteLine($" Dummy 0: {CH_Dummy0}"); + Console.WriteLine($" Checksum size: {CH_ChecksumSize}"); + Console.WriteLine(); + } + + /// + /// Print checksum map header information + /// + private void PrintChecksumMapHeader() + { + Console.WriteLine(" Checksum Map Header Information:"); + Console.WriteLine(" -------------------------"); + Console.WriteLine($" Dummy 0: {CMH_Dummy0}"); + Console.WriteLine($" Dummy 1: {CMH_Dummy1}"); + Console.WriteLine($" Item count: {CMH_ItemCount}"); + Console.WriteLine($" Checksum count: {CMH_ChecksumCount}"); + Console.WriteLine(); + } + + /// + /// Print checksum map entries information + /// + private void PrintChecksumMapEntries() + { + Console.WriteLine(" Checksum Map Entries Information:"); + Console.WriteLine(value: " -------------------------"); + if (ChecksumMapEntries == null || ChecksumMapEntries.Length == 0) + { + Console.WriteLine(" No checksum map entries"); + } + else + { + for (int i = 0; i < ChecksumMapEntries.Length; i++) + { + var checksumMapEntry = ChecksumMapEntries[i]; + Console.WriteLine($" Checksum Map Entry {i}"); + Console.WriteLine($" Checksum count: {checksumMapEntry.ChecksumCount}"); + Console.WriteLine($" First checksum index: {checksumMapEntry.FirstChecksumIndex}"); + } + } + Console.WriteLine(); + } + + /// + /// Print checksum entries information + /// + private void PrintChecksumEntries() + { + Console.WriteLine(" Checksum Entries Information:"); + Console.WriteLine(value: " -------------------------"); + if (ChecksumEntries == null || ChecksumEntries.Length == 0) + { + Console.WriteLine(" No checksum entries"); + } + else + { + for (int i = 0; i < ChecksumEntries.Length; i++) + { + var checksumEntry = ChecksumEntries[i]; + Console.WriteLine($" Checksum Entry {i}"); + Console.WriteLine($" Checksum: {checksumEntry.Checksum}"); + } + } + Console.WriteLine(); + } + + #endregion + } +} \ No newline at end of file diff --git a/BurnOutSharp/Tools/Utilities.cs b/BurnOutSharp/Tools/Utilities.cs index cb639c66..71702b42 100644 --- a/BurnOutSharp/Tools/Utilities.cs +++ b/BurnOutSharp/Tools/Utilities.cs @@ -628,7 +628,6 @@ namespace BurnOutSharp.Tools case SupportedFileType.MicrosoftCAB: return new FileType.MicrosoftCAB(); case SupportedFileType.MPQ: return new FileType.MPQ(); case SupportedFileType.MSI: return new FileType.MSI(); - case SupportedFileType.NCF: return new FileType.Valve(); case SupportedFileType.PAK: return new FileType.PKZIP(); case SupportedFileType.PKZIP: return new FileType.PKZIP(); case SupportedFileType.PLJ: return new FileType.PLJ(); diff --git a/Test/Program.cs b/Test/Program.cs index d72ae7dd..e0aa6d30 100644 --- a/Test/Program.cs +++ b/Test/Program.cs @@ -381,6 +381,25 @@ namespace Test cabinet.Print(); } + // NCF + else if (IsNCF(magic)) + { + // Build the NCF information + Console.WriteLine("Creating NCF deserializer"); + Console.WriteLine(); + + var ncf = NCF.Create(stream); + if (ncf == null) + { + Console.WriteLine("Something went wrong parsing NCF"); + Console.WriteLine(); + return; + } + + // Print the NCF info to screen + ncf.Print(); + } + // VPK else if (IsVPK(magic)) { @@ -477,6 +496,18 @@ namespace Test return magic[0] == 'M' && magic[1] == 'Z'; } + /// + /// Determine if the magic bytes indicate an NCF + /// + private static bool IsNCF(byte[] magic) + { + if (magic == null || magic.Length < 8) + return false; + + return magic[0] == 0x01 && magic[1] == 0x00 && magic[2] == 0x00 && magic[3] == 0x00 + && magic[4] == 0x02 && magic[5] == 0x00 && magic[6] == 0x00 && magic[7] == 0x00; + } + /// /// Determine if the magic bytes indicate a New Executable ///