Add BOS models

This commit is contained in:
Matt Nadareski
2023-09-04 00:11:04 -04:00
parent 68c6f9d61f
commit 1055187865
373 changed files with 23931 additions and 0 deletions

13
AACS/CopyrightRecord.cs Normal file
View File

@@ -0,0 +1,13 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <summary>
/// This record type is undocumented but found in real media key blocks
/// </summary>
public sealed class CopyrightRecord : Record
{
/// <summary>
/// Null-terminated ASCII string representing the copyright
/// </summary>
public string Copyright;
}
}

View File

@@ -0,0 +1,21 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class DriveRevocationListEntry
{
/// <summary>
/// A 2-byte Range value indicates the range of revoked IDs starting
/// from the ID contained in the record. A value of zero in the Range
/// field indicates that only one ID is being revoked, a value of one
/// in the Range field indicates two IDs are being revoked, and so on.
/// </summary>
public ushort Range;
/// <summary>
/// A 6-byte Drive ID value identifying the Licensed Drive being revoked
/// (or the first in a range of Licensed Drives being revoked, in the
/// case of a non-zero Range value).
/// </summary>
public byte[] DriveID;
}
}

View File

@@ -0,0 +1,26 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <summary>
/// A properly formatted type 3 or type 4 Media Key Block contains exactly
/// one Drive Revocation List Record. It follows the Host Revocation List
/// Record, although it may not immediately follow it.
///
/// The Drive Revocation List Record is identical to the Host Revocation
/// List Record, except it has type 2016, and it contains Drive Revocation
/// List Entries, not Host Revocation List Entries. The Drive Revocation List
/// Entries refer to Drive IDs in the Drive Certificates.
/// </summary>
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class DriveRevocationListRecord : Record
{
/// <summary>
/// The total number of Drive Revocation List Entry fields that follow.
/// </summary>
public uint TotalNumberOfEntries;
/// <summary>
/// Revocation list entries
/// </summary>
public DriveRevocationSignatureBlock[] SignatureBlocks;
}
}

View File

@@ -0,0 +1,17 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class DriveRevocationSignatureBlock
{
/// <summary>
/// The number of Drive Revocation List Entry fields in the signature block.
/// </summary>
public uint NumberOfEntries;
/// <summary>
/// A list of 8-byte Host Drive List Entry fields, the length of this
/// list being equal to the number in the signature block.
/// </summary>
public DriveRevocationListEntry[] EntryFields;
}
}

View File

@@ -0,0 +1,23 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <summary>
/// A properly formatted MKB shall contain an End of Media Key Block Record.
/// When a device encounters this Record it stops processing the MKB, using
/// whatever Km value it has calculated up to that point as the final Km for
/// that MKB (pending possible checks for correctness of the key, as
/// described previously).
/// </summary>
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class EndOfMediaKeyBlockRecord : Record
{
/// <summary>
/// AACS LAs signature on the data in the Media Key Block up to,
/// but not including, this record. Devices depending on the Version
/// Number in the Type and Version Record must verify the signature.
/// Other devices may ignore the signature data. If any device
/// determines that the signature does not verify or is omitted, it
/// must refuse to use the Media Key.
/// </summary>
public byte[] SignatureData;
}
}

46
AACS/Enums.cs Normal file
View File

@@ -0,0 +1,46 @@
namespace BinaryObjectScanner.Models.AACS
{
public enum MediaKeyBlockType : uint
{
/// <summary>
/// (Type 3). This is a normal Media Key Block suitable for being recorded
/// on a AACS Recordable Media. Both Class I and Class II Licensed Products
/// use it to directly calculate the Media Key.
/// </summary>
Type3 = 0x00031003,
/// <summary>
/// (Type 4). This is a Media Key Block that has been designed to use Key
/// Conversion Data (KCD). Thus, it is suitable only for pre-recorded media
/// from which the KCD is derived. Both Class I and Class II Licensed Products
/// use it to directly calculate the Media Key.
/// </summary>
Type4 = 0x00041003,
/// <summary>
/// (Type 10). This is a Class II Media Key Block (one that has the functionality
/// of a Sequence Key Block). This can only be processed by Class II Licensed
/// Products; Class I Licensed Products are revoked in Type 10 Media Key Blocks
/// and cannot process them. This type does not contain the Host Revocation List
/// Record, the Drive Revocation List Record, and the Media Key Data Record, as
/// described in the following sections. It does contain the records shown in
/// Section 3.2.5.2, which are only processed by Class II Licensed Products.
/// </summary>
Type10 = 0x000A1003,
}
public enum RecordType : byte
{
EndOfMediaKeyBlock = 0x02,
ExplicitSubsetDifference = 0x04,
MediaKeyData = 0x05,
SubsetDifferenceIndex = 0x07,
TypeAndVersion = 0x10,
DriveRevocationList = 0x20,
HostRevocationList = 0x21,
VerifyMediaKey = 0x81,
// Not documented
Copyright = 0x7F,
}
}

View File

@@ -0,0 +1,11 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class ExplicitSubsetDifferenceRecord : Record
{
/// <summary>
/// In this record, each subset-difference is encoded with 5 bytes.
/// </summary>
public SubsetDifference[] SubsetDifferences;
}
}

View File

@@ -0,0 +1,21 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class HostRevocationListEntry
{
/// <summary>
/// A 2-byte Range value indicates the range of revoked IDs starting
/// from the ID contained in the record. A value of zero in the Range
/// field indicates that only one ID is being revoked, a value of one
/// in the Range field indicates two IDs are being revoked, and so on.
/// </summary>
public ushort Range;
/// <summary>
/// A 6-byte Host ID value identifying the host being revoked (or the
/// first in a range of hosts being revoked, in the case of a non-zero
/// Range value).
/// </summary>
public byte[] HostID;
}
}

View File

@@ -0,0 +1,29 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <summary>
/// A properly formatted type 3 or type 4 Media Key Block shall have exactly
/// one Host Revocation List Record as its second record. This record provides
/// a list of hosts that have been revoked by the AACS LA. The AACS specification
/// is applicable to PC-based system where a Licensed Drive and PC Host act
/// together as the Recording Device and/or Playback Device for AACS Content.
/// AACS uses a drive-host authentication protocol for the host to verify the
/// integrity of the data received from the Licensed Drive, and for the Licensed
/// Drive to check the validity of the host application. The Type and Version
/// Record and the Host Revocation List Record are guaranteed to be the first two
/// records of a Media Key Block, to make it easier for Licensed Drives to extract
/// this data from an arbitrary Media Key Block.
/// </summary>
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class HostRevocationListRecord : Record
{
/// <summary>
/// The total number of Host Revocation List Entry fields that follow.
/// </summary>
public uint TotalNumberOfEntries;
/// <summary>
/// Revocation list entries
/// </summary>
public HostRevocationSignatureBlock[] SignatureBlocks;
}
}

View File

@@ -0,0 +1,17 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class HostRevocationSignatureBlock
{
/// <summary>
/// The number of Host Revocation List Entry fields in the signature block.
/// </summary>
public uint NumberOfEntries;
/// <summary>
/// A list of 8-byte Host Revocation List Entry fields, the length of this
/// list being equal to the number in the signature block.
/// </summary>
public HostRevocationListEntry[] EntryFields;
}
}

14
AACS/MediaKeyBlock.cs Normal file
View File

@@ -0,0 +1,14 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <summary>
/// A Media Key Block is formatted as a sequence of contiguous Records.
/// </summary>
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class MediaKeyBlock
{
/// <summary>
/// Records
/// </summary>
public Record[] Records { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <summary>
/// This record gives the associated encrypted media key data for the
/// subset-differences identified in the Explicit Subset-Difference Record.
/// </summary>
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class MediaKeyDataRecord : Record
{
/// <summary>
/// Each subset difference has its associated 16 bytes in this
/// record, in the same order it is encountered in the subset-difference
/// record. This 16 bytes is the ciphertext value C in the media
/// key calculation.
/// </summary>
public byte[][] MediaKeyData;
}
}

28
AACS/Record.cs Normal file
View File

@@ -0,0 +1,28 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <summary>
/// Each Record begins with a one-byte Record Type field, followed by a
/// three-byte Record Length field.
///
/// The following subsections describe the currently defined Record types,
/// and how a device processes each. All multi-byte integers, including
/// the length field, are “Big Endian”; in other words, the most significant
/// byte comes first in the record.
/// </summary>
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public abstract class Record
{
/// <summary>
/// The Record Type field value indicates the type of the Record.
/// </summary>
public RecordType RecordType;
/// <summary>
/// The Record Length field value indicates the number of bytes in
/// the Record, including the Record Type and the Record Length
/// fields themselves. Record lengths are always multiples of 4 bytes.
/// </summary>
// <remarks>UInt24 not UInt32</remarks>
public uint RecordLength;
}
}

20
AACS/SubsetDifference.cs Normal file
View File

@@ -0,0 +1,20 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class SubsetDifference
{
/// <summary>
/// The mask for u is given by the first byte. That byte is
/// treated as a number, the number of low-order 0-bits in
/// the mask. For example, the value 0x01 denotes a mask of
/// 0xFFFFFFFE; value 0x0A denotes a mask of 0xFFFFFC00.
/// </summary>
public byte Mask;
/// <summary>
/// The last 4 bytes are the uv number, most significant
/// byte first.
/// </summary>
public uint Number;
}
}

View File

@@ -0,0 +1,26 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <summary>
/// This is a speed-up record which can be ignored by devices not wishing to
/// take advantage of it. It is a lookup table which allows devices to quickly
/// find their subset-difference in the Explicit Subset-Difference record,
/// without processing the entire record. This Subset-Difference Index record
/// is always present, and always precedes the Explicit Subset-Difference record
/// in the MKB, although it does not necessarily immediately precede it.
/// </summary>
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class SubsetDifferenceIndexRecord : Record
{
/// <summary>
/// The number of devices per index offset.
/// </summary>
public uint Span;
/// <summary>
/// These offsets refer to the offset within the following Explicit
/// Subset-Difference record, with 0 being the start of the record.
/// </summary>
// <remarks>UInt24 not UInt32</remarks>
public uint[] Offsets;
}
}

View File

@@ -0,0 +1,32 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <summary>
/// Devices, except for recording devices which are writing Media Key Block
/// Extensions, may ignore this record. Recording devices shall verify the
/// signature (see End of Media Key Block record) and use the Version Number
/// in this record to determine if a new Media Key BLock Extension is, in
/// fact, more recent than the Media Key Block Extension that is currently
/// on the media.
/// </summary>
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class TypeAndVersionRecord : Record
{
/// <summary>
/// For AACS applications, the MKBType field is one of three values.
/// It is not an error for a Type 3 Media Key Block to be used for
/// controlling access to AACS Content on pre- recorded media. In
/// this case, the device shall not use the KCD.
/// </summary>
public MediaKeyBlockType MediaKeyBlockType;
/// <summary>
/// The Version Number is a 32-bit unsigned integer. Each time the
/// licensing agency changes the revocation, it increments the version
/// number and inserts the new value in subsequent Media Key Blocks.
/// Thus, larger values indicate more recent Media Key Blocks. The
/// Version Numbers begin at 1; 0 is a special value used for test
/// Media Key Blocks.
/// </summary>
public uint VersionNumber;
}
}

View File

@@ -0,0 +1,24 @@
namespace BinaryObjectScanner.Models.AACS
{
/// <summary>
/// A properly formatted MKB shall have exactly one Verify Media Key Record
/// as its first record. The presence of the Verify Media Key Record in an MKB
/// is mandatory, but the use of the Record by a device is not mandatory. The
/// device may use the Verify Media Key Record to verify the correctness of a
/// given MKB, or of its processing of it. If everything is correct, the device
/// should observe the condition:
/// [AES_128D(vKm, C]msb_64 == 0x0123456789ABCDEF)]
/// where Km is the Media Key value.
/// </summary>
/// <see href="https://aacsla.com/wp-content/uploads/2019/02/AACS_Spec_Common_Final_0953.pdf"/>
public sealed class VerifyMediaKeyRecord : Record
{
/// <summary>
/// Bytes 4 through 19 of the Record contain the ciphertext value
/// Cv = AES-128E (Km, 0x0123456789ABCDEF || 0xXXXXXXXXXXXXXXXX)
/// where 0xXXXXXXXXXXXXXXXX is an arbitrary 8-byte value, and Km is
/// the correct final Media Key value.
/// </summary>
public byte[] CiphertextValue;
}
}

7
BDPlus/Constants.cs Normal file
View File

@@ -0,0 +1,7 @@
namespace BinaryObjectScanner.Models.BDPlus
{
public static class Constants
{
public const string SignatureString = "BDSVM_CC";
}
}

46
BDPlus/SVM.cs Normal file
View File

@@ -0,0 +1,46 @@
namespace BinaryObjectScanner.Models.BDPlus
{
/// <see href="https://github.com/mwgoldsmith/bdplus/blob/master/src/libbdplus/bdsvm/loader.c"/>
public sealed class SVM
{
/// <summary>
/// "BDSVM_CC"
/// </summary>
public string Signature;
/// <summary>
/// 5 bytes of unknown data
/// </summary>
public byte[] Unknown1;
/// <summary>
/// Version year
/// </summary>
public ushort Year;
/// <summary>
/// Version month
/// </summary>
public byte Month;
/// <summary>
/// Version day
/// </summary>
public byte Day;
/// <summary>
/// 4 bytes of unknown data
/// </summary>
public byte[] Unknown2;
/// <summary>
/// Length
/// </summary>
public uint Length;
/// <summary>
/// Length bytes of data
/// </summary>
public byte[] Data;
}
}

19
BFPK/Archive.cs Normal file
View File

@@ -0,0 +1,19 @@
namespace BinaryObjectScanner.Models.BFPK
{
/// <summary>
/// BFPK custom archive format
/// </summary>
/// <see cref="https://forum.xentax.com/viewtopic.php?t=5102"/>
public sealed class Archive
{
/// <summary>
/// Header
/// </summary>
public Header Header { get; set; }
/// <summary>
/// Files
/// </summary>
public FileEntry[] Files { get; set; }
}
}

11
BFPK/Constants.cs Normal file
View File

