mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-09-21 22:35:06 +00:00
Add more extension properties; clean up
This commit is contained in:
@@ -12,6 +12,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extension Properties
|
||||
|
||||
/// <inheritdoc cref="BspHeader.Lumps"/>
|
||||
public BspLumpEntry[]? Lumps => Model.Header?.Lumps;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -86,12 +93,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool ExtractAllLumps(string outputDirectory)
|
||||
{
|
||||
// If we have no lumps
|
||||
if (Model.Header?.Lumps == null || Model.Header.Lumps.Length == 0)
|
||||
if (Lumps == null || Lumps.Length == 0)
|
||||
return false;
|
||||
|
||||
// Loop through and extract all lumps to the output
|
||||
bool allExtracted = true;
|
||||
for (int i = 0; i < Model.Header.Lumps.Length; i++)
|
||||
for (int i = 0; i < Lumps.Length; i++)
|
||||
{
|
||||
allExtracted &= ExtractLump(i, outputDirectory);
|
||||
}
|
||||
@@ -108,15 +115,15 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool ExtractLump(int index, string outputDirectory)
|
||||
{
|
||||
// If we have no lumps
|
||||
if (Model.Header?.Lumps == null || Model.Header.Lumps.Length == 0)
|
||||
if (Lumps == null || Lumps.Length == 0)
|
||||
return false;
|
||||
|
||||
// If the lumps index is invalid
|
||||
if (index < 0 || index >= Model.Header.Lumps.Length)
|
||||
if (index < 0 || index >= Lumps.Length)
|
||||
return false;
|
||||
|
||||
// Read the data
|
||||
var lump = Model.Header.Lumps[index];
|
||||
var lump = Lumps[index];
|
||||
var data = ReadFromDataSource(lump.Offset, lump.Length);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
@@ -391,10 +391,6 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// <returns>Ordered list of sector numbers, null on error</returns>
|
||||
public byte[]? GetMiniFATSectorChainData(SectorNumber startingSector)
|
||||
{
|
||||
// Ignore invalid data
|
||||
if (Model?.Header == null)
|
||||
return null;
|
||||
|
||||
// Validate the mini stream data
|
||||
if (MiniStreamData == null)
|
||||
return null;
|
||||
|
||||
@@ -52,24 +52,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CHD version
|
||||
/// </summary>
|
||||
public int Version
|
||||
{
|
||||
get
|
||||
{
|
||||
return Model switch
|
||||
{
|
||||
HeaderV1 => 1,
|
||||
HeaderV2 => 2,
|
||||
HeaderV3 => 3,
|
||||
HeaderV4 => 4,
|
||||
HeaderV5 => 5,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <inheritdoc cref="Header.Version"/>
|
||||
public uint Version => Model.Version;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -143,6 +143,9 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Models.GCF.DataBlockHeader.BlockSize"/>
|
||||
public uint BlockSize => Model.DataBlockHeader?.BlockSize ?? 0;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Variables
|
||||
@@ -283,7 +286,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
long dataBlockOffset = DataBlockOffsets[dataBlockIndex++];
|
||||
dataBlockOffsets.Add(dataBlockOffset);
|
||||
blockEntrySize -= Model.DataBlockHeader?.BlockSize ?? 0;
|
||||
blockEntrySize -= BlockSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,7 +317,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
long fileSize = file.Size;
|
||||
for (int i = 0; i < dataBlockOffsets.Count; i++)
|
||||
{
|
||||
int readSize = (int)Math.Min(Model.DataBlockHeader?.BlockSize ?? 0, fileSize);
|
||||
int readSize = (int)Math.Min(BlockSize, fileSize);
|
||||
var data = ReadFromDataSource((int)dataBlockOffsets[i], readSize);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
@@ -24,21 +24,33 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// <remarks>Only used in multi-file</remarks>
|
||||
public InstallShieldCabinet? Next { get; set; }
|
||||
|
||||
/// <inheritdoc cref="Cabinet.Components"/>
|
||||
public Component[]? Components => Model.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Number of components in the cabinet set
|
||||
/// </summary>
|
||||
public int ComponentCount => Model.Components?.Length ?? 0;
|
||||
public int ComponentCount => Components?.Length ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// Number of directories in the cabinet set
|
||||
/// </summary>
|
||||
public ushort DirectoryCount => Model.Descriptor?.DirectoryCount ?? 0;
|
||||
|
||||
/// <inheritdoc cref="Cabinet.DirectoryNames"/>
|
||||
public string[]? DirectoryNames => Model.DirectoryNames;
|
||||
|
||||
/// <summary>
|
||||
/// Number of files in the cabinet set
|
||||
/// </summary>
|
||||
public uint FileCount => Model.Descriptor?.FileCount ?? 0;
|
||||
|
||||
/// <inheritdoc cref="Cabinet.FileDescriptors"/>
|
||||
public FileDescriptor[]? FileDescriptors => Model.FileDescriptors;
|
||||
|
||||
/// <inheritdoc cref="Cabinet.FileGroups"/>
|
||||
public FileGroup[]? FileGroups => Model.FileGroups;
|
||||
|
||||
/// <summary>
|
||||
/// Number of file groups in the cabinet set
|
||||
/// </summary>
|
||||
@@ -249,13 +261,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
public string? GetComponentName(int index)
|
||||
{
|
||||
if (Model.Components == null)
|
||||
if (Components == null)
|
||||
return null;
|
||||
|
||||
if (index < 0 || index >= Model.Components.Length)
|
||||
if (index < 0 || index >= ComponentCount)
|
||||
return null;
|
||||
|
||||
var component = Model.Components[index];
|
||||
var component = Components[index];
|
||||
if (component?.Identifier == null)
|
||||
return null;
|
||||
|
||||
@@ -271,13 +283,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
public string? GetDirectoryName(int index)
|
||||
{
|
||||
if (Model.DirectoryNames == null)
|
||||
if (DirectoryNames == null)
|
||||
return null;
|
||||
|
||||
if (index < 0 || index >= Model.DirectoryNames.Length)
|
||||
if (index < 0 || index >= DirectoryNames.Length)
|
||||
return null;
|
||||
|
||||
return Model.DirectoryNames[index];
|
||||
return DirectoryNames[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -302,10 +314,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
public bool FileIsValid(int index)
|
||||
{
|
||||
if (Model.Descriptor == null)
|
||||
return false;
|
||||
|
||||
if (index < 0 || index > Model.Descriptor.FileCount)
|
||||
if (index < 0 || index > FileCount)
|
||||
return false;
|
||||
|
||||
FileDescriptor? descriptor = GetFileDescriptor(index);
|
||||
@@ -345,13 +354,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
public FileDescriptor? GetFileDescriptor(int index)
|
||||
{
|
||||
if (Model.FileDescriptors == null)
|
||||
if (FileDescriptors == null)
|
||||
return null;
|
||||
|
||||
if (index < 0 || index >= Model.FileDescriptors.Length)
|
||||
if (index < 0 || index >= FileDescriptors.Length)
|
||||
return null;
|
||||
|
||||
return Model.FileDescriptors[index];
|
||||
return FileDescriptors[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -424,13 +433,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
public FileGroup? GetFileGroup(int index)
|
||||
{
|
||||
if (Model.FileGroups == null)
|
||||
if (FileGroups == null)
|
||||
return null;
|
||||
|
||||
if (index < 0 || index >= Model.FileGroups.Length)
|
||||
if (index < 0 || index >= FileGroups.Length)
|
||||
return null;
|
||||
|
||||
return Model.FileGroups[index];
|
||||
return FileGroups[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -438,10 +447,10 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
public FileGroup? GetFileGroup(string name)
|
||||
{
|
||||
if (Model.FileGroups == null)
|
||||
if (FileGroups == null)
|
||||
return null;
|
||||
|
||||
return Array.Find(Model.FileGroups, fg => fg != null && string.Equals(fg.Name, name));
|
||||
return Array.Find(FileGroups, fg => fg != null && string.Equals(fg.Name, name));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -449,7 +458,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
public FileGroup? GetFileGroupFromFile(int index)
|
||||
{
|
||||
if (Model.FileGroups == null)
|
||||
if (FileGroups == null)
|
||||
return null;
|
||||
|
||||
if (index < 0 || index >= FileCount)
|
||||
|
||||
@@ -13,6 +13,22 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extension Properties
|
||||
|
||||
/// <inheritdoc cref="KWAJHeader.CompressionType"/>
|
||||
public KWAJCompressionType CompressionType => Model.Header?.CompressionType ?? KWAJCompressionType.NoCompression;
|
||||
|
||||
/// <inheritdoc cref="KWAJHeader.DataOffset"/>
|
||||
public ushort DataOffset => Model.Header?.DataOffset ?? 0;
|
||||
|
||||
/// <inheritdoc cref="KWAJHeaderExtensions.FileName"/>
|
||||
public string? FileName => Model.HeaderExtensions?.FileName;
|
||||
|
||||
/// <inheritdoc cref="KWAJHeaderExtensions.FileExtension"/>
|
||||
public string? FileExtension => Model.HeaderExtensions?.FileExtension;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -87,17 +103,17 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool Extract(string outputDirectory)
|
||||
{
|
||||
// Get the length of the compressed data
|
||||
long compressedSize = Length - Model.Header!.DataOffset;
|
||||
if (compressedSize < Model.Header.DataOffset)
|
||||
long compressedSize = Length - DataOffset;
|
||||
if (compressedSize < DataOffset)
|
||||
return false;
|
||||
|
||||
// Read in the data as an array
|
||||
byte[]? contents = ReadFromDataSource(Model.Header.DataOffset, (int)compressedSize);
|
||||
byte[]? contents = ReadFromDataSource(DataOffset, (int)compressedSize);
|
||||
if (contents == null)
|
||||
return false;
|
||||
|
||||
// Get the decompressor
|
||||
var decompressor = Decompressor.CreateKWAJ(contents, Model.Header!.CompressionType);
|
||||
var decompressor = Decompressor.CreateKWAJ(contents, CompressionType);
|
||||
if (decompressor == null)
|
||||
return false;
|
||||
|
||||
@@ -106,11 +122,9 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return false;
|
||||
|
||||
// Create the full output path
|
||||
string filename = "tempfile";
|
||||
if (Model.HeaderExtensions?.FileName != null)
|
||||
filename = Model.HeaderExtensions.FileName;
|
||||
if (Model.HeaderExtensions?.FileExtension != null)
|
||||
filename += $".{Model.HeaderExtensions.FileExtension}";
|
||||
string filename = FileName ?? "tempfile";
|
||||
if (FileExtension != null)
|
||||
filename += $".{FileExtension}";
|
||||
|
||||
// Ensure directory separators are consistent
|
||||
if (Path.DirectorySeparatorChar == '\\')
|
||||
|
||||
@@ -13,6 +13,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extension Properties
|
||||
|
||||
/// <inheritdoc cref="SZDDHeader.LastChar"/>
|
||||
public char LastChar => Model.Header?.LastChar ?? '\0';
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -151,7 +158,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (extension.Length == 1)
|
||||
{
|
||||
if (extension == "_" || extension == "$")
|
||||
return $"{Path.GetFileNameWithoutExtension(input)}.{char.ToLower(Model.Header!.LastChar)}";
|
||||
return $"{Path.GetFileNameWithoutExtension(input)}.{char.ToLower(LastChar)}";
|
||||
|
||||
return Path.GetFileNameWithoutExtension(input);
|
||||
}
|
||||
@@ -161,7 +168,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return Path.GetFileNameWithoutExtension(input);
|
||||
|
||||
// Handle replacing characters
|
||||
char c = (char.IsUpper(input[0]) ? char.ToLower(Model.Header!.LastChar) : char.ToUpper(Model.Header!.LastChar));
|
||||
char c = (char.IsUpper(input[0]) ? char.ToLower(LastChar) : char.ToUpper(LastChar));
|
||||
string text2 = extension.Substring(0, extension.Length - 1) + c;
|
||||
return Path.GetFileNameWithoutExtension(input) + "." + text2;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// <inheritdoc cref="Cart.CommonHeader"/>
|
||||
public CommonHeader? CommonHeader => Model.CommonHeader;
|
||||
|
||||
/// <inheritdoc cref="CommonHeader.GameCode"/>
|
||||
public uint GameCode => Model.CommonHeader?.GameCode ?? 0;
|
||||
|
||||
/// <inheritdoc cref="Cart.SecureArea"/>
|
||||
public byte[]? SecureArea => Model.SecureArea;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Encryption process variables
|
||||
@@ -138,15 +144,15 @@ namespace SabreTools.Serialization.Wrappers
|
||||
private void EncryptARM9(byte[] tableData)
|
||||
{
|
||||
// If the secure area is invalid, nothing can be done
|
||||
if (Model.SecureArea == null)
|
||||
if (SecureArea == null)
|
||||
return;
|
||||
|
||||
// Point to the beginning of the secure area
|
||||
int readOffset = 0;
|
||||
|
||||
// Grab the first two blocks
|
||||
uint p0 = Model.SecureArea.ReadUInt32(ref readOffset);
|
||||
uint p1 = Model.SecureArea.ReadUInt32(ref readOffset);
|
||||
uint p0 = SecureArea.ReadUInt32(ref readOffset);
|
||||
uint p1 = SecureArea.ReadUInt32(ref readOffset);
|
||||
|
||||
// Perform the initialization steps
|
||||
Init1(tableData);
|
||||
@@ -162,13 +168,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
uint size = 0x800 - 8;
|
||||
while (size > 0)
|
||||
{
|
||||
p0 = Model.SecureArea.ReadUInt32(ref readOffset);
|
||||
p1 = Model.SecureArea.ReadUInt32(ref readOffset);
|
||||
p0 = SecureArea.ReadUInt32(ref readOffset);
|
||||
p1 = SecureArea.ReadUInt32(ref readOffset);
|
||||
|
||||
Encrypt(ref p1, ref p0);
|
||||
|
||||
Model.SecureArea.Write(ref writeOffset, p0);
|
||||
Model.SecureArea.Write(ref writeOffset, p1);
|
||||
SecureArea.Write(ref writeOffset, p0);
|
||||
SecureArea.Write(ref writeOffset, p1);
|
||||
|
||||
size -= 8;
|
||||
}
|
||||
@@ -177,8 +183,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
readOffset = 0;
|
||||
writeOffset = 0;
|
||||
|
||||
p0 = Model.SecureArea.ReadUInt32(ref readOffset);
|
||||
p1 = Model.SecureArea.ReadUInt32(ref readOffset);
|
||||
p0 = SecureArea.ReadUInt32(ref readOffset);
|
||||
p1 = SecureArea.ReadUInt32(ref readOffset);
|
||||
|
||||
if (p0 == 0xE7FFDEFF && p1 == 0xE7FFDEFF)
|
||||
{
|
||||
@@ -190,8 +196,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
Init1(tableData);
|
||||
Encrypt(ref p1, ref p0);
|
||||
|
||||
Model.SecureArea.Write(ref writeOffset, p0);
|
||||
Model.SecureArea.Write(ref writeOffset, p1);
|
||||
SecureArea.Write(ref writeOffset, p0);
|
||||
SecureArea.Write(ref writeOffset, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -260,7 +266,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
private void DecryptARM9(byte[] tableData)
|
||||
{
|
||||
// If the secure area is invalid, nothing can be done
|
||||
if (Model.SecureArea == null)
|
||||
if (SecureArea == null)
|
||||
return;
|
||||
|
||||
// Point to the beginning of the secure area
|
||||
@@ -268,8 +274,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
int writeOffset = 0;
|
||||
|
||||
// Grab the first two blocks
|
||||
uint p0 = Model.SecureArea.ReadUInt32(ref readOffset);
|
||||
uint p1 = Model.SecureArea.ReadUInt32(ref readOffset);
|
||||
uint p0 = SecureArea.ReadUInt32(ref readOffset);
|
||||
uint p1 = SecureArea.ReadUInt32(ref readOffset);
|
||||
|
||||
// Perform the initialization steps
|
||||
Init1(tableData);
|
||||
@@ -286,8 +292,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
p1 = 0xE7FFDEFF;
|
||||
}
|
||||
|
||||
Model.SecureArea.Write(ref writeOffset, p0);
|
||||
Model.SecureArea.Write(ref writeOffset, p1);
|
||||
SecureArea.Write(ref writeOffset, p0);
|
||||
SecureArea.Write(ref writeOffset, p1);
|
||||
|
||||
// Ensure alignment
|
||||
readOffset = 0x08;
|
||||
@@ -297,13 +303,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
uint size = 0x800 - 8;
|
||||
while (size > 0)
|
||||
{
|
||||
p0 = Model.SecureArea.ReadUInt32(ref readOffset);
|
||||
p1 = Model.SecureArea.ReadUInt32(ref readOffset);
|
||||
p0 = SecureArea.ReadUInt32(ref readOffset);
|
||||
p1 = SecureArea.ReadUInt32(ref readOffset);
|
||||
|
||||
Decrypt(ref p1, ref p0);
|
||||
|
||||
Model.SecureArea.Write(ref writeOffset, p0);
|
||||
Model.SecureArea.Write(ref writeOffset, p1);
|
||||
SecureArea.Write(ref writeOffset, p0);
|
||||
SecureArea.Write(ref writeOffset, p1);
|
||||
|
||||
size -= 8;
|
||||
}
|
||||
@@ -341,15 +347,15 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool? CheckIfDecrypted(out string? message)
|
||||
{
|
||||
// Return empty if the secure area is undefined
|
||||
if (Model.SecureArea == null)
|
||||
if (SecureArea == null)
|
||||
{
|
||||
message = "Secure area is undefined. Cannot be encrypted or decrypted.";
|
||||
return null;
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
uint firstValue = Model.SecureArea.ReadUInt32(ref offset);
|
||||
uint secondValue = Model.SecureArea.ReadUInt32(ref offset);
|
||||
uint firstValue = SecureArea.ReadUInt32(ref offset);
|
||||
uint secondValue = SecureArea.ReadUInt32(ref offset);
|
||||
|
||||
// Empty secure area standard
|
||||
if (firstValue == 0x00000000 && secondValue == 0x00000000)
|
||||
@@ -439,7 +445,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
private void Init1(byte[] tableData)
|
||||
{
|
||||
Buffer.BlockCopy(tableData, 0, _cardHash, 0, 4 * (1024 + 18));
|
||||
_arg2 = [Model.CommonHeader!.GameCode, Model.CommonHeader.GameCode >> 1, Model.CommonHeader.GameCode << 1];
|
||||
_arg2 = [GameCode, GameCode >> 1, GameCode << 1];
|
||||
Init2();
|
||||
Init2();
|
||||
}
|
||||
|
||||
@@ -21,100 +21,32 @@ namespace SabreTools.Serialization.Wrappers
|
||||
#region Extension Properties
|
||||
|
||||
/// <summary>
|
||||
/// Header padding data, if it exists
|
||||
/// Dictionary of debug data
|
||||
/// </summary>
|
||||
public byte[]? HeaderPaddingData
|
||||
public Dictionary<int, object>? DebugData
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_headerPaddingData != null)
|
||||
return _headerPaddingData;
|
||||
// Use the cached data if possible
|
||||
if (_debugData != null && _debugData.Count != 0)
|
||||
return _debugData;
|
||||
|
||||
// TODO: Don't scan the known header data as well
|
||||
// If we have no resource table, just return
|
||||
if (DebugDirectoryTable == null || DebugDirectoryTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// If any required pieces are missing
|
||||
if (Model.Stub?.Header == null)
|
||||
return [];
|
||||
if (Model.SectionTable == null)
|
||||
return [];
|
||||
|
||||
// Populate the raw header padding data based on the source
|
||||
uint headerStartAddress = Model.Stub.Header.NewExeHeaderAddr;
|
||||
uint firstSectionAddress = uint.MaxValue;
|
||||
foreach (var s in Model.SectionTable)
|
||||
{
|
||||
if (s == null || s.PointerToRawData == 0)
|
||||
continue;
|
||||
if (s.PointerToRawData < headerStartAddress)
|
||||
continue;
|
||||
|
||||
if (s.PointerToRawData < firstSectionAddress)
|
||||
firstSectionAddress = s.PointerToRawData;
|
||||
}
|
||||
|
||||
// Check if the header length is more than 0 before reading data
|
||||
int headerLength = (int)(firstSectionAddress - headerStartAddress);
|
||||
if (headerLength <= 0)
|
||||
_headerPaddingData = [];
|
||||
else
|
||||
_headerPaddingData = ReadFromDataSource((int)headerStartAddress, headerLength);
|
||||
|
||||
// Cache and return the header padding data, even if null
|
||||
return _headerPaddingData;
|
||||
// Otherwise, build and return the cached dictionary
|
||||
ParseDebugTable();
|
||||
return _debugData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Header padding strings, if they exist
|
||||
/// </summary>
|
||||
public List<string>? HeaderPaddingStrings
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_headerPaddingStrings != null)
|
||||
return _headerPaddingStrings;
|
||||
|
||||
// TODO: Don't scan the known header data as well
|
||||
|
||||
// If any required pieces are missing
|
||||
if (Model.Stub?.Header == null)
|
||||
return [];
|
||||
if (Model.SectionTable == null)
|
||||
return [];
|
||||
|
||||
// Populate the header padding strings based on the source
|
||||
uint headerStartAddress = Model.Stub.Header.NewExeHeaderAddr;
|
||||
uint firstSectionAddress = uint.MaxValue;
|
||||
foreach (var s in Model.SectionTable)
|
||||
{
|
||||
if (s == null || s.PointerToRawData == 0)
|
||||
continue;
|
||||
if (s.PointerToRawData < headerStartAddress)
|
||||
continue;
|
||||
|
||||
if (s.PointerToRawData < firstSectionAddress)
|
||||
firstSectionAddress = s.PointerToRawData;
|
||||
}
|
||||
|
||||
// Check if the header length is more than 0 before reading strings
|
||||
int headerLength = (int)(firstSectionAddress - headerStartAddress);
|
||||
if (headerLength <= 0)
|
||||
_headerPaddingStrings = [];
|
||||
else
|
||||
_headerPaddingStrings = ReadStringsFromDataSource((int)headerStartAddress, headerLength, charLimit: 3);
|
||||
|
||||
// Cache and return the header padding data, even if null
|
||||
return _headerPaddingStrings;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <inheritdoc cref="Models.PortableExecutable.DebugTable.DebugDirectoryTable"/>
|
||||
public Models.PortableExecutable.DebugDirectoryEntry[]? DebugDirectoryTable
|
||||
=> Model.DebugTable?.DebugDirectoryTable;
|
||||
|
||||
/// <summary>
|
||||
/// Entry point data, if it exists
|
||||
@@ -156,6 +88,105 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Header padding data, if it exists
|
||||
/// </summary>
|
||||
public byte[]? HeaderPaddingData
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_headerPaddingData != null)
|
||||
return _headerPaddingData;
|
||||
|
||||
// TODO: Don't scan the known header data as well
|
||||
|
||||
// If any required pieces are missing
|
||||
if (Stub?.Header == null)
|
||||
return [];
|
||||
if (SectionTable == null)
|
||||
return [];
|
||||
|
||||
// Populate the raw header padding data based on the source
|
||||
uint headerStartAddress = Stub.Header.NewExeHeaderAddr;
|
||||
uint firstSectionAddress = uint.MaxValue;
|
||||
foreach (var s in SectionTable)
|
||||
{
|
||||
if (s == null || s.PointerToRawData == 0)
|
||||
continue;
|
||||
if (s.PointerToRawData < headerStartAddress)
|
||||
continue;
|
||||
|
||||
if (s.PointerToRawData < firstSectionAddress)
|
||||
firstSectionAddress = s.PointerToRawData;
|
||||
}
|
||||
|
||||
// Check if the header length is more than 0 before reading data
|
||||
int headerLength = (int)(firstSectionAddress - headerStartAddress);
|
||||
if (headerLength <= 0)
|
||||
_headerPaddingData = [];
|
||||
else
|
||||
_headerPaddingData = ReadFromDataSource((int)headerStartAddress, headerLength);
|
||||
|
||||
// Cache and return the header padding data, even if null
|
||||
return _headerPaddingData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Header padding strings, if they exist
|
||||
/// </summary>
|
||||
public List<string>? HeaderPaddingStrings
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_headerPaddingStrings != null)
|
||||
return _headerPaddingStrings;
|
||||
|
||||
// TODO: Don't scan the known header data as well
|
||||
|
||||
// If any required pieces are missing
|
||||
if (Stub?.Header == null)
|
||||
return [];
|
||||
if (SectionTable == null)
|
||||
return [];
|
||||
|
||||
// Populate the header padding strings based on the source
|
||||
uint headerStartAddress = Stub.Header.NewExeHeaderAddr;
|
||||
uint firstSectionAddress = uint.MaxValue;
|
||||
foreach (var s in SectionTable)
|
||||
{
|
||||
if (s == null || s.PointerToRawData == 0)
|
||||
continue;
|
||||
if (s.PointerToRawData < headerStartAddress)
|
||||
continue;
|
||||
|
||||
if (s.PointerToRawData < firstSectionAddress)
|
||||
firstSectionAddress = s.PointerToRawData;
|
||||
}
|
||||
|
||||
// Check if the header length is more than 0 before reading strings
|
||||
int headerLength = (int)(firstSectionAddress - headerStartAddress);
|
||||
if (headerLength <= 0)
|
||||
_headerPaddingStrings = [];
|
||||
else
|
||||
_headerPaddingStrings = ReadStringsFromDataSource((int)headerStartAddress, headerLength, charLimit: 3);
|
||||
|
||||
// Cache and return the header padding data, even if null
|
||||
return _headerPaddingStrings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Models.PortableExecutable.Executable.OptionalHeader"/>
|
||||
public Models.PortableExecutable.OptionalHeader? OptionalHeader => Model.OptionalHeader;
|
||||
|
||||
/// <summary>
|
||||
/// Address of the overlay, if it exists
|
||||
/// </summary>
|
||||
@@ -426,6 +457,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Models.PortableExecutable.Executable.SectionTable"/>
|
||||
public Models.PortableExecutable.SectionHeader[]? SectionTable => Model.SectionTable;
|
||||
|
||||
/// <inheritdoc cref="Models.PortableExecutable.Executable.Stub"/>
|
||||
public Models.MSDOS.Executable? Stub => Model.Stub;
|
||||
|
||||
/// <summary>
|
||||
/// Stub executable data, if it exists
|
||||
/// </summary>
|
||||
@@ -439,12 +476,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (_stubExecutableData != null)
|
||||
return _stubExecutableData;
|
||||
|
||||
if (Model.Stub?.Header?.NewExeHeaderAddr == null)
|
||||
if (Stub?.Header?.NewExeHeaderAddr == null)
|
||||
return null;
|
||||
|
||||
// Populate the raw stub executable data based on the source
|
||||
int endOfStubHeader = 0x40;
|
||||
int lengthOfStubExecutableData = (int)Model.Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
int lengthOfStubExecutableData = (int)Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
_stubExecutableData = ReadFromDataSource(endOfStubHeader, lengthOfStubExecutableData);
|
||||
|
||||
// Cache and return the stub executable data, even if null
|
||||
@@ -453,31 +490,6 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary of debug data
|
||||
/// </summary>
|
||||
public Dictionary<int, object>? DebugData
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_debugData != null && _debugData.Count != 0)
|
||||
return _debugData;
|
||||
|
||||
// If we have no resource table, just return
|
||||
if (Model.DebugTable?.DebugDirectoryTable == null
|
||||
|| Model.DebugTable.DebugDirectoryTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// Otherwise, build and return the cached dictionary
|
||||
ParseDebugTable();
|
||||
return _debugData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary of resource data
|
||||
/// </summary>
|
||||
@@ -1003,13 +1015,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
private void ParseDebugTable()
|
||||
{
|
||||
// If there is no debug table
|
||||
if (Model.DebugTable?.DebugDirectoryTable == null)
|
||||
if (DebugDirectoryTable == null || DebugDirectoryTable.Length == 0)
|
||||
return;
|
||||
|
||||
// Loop through all debug table entries
|
||||
for (int i = 0; i < Model.DebugTable.DebugDirectoryTable.Length; i++)
|
||||
for (int i = 0; i < DebugDirectoryTable.Length; i++)
|
||||
{
|
||||
var entry = Model.DebugTable.DebugDirectoryTable[i];
|
||||
var entry = DebugDirectoryTable[i];
|
||||
uint address = entry.PointerToRawData;
|
||||
uint size = entry.SizeOfData;
|
||||
|
||||
@@ -1446,19 +1458,19 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public int FindEntryPointSectionIndex()
|
||||
{
|
||||
// If the section table is missing
|
||||
if (Model.SectionTable == null)
|
||||
if (SectionTable == null)
|
||||
return -1;
|
||||
|
||||
// If the address is missing
|
||||
if (Model.OptionalHeader?.AddressOfEntryPoint == null)
|
||||
if (OptionalHeader?.AddressOfEntryPoint == null)
|
||||
return -1;
|
||||
|
||||
// If we don't have an entry point
|
||||
if (Model.OptionalHeader.AddressOfEntryPoint.ConvertVirtualAddress(Model.SectionTable) == 0)
|
||||
if (OptionalHeader.AddressOfEntryPoint.ConvertVirtualAddress(SectionTable) == 0)
|
||||
return -1;
|
||||
|
||||
// Otherwise, find the section it exists within
|
||||
return Model.OptionalHeader.AddressOfEntryPoint.ContainingSectionIndex(Model.SectionTable);
|
||||
return OptionalHeader.AddressOfEntryPoint.ContainingSectionIndex(SectionTable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1470,7 +1482,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public Models.PortableExecutable.SectionHeader? GetFirstSection(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || SectionNames.Length == 0 || Model.SectionTable == null || Model.SectionTable.Length == 0)
|
||||
if (SectionNames == null || SectionNames.Length == 0 || SectionTable == null || SectionTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1483,7 +1495,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return null;
|
||||
|
||||
// Return the section
|
||||
return Model.SectionTable[index];
|
||||
return SectionTable[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1495,7 +1507,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public Models.PortableExecutable.SectionHeader? GetLastSection(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || SectionNames.Length == 0 || Model.SectionTable == null || Model.SectionTable.Length == 0)
|
||||
if (SectionNames == null || SectionNames.Length == 0 || SectionTable == null || SectionTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1508,7 +1520,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return null;
|
||||
|
||||
// Return the section
|
||||
return Model.SectionTable[index];
|
||||
return SectionTable[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1519,15 +1531,15 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public Models.PortableExecutable.SectionHeader? GetSection(int index)
|
||||
{
|
||||
// If we have no sections
|
||||
if (Model.SectionTable == null || Model.SectionTable.Length == 0)
|
||||
if (SectionTable == null || SectionTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
if (index < 0 || index >= Model.SectionTable.Length)
|
||||
if (index < 0 || index >= SectionTable.Length)
|
||||
return null;
|
||||
|
||||
// Return the section
|
||||
return Model.SectionTable[index];
|
||||
return SectionTable[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1539,7 +1551,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public byte[]? GetFirstSectionData(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || SectionNames.Length == 0 || Model.SectionTable == null || Model.SectionTable.Length == 0)
|
||||
if (SectionNames == null || SectionNames.Length == 0 || SectionTable == null || SectionTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1560,7 +1572,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public byte[]? GetLastSectionData(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || SectionNames.Length == 0 || Model.SectionTable == null || Model.SectionTable.Length == 0)
|
||||
if (SectionNames == null || SectionNames.Length == 0 || SectionTable == null || SectionTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1580,19 +1592,19 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public byte[]? GetSectionData(int index)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || SectionNames.Length == 0 || Model.SectionTable == null || Model.SectionTable.Length == 0)
|
||||
if (SectionNames == null || SectionNames.Length == 0 || SectionTable == null || SectionTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
if (index < 0 || index >= Model.SectionTable.Length)
|
||||
if (index < 0 || index >= SectionTable.Length)
|
||||
return null;
|
||||
|
||||
// Get the section data from the table
|
||||
var section = Model.SectionTable[index];
|
||||
var section = SectionTable[index];
|
||||
if (section == null)
|
||||
return null;
|
||||
|
||||
uint address = section.VirtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
uint address = section.VirtualAddress.ConvertVirtualAddress(SectionTable);
|
||||
if (address == 0)
|
||||
return null;
|
||||
|
||||
@@ -1625,7 +1637,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public List<string>? GetFirstSectionStrings(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || SectionNames.Length == 0 || Model.SectionTable == null || Model.SectionTable.Length == 0)
|
||||
if (SectionNames == null || SectionNames.Length == 0 || SectionTable == null || SectionTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1646,7 +1658,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public List<string>? GetLastSectionStrings(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || SectionNames.Length == 0 || Model.SectionTable == null || Model.SectionTable.Length == 0)
|
||||
if (SectionNames == null || SectionNames.Length == 0 || SectionTable == null || SectionTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1666,19 +1678,19 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public List<string>? GetSectionStrings(int index)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || SectionNames.Length == 0 || Model.SectionTable == null || Model.SectionTable.Length == 0)
|
||||
if (SectionNames == null || SectionNames.Length == 0 || SectionTable == null || SectionTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
if (index < 0 || index >= Model.SectionTable.Length)
|
||||
if (index < 0 || index >= SectionTable.Length)
|
||||
return null;
|
||||
|
||||
// Get the section data from the table
|
||||
var section = Model.SectionTable[index];
|
||||
var section = SectionTable[index];
|
||||
if (section == null)
|
||||
return null;
|
||||
|
||||
uint address = section.VirtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
uint address = section.VirtualAddress.ConvertVirtualAddress(SectionTable);
|
||||
if (address == 0)
|
||||
return null;
|
||||
|
||||
@@ -1706,6 +1718,41 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#region Tables
|
||||
|
||||
/// <summary>
|
||||
/// Get the table based on index, if possible
|
||||
/// </summary>
|
||||
/// <param name="index">Index of the table to check for</param>
|
||||
/// <returns>Table on success, null on error</returns>
|
||||
public Models.PortableExecutable.DataDirectory? GetTable(int index)
|
||||
{
|
||||
// If the table doesn't exist
|
||||
if (OptionalHeader == null || index < 0 || index > 16)
|
||||
return null;
|
||||
|
||||
return index switch
|
||||
{
|
||||
1 => OptionalHeader.ExportTable,
|
||||
2 => OptionalHeader.ImportTable,
|
||||
3 => OptionalHeader.ResourceTable,
|
||||
4 => OptionalHeader.ExceptionTable,
|
||||
5 => OptionalHeader.CertificateTable,
|
||||
6 => OptionalHeader.BaseRelocationTable,
|
||||
7 => OptionalHeader.Debug,
|
||||
8 => null, // Architecture Table
|
||||
9 => OptionalHeader.GlobalPtr,
|
||||
10 => OptionalHeader.ThreadLocalStorageTable,
|
||||
11 => OptionalHeader.LoadConfigTable,
|
||||
12 => OptionalHeader.BoundImport,
|
||||
13 => OptionalHeader.ImportAddressTable,
|
||||
14 => OptionalHeader.DelayImportDescriptor,
|
||||
15 => OptionalHeader.CLRRuntimeHeader,
|
||||
16 => null, // Reserved
|
||||
|
||||
// Should never be possible
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the table data based on index, if possible
|
||||
/// </summary>
|
||||
@@ -1714,85 +1761,22 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public byte[]? GetTableData(int index)
|
||||
{
|
||||
// If the table doesn't exist
|
||||
if (Model.OptionalHeader == null || index < 0 || index > 16)
|
||||
if (OptionalHeader == null || index < 0 || index > 16)
|
||||
return null;
|
||||
|
||||
// Get the table from the optional header
|
||||
var table = GetTable(index);
|
||||
|
||||
// Get the virtual address and size from the entries
|
||||
uint virtualAddress = 0, size = 0;
|
||||
switch (index)
|
||||
{
|
||||
case 1:
|
||||
virtualAddress = Model.OptionalHeader.ExportTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ExportTable?.Size ?? 0;
|
||||
break;
|
||||
case 2:
|
||||
virtualAddress = Model.OptionalHeader.ImportTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ImportTable?.Size ?? 0;
|
||||
break;
|
||||
case 3:
|
||||
virtualAddress = Model.OptionalHeader.ResourceTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ResourceTable?.Size ?? 0;
|
||||
break;
|
||||
case 4:
|
||||
virtualAddress = Model.OptionalHeader.ExceptionTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ExceptionTable?.Size ?? 0;
|
||||
break;
|
||||
case 5:
|
||||
virtualAddress = Model.OptionalHeader.CertificateTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.CertificateTable?.Size ?? 0;
|
||||
break;
|
||||
case 6:
|
||||
virtualAddress = Model.OptionalHeader.BaseRelocationTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.BaseRelocationTable?.Size ?? 0;
|
||||
break;
|
||||
case 7:
|
||||
virtualAddress = Model.OptionalHeader.Debug?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.Debug?.Size ?? 0;
|
||||
break;
|
||||
case 8: // Architecture Table
|
||||
virtualAddress = 0;
|
||||
size = 0;
|
||||
break;
|
||||
case 9:
|
||||
virtualAddress = Model.OptionalHeader.GlobalPtr?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.GlobalPtr?.Size ?? 0;
|
||||
break;
|
||||
case 10:
|
||||
virtualAddress = Model.OptionalHeader.ThreadLocalStorageTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ThreadLocalStorageTable?.Size ?? 0;
|
||||
break;
|
||||
case 11:
|
||||
virtualAddress = Model.OptionalHeader.LoadConfigTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.LoadConfigTable?.Size ?? 0;
|
||||
break;
|
||||
case 12:
|
||||
virtualAddress = Model.OptionalHeader.BoundImport?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.BoundImport?.Size ?? 0;
|
||||
break;
|
||||
case 13:
|
||||
virtualAddress = Model.OptionalHeader.ImportAddressTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ImportAddressTable?.Size ?? 0;
|
||||
break;
|
||||
case 14:
|
||||
virtualAddress = Model.OptionalHeader.DelayImportDescriptor?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.DelayImportDescriptor?.Size ?? 0;
|
||||
break;
|
||||
case 15:
|
||||
virtualAddress = Model.OptionalHeader.CLRRuntimeHeader?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.CLRRuntimeHeader?.Size ?? 0;
|
||||
break;
|
||||
case 16: // Reserved
|
||||
virtualAddress = 0;
|
||||
size = 0;
|
||||
break;
|
||||
}
|
||||
uint virtualAddress = table?.VirtualAddress ?? 0;
|
||||
uint size = table?.Size ?? 0;
|
||||
|
||||
// If there is no section table
|
||||
if (Model.SectionTable == null)
|
||||
if (SectionTable == null)
|
||||
return null;
|
||||
|
||||
// Get the physical address from the virtual one
|
||||
uint address = virtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
uint address = virtualAddress.ConvertVirtualAddress(SectionTable);
|
||||
if (address == 0 || size == 0)
|
||||
return null;
|
||||
|
||||
@@ -1822,85 +1806,22 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public List<string>? GetTableStrings(int index)
|
||||
{
|
||||
// If the table doesn't exist
|
||||
if (Model.OptionalHeader == null || index < 0 || index > 16)
|
||||
if (OptionalHeader == null || index < 0 || index > 16)
|
||||
return null;
|
||||
|
||||
// Get the table from the optional header
|
||||
var table = GetTable(index);
|
||||
|
||||
// Get the virtual address and size from the entries
|
||||
uint virtualAddress = 0, size = 0;
|
||||
switch (index)
|
||||
{
|
||||
case 1:
|
||||
virtualAddress = Model.OptionalHeader.ExportTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ExportTable?.Size ?? 0;
|
||||
break;
|
||||
case 2:
|
||||
virtualAddress = Model.OptionalHeader.ImportTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ImportTable?.Size ?? 0;
|
||||
break;
|
||||
case 3:
|
||||
virtualAddress = Model.OptionalHeader.ResourceTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ResourceTable?.Size ?? 0;
|
||||
break;
|
||||
case 4:
|
||||
virtualAddress = Model.OptionalHeader.ExceptionTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ExceptionTable?.Size ?? 0;
|
||||
break;
|
||||
case 5:
|
||||
virtualAddress = Model.OptionalHeader.CertificateTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.CertificateTable?.Size ?? 0;
|
||||
break;
|
||||
case 6:
|
||||
virtualAddress = Model.OptionalHeader.BaseRelocationTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.BaseRelocationTable?.Size ?? 0;
|
||||
break;
|
||||
case 7:
|
||||
virtualAddress = Model.OptionalHeader.Debug?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.Debug?.Size ?? 0;
|
||||
break;
|
||||
case 8: // Architecture Table
|
||||
virtualAddress = 0;
|
||||
size = 0;
|
||||
break;
|
||||
case 9:
|
||||
virtualAddress = Model.OptionalHeader.GlobalPtr?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.GlobalPtr?.Size ?? 0;
|
||||
break;
|
||||
case 10:
|
||||
virtualAddress = Model.OptionalHeader.ThreadLocalStorageTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ThreadLocalStorageTable?.Size ?? 0;
|
||||
break;
|
||||
case 11:
|
||||
virtualAddress = Model.OptionalHeader.LoadConfigTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.LoadConfigTable?.Size ?? 0;
|
||||
break;
|
||||
case 12:
|
||||
virtualAddress = Model.OptionalHeader.BoundImport?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.BoundImport?.Size ?? 0;
|
||||
break;
|
||||
case 13:
|
||||
virtualAddress = Model.OptionalHeader.ImportAddressTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ImportAddressTable?.Size ?? 0;
|
||||
break;
|
||||
case 14:
|
||||
virtualAddress = Model.OptionalHeader.DelayImportDescriptor?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.DelayImportDescriptor?.Size ?? 0;
|
||||
break;
|
||||
case 15:
|
||||
virtualAddress = Model.OptionalHeader.CLRRuntimeHeader?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.CLRRuntimeHeader?.Size ?? 0;
|
||||
break;
|
||||
case 16: // Reserved
|
||||
virtualAddress = 0;
|
||||
size = 0;
|
||||
break;
|
||||
}
|
||||
uint virtualAddress = table?.VirtualAddress ?? 0;
|
||||
uint size = table?.Size ?? 0;
|
||||
|
||||
// If there is no section table
|
||||
if (Model.SectionTable == null)
|
||||
if (SectionTable == null)
|
||||
return null;
|
||||
|
||||
// Get the physical address from the virtual one
|
||||
uint address = virtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
uint address = virtualAddress.ConvertVirtualAddress(SectionTable);
|
||||
if (address == 0 || size == 0)
|
||||
return null;
|
||||
|
||||
|
||||
@@ -12,6 +12,22 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extension Properties
|
||||
|
||||
/// <inheritdoc cref="Archive.CompressedDataOffset"/>
|
||||
public long CompressedDataOffset => Model.CompressedDataOffset;
|
||||
|
||||
/// <inheritdoc cref="Header.FileCount"/>
|
||||
public ushort FileCount => Model.Header?.FileCount ?? 0;
|
||||
|
||||
/// <inheritdoc cref="Archive.FileList"/>
|
||||
public FileDescriptor[] FileList => Model.FileList ?? [];
|
||||
|
||||
/// <inheritdoc cref="Archive.Header"/>
|
||||
public Header? Header => Model.Header;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -76,19 +92,6 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extension Properties
|
||||
|
||||
/// <inheritdoc cref="Archive.CompressedDataOffset"/>
|
||||
public long CompressedDataOffset => Model.CompressedDataOffset;
|
||||
|
||||
/// <inheritdoc cref="Header.FileCount"/>
|
||||
public ushort FileCount => Model.Header?.FileCount ?? 0;
|
||||
|
||||
/// <inheritdoc cref="Archive.FileList"/>
|
||||
public FileDescriptor[] FileList => Model.FileList ?? [];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extraction
|
||||
|
||||
/// <summary>
|
||||
@@ -121,7 +124,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool ExtractFile(int index, string outputDirectory)
|
||||
{
|
||||
// If we have no files
|
||||
if (Model.Header == null || FileCount == 0 || FileList == null || FileList.Length == 0)
|
||||
if (Header == null || FileCount == 0 || FileList == null || FileList.Length == 0)
|
||||
return false;
|
||||
|
||||
// If we have an invalid index
|
||||
|
||||
@@ -12,6 +12,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extension Properties
|
||||
|
||||
/// <inheritdoc cref="VbspHeader.Lumps"/>
|
||||
public VbspLumpEntry[]? Lumps => Model.Header?.Lumps;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -86,12 +93,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool ExtractAllLumps(string outputDirectory)
|
||||
{
|
||||
// If we have no lumps
|
||||
if (Model.Header?.Lumps == null || Model.Header.Lumps.Length == 0)
|
||||
if (Lumps == null || Lumps.Length == 0)
|
||||
return false;
|
||||
|
||||
// Loop through and extract all lumps to the output
|
||||
bool allExtracted = true;
|
||||
for (int i = 0; i < Model.Header.Lumps.Length; i++)
|
||||
for (int i = 0; i < Lumps.Length; i++)
|
||||
{
|
||||
allExtracted &= ExtractLump(i, outputDirectory);
|
||||
}
|
||||
@@ -108,15 +115,15 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool ExtractLump(int index, string outputDirectory)
|
||||
{
|
||||
// If we have no lumps
|
||||
if (Model.Header?.Lumps == null || Model.Header.Lumps.Length == 0)
|
||||
if (Lumps == null || Lumps.Length == 0)
|
||||
return false;
|
||||
|
||||
// If the lumps index is invalid
|
||||
if (index < 0 || index >= Model.Header.Lumps.Length)
|
||||
if (index < 0 || index >= Lumps.Length)
|
||||
return false;
|
||||
|
||||
// Read the data
|
||||
var lump = Model.Header.Lumps[index];
|
||||
var lump = Lumps[index];
|
||||
var data = ReadFromDataSource(lump.Offset, lump.Length);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// Get the archive count
|
||||
ushort archiveCount = 0;
|
||||
foreach (var di in Model.DirectoryItems ?? [])
|
||||
foreach (var di in DirectoryItems ?? [])
|
||||
{
|
||||
if (di.DirectoryEntry == null)
|
||||
continue;
|
||||
@@ -71,6 +71,9 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Models.VPK.File.DirectoryItems"/>
|
||||
public Models.VPK.DirectoryItem[]? DirectoryItems => Model.DirectoryItems;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Variables
|
||||
@@ -156,12 +159,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool ExtractAll(string outputDirectory)
|
||||
{
|
||||
// If we have no directory items
|
||||
if (Model.DirectoryItems == null || Model.DirectoryItems.Length == 0)
|
||||
if (DirectoryItems == null || DirectoryItems.Length == 0)
|
||||
return false;
|
||||
|
||||
// Loop through and extract all files to the output
|
||||
bool allExtracted = true;
|
||||
for (int i = 0; i < Model.DirectoryItems.Length; i++)
|
||||
for (int i = 0; i < DirectoryItems.Length; i++)
|
||||
{
|
||||
allExtracted &= ExtractFile(i, outputDirectory);
|
||||
}
|
||||
@@ -178,15 +181,15 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool ExtractFile(int index, string outputDirectory)
|
||||
{
|
||||
// If we have no directory items
|
||||
if (Model.DirectoryItems == null || Model.DirectoryItems.Length == 0)
|
||||
if (DirectoryItems == null || DirectoryItems.Length == 0)
|
||||
return false;
|
||||
|
||||
// If the directory item index is invalid
|
||||
if (index < 0 || index >= Model.DirectoryItems.Length)
|
||||
if (index < 0 || index >= DirectoryItems.Length)
|
||||
return false;
|
||||
|
||||
// Get the directory item
|
||||
var directoryItem = Model.DirectoryItems[index];
|
||||
var directoryItem = DirectoryItems[index];
|
||||
if (directoryItem.DirectoryEntry == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -11,6 +11,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extension Properties
|
||||
|
||||
/// <inheritdoc cref="Models.WAD3.File.DirEntries"/>
|
||||
public Models.WAD3.DirEntry[]? DirEntries => Model.DirEntries;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -85,12 +92,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool ExtractAllLumps(string outputDirectory)
|
||||
{
|
||||
// If we have no lumps
|
||||
if (Model.DirEntries == null || Model.DirEntries.Length == 0)
|
||||
if (DirEntries == null || DirEntries.Length == 0)
|
||||
return false;
|
||||
|
||||
// Loop through and extract all lumps to the output
|
||||
bool allExtracted = true;
|
||||
for (int i = 0; i < Model.DirEntries.Length; i++)
|
||||
for (int i = 0; i < DirEntries.Length; i++)
|
||||
{
|
||||
allExtracted &= ExtractLump(i, outputDirectory);
|
||||
}
|
||||
@@ -107,15 +114,15 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool ExtractLump(int index, string outputDirectory)
|
||||
{
|
||||
// If we have no lumps
|
||||
if (Model.DirEntries == null || Model.DirEntries.Length == 0)
|
||||
if (DirEntries == null || DirEntries.Length == 0)
|
||||
return false;
|
||||
|
||||
// If the lumps index is invalid
|
||||
if (index < 0 || index >= Model.DirEntries.Length)
|
||||
if (index < 0 || index >= DirEntries.Length)
|
||||
return false;
|
||||
|
||||
// Read the data -- TODO: Handle uncompressed lumps (see BSP.ExtractTexture)
|
||||
var lump = Model.DirEntries[index];
|
||||
var lump = DirEntries[index];
|
||||
var data = ReadFromDataSource((int)lump.Offset, (int)lump.Length);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
@@ -12,6 +12,16 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extension Properties
|
||||
|
||||
/// <inheritdoc cref="Models.XZP.File.DirectoryEntries"/>
|
||||
public Models.XZP.DirectoryEntry[]? DirectoryEntries => Model.DirectoryEntries;
|
||||
|
||||
/// <inheritdoc cref="Models.XZP.File.DirectoryItems"/>
|
||||
public Models.XZP.DirectoryItem[]? DirectoryItems => Model.DirectoryItems;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -86,12 +96,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool ExtractAll(string outputDirectory)
|
||||
{
|
||||
// If we have no directory entries
|
||||
if (Model.DirectoryEntries == null || Model.DirectoryEntries.Length == 0)
|
||||
if (DirectoryEntries == null || DirectoryEntries.Length == 0)
|
||||
return false;
|
||||
|
||||
// Loop through and extract all files to the output
|
||||
bool allExtracted = true;
|
||||
for (int i = 0; i < Model.DirectoryEntries.Length; i++)
|
||||
for (int i = 0; i < DirectoryEntries.Length; i++)
|
||||
{
|
||||
allExtracted &= ExtractFile(i, outputDirectory);
|
||||
}
|
||||
@@ -108,20 +118,20 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public bool ExtractFile(int index, string outputDirectory)
|
||||
{
|
||||
// If we have no directory entries
|
||||
if (Model.DirectoryEntries == null || Model.DirectoryEntries.Length == 0)
|
||||
if (DirectoryEntries == null || DirectoryEntries.Length == 0)
|
||||
return false;
|
||||
|
||||
// If we have no directory items
|
||||
if (Model.DirectoryItems == null || Model.DirectoryItems.Length == 0)
|
||||
if (DirectoryItems == null || DirectoryItems.Length == 0)
|
||||
return false;
|
||||
|
||||
// If the directory entry index is invalid
|
||||
if (index < 0 || index >= Model.DirectoryEntries.Length)
|
||||
if (index < 0 || index >= DirectoryEntries.Length)
|
||||
return false;
|
||||
|
||||
// Get the associated directory item
|
||||
var directoryEntry = Model.DirectoryEntries[index];
|
||||
var directoryItem = Array.Find(Model.DirectoryItems, di => di?.FileNameCRC == directoryEntry.FileNameCRC);
|
||||
var directoryEntry = DirectoryEntries[index];
|
||||
var directoryItem = Array.Find(DirectoryItems, di => di?.FileNameCRC == directoryEntry.FileNameCRC);
|
||||
if (directoryItem == null)
|
||||
return false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user