@@ -0,0 +1,11 @@
namespace BinaryObjectScanner.Models.BFPK
{
public static class Constants
{
public static readonly byte[] SignatureBytes = new byte[] { 0x42, 0x46, 0x50, 0x4b };
public const string SignatureString = "BFPK";
public const uint SignatureUInt32 = 0x4b504642;
}
}

34
BFPK/FileEntry.cs Normal file
View File

@@ -0,0 +1,34 @@
namespace BinaryObjectScanner.Models.BFPK
{
/// <summary>
/// File entry
/// </summary>
/// <see cref="https://forum.xentax.com/viewtopic.php?t=5102"/>
public sealed class FileEntry
{
/// <summary>
/// Name size
/// </summary>
public int NameSize;
/// <summary>
/// Name
/// </summary>
public string Name;
/// <summary>
/// Uncompressed size
/// </summary>
public int UncompressedSize;
/// <summary>
/// Offset
/// </summary>
public int Offset;
/// <summary>
/// Compressed size
/// </summary>
public int CompressedSize;
}
}

27
BFPK/Header.cs Normal file
View File

@@ -0,0 +1,27 @@
using System.Runtime.InteropServices;
namespace BinaryObjectScanner.Models.BFPK
{
/// <summary>
/// Header
/// </summary>
/// <see cref="https://forum.xentax.com/viewtopic.php?t=5102"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Header
{
/// <summary>
/// "BFPK"
/// </summary>
public string Magic;
/// <summary>
/// Version
/// </summary>
public int Version;
/// <summary>
/// Files
/// </summary>
public int Files;
}
}

35
BMP/BITMAPFILEHEADER.cs Normal file
View File

@@ -0,0 +1,35 @@
namespace BinaryObjectScanner.Models.BMP
{
/// <summary>
/// The BITMAPFILEHEADER structure contains information about the type, size,
/// and layout of a file that contains a DIB.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapfileheader"/>
public sealed class BITMAPFILEHEADER
{
/// <summary>
/// The file type; must be BM.
/// </summary>
public ushort Type;
/// <summary>
/// The size, in bytes, of the bitmap file.
/// </summary>
public uint Size;
/// <summary>
/// Reserved; must be zero.
/// </summary>
public ushort Reserved1;
/// <summary>
/// Reserved; must be zero.
/// </summary>
public ushort Reserved2;
/// <summary>
/// The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.
/// </summary>
public uint OffBits;
}
}

94
BMP/BITMAPINFOHEADER.cs Normal file
View File

@@ -0,0 +1,94 @@
namespace BinaryObjectScanner.Models.BMP
{
/// <summary>
/// The BITMAPINFOHEADER structure contains information about the dimensions and
/// color format of a device-independent bitmap (DIB).
/// </summary>
public sealed class BITMAPINFOHEADER
{
/// <summary>
/// Specifies the number of bytes required by the structure. This value does
/// not include the size of the color table or the size of the color masks,
/// if they are appended to the end of structure.
/// </summary>
public uint Size;
/// <summary>
/// Specifies the width of the bitmap, in pixels.
/// </summary>
public int Width;
/// <summary>
/// Specifies the height of the bitmap, in pixels.
/// - For uncompressed RGB bitmaps, if biHeight is positive, the bitmap is a
/// bottom-up DIB with the origin at the lower left corner. If biHeight is
/// negative, the bitmap is a top-down DIB with the origin at the upper left
/// corner.
/// - For YUV bitmaps, the bitmap is always top-down, regardless of the sign of
/// biHeight. Decoders should offer YUV formats with positive biHeight, but for
/// backward compatibility they should accept YUV formats with either positive
/// or negative biHeight.
/// - For compressed formats, biHeight must be positive, regardless of image orientation.
/// </summary>
public int Height;
/// <summary>
/// Specifies the number of planes for the target device. This value must be set to 1.
/// </summary>
public ushort Planes;
/// <summary>
/// Specifies the number of bits per pixel (bpp). For uncompressed formats, this value
/// is the average number of bits per pixel. For compressed formats, this value is the
/// implied bit depth of the uncompressed image, after the image has been decoded.
/// </summary>
public ushort BitCount;
/// <summary>
/// For compressed video and YUV formats, this member is a FOURCC code, specified as a
/// DWORD in little-endian order. For example, YUYV video has the FOURCC 'VYUY' or
/// 0x56595559. For more information, see FOURCC Codes.
///
/// For uncompressed RGB formats, the following values are possible:
/// - BI_RGB: Uncompressed RGB.
/// - BI_BITFIELDS: Uncompressed RGB with color masks. Valid for 16-bpp and 32-bpp bitmaps.
///
/// Note that BI_JPG and BI_PNG are not valid video formats.
///
/// For 16-bpp bitmaps, if biCompression equals BI_RGB, the format is always RGB 555.
/// If biCompression equals BI_BITFIELDS, the format is either RGB 555 or RGB 565. Use
/// the subtype GUID in the AM_MEDIA_TYPE structure to determine the specific RGB type.
/// </summary>
public uint Compression;
/// <summary>
/// Specifies the size, in bytes, of the image. This can be set to 0 for uncompressed
/// RGB bitmaps.
/// </summary>
public uint SizeImage;
/// <summary>
/// Specifies the horizontal resolution, in pixels per meter, of the target device for
/// the bitmap.
/// </summary>
public int XPelsPerMeter;
/// <summary>
/// Specifies the vertical resolution, in pixels per meter, of the target device for
/// the bitmap.
/// </summary>
public int YPelsPerMeter;
/// <summary>
/// Specifies the number of color indices in the color table that are actually used by
/// the bitmap.
/// </summary>
public uint ClrUsed;
/// <summary>
/// Specifies the number of color indices that are considered important for displaying
/// the bitmap. If this value is zero, all colors are important.
/// </summary>
public uint ClrImportant;
}
}

25
BSP/Constants.cs Normal file
View File

@@ -0,0 +1,25 @@
namespace BinaryObjectScanner.Models.BSP
{
public static class Constants
{
/// <summary>
/// Number of lumps in a BSP
/// </summary>
public const int HL_BSP_LUMP_COUNT = 15;
/// <summary>
/// Index for the entities lump
/// </summary>
public const int HL_BSP_LUMP_ENTITIES = 0;
/// <summary>
/// Index for the texture data lump
/// </summary>
public const int HL_BSP_LUMP_TEXTUREDATA = 2;
/// <summary>
/// Number of valid mipmap levels
/// </summary>
public const int HL_BSP_MIPMAP_COUNT = 4;
}
}

29
BSP/File.cs Normal file
View File

@@ -0,0 +1,29 @@
namespace BinaryObjectScanner.Models.BSP
{
/// <summary>
/// Half-Life Level
/// </summary>
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
public sealed class File
{
/// <summary>
/// Header data
/// </summary>
public Header Header { get; set; }
/// <summary>
/// Lumps
/// </summary>
public Lump[] Lumps { get; set; }
/// <summary>
/// Texture header data
/// </summary>
public TextureHeader TextureHeader { get; set; }
/// <summary>
/// Textures
/// </summary>
public Texture[] Textures { get; set; }
}
}

11
BSP/Header.cs Normal file
View File

@@ -0,0 +1,11 @@
namespace BinaryObjectScanner.Models.BSP
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
public sealed class Header
{
/// <summary>
/// Version
/// </summary>
public uint Version;
}
}

16
BSP/Lump.cs Normal file
View File

@@ -0,0 +1,16 @@
namespace BinaryObjectScanner.Models.BSP
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
public sealed class Lump
{
/// <summary>
/// Offset
/// </summary>
public uint Offset;
/// <summary>
/// Length
/// </summary>
public uint Length;
}
}

41
BSP/Texture.cs Normal file
View File

@@ -0,0 +1,41 @@
namespace BinaryObjectScanner.Models.BSP
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
public sealed class Texture
{
/// <summary>
/// Name
/// </summary>
public string Name;
/// <summary>
/// Width
/// </summary>
public uint Width;
/// <summary>
/// Height
/// </summary>
public uint Height;
/// <summary>
/// Offsets
/// </summary>
public uint[] Offsets;
/// <summary>
/// Texture data
/// </summary>
public byte[] TextureData;
/// <summary>
/// Palette size
/// </summary>
public uint PaletteSize;
/// <summary>
/// Palette data
/// </summary>
public byte[] PaletteData;
}
}

16
BSP/TextureHeader.cs Normal file
View File

@@ -0,0 +1,16 @@
namespace BinaryObjectScanner.Models.BSP
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
public sealed class TextureHeader
{
/// <summary>
/// Texture count
/// </summary>
public uint TextureCount;
/// <summary>
/// Offsets
/// </summary>
public uint[] Offsets;
}
}

92
CFB/Binary.cs Normal file
View File

@@ -0,0 +1,92 @@
namespace BinaryObjectScanner.Models.CFB
{
/// <summary>
/// Microsoft Compound File Binary (CFB) file format, also known as the
/// Object Linking and Embedding (OLE) or Component Object Model (COM)
/// structured storage compound file implementation binary file format.
/// This structure name can be shortened to compound file.
/// </summary>
/// <see href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-CFB/%5bMS-CFB%5d.pdf"/>
public sealed class Binary
{
/// <summary>
/// Compound file header
/// </summary>
public FileHeader Header { get; set; }
/// <summary>
/// The FAT is the main allocator for space within a compound file.
/// Every sector in the file is represented within the FAT in some
/// fashion, including those sectors that are unallocated (free).
/// The FAT is a sector chain that is made up of one or more FAT sectors.
/// </summary>
/// <remarks>
/// If Header Major Version is 3, there MUST be 128 fields specified to fill a 512-byte sector.
///
/// If Header Major Version is 4, there MUST be 1,024 fields specified to fill a 4,096-byte sector
/// </remarks>
public SectorNumber[] FATSectorNumbers { get; set; }
/// <summary>
/// The mini FAT is used to allocate space in the mini stream.
/// The mini stream is divided intosmaller, equal-length sectors,
/// and the sector size that is used for the mini stream is specified
/// from the Compound File Header (64 bytes).
/// </summary>
/// <remarks>
/// If Header Major Version is 3, there MUST be 128 fields specified to fill a 512-byte sector.
///
/// If Header Major Version is 4, there MUST be 1,024 fields specified to fill a 4,096-byte sector
/// </remarks>
public SectorNumber[] MiniFATSectorNumbers { get; set; }
/// <summary>
/// The DIFAT array is used to represent storage of the FAT sectors.
/// The DIFAT is represented by an array of 32-bit sector numbers.
/// The DIFAT array is stored both in the header and in DIFAT sectors.
/// In the header, the DIFAT array occupies 109 entries, and in each
/// DIFAT sector, the DIFAT array occupies the entire sector minus
/// 4 bytes. (The last field is for chaining the DIFAT sector chain.)
/// </summary>
/// <remarks>
/// If Header Major Version is 3, there MUST be 127 fields specified to
/// fill a 512-byte sector minus the "Next DIFAT Sector Location" field.
///
/// If Header Major Version is 4, there MUST be 1,023 fields specified
/// to fill a 4,096-byte sector minus the "Next DIFAT Sector Location" field.
/// </remarks>
public SectorNumber[] DIFATSectorNumbers { get; set; }
/// <summary>
/// The directory entry array is an array of directory entries that
/// are grouped into a directory sector. Each storage object or stream
/// object within a compound file is represented by a single directory
/// entry. The space for the directory sectors that are holding the
/// array is allocated from the FAT.
/// </summary>
/// <remarks>
/// The first entry in the first sector of the directory chain (also
/// referred to as the first element of the directory array, or stream
/// ID #0) is known as the root directory entry, and it is reserved for
/// two purposes. First, it provides a root parent for all objects that
/// are stationed at the root of the compound file. Second, its function
/// is overloaded to store the size and starting sector for the mini stream.
///
/// The root directory entry behaves as both a stream and a storage object.
/// The root directory entry's Name field MUST contain the null-terminated
/// string "Root Entry" in Unicode UTF-16.
///
/// The object class GUID (CLSID) that is stored in the root directory
/// entry can be used for COM activation of the document's application.
///
/// The time stamps for the root storage are not maintained in the root
/// directory entry. Rather, the root storage's creation and modification
/// time stamps are normally stored on the file itself in the file system.
///
/// The Creation Time field in the root storage directory entry MUST be
/// all zeroes. The Modified Time field in the root storage directory
/// entry MAY be all zeroes.
/// <remarks>
public DirectoryEntry[] DirectoryEntries { get; set; }
}
}

52
CFB/Constants.cs Normal file
View File

@@ -0,0 +1,52 @@
using System;
namespace BinaryObjectScanner.Models.CFB
{
public static class Constants
{
public static readonly byte[] SignatureBytes = new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
public const ulong SignatureUInt64 = 0xE11AB1A1E011CFD0;
/// <see href="https://devblogs.microsoft.com/setup/identifying-windows-installer-file-types/"/>
#region Class IDs
/// <summary>
/// Installer Package (msi), Merge Module (msm), Patch Creation Properties (pcp)
/// </summary>
public static readonly Guid InstallerPackage = new Guid("000c1084-0000-0000-c000-000000000046");
/// <summary>
/// Patch Package (msp)
/// </summary>
public static readonly Guid PatchPackage = new Guid("000C1086-0000-0000-C000-000000000046");
/// <summary>
/// Transform (mst)
/// </summary>
public static readonly Guid Transform = new Guid("000C1082-0000-0000-C000-000000000046");
#endregion
/// <see href="https://learn.microsoft.com/en-us/windows/win32/stg/predefined-property-set-format-identifiers"/>
#region Property Set Format IDs
/// <summary>
/// The Summary Information Property Set
/// </summary>
public static readonly Guid FMTID_SummaryInformation = new Guid("F29F85E0-4FF9-1068-AB91-08002B27B3D9");
/// <summary>
/// The DocumentSummaryInformation and UserDefined Property Sets
/// </summary>
public static readonly Guid FMTID_DocSummaryInformation = new Guid("D5CDD502-2E9C-101B-9397-08002B2CF9AE");
/// <summary>
/// The DocumentSummaryInformation and UserDefined Property Sets
/// </summary>
public static readonly Guid FMTID_UserDefinedProperties = new Guid("D5CDD505-2E9C-101B-9397-08002B2CF9AE");
#endregion
}
}

133
CFB/DirectoryEntry.cs Normal file
View File

@@ -0,0 +1,133 @@
using System;
namespace BinaryObjectScanner.Models.CFB
{
/// <see href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-CFB/%5bMS-CFB%5d.pdf"/>
public sealed class DirectoryEntry
{
/// <summary>
/// This field MUST contain a Unicode string for the storage or stream
/// name encoded in UTF-16. The name MUST be terminated with a UTF-16
/// terminating null character. Thus, storage and stream names are limited
/// to 32 UTF-16 code points, including the terminating null character.
/// When locating an object in the compound file except for the root
/// storage, the directory entry name is compared by using a special
/// case-insensitive uppercase mapping, described in Red-Black Tree.
/// The following characters are illegal and MUST NOT be part of the
/// name: '/', '\', ':', '!'.
/// </summary>
public string Name;
/// <summary>
/// This field MUST be 0x00, 0x01, 0x02, or 0x05, depending on the
/// actual type of object. All other values are not valid.
/// </summary>
public ushort NameLength;
/// <summary>
/// This field MUST match the length of the Directory Entry Name Unicode
/// string in bytes. The length MUST be a multiple of 2 and include the
/// terminating null character in the count. This length MUST NOT exceed 64,
/// the maximum size of the Directory Entry Name field.
/// </summary>
public ObjectType ObjectType;
/// <summary>
/// This field MUST be 0x00 (red) or 0x01 (black). All other values are not valid.
/// </summary>
public ColorFlag ColorFlag;
/// <summary>
/// This field contains the stream ID of the left sibling. If there
/// is no left sibling, the field MUST be set to NOSTREAM (0xFFFFFFFF).
/// </summary>
public StreamID LeftSiblingID;
/// <summary>
/// This field contains the stream ID of the right sibling. If there
/// is no right sibling, the field MUST be set to NOSTREAM (0xFFFFFFFF).
/// </summary>
public StreamID RightSiblingID;
/// <summary>
/// This field contains the stream ID of a child object. If there is no
/// child object, including all entries for stream objects, the field
/// MUST be set to NOSTREAM (0xFFFFFFFF).
/// </summary>
public StreamID ChildID;
/// <summary>
/// This field contains an object class GUID, if this entry is for a
/// storage object or root storage object. For a stream object, this field
/// MUST be set to all zeroes. A value containing all zeroes in a storage
/// or root storage directory entry is valid, and indicates that no object
/// class is associated with the storage. If an implementation of the file
/// format enables applications to create storage objects without explicitly
/// setting an object class GUID, it MUST write all zeroes by default. If
/// this value is not all zeroes, the object class GUID can be used as a
/// parameter to start applications.
/// </summary>
public Guid CLSID;
/// <summary>
/// This field contains the user-defined flags if this entry is for a storage
/// object or root storage object. For a stream object, this field SHOULD be
/// set to all zeroes because many implementations provide no way for
/// applications to retrieve state bits from a stream object. If an
/// implementation of the file format enables applications to create storage
/// objects without explicitly setting state bits, it MUST write all zeroes
/// by default.
/// </summary>
public uint StateBits;
/// <summary>
/// This field contains the creation time for a storage object, or all zeroes
/// to indicate that the creation time of the storage object was not recorded.
/// The Windows FILETIME structure is used to represent this field in UTC.
/// For a stream object, this field MUST be all zeroes. For a root storage
/// object, this field MUST be all zeroes, and the creation time is retrieved
/// or set on the compound file itself.
/// </summary>
public ulong CreationTime;
/// <summary>
/// This field contains the modification time for a storage object, or all
/// zeroes to indicate that the modified time of the storage object was not
/// recorded. The Windows FILETIME structure is used to represent this field
/// in UTC. For a stream object, this field MUST be all zeroes. For a root
/// storage object, this field MAY<2> be set to all zeroes, and the modified
/// time is retrieved or set on the compound file itself.
/// </summary>
public ulong ModifiedTime;
/// <summary>
/// This field contains the first sector location if this is a stream object.
/// For a root storage object, this field MUST contain the first sector of the
/// mini stream, if the mini stream exists. For a storage object, this field MUST
/// be set to all zeroes.
/// </summary>
public uint StartingSectorLocation;
/// <summary>
/// This 64-bit integer field contains the size of the user-defined data if this
/// is a stream object. For a root storage object, this field contains the size
/// of the mini stream. For a storage object, this field MUST be set to all zeroes.
/// </summary>
/// <remarks>
/// For a version 3 compound file 512-byte sector size, the value of this field MUST
/// be less than or equal to 0x80000000. (Equivalently, this requirement can be stated:
/// the size of a stream or of the mini stream in a version 3 compound file MUST be
/// less than or equal to 2 gigabytes (GB).) Note that as a consequence of this
/// requirement, the most significant 32 bits of this field MUST be zero in a version
/// 3 compound file. However, implementers should be aware that some older
/// implementations did not initialize the most significant 32 bits of this field,
/// and these bits might therefore be nonzero in files that are otherwise valid
/// version 3 compound files. Although this document does not normatively specify
/// parser behavior, it is recommended that parsers ignore the most significant 32 bits
/// of this field in version 3 compound files, treating it as if its value were zero,
/// unless there is a specific reason to do otherwise (for example, a parser whose
/// purpose is to verify the correctness of a compound file).
/// </remarks>
public ulong StreamSize;
}
}

474
CFB/Enums.cs Normal file
View File

@@ -0,0 +1,474 @@
namespace BinaryObjectScanner.Models.CFB
{
public enum ColorFlag : byte
{
Red = 0x00,
Black = 0x01,
}
public enum ObjectType : byte
{
Unknown = 0x00,
StorageObject = 0x01,
StreamObject = 0x02,
RootStorageObject = 0x05,
}
public enum SectorNumber : uint
{
/// <summary>
/// Regular sector number.
/// </summary>
REGSECT = 0x00000000, // 0x00000000 - 0xFFFFFFF9
/// <summary>
/// Maximum regular sector number.
/// </summary>
MAXREGSECT = 0xFFFFFFFA,
/// <summary>
/// Reserved for future use.
/// </summary>
NotApplicable = 0xFFFFFFFB,
/// <summary>
/// Specifies a DIFAT sector in the FAT.
/// </summary>
DIFSECT = 0xFFFFFFFC,
/// <summary>
/// Specifies a FAT sector in the FAT.
/// </summary>
FATSECT = 0xFFFFFFFD,
/// <summary>
/// End of a linked chain of sectors.
/// </summary>
ENDOFCHAIN = 0xFFFFFFFE,
/// <summary>
/// Specifies an unallocated sector in the FAT, Mini FAT, or DIFAT.
/// </summary>
FREESECT = 0xFFFFFFFF,
}
public enum StreamID : uint
{
/// <summary>
/// Regular stream ID to identify the directory entry.
/// </summary>
REGSID = 0x00000000, // 0x00000000 - 0xFFFFFFF9
/// <summary>
/// Maximum regular stream ID.
/// </summary>
MAXREGSID = 0xFFFFFFFA,
/// <summary>
/// Terminator or empty pointer.
/// </summary>
NOSTREAM = 0xFFFFFFFF,
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/stg/the-summary-information-property-set"/>
public enum SummaryInformationProperty : uint
{
/// <summary>
/// Title
/// </summary>
PIDSI_TITLE = 0x00000002,
/// <summary>
/// Subject
/// </summary>
PIDSI_SUBJECT = 0x00000003,
/// <summary>
/// Author
/// </summary>
PIDSI_AUTHOR = 0x00000004,
/// <summary>
/// Keywords
/// </summary>
PIDSI_KEYWORDS = 0x00000005,
/// <summary>
/// Comments
/// </summary>
PIDSI_COMMENTS = 0x00000006,
/// <summary>
/// Template
/// </summary>
PIDSI_TEMPLATE = 0x00000007,
/// <summary>
/// Last Saved By
/// </summary>
PIDSI_LASTAUTHOR = 0x00000008,
/// <summary>
/// Revision Number
/// </summary>
PIDSI_REVNUMBER = 0x00000009,
/// <summary>
/// Total Editing Time
/// </summary>
PIDSI_EDITTIME = 0x0000000A,
/// <summary>
/// Last Printed
/// </summary>
PIDSI_LASTPRINTED = 0x0000000B,
/// <summary>
/// Create Time/Date
/// </summary>
PIDSI_CREATE_DTM = 0x0000000C,
/// <summary>
/// Last saved Time/Date
/// </summary>
PIDSI_LASTSAVE_DTM = 0x0000000D,
/// <summary>
/// Number of Pages
/// </summary>
PIDSI_PAGECOUNT = 0x0000000E,
/// <summary>
/// Number of Words
/// </summary>
PIDSI_WORDCOUNT = 0x0000000F,
/// <summary>
/// Number of Characters
/// </summary>
PIDSI_CHARCOUNT = 0x00000010,
/// <summary>
/// Thumbnail
/// </summary>
PIDSI_THUMBNAIL = 0x00000011,
/// <summary>
/// Name of Creating Application
/// </summary>
PIDSI_APPNAME = 0x00000012,
/// <summary>
/// Security
/// </summary>
PIDSI_SECURITY = 0x00000013,
}
/// <remarks>Also includes the DocumentSummaryInformation set</remarks>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/stg/the-documentsummaryinformation-and-userdefined-property-sets"/>
public enum UserDefinedProperty : uint
{
/// <summary>
/// Category - A text string typed by the user that indicates what
/// category the file belongs to (memo, proposal, and so on). It
/// is useful for finding files of same type.
/// </summary>
PIDDSI_CATEGORY = 0x00000002,
/// <summary>
/// PresentationTarget - Target format for presentation (35mm,
/// printer, video, and so on).
/// </summary>
PIDDSI_PRESFORMAT = 0x00000003,
/// <summary>
/// Bytes - Number of bytes.
/// </summary>
PIDDSI_BYTECOUNT = 0x00000004,
/// <summary>
/// Lines - Number of lines.
/// </summary>
PIDDSI_LINECOUNT = 0x00000005,
/// <summary>
/// Paragraphs - Number of paragraphs.
/// </summary>
PIDDSI_PARCOUNT = 0x00000006,
/// <summary>
/// Slides - Number of slides.
/// </summary>
PIDDSI_SLIDECOUNT = 0x00000007,
/// <summary>
/// Notes - Number of pages that contain notes.
/// </summary>
PIDDSI_NOTECOUNT = 0x00000008,
/// <summary>
/// HiddenSlides - Number of slides that are hidden.
/// </summary>
PIDDSI_HIDDENCOUNT = 0x00000009,
/// <summary>
/// MMClips - Number of sound or video clips.
/// </summary>
PIDDSI_MMCLIPCOUNT = 0x0000000A,
/// <summary>
/// ScaleCrop - Set to True (-1) when scaling of the thumbnail
/// is desired. If not set, cropping is desired.
/// </summary>
PIDDSI_SCALE = 0x0000000B,
/// <summary>
/// HeadingPairs - Internally used property indicating the
/// grouping of different document parts and the number of
/// items in each group. The titles of the document parts are
/// stored in the TitlesofParts property. The HeadingPairs
/// property is stored as a vector of variants, in repeating
/// pairs of VT_LPSTR (or VT_LPWSTR) and VT_I4 values. The
/// VT_LPSTR value represents a heading name, and the VT_I4
/// value indicates the count of document parts under that heading.
/// </summary>
PIDDSI_HEADINGPAIR = 0x0000000C,
/// <summary>
/// TitlesofParts - Names of document parts.
/// </summary>
PIDDSI_DOCPARTS = 0x0000000D,
/// <summary>
/// Manager - Manager of the project.
/// </summary>
PIDDSI_MANAGER = 0x0000000E,
/// <summary>
/// Company - Company name.
/// </summary>
PIDDSI_COMPANY = 0x0000000F,
/// <summary>
/// LinksUpToDate - Boolean value to indicate whether the custom
/// links are hampered by excessive noise, for all applications.
/// </summary>
PIDDSI_LINKSDIRTY = 0x00000010,
}
/// <see href="https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-oaut/3fe7db9f-5803-4dc4-9d14-5425d3f5461f"/>
public enum VariantType : ushort
{
/// <summary>
/// The type of the contained field is undefined. When this flag is
/// specified, the VARIANT MUST NOT contain a data field.
/// </summary>
VT_EMPTY = 0x0000,
/// <summary>
/// The type of the contained field is NULL. When this flag is
/// specified, the VARIANT MUST NOT contain a data field.
/// </summary>
VT_NULL = 0x0001,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be a 2-byte signed integer.
/// </summary>
VT_I2 = 0x0002,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be a 4-byte signed integer.
/// </summary>
VT_I4 = 0x0003,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be a 4-byte IEEE floating-point number.
/// </summary>
VT_R4 = 0x0004,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be an 8-byte IEEE floating-point number.
/// </summary>
VT_R8 = 0x0005,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be CURRENCY.
/// </summary>
VT_CY = 0x0006,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be DATE.
/// </summary>
VT_DATE = 0x0007,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be BSTR.
/// </summary>
VT_BSTR = 0x0008,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be a pointer to IDispatch.
/// </summary>
VT_DISPATCH = 0x0009,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be HRESULT.
/// </summary>
VT_ERROR = 0x000A,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be VARIANT_BOOL.
/// </summary>
VT_BOOL = 0x000B,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be VARIANT. It MUST appear with the bit flag VT_BYREF.
/// </summary>
VT_VARIANT = 0x000C,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be a pointer to IUnknown.
/// </summary>
VT_UNKNOWN = 0x000D,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be DECIMAL.
/// </summary>
VT_DECIMAL = 0x000E,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be a 1-byte integer.
/// </summary>
VT_I1 = 0x0010,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be a 1-byte unsigned integer.
/// </summary>
VT_UI1 = 0x0011,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be a 2-byte unsigned integer.
/// </summary>
VT_UI2 = 0x0012,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be a 4-byte unsigned integer.
/// </summary>
VT_UI4 = 0x0013,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be an 8-byte signed integer.
/// </summary>
VT_I8 = 0x0014,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be an 8-byte unsigned integer.
/// </summary>
VT_UI8 = 0x0015,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be a 4-byte signed integer.
/// </summary>
VT_INT = 0x0016,
/// <summary>
/// Either the specified type, or the type of the element or contained
/// field MUST be a 4-byte unsigned integer.
/// </summary>
VT_UINT = 0x0017,
/// <summary>
/// The specified type MUST be void.
/// </summary>
VT_VOID = 0x0018,
/// <summary>
/// The specified type MUST be HRESULT.
/// </summary>
VT_HRESULT = 0x0019,
/// <summary>
/// The specified type MUST be a unique pointer.
/// </summary>
VT_PTR = 0x001A,
/// <summary>
/// The specified type MUST be SAFEARRAY.
/// </summary>
VT_SAFEARRAY = 0x001B,
/// <summary>
/// The specified type MUST be a fixed-size array.
/// </summary>
VT_CARRAY = 0x001C,
/// <summary>
/// The specified type MUST be user defined.
/// </summary>
VT_USERDEFINED = 0x001D,
/// <summary>
/// The specified type MUST be a NULL-terminated string.
/// </summary>
VT_LPSTR = 0x001E,
/// <summary>
/// The specified type MUST be a zero-terminated string of
/// UNICODE characters.
/// </summary>
VT_LPWSTR = 0x001F,
/// <summary>
/// The type of the element or contained field MUST be a BRECORD.
/// </summary>
VT_RECORD = 0x0024,
/// <summary>
/// The specified type MUST be either a 4-byte or an 8-byte signed
/// integer. The size of the integer is platform specific and
/// determines the system pointer size value.
/// </summary>
VT_INT_PTR = 0x0025,
/// <summary>
/// The specified type MUST be either a 4 byte or an 8 byte unsigned
/// integer. The size of the integer is platform specific and
/// determines the system pointer size value
/// </summary>
VT_UINT_PTR = 0x0026,
/// <summary>
/// The type of the element or contained field MUST be a SAFEARRAY.
/// </summary>
VT_ARRAY = 0x2000,
/// <summary>
/// The type of the element or contained field MUST be a pointer to
/// one of the types listed in the previous rows of this table. If
/// present, this bit flag MUST appear in a VARIANT discriminant
/// with one of the previous flags.
/// </summary>
VT_BYREF = 0x4000
}
}

127
CFB/FileHeader.cs Normal file
View File

@@ -0,0 +1,127 @@
using System;
namespace BinaryObjectScanner.Models.CFB
{
/// <see href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-CFB/%5bMS-CFB%5d.pdf"/>
public sealed class FileHeader
{
/// <summary>
/// Iddentification signature for the compound file structure, and MUST be
/// set to the value 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1.
/// </summary>
public ulong Signature;
/// <summary>
/// Reserved and unused class ID that MUST be set to all zeroes (CLSID_NULL)
/// </summary>
public Guid CLSID;
/// <summary>
/// Version number for nonbreaking changes. This field SHOULD be set to
/// 0x003E if the major version field is either 0x0003 or 0x0004.
/// </summary>
public ushort MinorVersion;
/// <summary>
/// Version number for breaking changes. This field MUST be set to either
/// 0x0003 (version 3) or 0x0004 (version 4).
/// </summary>
public ushort MajorVersion;
/// <summary>
/// This field MUST be set to 0xFFFE. This field is a byte order mark for
/// all integer fields, specifying little-endian byte order.
/// </summary>
public ushort ByteOrder;
/// <summary>
/// This field MUST be set to 0x0009, or 0x000c, depending on the Major
/// Version field. This field specifies the sector size of the compound file
/// as a power of 2.
///
/// If Major Version is 3, the Sector Shift MUST be 0x0009, specifying a
/// sector size of 512 bytes.
///
/// If Major Version is 4, the Sector Shift MUST be 0x000C, specifying a
/// sector size of 4096 bytes.
/// </summary>
public ushort SectorShift;
/// <summary>
/// This field MUST be set to 0x0006. This field specifies the sector size
/// of the Mini Stream as a power of 2. The sector size of the Mini Stream
/// MUST be 64 bytes.
/// </summary>
public ushort MiniSectorShift;
/// <summary>
/// This field MUST be set to all zeroes.
/// </summary>
public byte[] Reserved;
/// <summary>
/// This integer field contains the count of the number of directory sectors
/// in the compound file.
///
/// If Major Version is 3, the Number of Directory Sectors MUST be zero. This
/// field is not supported for version 3 compound files.
/// </summary>
public uint NumberOfDirectorySectors;
/// <summary>
/// This integer field contains the count of the number of FAT sectors in the
/// compound file.
/// </summary>
public uint NumberOfFATSectors;
/// <summary>
/// This integer field contains the starting sector number for the directory stream.
/// </summary>
public uint FirstDirectorySectorLocation;
/// <summary>
/// This integer field MAY contain a sequence number that is incremented every time
/// the compound file is saved by an implementation that supports file transactions.
/// This is the field that MUST be set to all zeroes if file transactions are not
/// implemented.
/// </summary>
public uint TransactionSignatureNumber;
/// <summary>
/// This integer field MUST be set to 0x00001000. This field specifies the maximum
/// size of a user-defined data stream that is allocated from the mini FAT and mini
/// stream, and that cutoff is 4,096 bytes. Any user-defined data stream that is
/// greater than or equal to this cutoff size must be allocated as normal sectors from
/// the FAT.
/// </summary>
public uint MiniStreamCutoffSize;
/// <summary>
/// This integer field contains the starting sector number for the mini FAT.
/// </summary>
public uint FirstMiniFATSectorLocation;
/// <summary>
/// This integer field contains the count of the number of mini FAT sectors in the
/// compound file.
/// </summary>
public uint NumberOfMiniFATSectors;
/// <summary>
/// This integer field contains the starting sector number for the DIFAT.
/// </summary>
public uint FirstDIFATSectorLocation;
/// <summary>
/// This integer field contains the count of the number of DIFAT sectors in the
/// compound file.
/// </summary>
public uint NumberOfDIFATSectors;
/// <summary>
/// This array of 32-bit integer fields contains the first 109 FAT sector
/// locations of the compound file
/// </summary>
public SectorNumber[] DIFAT;
}
}

82
CFB/SummaryInformation.cs Normal file
View File

@@ -0,0 +1,82 @@
using System;
namespace BinaryObjectScanner.Models.CFB
{
/// <see href="https://github.com/GNOME/msitools/blob/master/libmsi/libmsi-summary-info.c"/>
public sealed class SummaryInformation
{
#region Set Header
/// <summary>
/// This field MUST be set to 0xFFFE. This field is a byte order mark for
/// all integer fields, specifying little-endian byte order.
/// </summary>
public ushort ByteOrder;
/// <summary>
/// Format
/// </summary>
public ushort Format;
/// <summary>
/// Build
/// </summary>
public ushort Build;
/// <summary>
/// Platform ID
/// </summary>
public ushort PlatformID;
/// <summary>
/// CLSID
/// </summary>
public Guid CLSID;
/// <summary>
/// 4 bytes of reserved data
/// </summary>
public byte[] Reserved;
#endregion
#region Format Header
/// <summary>
/// Format ID, should be <see cref="Constants.FMTID_SummaryInformation"/>
/// </summary>
public Guid FormatID;
/// <summary>
/// 16 bytes of unknown data
/// </summary>
public byte[] Unknown;
#endregion
#region Section Header
/// <summary>
/// Location of the section
/// </summary>
public uint Offset;
/// <summary>
/// Section count(?)
/// </summary>
public uint SectionCount;
/// <summary>
/// Property count
/// </summary>
public uint PropertyCount;
/// <summary>
/// Properties
/// </summary>
/// <remarks>Each Variant might be followed by an index and offset value</remarks>
public Variant[] Properties;
#endregion
}
}

45
CFB/Variant.cs Normal file
View File

@@ -0,0 +1,45 @@
namespace BinaryObjectScanner.Models.CFB
{
/// <summary>
/// VARIANT is a container for a union that can hold many types of data.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-oaut/b2ee2b50-665e-43e6-a92c-8f2a29fd7add"/>
public sealed class Variant
{
/// <summary>
/// MUST be set to the size, in quad words (64 bits), of the structure.
/// </summary>
public uint Size;
/// <summary>
/// MUST be set to 0 and MUST be ignored by the recipient.
/// </summary>
public uint RpcReserved;
/// <summary>
/// MUST be set to one of the values specified with a "V".
/// </summary>
public VariantType VariantType;
/// <summary>
/// MAY be set to 0 and MUST be ignored by the recipient.
/// </summary>
public ushort Reserved1;
/// <summary>
/// MAY be set to 0 and MUST be ignored by the recipient.
/// </summary>
public ushort Reserved2;
/// <summary>
/// MAY be set to 0 and MUST be ignored by the recipient.
/// </summary>
public ushort Reserved3;
/// <summary>
/// MUST contain an instance of the type, according to the value
/// in the <see cref="VariantType"/> field.
/// </summary>
public object Union;
}
}

View File

@@ -0,0 +1,23 @@
namespace BinaryObjectScanner.Models.Compression.LZ
{
public static class Constants
{
public const int GETLEN = 2048;
public const int LZ_MAGIC_LEN = 8;
public const int LZ_HEADER_LEN = 14;
public static readonly byte[] MagicBytes = new byte[] { 0x53, 0x5a, 0x44, 0x44, 0x88, 0xf0, 0x27, 0x33 };
public static readonly string MagicString = System.Text.Encoding.ASCII.GetString(MagicBytes);
public const ulong MagicUInt64 = 0x3327f08844445a53;
public const int LZ_TABLE_SIZE = 0x1000;
public const int MAX_LZSTATES = 16;
public const int LZ_MIN_HANDLE = 0x400;
}
}

17
Compression/LZ/Enums.cs Normal file
View File

@@ -0,0 +1,17 @@
namespace BinaryObjectScanner.Models.Compression.LZ
{
/// <see href="https://github.com/wine-mirror/wine/blob/master/include/lzexpand.h"/>
public enum LZERROR
{
LZERROR_OK = 1,
LZERROR_NOT_LZ = 0,
LZERROR_BADINHANDLE = -1,
LZERROR_BADOUTHANDLE = -2,
LZERROR_READ = -3,
LZERROR_WRITE = -4,
LZERROR_GLOBALLOC = -5,
LZERROR_GLOBLOCK = -6,
LZERROR_BADVALUE = -7,
LZERROR_UNKNOWNALG = -8,
}
}

View File

@@ -0,0 +1,17 @@
namespace BinaryObjectScanner.Models.Compression.LZ
{
/// <summary>
/// Format of first 14 byte of LZ compressed file
/// </summary>
/// <see href="https://github.com/wine-mirror/wine/blob/master/dlls/kernel32/lzexpand.c"/>
public sealed class FileHeaader
{
public string Magic;
public byte CompressionType;
public char LastChar;
public uint RealLength;
}
}

72
Compression/LZ/State.cs Normal file
View File

@@ -0,0 +1,72 @@
using System.IO;
namespace BinaryObjectScanner.Models.Compression.LZ
{
public sealed class State
{
/// <summary>
/// Internal backing stream
/// </summary>
public Stream Source { get; set; }
/// <summary>
/// The last char of the filename for replacement
/// </summary>
public char LastChar { get; set; }
/// <summary>
/// Decompressed length of the file
/// </summary>
public uint RealLength { get; set; }
/// <summary>
/// Position the decompressor currently is
/// </summary>
public uint RealCurrent { get; set; }
/// <summary>
/// Position the user wants to read from
/// </summary>
public uint RealWanted { get; set; }
/// <summary>
/// The rotating LZ table
/// </summary>
public byte[] Table { get; set; }
/// <summary>
/// CURrent TABle ENTry
/// </summary>
public uint CurrentTableEntry { get; set; }
/// <summary>
/// Length and position of current string
/// </summary>
public byte StringLength { get; set; }
/// <summary>
/// From stringtable
/// </summary>
public uint StringPosition { get; set; }
/// <summary>
/// Bitmask within blocks
/// </summary>
public ushort ByteType { get; set; }
/// <summary>
/// GETLEN bytes
/// </summary>
public byte[] Window { get; set; }
/// <summary>
/// Current read
/// </summary>
public uint WindowCurrent { get; set; }
/// <summary>
/// Length last got
/// </summary>
public uint WindowLength { get; set; }
}
}

View File

@@ -0,0 +1,61 @@
namespace BinaryObjectScanner.Models.Compression.LZX
{
/// <summary>
/// An aligned offset block is identical to the verbatim block except for the presence of the aligned offset
/// tree preceding the other trees.
/// </summary>
/// <see href="https://interoperability.blob.core.windows.net/files/MS-PATCH/%5bMS-PATCH%5d.pdf"/>
public class AlignedOffsetBlock
{
/// <summary>
/// Generic block header
/// </summary>
public BlockHeader Header;
/// <summary>
/// Aligned offset tree
/// </summary>
/// <remarks>8 elements, 3 bits each</remarks>
public byte[] AlignedOffsetTree;
/// <summary>
/// Pretree for first 256 elements of main tree
/// </summary>
/// <remarks>20 elements, 4 bits each</remarks>
public byte[] PretreeFirst256;
/// <summary>
/// Path lengths of first 256 elements of main tree
/// </summary>
/// <remarks>Encoded using pretree</remarks>
public int[] PathLengthsFirst256;
/// <summary>
/// Pretree for remainder of main tree
/// </summary>
/// <remarks>20 elements, 4 bits each</remarks>
public byte[] PretreeRemainder;
/// <summary>
/// Path lengths of remaining elements of main tree
/// </summary>
/// <remarks>Encoded using pretree</remarks>
public int[] PathLengthsRemainder;
/// <summary>
/// Pretree for length tree
/// </summary>
/// <remarks>20 elements, 4 bits each</remarks>
public byte[] PretreeLengthTree;
/// <summary>
/// Path lengths of elements in length tree
/// </summary>
/// <remarks>Encoded using pretree</remarks>
public int[] PathLengthsLengthTree;
// Entry Comments Size
// ---------------------------------------------------------------------------------------
// Token sequence (matches and literals) Specified in section 2.6 Variable
}
}

View File

@@ -0,0 +1,38 @@
namespace BinaryObjectScanner.Models.Compression.LZX
{
/// <summary>
/// An LZXD block represents a sequence of compressed data that is encoded with the same set of
/// Huffman trees, or a sequence of uncompressed data. There can be one or more LZXD blocks in a
/// compressed stream, each with its own set of Huffman trees. Blocks do not have to start or end on a
/// chunk boundary; blocks can span multiple chunks, or a single chunk can contain multiple blocks. The
/// number of chunks is related to the size of the data being compressed, while the number of blocks is
/// related to how well the data is compressed. The Block Type field, as specified in section 2.3.1.1,
/// indicates which type of block follows, and the Block Size field, as specified in section 2.3.1.2,
/// indicates the number of uncompressed bytes represented by the block. Following the generic block
/// header is a type-specific header that describes the remainder of the block.
/// </summary>
/// <see href="https://interoperability.blob.core.windows.net/files/MS-PATCH/%5bMS-PATCH%5d.pdf"/>
public class BlockHeader
{
/// <remarks>3 bits</remarks>
public BlockType BlockType;
/// <summary>
/// Block size is the high 8 bits of 24
/// </summary>
/// <remarks>8 bits</remarks>
public byte BlockSizeMSB;
/// <summary>
/// Block size is the middle 8 bits of 24
/// </summary>
/// <remarks>8 bits</remarks>
public byte BlockSizeByte2;
/// <summary>
/// Block size is the low 8 bits of 24
/// </summary>
/// <remarks>8 bits</remarks>
public byte BlocksizeLSB;
}
}

View File

@@ -0,0 +1,46 @@
namespace BinaryObjectScanner.Models.Compression.LZX
{
public static class Constants
{
/* some constants defined by the LZX specification */
public const int LZX_MIN_MATCH = (2);
public const int LZX_MAX_MATCH = (257);
public const int LZX_NUM_CHARS = (256);
/// <summary>
/// also blocktypes 4-7 invalid
/// </summary>
public const int LZX_BLOCKTYPE_INVALID = (0);
public const int LZX_BLOCKTYPE_VERBATIM = (1);
public const int LZX_BLOCKTYPE_ALIGNED = (2);
public const int LZX_BLOCKTYPE_UNCOMPRESSED = (3);
public const int LZX_PRETREE_NUM_ELEMENTS = (20);
/// <summary>
/// aligned offset tree #elements
/// </summary>
public const int LZX_ALIGNED_NUM_ELEMENTS = (8);
/// <summary>
/// this one missing from spec!
/// </summary>
public const int LZX_NUM_PRIMARY_LENGTHS = (7);
/// <summary>
/// length tree #elements
/// </summary>
public const int LZX_NUM_SECONDARY_LENGTHS = (249);
/* LZX huffman defines: tweak tablebits as desired */
public const int LZX_PRETREE_MAXSYMBOLS = (LZX_PRETREE_NUM_ELEMENTS);
public const int LZX_PRETREE_TABLEBITS = (6);
public const int LZX_MAINTREE_MAXSYMBOLS = (LZX_NUM_CHARS + 50 * 8);
public const int LZX_MAINTREE_TABLEBITS = (12);
public const int LZX_LENGTH_MAXSYMBOLS = (LZX_NUM_SECONDARY_LENGTHS + 1);
public const int LZX_LENGTH_TABLEBITS = (12);
public const int LZX_ALIGNED_MAXSYMBOLS = (LZX_ALIGNED_NUM_ELEMENTS);
public const int LZX_ALIGNED_TABLEBITS = (7);
public const int LZX_LENTABLE_SAFETY = (64); /* we allow length table decoding overruns */
}
}

48
Compression/LZX/Enums.cs Normal file
View File

@@ -0,0 +1,48 @@
namespace BinaryObjectScanner.Models.Compression.LZX
{
/// <summary>
/// 3-bit block type
/// </summary>
public enum BlockType : byte
{
/// <summary>
/// Not valid
/// </summary>
INVALID_0 = 0b000,
/// <summary>
/// Verbatim block
/// </summary>
Verbatim = 0b001,
/// <summary>
/// Aligned offset block
/// </summary>
AlignedOffset = 0b010,
/// <summary>
/// Uncompressed block
/// </summary>
Uncompressed = 0b011,
/// <summary>
/// Not valid
/// </summary>
INVALID_4 = 0b100,
/// <summary>
/// Not valid
/// </summary>
INVALID_5 = 0b101,
/// <summary>
/// Not valid
/// </summary>
INVALID_6 = 0b110,
/// <summary>
/// Not valid
/// </summary>
INVALID_7 = 0b111,
}
}

102
Compression/LZX/Header.cs Normal file
View File

@@ -0,0 +1,102 @@
namespace BinaryObjectScanner.Models.Compression.LZX
{
public class Header
{
/*
2.2 Header
2.2.1 Chunk Size
The LZXD compressor emits chunks of compressed data. A chunk represents exactly 32 KB of
uncompressed data until the last chunk in the stream, which can represent less than 32 KB. To
ensure that an exact number of input bytes represent an exact number of output bytes for each
chunk, after each 32 KB of uncompressed data is represented in the output compressed bitstream, the
output bitstream is padded with up to 15 bits of zeros to realign the bitstream on a 16-bit boundary
(even byte boundary) for the next 32 KB of data. This results in a compressed chunk of a byte-aligned
size. The compressed chunk could be smaller than 32 KB or larger than 32 KB if the data is
incompressible when the chunk is not the last one.
The LZXD engine encodes a compressed, chunk-size prefix field preceding each compressed chunk in
the compressed byte stream. The compressed, chunk-size prefix field is a byte aligned, little-endian,
16-bit field. The chunk prefix chain could be followed in the compressed stream without
decompressing any data. The next chunk prefix is at a location computed by the absolute byte offset
location of this chunk prefix plus 2 (for the size of the chunk-size prefix field) plus the current chunk
size.
2.2.2 E8 Call Translation
E8 call translation is an optional feature that can be used when the data to compress contains x86
instruction sequences. E8 translation operates as a preprocessing stage before compressing each
chunk, and the compressed stream header contains a bit that indicates whether the decoder shall
reverse the translation as a postprocessing step after decompressing each chunk.
The x86 instruction beginning with a byte value of 0xE8 is followed by a 32-bit, little-endian relative
displacement to the call target. When E8 call translation is enabled, the following preprocessing steps
are performed on the uncompressed input before compression (assuming little-endian byte ordering):
Let chunk_offset refer to the total number of uncompressed bytes preceding this chunk.
Let E8_file_size refer to the caller-specified value given to the compressor or decoded from the header
of the compressed stream during decompression.
The following example shows how E8 translation is performed for each 32-KB chunk of uncompressed
data (or less than 32 KB if last chunk to compress).
if (( chunk_offset < 0x40000000 ) && ( chunk_size > 10 ))
for ( i = 0; i < (chunk_size 10); i++ )
if ( chunk_byte[ i ] == 0xE8 )
long current_pointer = chunk_offset + i;
long displacement = chunk_byte[ i+1 ] |
chunk_byte[ i+2 ] << 8 |
chunk_byte[ i+3 ] << 16 |
chunk_byte[ i+4 ] << 24;
long target = current_pointer + displacement;
if (( target >= 0 ) && ( target < E8_file_size+current_pointer))
if ( target >= E8_file_size )
target = displacement E8_file_size;
endif
chunk_byte[ i+1 ] = (byte)( target );
chunk_byte[ i+2 ] = (byte)( target >> 8 );
chunk_byte[ i+3 ] = (byte)( target >> 16 );
chunk_byte[ i+4 ] = (byte)( target >> 24 );
endif
i += 4;
endif
endfor
endif
After decompression, the E8 scanning algorithm is the same. The following example shows how E8
translation reversal is performed.
long value = chunk_byte[ i+1 ] |
chunk_byte[ i+2 ] << 8 |
chunk_byte[ i+3 ] << 16 |
chunk_byte[ i+4 ] << 24;
if (( value >= -current_pointer ) && ( value < E8_file_size ))
if ( value >= 0 )
displacement = value current_pointer;
else
displacement = value + E8_file_size;
endif
chunk_byte[ i+1 ] = (byte)( displacement );
chunk_byte[ i+2 ] = (byte)( displacement >> 8 );
chunk_byte[ i+3 ] = (byte)( displacement >> 16 );
chunk_byte[ i+4 ] = (byte)( displacement >> 24 );
endif
The first bit in the first chunk in the LZXD bitstream (following the 2-byte, chunk-size prefix described
in section 2.2.1) indicates the presence or absence of two 16-bit fields immediately following the
single bit. If the bit is set, E8 translation is enabled for all the following chunks in the stream using the
32-bit value derived from the two 16-bit fields as the E8_file_size provided to the compressor when E8
translation was enabled. Note that E8_file_size is completely independent of the length of the
uncompressed data. E8 call translation is disabled after the 32,768th chunk (after 1 gigabyte (GB) of
uncompressed data).
Field Comments Size
----------------------------------------------------------------
E8 translation 0-disabled, 1-enabled 1 bit
Translation size high word Only present if enabled 0 or 16 bits
Translation size low word Only present if enabled 0 or 16 bits
*/
}
}

View File

@@ -0,0 +1,59 @@
namespace BinaryObjectScanner.Models.Compression.LZX
{
/// <summary>
/// Following the generic block header, an uncompressed block begins with 1 to 16 bits of zero padding
/// to align the bit buffer on a 16-bit boundary. At this point, the bitstream ends and a byte stream
/// begins. Following the zero padding, new 32-bit values for R0, R1, and R2 are output in little-endian
/// form, followed by the uncompressed data bytes themselves. Finally, if the uncompressed data length
/// is odd, one extra byte of zero padding is encoded to realign the following bitstream.
///
/// Then the bitstream of byte-swapped 16-bit integers resumes for the next Block Type field (if there
/// are subsequent blocks).
///
/// The decoded R0, R1, and R2 values are used as initial repeated offset values to decode the
/// subsequent compressed block if present.
/// </summary>
/// <see href="https://interoperability.blob.core.windows.net/files/MS-PATCH/%5bMS-PATCH%5d.pdf"/>
public class UncompressedBlock
{
/// <summary>
/// Generic block header
/// </summary>
public BlockHeader Header;
/// <summary>
/// Padding to align following field on 16-bit boundary
/// </summary>
/// <remarks>Bits have a value of zero</remarks>
public ushort PaddingBits;
/// <summary>
/// Least significant to most significant byte (little-endian DWORD ([MS-DTYP]))
/// </summary>
/// <remarks>Encoded directly in the byte stream, not in the bitstream of byte-swapped 16-bit words</remarks>
public uint R0;
/// <summary>
/// Least significant to most significant byte (little-endian DWORD)
/// </summary>
/// <remarks>Encoded directly in the byte stream, not in the bitstream of byte-swapped 16-bit words</remarks>
public uint R1;
/// <summary>
/// Least significant to most significant byte (little-endian DWORD)
/// </summary>
/// <remarks>Encoded directly in the byte stream, not in the bitstream of byte-swapped 16-bit words</remarks>
public uint R2;
/// <summary>
/// Can use the direct memcpy function, as specified in [IEEE1003.1]
/// </summary>
/// <remarks>Encoded directly in the byte stream, not in the bitstream of byte-swapped 16-bit words</remarks>
public byte[] RawDataBytes;
/// <summary>
/// Only if uncompressed size is odd
/// </summary>
public byte AlignmentByte;
}
}

View File

@@ -0,0 +1,54 @@
namespace BinaryObjectScanner.Models.Compression.LZX
{
/// <summary>
/// The fields of a verbatim block that follow the generic block header
/// </summary>
/// <see href="https://interoperability.blob.core.windows.net/files/MS-PATCH/%5bMS-PATCH%5d.pdf"/>
public class VerbatimBlock
{
/// <summary>
/// Generic block header
/// </summary>
public BlockHeader Header;
/// <summary>
/// Pretree for first 256 elements of main tree
/// </summary>
/// <remarks>20 elements, 4 bits each</remarks>
public byte[] PretreeFirst256;
/// <summary>
/// Path lengths of first 256 elements of main tree
/// </summary>
/// <remarks>Encoded using pretree</remarks>
public int[] PathLengthsFirst256;
/// <summary>
/// Pretree for remainder of main tree
/// </summary>
/// <remarks>20 elements, 4 bits each</remarks>
public byte[] PretreeRemainder;
/// <summary>
/// Path lengths of remaining elements of main tree
/// </summary>
/// <remarks>Encoded using pretree</remarks>
public int[] PathLengthsRemainder;
/// <summary>
/// Pretree for length tree
/// </summary>
/// <remarks>20 elements, 4 bits each</remarks>
public byte[] PretreeLengthTree;
/// <summary>
/// Path lengths of elements in length tree
/// </summary>
/// <remarks>Encoded using pretree</remarks>
public int[] PathLengthsLengthTree;
// Entry Comments Size
// ---------------------------------------------------------------------------------------
// Token sequence (matches and literals) Specified in section 2.6 Variable
}
}

View File

@@ -0,0 +1,28 @@
namespace BinaryObjectScanner.Models.Compression.MSZIP
{
/// <summary>
/// Each MSZIP block MUST consist of a 2-byte MSZIP signature and one or more RFC 1951 blocks. The
/// 2-byte MSZIP signature MUST consist of the bytes 0x43 and 0x4B. The MSZIP signature MUST be
/// the first 2 bytes in the MSZIP block. The MSZIP signature is shown in the following packet diagram.
///
/// Each MSZIP block is the result of a single deflate compression operation, as defined in [RFC1951].
/// The compressor that performs the compression operation MUST generate one or more RFC 1951
/// blocks, as defined in [RFC1951]. The number, deflation mode, and type of RFC 1951 blocks in each
/// MSZIP block is determined by the compressor, as defined in [RFC1951]. The last RFC 1951 block in
/// each MSZIP block MUST be marked as the "end" of the stream(1), as defined by [RFC1951]
/// section 3.2.3. Decoding trees MUST be discarded after each RFC 1951 block, but the history buffer
/// MUST be maintained.Each MSZIP block MUST represent no more than 32 KB of uncompressed data.
///
/// The maximum compressed size of each MSZIP block is 32 KB + 12 bytes. This enables the MSZIP
/// block to contain 32 KB of data split between two noncompressed RFC 1951 blocks, each of which
/// has a value of BTYPE = 00.
/// </summary>
/// <see href="https://interoperability.blob.core.windows.net/files/MS-MCI/%5bMS-MCI%5d.pdf"/>
public class BlockHeader
{
/// <summary>
/// 'CK'
/// </summary>
public ushort Signature;
}
}

View File

@@ -0,0 +1,89 @@
namespace BinaryObjectScanner.Models.Compression.MSZIP
{
/// <see href="https://github.com/wine-mirror/wine/blob/master/dlls/cabinet/cabinet.h"/>
public static class Constants
{
/// <summary>
/// Window size
/// </summary>
public const ushort ZIPWSIZE = 0x8000;
/// <summary>
/// Bits in base literal/length lookup table
/// </summary>
public const int ZIPLBITS = 9;
/// <summary>
/// Bits in base distance lookup table
/// </summary>
public const int ZIPDBITS = 6;
/// <summary>
/// Maximum bit length of any code
/// </summary>
public const int ZIPBMAX = 16;
/// <summary>
/// Maximum number of codes in any set
/// </summary>
public const int ZIPN_MAX = 288;
#region THOSE_ZIP_CONSTS
/// <summary>
/// Order of the bit length code lengths
/// </summary>
public static readonly byte[] BitLengthOrder = new byte[]
{
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
};
/// <summary>
/// Copy lengths for literal codes 257..285
/// </summary>
public static readonly ushort[] CopyLengths = new ushort[]
{
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51,
59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
};
/// <summary>
/// Extra bits for literal codes 257..285
/// </summary>
/// <remarks>99 == invalid</remarks>
public static readonly ushort[] LiteralExtraBits = new ushort[]
{
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
4, 5, 5, 5, 5, 0, 99, 99
};
/// <summary>
/// Copy offsets for distance codes 0..29
/// </summary>
public static readonly ushort[] CopyOffsets = new ushort[]
{
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
};
/// <summary>
/// Extra bits for distance codes
/// </summary>
public static readonly ushort[] DistanceExtraBits = new ushort[]
{
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
10, 11, 11, 12, 12, 13, 13
};
/// <summary>
/// And'ing with Zipmask[n] masks the lower n bits
/// </summary>
public static readonly ushort[] BitMasks = new ushort[17]
{
0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};
#endregion
}
}

View File

@@ -0,0 +1,18 @@
namespace BinaryObjectScanner.Models.Compression.MSZIP
{
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
public class DeflateBlockHeader
{
/// <summary>
/// Set if and only if this is the last block of the data set.
/// </summary>
/// <remarks>Bit 0</remarks>
public bool BFINAL { get; set; }
/// <summary>
/// Specifies how the data are compressed
/// </summary>
/// <remarks>Bits 1-2</remarks>
public CompressionType BTYPE { get; set; }
}
}

View File

@@ -0,0 +1,19 @@
namespace BinaryObjectScanner.Models.Compression.MSZIP
{
/// <summary>
/// Compression with dynamic Huffman codes (BTYPE=10)
/// </summary>
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
public class DynamicHuffmanCompressedBlockHeader
{
/// <summary>
/// Huffman code lengths for the literal / length alphabet
/// </summary>
public int[] LiteralLengths;
/// <summary>
/// Huffman distance codes for the literal / length alphabet
/// </summary>
public int[] DistanceCodes;
}
}

View File

@@ -0,0 +1,25 @@
namespace BinaryObjectScanner.Models.Compression.MSZIP
{
public enum CompressionType : byte
{
/// <summary>
/// no compression
/// </summary>
NoCompression = 0b00,
/// <summary>
/// Compressed with fixed Huffman codes
/// </summary>
FixedHuffman = 0b01,
/// <summary>
/// Compressed with dynamic Huffman codes
/// </summary>
DynamicHuffman = 0b10,
/// <summary>
/// Reserved (error)
/// </summary>
Reserved = 0b11,
}
}

View File

@@ -0,0 +1,94 @@
using System;
namespace BinaryObjectScanner.Models.Compression.MSZIP
{
/// <summary>
/// Compression with fixed Huffman codes (BTYPE=01)
/// </summary>
/// <see href="https://interoperability.blob.core.windows.net/files/MS-MCI/%5bMS-MCI%5d.pdf"/>
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
public class FixedHuffmanCompressedBlockHeader
{
#region Properties
/// <summary>
/// Huffman code lengths for the literal / length alphabet
/// </summary>
public uint[] LiteralLengths
{
get
{
// If we have cached lengths, use those
if (_literalLengths != null)
return _literalLengths;
// Otherwise, build it from scratch
_literalLengths = new uint[288];
// Literal Value 0 - 143, 8 bits
for (int i = 0; i < 144; i++)
_literalLengths[i] = 8;
// Literal Value 144 - 255, 9 bits
for (int i = 144; i < 256; i++)
_literalLengths[i] = 9;
// Literal Value 256 - 279, 7 bits
for (int i = 256; i < 280; i++)
_literalLengths[i] = 7;
// Literal Value 280 - 287, 8 bits
for (int i = 280; i < 288; i++)
_literalLengths[i] = 8;
return _literalLengths;
}
set
{
throw new FieldAccessException();
}
}
/// <summary>
/// Huffman distance codes for the literal / length alphabet
/// </summary>
public uint[] DistanceCodes
{
get
{
// If we have cached distances, use those
if (_distanceCodes != null)
return _distanceCodes;
// Otherwise, build it from scratch
_distanceCodes = new uint[30];
// Fixed length, 5 bits
for (int i = 0; i < 30; i++)
_distanceCodes[i] = 5;
return _distanceCodes;
}
set
{
throw new FieldAccessException();
}
}
#endregion
#region Instance Variables
/// <summary>
/// Huffman code lengths for the literal / length alphabet
/// </summary>
private uint[] _literalLengths = null;
/// <summary>
/// Huffman distance codes for the literal / length alphabet
/// </summary>
private uint[] _distanceCodes = null;
#endregion
}
}

View File

@@ -0,0 +1,21 @@
namespace BinaryObjectScanner.Models.Compression.MSZIP
{
/// <summary>
/// Non-compressed blocks (BTYPE=00)
/// </summary>
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
public class NonCompressedBlockHeader
{
/// <summary>
/// The number of data bytes in the block
/// </summary>
/// <remarks>Bytes 0-1</remarks>
public ushort LEN;
/// <summary>
/// The one's complement of LEN
/// </summary>
/// <remarks>Bytes 2-3</remarks>
public ushort NLEN;
}
}

View File

@@ -0,0 +1,45 @@
namespace BinaryObjectScanner.Models.Compression.Quantum
{
public static class Constants
{
/// <summary>
/// Mask for Quantum Compression Level
/// </summary>
public const ushort MASK_QUANTUM_LEVEL = 0x00F0;
/// <summary>
/// Lowest Quantum Level (1)
/// </summary>
public const ushort QUANTUM_LEVEL_LO = 0x0010;
/// <summary>
/// Highest Quantum Level (7)
/// </summary>
public const ushort QUANTUM_LEVEL_HI = 0x0070;
/// <summary>
/// Amount to shift over to get int
/// </summary>
public const ushort SHIFT_QUANTUM_LEVEL = 4;
/// <summary>
/// Mask for Quantum Compression Memory
/// </summary>
public const ushort MASK_QUANTUM_MEM = 0x1F00;
/// <summary>
/// Lowest Quantum Memory (10)
/// </summary>
public const ushort QUANTUM_MEM_LO = 0x0A00;
/// <summary>
/// Highest Quantum Memory (21)
/// </summary>
public const ushort QUANTUM_MEM_HI = 0x1500;
/// <summary>
/// Amount to shift over to get int
/// </summary>
public const ushort SHIFT_QUANTUM_MEM = 8;
}
}

View File

@@ -0,0 +1,45 @@
namespace BinaryObjectScanner.Models.Compression.Quantum
{
public enum SelectorModel
{
/// <summary>
/// Literal model, 64 entries, start at symbol 0
/// </summary>
SELECTOR_0 = 0,
/// <summary>
/// Literal model, 64 entries, start at symbol 64
/// </summary>
SELECTOR_1 = 1,
/// <summary>
/// Literal model, 64 entries, start at symbol 128
/// </summary>
SELECTOR_2 = 2,
/// <summary>
/// Literal model, 64 entries, start at symbol 192
/// </summary>
SELECTOR_3 = 3,
/// <summary>
/// LZ model, 3 character matches, max 24 entries, start at symbol 0
/// </summary>
SELECTOR_4 = 4,
/// <summary>
/// LZ model, 4 character matches, max 36 entries, start at symbol 0
/// </summary>
SELECTOR_5 = 5,
/// <summary>
/// LZ model, 5+ character matches, max 42 entries, start at symbol 0
/// </summary>
SELECTOR_6_POSITION = 6,
/// <summary>
/// LZ model, 5+ character matches, 27 entries, start at symbol 0
/// </summary>
SELECTOR_6_LENGTH = 7,
}
}

View File

@@ -0,0 +1,15 @@
namespace BinaryObjectScanner.Models.Compression.Quantum
{
/// <see href="https://github.com/wine-mirror/wine/blob/master/dlls/cabinet/cabinet.h"/>
/// <see href="http://www.russotto.net/quantumcomp.html"/>
public sealed class Model
{
public int TimeToReorder;
public int Entries;
public ModelSymbol[] Symbols;
public ushort[] LookupTable = new ushort[256];
}
}

View File

@@ -0,0 +1,11 @@
namespace BinaryObjectScanner.Models.Compression.Quantum
{
/// <see href="https://github.com/wine-mirror/wine/blob/master/dlls/cabinet/cabinet.h"/>
/// <see href="http://www.russotto.net/quantumcomp.html"/>
public sealed class ModelSymbol
{
public ushort Symbol;
public ushort CumulativeFrequency;
}
}

View File

@@ -0,0 +1,31 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo.html"/>
public sealed class AudioSubPictureAttributesTable
{
/// <summary>
/// Number of title sets
/// </summary>
public ushort NumberOfTitleSets;
/// <summary>
/// Reserved
/// </summary>
public byte[] Reserved;
/// <summary>
/// End address (last byte of last VTS_ATRT)
/// </summary>
public uint EndAddress;
/// <summary>
/// Offset to VTS_ATRT n
/// </summary>
public uint[] Offsets;
/// <summary>
/// Entries
/// </summary>
public AudioSubPictureAttributesTableEntry[] Entries;
}
}

View File

@@ -0,0 +1,23 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo.html"/>
public sealed class AudioSubPictureAttributesTableEntry
{
/// <summary>
/// End address (EA)
/// </summary>
public uint EndAddress;
/// <summary>
/// VTS_CAT (copy of offset 022-025 of the VTS IFO file)
/// 0=unspecified, 1=Karaoke
/// </summary>
public uint Category;
/// <summary>
/// Copy of VTS attributes (offset 100 and on from the VTS IFO
/// file, usually 0x300 bytes long)
/// </summary>
public byte[] AttributesCopy;
}
}

26
DVD/CellAddressTable.cs Normal file
View File

@@ -0,0 +1,26 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo.html"/>
public sealed class CellAddressTable
{
/// <summary>
/// Number of VOB IDs
/// </summary>
public ushort NumberOfVOBIDs;
/// <summary>
/// Reserved
/// </summary>
public byte[] Reserved;
/// <summary>
/// End address (last byte of last entry)
/// </summary>
public uint EndAddress;
/// <summary>
/// 12-byte entries
/// </summary>
public CellAddressTableEntry[] Entries;
}
}

View File

@@ -0,0 +1,31 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo.html"/>
public sealed class CellAddressTableEntry
{
/// <summary>
/// VOBidn
/// </summary>
public ushort VOBIdentity;
/// <summary>
/// CELLidn
/// </summary>
public byte CellIdentity;
/// <summary>
/// Reserved
/// </summary>
public byte Reserved;
/// <summary>
/// Starting sector within VOB
/// </summary>
public uint StartingSectorWithinVOB;
/// <summary>
/// Ending sector within VOB
/// </summary>
public uint EndingSectorWithinVOB;
}
}

9
DVD/Constants.cs Normal file
View File

@@ -0,0 +1,9 @@
namespace BinaryObjectScanner.Models.DVD
{
public static class Constants
{
public const string VideoManagerIFOSignature = "DVDVIDEO-VMG";
public const string VideoTitleSetIFOSignature = "DVDVIDEO-VTS";
}
}

56
DVD/Enums.cs Normal file
View File

@@ -0,0 +1,56 @@
using System;
namespace BinaryObjectScanner.Models.DVD
{
[Flags]
public enum ProgramChainCategory : byte
{
MenuTypeTitle = 0x02,
Entry = 0x80,
}
[Flags]
public enum TitleType : byte
{
/// <summary>
/// Uop0 Time play or search
/// </summary>
Uop0TimePlayOrSearch = 0x01,
/// <summary>
/// Uop1 PTT play or search
/// </summary>
Uop1PTTPlayOrSearch = 0x02,
/// <summary>
/// Jump/Link/Call commands - exist
/// </summary>
JumpLinkCallExist = 0x04,
/// <summary>
/// Jump/Link/Call commands - button
/// </summary>
JumpLinkCallButton = 0x08,
/// <summary>
/// Jump/Link/Call commands - pre/post
/// </summary>
JumpLinkCallPrePost = 0x10,
/// <summary>
/// Jump/Link/Call commands - cell
/// </summary>
JumpLinkCallCell = 0x20,
/// <summary>
/// 0=one_sequential_pgc
/// 1=not one_sequential (random, shuffle, stills, loops, or more than one pgc)
/// </summary>
ComplexPGC = 0x40,
/// <summary>
/// Reserved
/// </summary>
Reserved = 0x80,
}
}

32
DVD/LanguageUnitTable.cs Normal file
View File

@@ -0,0 +1,32 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo_vmg.html"/>
public sealed class LanguageUnitTable
{
/// <summary>
/// Number of Language Units
/// </summary>
public ushort NumberOfLanguageUnits;
/// <summary>
/// Reserved
/// </summary>
public byte[] Reserved;
/// <summary>
/// End address (last byte of last PGC in last LU)
/// relative to VMGM_PGCI_UT
/// </summary>
public uint EndAddress;
/// <summary>
/// Language Units
/// </summary>
public LanguageUnitTableEntry[] Entries;
/// <summary>
/// Program Chains
/// </summary>
public ProgramChainTable[] ProgramChains;
}
}

View File

@@ -0,0 +1,26 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo_vmg.html"/>
public sealed class LanguageUnitTableEntry
{
/// <summary>
/// ISO639 language code
/// </summary>
public ushort ISO639LanguageCode;
/// <summary>
/// Reserved for language code extension
/// </summary>
public byte Reserved;
/// <summary>
/// Menu existence flag [80 = title]
/// </summary>
public byte MenuExistenceFlag;
/// <summary>
/// Offset to VMGM_LU, relative to VMGM_PGCI_UT
/// </summary>
public uint LanguageUnitOffset;
}
}

View File

@@ -0,0 +1,37 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <summary>
/// The VMG_PTL_MAIT is searched by country, and points to
/// the table for each country.
/// </summary>
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo_vmg.html"/>
public sealed class ParentalManagementMasksTable
{
/// <summary>
/// Number of countries
/// </summary>
public ushort NumberOfCountries;
/// <summary>
/// Number of title sets (NTs)
/// </summary>
public ushort NumberOfTitleSets;
/// <summary>
/// End address (last byte of last PTL_MAIT)
/// </summary>
public uint EndAddress;
/// <summary>
/// Entries
/// </summary>
public ParentalManagementMasksTableEntry[] Entries;
/// <summary>
/// The PTL_MAIT contains the 16-bit masks for the VMG and
/// all title sets for parental management level 8 followed
/// by the masks for level 7, and so on to level 1.
/// </summary>
public byte[][] BitMasks;
}
}

View File

@@ -0,0 +1,21 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo_vmg.html"/>
public sealed class ParentalManagementMasksTableEntry
{
/// <summary>
/// Country code
/// </summary>
public ushort CountryCode;
/// <summary>
/// Reserved
/// </summary>
public byte[] Reserved;
/// <summary>
/// Offset to PTL_MAIT
/// </summary>
public uint Offset;
}
}

27
DVD/ProgramChainTable.cs Normal file
View File

@@ -0,0 +1,27 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo_vmg.html"/>
public sealed class ProgramChainTable
{
/// <summary>
/// Number of Program Chains
/// </summary>
public ushort NumberOfProgramChains;
/// <summary>
/// Reserved
/// </summary>
public byte[] Reserved;
/// <summary>
/// End address (last byte of last PGC in this LU)
/// relative to VMGM_LU
/// </summary>
public uint EndAddress;
/// <summary>
/// Program Chains
/// </summary>
public ProgramChainTableEntry[] Entries;
}
}

View File

@@ -0,0 +1,26 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo_vmg.html"/>
public sealed class ProgramChainTableEntry
{
/// <summary>
/// PGC category
/// </summary>
public ProgramChainCategory Category;
/// <summary>
/// Unknown
/// </summary>
public byte Unknown;
/// <summary>
/// Parental management mask
/// </summary>
public ushort ParentalManagementMask;
/// <summary>
/// Offset to VMGM_PGC, relative to VMGM_LU
/// </summary>
public uint Offset;
}
}

26
DVD/TitlesTable.cs Normal file
View File

@@ -0,0 +1,26 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo_vmg.html"/>
public sealed class TitlesTable
{
/// <summary>
/// Number of titles
/// </summary>
public ushort NumberOfTitles;
/// <summary>
/// Reserved
/// </summary>
public byte[] Reserved;
/// <summary>
/// End address (last byte of last entry)
/// </summary>
public uint EndAddress;
/// <summary>
/// 12-byte entries
/// </summary>
public TitlesTableEntry[] Entries;
}
}

42
DVD/TitlesTableEntry.cs Normal file
View File

@@ -0,0 +1,42 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo_vmg.html"/>
public sealed class TitlesTableEntry
{
/// <summary>
/// Title type
/// </summary>
public TitleType TitleType;
/// <summary>
/// Number of angles
/// </summary>
public byte NumberOfAngles;
/// <summary>
/// Number of chapters (PTTs)
/// </summary>
public ushort NumberOfChapters;
/// <summary>
/// Parental management mask
/// </summary>
public ushort ParentalManagementMask;
/// <summary>
/// Video Title Set number (VTSN)
/// </summary>
public byte VideoTitleSetNumber;
/// <summary>
/// Title number within VTS (VTS_TTN)
/// </summary>
public byte TitleNumberWithinVTS;
/// <summary>
/// Start sector for VTS, referenced to whole disk
/// (video_ts.ifo starts at sector 00000000)
/// </summary>
public uint VTSStartSector;
}
}

16
DVD/VOBUAddressMap.cs Normal file
View File

@@ -0,0 +1,16 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo.html"/>
public sealed class VOBUAddressMap
{
/// <summary>
/// End address (last byte of last entry)
/// </summary>
public uint EndAddress;
/// <summary>
/// Starting sector within VOB of nth VOBU
/// </summary>
public uint[] StartingSectors;
}
}

150
DVD/VideoManagerIFO.cs Normal file
View File

@@ -0,0 +1,150 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo.html"/>
public sealed class VideoManagerIFO
{
/// <summary>
/// "DVDVIDEO-VMG"
/// </summary>
public string Signature;
/// <summary>
/// Last sector of VMG set (last sector of BUP)
/// </summary>
public uint LastVMGSetSector;
/// <summary>
/// Last sector of IFO
/// </summary>
public uint LastIFOSector;
/// <summary>
/// Version number
/// - Byte 0 - Reserved, should be 0
/// - Byte 1, Bits 7-4 - Major version number
/// - Byte 1, Bits 3-0 - Minor version number
/// </summary>
public ushort VersionNumber;
/// <summary>
/// VMG category
/// </summary>
/// <remarks>byte1=prohibited region mask</remarks>
public uint VMGCategory;
/// <summary>
/// Number of volumes
/// </summary>
public ushort NumberOfVolumes;
/// <summary>
/// Volume number
/// </summary>
public ushort VolumeNumber;
/// <summary>
/// Side ID
/// </summary>
public byte SideID;
/// <summary>
/// Number of title sets
/// </summary>
public ushort NumberOfTitleSets;
/// <summary>
/// Provider ID
/// </summary>
public byte[] ProviderID;
/// <summary>
/// VMG POS
/// </summary>
public ulong VMGPOS;
/// <summary>
/// End byte address of VMGI_MAT
/// </summary>
public uint InformationManagementTableEndByteAddress;
/// <summary>
/// Start address of FP_PGC (First Play program chain)
/// </summary>
public uint FirstPlayProgramChainStartAddress;
/// <summary>
/// Start sector of Menu VOB
/// </summary>
public uint MenuVOBStartSector;
/// <summary>
/// Sector pointer to TT_SRPT (table of titles)
/// </summary>
public uint TableOfTitlesSectorPointer;
/// <summary>
/// Sector pointer to VMGM_PGCI_UT (Menu Program Chain table)
/// </summary>
public uint MenuProgramChainTableSectorPointer;
/// <summary>
/// Sector pointer to VMG_PTL_MAIT (Parental Management masks)
/// </summary>
public uint ParentalManagementMasksSectorPointer;
/// <summary>
/// Sector pointer to VMG_VTS_ATRT (copies of VTS audio/sub-picture attributes)
/// </summary>
public uint AudioSubPictureAttributesSectorPointer;
/// <summary>
/// Sector pointer to VMG_TXTDT_MG (text data)
/// </summary>
public uint TextDataSectorPointer;
/// <summary>
/// Sector pointer to VMGM_C_ADT (menu cell address table)
/// </summary>
public uint MenuCellAddressTableSectorPointer;
/// <summary>
/// Sector pointer to VMGM_VOBU_ADMAP (menu VOBU address map)
/// </summary>
public uint MenuVOBUAddressMapSectorPointer;
/// <summary>
/// Video attributes of VMGM_VOBS
/// </summary>
public byte[] VideoAttributes;
/// <summary>
/// Number of audio streams in VMGM_VOBS
/// </summary>
public ushort NumberOfAudioStreams;
/// <summary>
/// Audio attributes of VMGM_VOBS
/// </summary>
public byte[][] AudioAttributes;
/// <summary>
/// Unknown
/// </summary>
public byte[] Unknown;
/// <summary>
/// Number of subpicture streams in VMGM_VOBS (0 or 1)
/// </summary>
public ushort NumberOfSubpictureStreams;
/// <summary>
/// Subpicture attributes of VMGM_VOBS
/// </summary>
public byte[] SubpictureAttributes;
/// <summary>
/// Reserved
/// </summary>
public byte[] Reserved;
}
}

160
DVD/VideoTitleSetIFO.cs Normal file
View File

@@ -0,0 +1,160 @@
namespace BinaryObjectScanner.Models.DVD
{
/// <see href="https://dvd.sourceforge.net/dvdinfo/ifo.html"/>
public sealed class VideoTitleSetIFO
{
/// <summary>
/// "DVDVIDEO-VTS"
/// </summary>
public string Signature;
/// <summary>
/// Last sector of title set (last sector of BUP)
/// </summary>
public uint LastTitleSetSector;
/// <summary>
/// Last sector of IFO
/// </summary>
public uint LastIFOSector;
/// <summary>
/// Version number
/// - Byte 0 - Reserved, should be 0
/// - Byte 1, Bits 7-4 - Major version number
/// - Byte 1, Bits 3-0 - Minor version number
/// </summary>
public ushort VersionNumber;
/// <summary>
/// VTS category
/// </summary>
/// <remarks>0=unspecified, 1=Karaoke</remarks>
public uint VMGCategory;
/// <summary>
/// Number of volumes
/// </summary>
public ushort NumberOfVolumes;
/// <summary>
/// Volume number
/// </summary>
public ushort VolumeNumber;
/// <summary>
/// Side ID
/// </summary>
public byte SideID;
/// <summary>
/// Number of title sets
/// </summary>
public ushort NumberOfTitleSets;
/// <summary>
/// Provider ID
/// </summary>
public byte[] ProviderID;
/// <summary>
/// VMG POS
/// </summary>
public ulong VMGPOS;
/// <summary>
/// End byte address of VTS_MAT
/// </summary>
public uint InformationManagementTableEndByteAddress;
/// <summary>
/// Start address of FP_PGC (First Play program chain)
/// </summary>
public uint FirstPlayProgramChainStartAddress;
/// <summary>
/// Start sector of Menu VOB
/// </summary>
public uint MenuVOBStartSector;
/// <summary>
/// Start sector of Title VOB
/// </summary>
public uint TitleVOBStartSector;
/// <summary>
/// Sector pointer to VTS_PTT_SRPT (table of Titles and Chapters)
/// </summary>
public uint TableOfTitlesAndChaptersSectorPointer;
/// <summary>
/// Sector pointer to VTS_PGCI (Title Program Chain table)
/// </summary>
public uint TitleProgramChainTableSectorPointer;
/// <summary>
/// Sector pointer to VTSM_PGCI_UT (Menu Program Chain table)
/// </summary>
public uint MenuProgramChainTableSectorPointer;
/// <summary>
/// Sector pointer to VTS_TMAPTI (time map)
/// </summary>
public uint TimeMapSectorPointer;
/// <summary>
/// Sector pointer to VTSM_C_ADT (menu cell address table)
/// </summary>
public uint MenuCellAddressTableSectorPointer;
/// <summary>
/// Sector pointer to VTSM_VOBU_ADMAP (menu VOBU address map)
/// </summary>
public uint MenuVOBUAddressMapSectorPointer;
/// <summary>
/// Sector pointer to VTS_C_ADT (title set cell address table)
/// </summary>
public uint TitleSetCellAddressTableSectorPointer;
/// <summary>
/// Sector pointer to VTS_VOBU_ADMAP (title set VOBU address map)
/// </summary>
public uint TitleSetVOBUAddressMapSectorPointer;
/// <summary>
/// Video attributes of VTSM_VOBS
/// </summary>
public byte[] VideoAttributes;
/// <summary>
/// Number of audio streams in VTSM_VOBS
/// </summary>
public ushort NumberOfAudioStreams;
/// <summary>
/// Audio attributes of VTSM_VOBS
/// </summary>
public byte[][] AudioAttributes;
/// <summary>
/// Unknown
/// </summary>
public byte[] Unknown;
/// <summary>
/// Number of subpicture streams in VTSM_VOBS (0 or 1)
/// </summary>
public ushort NumberOfSubpictureStreams;
/// <summary>
/// Subpicture attributes of VTSM_VOBS
/// </summary>
public byte[] SubpictureAttributes;
/// <summary>
/// Reserved
/// </summary>
public byte[] Reserved;
}
}

41
GCF/BlockEntry.cs Normal file
View File

@@ -0,0 +1,41 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class BlockEntry
{
/// <summary>
/// Flags for the block entry. 0x200F0000 == Not used.
/// </summary>
public uint EntryFlags;
/// <summary>
/// The offset for the data contained in this block entry in the file.
/// </summary>
public uint FileDataOffset;
/// <summary>
/// The length of the data in this block entry.
/// </summary>
public uint FileDataSize;
/// <summary>
/// The offset to the first data block of this block entry's data.
/// </summary>
public uint FirstDataBlockIndex;
/// <summary>
/// The next block entry in the series. (N/A if == BlockCount.)
/// </summary>
public uint NextBlockEntryIndex;
/// <summary>
/// The previous block entry in the series. (N/A if == BlockCount.)
/// </summary>
public uint PreviousBlockEntryIndex;
/// <summary>
/// The offset of the block entry in the directory.
/// </summary>
public uint DirectoryIndex;
}
}

46
GCF/BlockEntryHeader.cs Normal file
View File

@@ -0,0 +1,46 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class BlockEntryHeader
{
/// <summary>
/// Number of data blocks.
/// </summary>
public uint BlockCount;
/// <summary>
/// Number of data blocks that point to data.
/// </summary>
public uint BlocksUsed;
/// <summary>
/// Reserved
/// </summary>
public uint Dummy0;
/// <summary>
/// Reserved
/// </summary>
public uint Dummy1;
/// <summary>
/// Reserved
/// </summary>
public uint Dummy2;
/// <summary>
/// Reserved
/// </summary>
public uint Dummy3;
/// <summary>
/// Reserved
/// </summary>
public uint Dummy4;
/// <summary>
/// Header checksum.
/// </summary>
public uint Checksum;
}
}

19
GCF/BlockEntryMap.cs Normal file
View File

@@ -0,0 +1,19 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <remarks>
/// Part of version 5 but not version 6.
/// </remarks>
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class BlockEntryMap
{
/// <summary>
/// The previous block entry. (N/A if == BlockCount.)
/// </summary>
public uint PreviousBlockEntryIndex;
/// <summary>
/// The next block entry. (N/A if == BlockCount.)
/// </summary>
public uint NextBlockEntryIndex;
}
}

View File

@@ -0,0 +1,34 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <remarks>
/// Part of version 5 but not version 6.
/// </remarks>
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class BlockEntryMapHeader
{
/// <summary>
/// Number of data blocks.
/// </summary>
public uint BlockCount;
/// <summary>
/// Index of the first block entry.
/// </summary>
public uint FirstBlockEntryIndex;
/// <summary>
/// Index of the last block entry.
/// </summary>
public uint LastBlockEntryIndex;
/// <summary>
/// Reserved
/// </summary>
public uint Dummy0;
/// <summary>
/// Header checksum.
/// </summary>
public uint Checksum;
}
}

11
GCF/ChecksumEntry.cs Normal file
View File

@@ -0,0 +1,11 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class ChecksumEntry
{
/// <summary>
/// Checksum.
/// </summary>
public uint Checksum;
}
}

16
GCF/ChecksumHeader.cs Normal file
View File

@@ -0,0 +1,16 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class ChecksumHeader
{
/// <summary>
/// Always 0x00000001
/// </summary>
public uint Dummy0;
/// <summary>
/// Size of LPGCFCHECKSUMHEADER & LPGCFCHECKSUMMAPHEADER & in bytes.
/// </summary>
public uint ChecksumSize;
}
}

16
GCF/ChecksumMapEntry.cs Normal file
View File

@@ -0,0 +1,16 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class ChecksumMapEntry
{
/// <summary>
/// Number of checksums.
/// </summary>
public uint ChecksumCount;
/// <summary>
/// Index of first checksum.
/// </summary>
public uint FirstChecksumIndex;
}
}

26
GCF/ChecksumMapHeader.cs Normal file
View File

@@ -0,0 +1,26 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class ChecksumMapHeader
{
/// <summary>
/// Always 0x14893721
/// </summary>
public uint Dummy0;
/// <summary>
/// Always 0x00000001
/// </summary>
public uint Dummy1;
/// <summary>
/// Number of items.
/// </summary>
public uint ItemCount;
/// <summary>
/// Number of checksums.
/// </summary>
public uint ChecksumCount;
}
}

10
GCF/Constants.cs Normal file
View File

@@ -0,0 +1,10 @@
namespace BinaryObjectScanner.Models.GCF
{
public static class Constants
{
/// <summary>
/// The maximum data allowed in a 32 bit checksum.
/// </summary>
public const int HL_GCF_CHECKSUM_LENGTH = 0x00008000;
}
}

36
GCF/DataBlockHeader.cs Normal file
View File

@@ -0,0 +1,36 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class DataBlockHeader
{
/// <summary>
/// GCF file version. This field is not part of all file versions.
/// </summary>
public uint LastVersionPlayed;
/// <summary>
/// Number of data blocks.
/// </summary>
public uint BlockCount;
/// <summary>
/// Size of each data block in bytes.
/// </summary>
public uint BlockSize;
/// <summary>
/// Offset to first data block.
/// </summary>
public uint FirstBlockOffset;
/// <summary>
/// Number of data blocks that contain data.
/// </summary>
public uint BlocksUsed;
/// <summary>
/// Header checksum.
/// </summary>
public uint Checksum;
}
}

11
GCF/DirectoryCopyEntry.cs Normal file
View File

@@ -0,0 +1,11 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class DirectoryCopyEntry
{
/// <summary>
/// Index of the directory item.
/// </summary>
public uint DirectoryIndex;
}
}

46
GCF/DirectoryEntry.cs Normal file
View File

@@ -0,0 +1,46 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class DirectoryEntry
{
/// <summary>
/// Offset to the directory item name from the end of the directory items.
/// </summary>
public uint NameOffset;
/// <summary>
/// Directory item name from the end of the directory items.
/// </summary>
public string Name;
/// <summary>
/// Size of the item. (If file, file size. If folder, num items.)
/// </summary>
public uint ItemSize;
/// <summary>
/// Checksome index. (0xFFFFFFFF == None).
/// </summary>
public uint ChecksumIndex;
/// <summary>
/// Flags for the directory item. (0x00000000 == Folder).
/// </summary>
public HL_GCF_FLAG DirectoryFlags;
/// <summary>
/// Index of the parent directory item. (0xFFFFFFFF == None).
/// </summary>
public uint ParentIndex;
/// <summary>
/// Index of the next directory item. (0x00000000 == None).
/// </summary>
public uint NextIndex;
/// <summary>
/// Index of the first directory item. (0x00000000 == None).
/// </summary>
public uint FirstIndex;
}
}

76
GCF/DirectoryHeader.cs Normal file
View File

@@ -0,0 +1,76 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class DirectoryHeader
{
/// <summary>
/// Always 0x00000004
/// </summary>
public uint Dummy0;
/// <summary>
/// Cache ID.
/// </summary>
public uint CacheID;
/// <summary>
/// GCF file version.
/// </summary>
public uint LastVersionPlayed;
/// <summary>
/// Number of items in the directory.
/// </summary>
public uint ItemCount;
/// <summary>
/// Number of files in the directory.
/// </summary>
public uint FileCount;
/// <summary>
/// Always 0x00008000. Data per checksum?
/// </summary>
public uint Dummy1;
/// <summary>
/// Size of lpGCFDirectoryEntries & lpGCFDirectoryNames & lpGCFDirectoryInfo1Entries & lpGCFDirectoryInfo2Entries & lpGCFDirectoryCopyEntries & lpGCFDirectoryLocalEntries in bytes.
/// </summary>
public uint DirectorySize;
/// <summary>
/// Size of the directory names in bytes.
/// </summary>
public uint NameSize;
/// <summary>
/// Number of Info1 entires.
/// </summary>
public uint Info1Count;
/// <summary>
/// Number of files to copy.
/// </summary>
public uint CopyCount;
/// <summary>
/// Number of files to keep local.
/// </summary>
public uint LocalCount;
/// <summary>
/// Reserved
/// </summary>
public uint Dummy2;
/// <summary>
/// Reserved
/// </summary>
public uint Dummy3;
/// <summary>
/// Header checksum.
/// </summary>
public uint Checksum;
}
}

View File

@@ -0,0 +1,11 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class DirectoryInfo1Entry
{
/// <summary>
/// Reserved
/// </summary>
public uint Dummy0;
}
}

View File

@@ -0,0 +1,11 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class DirectoryInfo2Entry
{
/// <summary>
/// Reserved
/// </summary>
public uint Dummy0;
}
}

View File

@@ -0,0 +1,11 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class DirectoryLocalEntry
{
/// <summary>
/// Index of the directory item.
/// </summary>
public uint DirectoryIndex;
}
}

11
GCF/DirectoryMapEntry.cs Normal file
View File

@@ -0,0 +1,11 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class DirectoryMapEntry
{
/// <summary>
/// Index of the first data block. (N/A if == BlockCount.)
/// </summary>
public uint FirstBlockIndex;
}
}

19
GCF/DirectoryMapHeader.cs Normal file
View File

@@ -0,0 +1,19 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <remarks>
/// Added in version 4 or version 5.
/// </remarks>
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class DirectoryMapHeader
{
/// <summary>
/// Always 0x00000001
/// </summary>
public uint Dummy0;
/// <summary>
/// Always 0x00000000
/// </summary>
public uint Dummy1;
}
}

38
GCF/Enums.cs Normal file
View File

@@ -0,0 +1,38 @@
using System;
namespace BinaryObjectScanner.Models.GCF
{
[Flags]
public enum HL_GCF_FLAG : uint
{
/// <summary>
/// Folder
/// </summary>
HL_GCF_FLAG_FOLDER = 0x00000000,
/// <summary>
/// Don't overwrite the item if copying it to the disk and the item already exists.
/// </summary>
HL_GCF_FLAG_COPY_LOCAL_NO_OVERWRITE = 0x00000001,
/// <summary>
/// The item is to be copied to the disk.
/// </summary>
HL_GCF_FLAG_COPY_LOCAL = 0x0000000A,
/// <summary>
/// Backup the item before overwriting it.
/// </summary>
HL_GCF_FLAG_BACKUP_LOCAL = 0x00000040,
/// <summary>
/// The item is encrypted.
/// </summary>
HL_GCF_FLAG_ENCRYPTED = 0x00000100,
/// <summary>
/// The item is a file.
/// </summary>
HL_GCF_FLAG_FILE = 0x00004000,
}
}

118
GCF/File.cs Normal file
View File

@@ -0,0 +1,118 @@
using System.Collections.Generic;
namespace BinaryObjectScanner.Models.GCF
{
/// <summary>
/// Half-Life Game Cache File
/// </summary>
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class File
{
/// <summary>
/// Header data
/// </summary>
public Header Header { get; set; }
/// <summary>
/// Block entry header data
/// </summary>
public BlockEntryHeader BlockEntryHeader { get; set; }
/// <summary>
/// Block entries data
/// </summary>
public BlockEntry[] BlockEntries { get; set; }
/// <summary>
/// Fragmentation map header data
/// </summary>
public FragmentationMapHeader FragmentationMapHeader { get; set; }
/// <summary>
/// Fragmentation map data
/// </summary>
public FragmentationMap[] FragmentationMaps { get; set; }
/// <summary>
/// Block entry map header data
/// </summary>
/// <remarks>Part of version 5 but not version 6.</remarks>
public BlockEntryMapHeader BlockEntryMapHeader { get; set; }
/// <summary>
/// Block entry map data
/// </summary>
/// <remarks>Part of version 5 but not version 6.</remarks>
public BlockEntryMap[] BlockEntryMaps { get; set; }
/// <summary>
/// Directory header data
/// </summary>
public DirectoryHeader DirectoryHeader { get; set; }
/// <summary>
/// Directory entries data
/// </summary>
public DirectoryEntry[] DirectoryEntries { get; set; }
/// <summary>
/// Directory names data
/// </summary>
public Dictionary<long, string> DirectoryNames { get; set; }
/// <summary>
/// Directory info 1 entries data
/// </summary>
public DirectoryInfo1Entry[] DirectoryInfo1Entries { get; set; }
/// <summary>
/// Directory info 2 entries data
/// </summary>
public DirectoryInfo2Entry[] DirectoryInfo2Entries { get; set; }
/// <summary>
/// Directory copy entries data
/// </summary>
public DirectoryCopyEntry[] DirectoryCopyEntries { get; set; }
/// <summary>
/// Directory local entries data
/// </summary>
public DirectoryLocalEntry[] DirectoryLocalEntries { get; set; }
/// <summary>
/// Directory map header data
/// </summary>
public DirectoryMapHeader DirectoryMapHeader { get; set; }
/// <summary>
/// Directory map entries data
/// </summary>
public DirectoryMapEntry[] DirectoryMapEntries { get; set; }
/// <summary>
/// Checksum header data
/// </summary>
public ChecksumHeader ChecksumHeader { get; set; }
/// <summary>
/// Checksum map header data
/// </summary>
public ChecksumMapHeader ChecksumMapHeader { get; set; }
/// <summary>
/// Checksum map entries data
/// </summary>
public ChecksumMapEntry[] ChecksumMapEntries { get; set; }
/// <summary>
/// Checksum entries data
/// </summary>
public ChecksumEntry[] ChecksumEntries { get; set; }
/// <summary>
/// Data block header data
/// </summary>
public DataBlockHeader DataBlockHeader { get; set; }
}
}

11
GCF/FragmentationMap.cs Normal file
View File

@@ -0,0 +1,11 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class FragmentationMap
{
/// <summary>
/// The index of the next data block.
/// </summary>
public uint NextDataBlockIndex;
}
}

View File

@@ -0,0 +1,26 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class FragmentationMapHeader
{
/// <summary>
/// Number of data blocks.
/// </summary>
public uint BlockCount;
/// <summary>
/// The index of the first unused fragmentation map entry.
/// </summary>
public uint FirstUnusedEntry;
/// <summary>
/// The block entry terminator; 0 = 0x0000ffff or 1 = 0xffffffff.
/// </summary>
public uint Terminator;
/// <summary>
/// Header checksum.
/// </summary>
public uint Checksum;
}
}

61
GCF/Header.cs Normal file
View File

@@ -0,0 +1,61 @@
namespace BinaryObjectScanner.Models.GCF
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/GCFFile.h"/>
public sealed class Header
{
/// <summary>
/// Always 0x00000001
/// </summary>
public uint Dummy0;
/// <summary>
/// Always 0x00000001
/// </summary>
public uint MajorVersion;
/// <summary>
/// GCF version number.
/// </summary>
public uint MinorVersion;
/// <summary>
/// Cache ID
/// </summary>
public uint CacheID;
/// <summary>
/// Last version played
/// </summary>
public uint LastVersionPlayed;
/// <summary>
/// Reserved
/// </summary>
public uint Dummy1;
/// <summary>
/// Reserved
/// </summary>
public uint Dummy2;
/// <summary>
/// Total size of GCF file in bytes.
/// </summary>
public uint FileSize;
/// <summary>
/// Size of each data block in bytes.
/// </summary>
public uint BlockSize;
/// <summary>
/// Number of data blocks.
/// </summary>
public uint BlockCount;
/// <summary>
/// Reserved
/// </summary>
public uint Dummy3;
}
}

Some files were not shown because too many files have changed in this diff Show More