mirror of
https://github.com/SabreTools/SabreTools.Models.git
synced 2026-02-06 05:35:33 +00:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f18b6c8850 | ||
|
|
8f1e49e464 | ||
|
|
6547242f93 | ||
|
|
edf00f3ab2 | ||
|
|
bce4736037 | ||
|
|
81f28974c0 | ||
|
|
30ebe84af4 | ||
|
|
b07fbdedd6 | ||
|
|
cd8fff4a86 | ||
|
|
3d3275e3cb | ||
|
|
4c76ce1230 | ||
|
|
0c4e3b4bf2 | ||
|
|
e8f4386199 | ||
|
|
ab66ccf3c5 | ||
|
|
cc60d54a33 | ||
|
|
e805f4cb9a | ||
|
|
328c893a38 | ||
|
|
ab2a12c996 | ||
|
|
362b123661 | ||
|
|
4a8a4746a2 | ||
|
|
3f368a3be8 | ||
|
|
2749c2f5bd | ||
|
|
41ce962700 | ||
|
|
85b7103bd3 | ||
|
|
4c61a191e8 | ||
|
|
0f70598969 | ||
|
|
d6b057d808 | ||
|
|
3d8036e7b5 | ||
|
|
bb35946866 | ||
|
|
78f9f1b36f | ||
|
|
9d1b1ca36d | ||
|
|
6e1f8bf55e | ||
|
|
a19afc240c | ||
|
|
148e97ef64 | ||
|
|
676b446025 | ||
|
|
aeff75d8d3 | ||
|
|
e20e515f56 |
@@ -1,4 +1,4 @@
|
||||
name: Nuget Pack
|
||||
name: Build and Test
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -16,25 +16,22 @@ jobs:
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
dotnet-version: |
|
||||
6.0.x
|
||||
8.0.x
|
||||
9.0.x
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Pack
|
||||
run: dotnet pack
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'Nuget Package'
|
||||
path: 'SabreTools.Models/bin/Release/*.nupkg'
|
||||
- name: Run publish script
|
||||
run: ./publish-nix.sh
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
allowUpdates: True
|
||||
artifacts: 'SabreTools.Models/bin/Release/*.nupkg'
|
||||
artifacts: "*.nupkg,*.snupkg"
|
||||
body: 'Last built commit: ${{ github.sha }}'
|
||||
name: 'Rolling Release'
|
||||
prerelease: True
|
||||
10
.github/workflows/check_pr.yml
vendored
10
.github/workflows/check_pr.yml
vendored
@@ -11,7 +11,13 @@ jobs:
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
dotnet-version: |
|
||||
6.0.x
|
||||
8.0.x
|
||||
9.0.x
|
||||
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
run: dotnet build
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
# SabreTools.Models
|
||||
|
||||
[](https://github.com/SabreTools/SabreTools.Models/actions/workflows/build_and_test.yml)
|
||||
|
||||
This library comprises of models that represent either directly serializable or representative structures for all SabreTools projects. All of the main models representing metadata files should have parsers created outside of the current code.
|
||||
|
||||
Find the link to the Nuget package [here](https://www.nuget.org/packages/SabreTools.Models).
|
||||
|
||||
## Releases
|
||||
|
||||
For the most recent stable build, download the latest release here: [Releases Page](https://github.com/SabreTools/SabreTools.Models/releases)
|
||||
|
||||
For the latest WIP build here: [Rolling Release](https://github.com/SabreTools/SabreTools.Models/releases/rolling)
|
||||
|
||||
## Missing Metadata Models
|
||||
|
||||
The following metadata file formats do not have models included in this library yet and, as such, do not have serializers:
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace SabreTools.Models.Compression.Deflate
|
||||
{
|
||||
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
|
||||
public class BlockHeader
|
||||
{
|
||||
/// <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; }
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace SabreTools.Models.Compression.Deflate
|
||||
{
|
||||
/// <summary>
|
||||
/// Compression with Huffman codes (BTYPE=01 or BTYPE=02)
|
||||
/// </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 abstract class CompressedDataHeader : DataHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// Huffman code lengths for the literal / length alphabet
|
||||
/// </summary>
|
||||
public virtual uint[]? LiteralLengths { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Huffman distance codes for the literal / length alphabet
|
||||
/// </summary>
|
||||
public virtual uint[]? DistanceCodes { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
namespace SabreTools.Models.Compression.Deflate
|
||||
{
|
||||
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
|
||||
public static class Constants
|
||||
{
|
||||
/// <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 Fixed Huffman Codes
|
||||
|
||||
/// <summary>
|
||||
/// Fixed Huffman code lengths for the literal / length alphabet
|
||||
/// </summary>
|
||||
public static readonly uint[] FixedLiteralLengths =
|
||||
[
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Fixed Huffman distance codes for the literal / length alphabet
|
||||
/// </summary>
|
||||
public static readonly uint[] FixedDistanceCodes =
|
||||
[
|
||||
5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5,
|
||||
];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Literal and Length Alphabets
|
||||
|
||||
/// <summary>
|
||||
/// Extra bits for distance codes
|
||||
/// </summary>
|
||||
public static readonly ushort[] DistanceExtraBits =
|
||||
[
|
||||
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>
|
||||
/// Copy offsets for distance codes 0..29
|
||||
/// </summary>
|
||||
public static readonly ushort[] DistanceOffsets =
|
||||
[
|
||||
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 literal codes 257..285
|
||||
/// </summary>
|
||||
public static readonly ushort[] LiteralExtraBits =
|
||||
[
|
||||
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,
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Copy lengths for literal codes 257..285
|
||||
/// </summary>
|
||||
public static readonly ushort[] LiteralLengths =
|
||||
[
|
||||
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,
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Order of the bit length code lengths
|
||||
/// </summary>
|
||||
public static readonly byte[] BitLengthOrder =
|
||||
[
|
||||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
||||
];
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace SabreTools.Models.Compression.Deflate
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for all data headers (BTYPE=00, BTYPE=01, or BTYPE=02)
|
||||
/// </summary>
|
||||
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
|
||||
public abstract class DataHeader
|
||||
{
|
||||
// No common fields between all data headers
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace SabreTools.Models.Compression.Deflate
|
||||
{
|
||||
/// <summary>
|
||||
/// Compression with dynamic Huffman codes (BTYPE=10)
|
||||
/// </summary>
|
||||
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
|
||||
public class DynamicCompressedDataHeader : CompressedDataHeader
|
||||
{
|
||||
// Codes are provided externally
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
namespace SabreTools.Models.Compression.Deflate
|
||||
{
|
||||
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
namespace SabreTools.Models.Compression.Deflate
|
||||
{
|
||||
/// <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 FixedCompressedDataHeader : CompressedDataHeader
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Huffman code lengths for the literal / length alphabet
|
||||
/// </summary>
|
||||
public override uint[]? LiteralLengths => Constants.FixedLiteralLengths;
|
||||
|
||||
/// <summary>
|
||||
/// Huffman distance codes for the literal / length alphabet
|
||||
/// </summary>
|
||||
public override uint[]? DistanceCodes => Constants.FixedDistanceCodes;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
namespace SabreTools.Models.Compression.Deflate
|
||||
{
|
||||
/// <summary>
|
||||
/// Non-compressed blocks (BTYPE=00)
|
||||
/// </summary>
|
||||
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
|
||||
public class NonCompressedBlockHeader : DataHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of data bytes in the block
|
||||
/// </summary>
|
||||
/// <remarks>Bytes 0-1</remarks>
|
||||
public ushort LEN { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The one's complement of LEN
|
||||
/// </summary>
|
||||
/// <remarks>Bytes 2-3</remarks>
|
||||
public ushort NLEN { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
namespace SabreTools.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 = [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;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace SabreTools.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,
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SabreTools.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"/>
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public sealed class FileHeaader
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
|
||||
public string? Magic;
|
||||
|
||||
public byte CompressionType;
|
||||
|
||||
[MarshalAs(UnmanagedType.U1)]
|
||||
public char LastChar;
|
||||
|
||||
public uint RealLength;
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace SabreTools.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; }
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
namespace SabreTools.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 Block
|
||||
{
|
||||
/// <summary>
|
||||
/// Block header
|
||||
/// </summary>
|
||||
public BlockHeader? BlockHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Compressed blocks
|
||||
/// </summary>
|
||||
public DeflateBlock[]? CompressedBlocks { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,18 @@ namespace SabreTools.Models.Compression.MSZIP
|
||||
/// 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
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace SabreTools.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>
|
||||
/// And'ing with Zipmask[n] masks the lower n bits
|
||||
/// </summary>
|
||||
public static readonly ushort[] BitMasks =
|
||||
[
|
||||
0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
|
||||
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
namespace SabreTools.Models.Compression.MSZIP
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <see href="https://interoperability.blob.core.windows.net/files/MS-MCI/%5bMS-MCI%5d.pdf"/>
|
||||
public class DeflateBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Deflate block (RFC-1951) header
|
||||
/// </summary>
|
||||
public Deflate.BlockHeader? Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Compression-specific data header
|
||||
/// </summary>
|
||||
public Deflate.DataHeader? DataHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// MSZIP data
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Depending on the implementation of these models, this property could either be
|
||||
/// compressed or uncompressed data. Keep this in mind when using the built
|
||||
/// versions of this model.
|
||||
/// </remarks>
|
||||
public byte[]? Data { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,9 @@ namespace SabreTools.Models.DosCenter
|
||||
[Required]
|
||||
public string? CRC { get; set; }
|
||||
|
||||
/// <remarks>sha1, attribute</remarks>
|
||||
public string? SHA1 { get; set; }
|
||||
|
||||
/// <remarks>date, attribute</remarks>
|
||||
public string? Date { get; set; }
|
||||
}
|
||||
|
||||
17
SabreTools.Models/LZ/Constants.cs
Normal file
17
SabreTools.Models/LZ/Constants.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace SabreTools.Models.LZ
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
public const string KWAJPrefix = "KWAJ";
|
||||
|
||||
public static readonly byte[] KWAJSignatureBytes = [0x4B, 0x57, 0x41, 0x4A, 0x88, 0xF0, 0x27, 0xD1];
|
||||
|
||||
public const string QBasicPrefix = "SZ ";
|
||||
|
||||
public static readonly byte[] QBasicSignatureBytes = [0x53, 0x5A, 0x20, 0x88, 0xF0, 0x27, 0x33, 0xD1];
|
||||
|
||||
public const string SZDDPrefix = "SZDD";
|
||||
|
||||
public static readonly byte[] SZDDSignatureBytes = [0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33];
|
||||
}
|
||||
}
|
||||
82
SabreTools.Models/LZ/Enums.cs
Normal file
82
SabreTools.Models/LZ/Enums.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Models.LZ
|
||||
{
|
||||
/// <see href="https://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html"/>
|
||||
public enum KWAJCompressionType : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// No compression
|
||||
/// </summary>
|
||||
NoCompression = 0,
|
||||
|
||||
/// <summary>
|
||||
/// No compression, data is XORed with byte 0xFF
|
||||
/// </summary>
|
||||
NoCompressionXor = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The same compression method as the QBasic variant of SZDD
|
||||
/// </summary>
|
||||
QBasic = 2,
|
||||
|
||||
/// <summary>
|
||||
/// LZ + Huffman "Jeff Johnson" compression
|
||||
/// </summary>
|
||||
LZH = 3,
|
||||
|
||||
/// <summary>
|
||||
/// MS-ZIP
|
||||
/// </summary>
|
||||
MSZIP = 4,
|
||||
}
|
||||
|
||||
/// <see href="https://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html"/>
|
||||
[Flags]
|
||||
public enum KWAJHeaderFlags : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Header extensions contains 4-byte decompressed length
|
||||
/// </summary>
|
||||
HasDecompressedLength = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// Header extensions contains 2-byte unknown value
|
||||
/// </summary>
|
||||
HasUnknownFlag = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// Header extensions contains 2-byte prefix followed by
|
||||
/// that many bytes of (unknown purpose) data
|
||||
/// </summary>
|
||||
HasPrefixedData = 0x0004,
|
||||
|
||||
/// <summary>
|
||||
/// Header extensions contains null-terminated string of
|
||||
/// max length 8 representing the file name
|
||||
/// </summary>
|
||||
HasFileName = 0x0008,
|
||||
|
||||
/// <summary>
|
||||
/// Header extensions contains null-terminated string of
|
||||
/// max length 3 representing the file name
|
||||
/// </summary>
|
||||
HasFileExtension = 0x0010,
|
||||
|
||||
/// <summary>
|
||||
/// Header extensions contains 2-byte prefix followed by
|
||||
/// that many bytes of (arbitrary text) data
|
||||
/// </summary>
|
||||
HasAdditionalText = 0x0020,
|
||||
}
|
||||
|
||||
/// <see href="https://github.com/wine-mirror/wine/blob/master/dlls/kernel32/lzexpand.c"/>
|
||||
/// <see href="https://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html"/>
|
||||
public enum ExpandCompressionType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Only valid compression type: 'A'
|
||||
/// </summary>
|
||||
A = 0x41,
|
||||
}
|
||||
}
|
||||
21
SabreTools.Models/LZ/KWAJFile.cs
Normal file
21
SabreTools.Models/LZ/KWAJFile.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace SabreTools.Models.LZ
|
||||
{
|
||||
/// <summary>
|
||||
/// LZ variant with variable compression
|
||||
/// </summary>
|
||||
/// <see href="https://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html"/>
|
||||
public sealed class KWAJFile
|
||||
{
|
||||
/// <summary>
|
||||
/// Header
|
||||
/// </summary>
|
||||
public KWAJHeader? Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional extensions defined by <see cref="KWAJHeader.HeaderFlags"/>
|
||||
/// </summary>
|
||||
public KWAJHeaderExtensions? HeaderExtensions { get; set; }
|
||||
|
||||
// Followed immediately by compressed data
|
||||
}
|
||||
}
|
||||
35
SabreTools.Models/LZ/KWAJHeader.cs
Normal file
35
SabreTools.Models/LZ/KWAJHeader.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SabreTools.Models.LZ
|
||||
{
|
||||
/// <summary>
|
||||
/// LZ variant with variable compression
|
||||
/// </summary>
|
||||
/// <see href="https://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html"/>
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public sealed class KWAJHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// "KWAJ" signature
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
|
||||
public byte[]? Magic;
|
||||
|
||||
/// <summary>
|
||||
/// Compression method
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.U2)]
|
||||
public KWAJCompressionType CompressionType;
|
||||
|
||||
/// <summary>
|
||||
/// File offset of compressed data
|
||||
/// </summary>
|
||||
public ushort DataOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Header flags to mark header extensions
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.U2)]
|
||||
public KWAJHeaderFlags HeaderFlags;
|
||||
}
|
||||
}
|
||||
51
SabreTools.Models/LZ/KWAJHeaderExtensions.cs
Normal file
51
SabreTools.Models/LZ/KWAJHeaderExtensions.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
namespace SabreTools.Models.LZ
|
||||
{
|
||||
/// <summary>
|
||||
/// Additional information stored after the KWAJ header
|
||||
/// </summary>
|
||||
/// <see href="https://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html"/>
|
||||
public sealed class KWAJHeaderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Decompressed length of file
|
||||
/// </summary>
|
||||
public uint? DecompressedLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unknown purpose
|
||||
/// </summary>
|
||||
public ushort? UnknownPurpose { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of <see cref="UnknownData"/>
|
||||
/// </summary>
|
||||
public ushort? UnknownDataLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unknown purpose data whose length is defined
|
||||
/// by <see cref="UnknownDataLength"/>
|
||||
/// </summary>
|
||||
public byte[]? UnknownData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Null-terminated string with max length 8: file name
|
||||
/// </summary>
|
||||
public string? FileName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Null-terminated string with max length 3: file extension
|
||||
/// </summary>
|
||||
public string? FileExtension { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of <see cref="ArbitraryText"/>
|
||||
/// </summary>
|
||||
public ushort? ArbitraryTextLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Arbitrary text data whose length is defined
|
||||
/// by <see cref="ArbitraryTextLength"/>
|
||||
/// </summary>
|
||||
public byte[]? ArbitraryText { get; set; }
|
||||
}
|
||||
}
|
||||
16
SabreTools.Models/LZ/QBasicFile.cs
Normal file
16
SabreTools.Models/LZ/QBasicFile.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace SabreTools.Models.LZ
|
||||
{
|
||||
/// <summary>
|
||||
/// LZ variant used in QBasic 4.5 installer
|
||||
/// </summary>
|
||||
/// <see href="https://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html"/>
|
||||
public sealed class QBasicFile
|
||||
{
|
||||
/// <summary>
|
||||
/// Header
|
||||
/// </summary>
|
||||
public QBasicHeader? Header { get; set; }
|
||||
|
||||
// Followed immediately by compressed data
|
||||
}
|
||||
}
|
||||
23
SabreTools.Models/LZ/QBasicHeader.cs
Normal file
23
SabreTools.Models/LZ/QBasicHeader.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SabreTools.Models.LZ
|
||||
{
|
||||
/// <summary>
|
||||
/// LZ variant used in QBasic 4.5 installer
|
||||
/// </summary>
|
||||
/// <see href="https://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html"/>
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public sealed class QBasicHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// "SZ" signature
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
|
||||
public byte[]? Magic;
|
||||
|
||||
/// <summary>
|
||||
/// The integer length of the file when unpacked
|
||||
/// </summary>
|
||||
public uint RealLength;
|
||||
}
|
||||
}
|
||||
17
SabreTools.Models/LZ/SZDDFile.cs
Normal file
17
SabreTools.Models/LZ/SZDDFile.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace SabreTools.Models.LZ
|
||||
{
|
||||
/// <summary>
|
||||
/// Standard LZ variant
|
||||
/// </summary>
|
||||
/// <see href="https://github.com/wine-mirror/wine/blob/master/dlls/kernel32/lzexpand.c"/>
|
||||
/// <see href="https://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html"/>
|
||||
public sealed class SZDDFile
|
||||
{
|
||||
/// <summary>
|
||||
/// Header
|
||||
/// </summary>
|
||||
public SZDDHeader? Header { get; set; }
|
||||
|
||||
// Followed immediately by compressed data
|
||||
}
|
||||
}
|
||||
38
SabreTools.Models/LZ/SZDDHeader.cs
Normal file
38
SabreTools.Models/LZ/SZDDHeader.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SabreTools.Models.LZ
|
||||
{
|
||||
/// <summary>
|
||||
/// Standard LZ variant
|
||||
/// </summary>
|
||||
/// <see href="https://github.com/wine-mirror/wine/blob/master/dlls/kernel32/lzexpand.c"/>
|
||||
/// <see href="https://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html"/>
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public sealed class SZDDHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// "SZDD" signature
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
|
||||
public byte[]? Magic;
|
||||
|
||||
/// <summary>
|
||||
/// Compression mode
|
||||
/// </summary>
|
||||
/// <remarks>Only <see cref="ExpandCompressionType.A"/> is supported</remarks>
|
||||
[MarshalAs(UnmanagedType.U1)]
|
||||
public ExpandCompressionType CompressionType;
|
||||
|
||||
/// <summary>
|
||||
/// The character missing from the end of the filename
|
||||
/// </summary>
|
||||
/// <remarks>0 means unknown</remarks>
|
||||
[MarshalAs(UnmanagedType.U1)]
|
||||
public char LastChar;
|
||||
|
||||
/// <summary>
|
||||
/// The integer length of the file when unpacked
|
||||
/// </summary>
|
||||
public uint RealLength;
|
||||
}
|
||||
}
|
||||
16
SabreTools.Models/Listxml/Mess.cs
Normal file
16
SabreTools.Models/Listxml/Mess.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace SabreTools.Models.Listxml
|
||||
{
|
||||
[XmlRoot("mess")]
|
||||
public class Mess
|
||||
{
|
||||
[XmlAttribute("version")]
|
||||
public string? Version { get; set; }
|
||||
|
||||
[XmlElement("machine", typeof(Machine))]
|
||||
[XmlElement("game", typeof(Game))]
|
||||
public GameBase[]? Game { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,9 @@ namespace SabreTools.Models.Logiqx
|
||||
[XmlAttribute("name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[XmlElement("dir", typeof(Game))]
|
||||
public Dir[]? Subdir { get; set; }
|
||||
|
||||
[XmlElement("game", typeof(Game))]
|
||||
[XmlElement("machine", typeof(Machine))]
|
||||
public GameBase[]? Game { get; set; }
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace SabreTools.Models.Metadata
|
||||
|
||||
string[]? asArray = Read<string[]>(key);
|
||||
if (asArray != null)
|
||||
#if NETFRAMEWORK
|
||||
#if NETFRAMEWORK || NETSTANDARD2_0
|
||||
return string.Join(",", asArray);
|
||||
#else
|
||||
return string.Join(',', asArray);
|
||||
|
||||
@@ -4,6 +4,16 @@ namespace SabreTools.Models.PlayStation3
|
||||
/// <see href="https://psdevwiki.com/ps3/PS3_DISC.SFB"/>
|
||||
public static class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifying bytes for SFO file
|
||||
/// </summary>
|
||||
public const uint SFOMagic = 0x00505346;
|
||||
|
||||
/// <summary>
|
||||
/// Identifying bytes for SFB file
|
||||
/// </summary>
|
||||
public const uint SFBMagic = 0x2E534642;
|
||||
|
||||
#region Hybrid Flags
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,8 +9,7 @@ namespace SabreTools.Models.PlayStation3
|
||||
/// <summary>
|
||||
/// ".SFB"
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public byte[]? Magic;
|
||||
public uint Magic;
|
||||
|
||||
/// <summary>
|
||||
/// File version(?)
|
||||
|
||||
@@ -9,8 +9,7 @@ namespace SabreTools.Models.PlayStation3
|
||||
/// <summary>
|
||||
/// "\0PSF"
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public byte[]? Magic;
|
||||
public uint Magic;
|
||||
|
||||
/// <summary>
|
||||
/// Version
|
||||
|
||||
237
SabreTools.Models/PlayStation4/AppPkgHeader.cs
Normal file
237
SabreTools.Models/PlayStation4/AppPkgHeader.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SabreTools.Models.PlayStation4
|
||||
{
|
||||
/// <see href="https://www.psdevwiki.com/ps4/PKG_files"/>
|
||||
/// <remarks>All numeric values are big-endian</remarks>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class AppPkgHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifying bytes for app.pkg file, "\7FCNT"
|
||||
/// </summary>
|
||||
public uint Magic;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Type
|
||||
/// </summary>
|
||||
public uint Type;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Unknown Field
|
||||
/// </summary>
|
||||
public uint PKGUnknown;
|
||||
|
||||
/// <summary>
|
||||
/// PKG File count
|
||||
/// </summary>
|
||||
public uint FileCount;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Entry count
|
||||
/// </summary>
|
||||
public uint EntryCount;
|
||||
|
||||
/// <summary>
|
||||
/// SC Entry count
|
||||
/// </summary>
|
||||
public ushort SCEntryCount;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Entry count (duplicated)
|
||||
/// </summary>
|
||||
public ushort EntryCount2;
|
||||
|
||||
/// <summary>
|
||||
/// PKG File Table offset
|
||||
/// </summary>
|
||||
public uint TableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Entry data size
|
||||
/// </summary>
|
||||
public uint EntryDataSize;
|
||||
|
||||
/// <summary>
|
||||
/// Offset of PKG Entries
|
||||
/// </summary>
|
||||
public ulong BodyOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Length of all PKG Entries
|
||||
/// </summary>
|
||||
public ulong BodySize;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Content offset
|
||||
/// </summary>
|
||||
public ulong ContentOffset;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Content size
|
||||
/// </summary>
|
||||
public ulong ContentSize;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Content ID
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x24)]
|
||||
public string? ContentID;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Content Padding (Zeroes)
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xC)]
|
||||
public byte[]? ContentZeroes;
|
||||
|
||||
/// <summary>
|
||||
/// PKG DRM Type
|
||||
/// </summary>
|
||||
public uint DRMType;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Content Type
|
||||
/// </summary>
|
||||
public uint ContentType;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Content Flags
|
||||
/// </summary>
|
||||
public uint ContentFlags;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Promote Size
|
||||
/// </summary>
|
||||
public uint PromoteSize;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Version Date
|
||||
/// </summary>
|
||||
public uint VersionDate;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Content Flags
|
||||
/// </summary>
|
||||
public uint VersionHash;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Padding Section 1
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x78)]
|
||||
public byte[]? Zeroes1;
|
||||
|
||||
/// <summary>
|
||||
/// PKG SHA256 for Main Entry 1
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
|
||||
public byte[]? MainEntry1SHA256;
|
||||
|
||||
/// <summary>
|
||||
/// PKG SHA256 for Main Entry 2
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
|
||||
public byte[]? MainEntry2SHA256;
|
||||
|
||||
/// <summary>
|
||||
/// PKG SHA256 for Digest Table
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
|
||||
public byte[]? DigestTableSHA256;
|
||||
|
||||
/// <summary>
|
||||
/// PKG SHA256 for Main Table
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
|
||||
public byte[]? MainTableSHA256;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Padding Section 2
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x280)]
|
||||
public byte[]? Zeroes2;
|
||||
|
||||
/// <summary>
|
||||
/// PFS Unknown Field
|
||||
/// </summary>
|
||||
public uint PFSUnknown;
|
||||
|
||||
/// <summary>
|
||||
/// PFS Image Count
|
||||
/// </summary>
|
||||
public uint PFSImageCount;
|
||||
|
||||
/// <summary>
|
||||
/// PFS Image Flags
|
||||
/// </summary>
|
||||
public ulong PFSImageFlags;
|
||||
|
||||
/// <summary>
|
||||
/// PFS Image Offset
|
||||
/// </summary>
|
||||
public ulong PFSImageOffset;
|
||||
|
||||
/// <summary>
|
||||
/// PFS Image Size
|
||||
/// </summary>
|
||||
public ulong PFSImageSize;
|
||||
|
||||
/// <summary>
|
||||
/// Mount Image Offset
|
||||
/// </summary>
|
||||
public ulong MountImageOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Mount Image Size
|
||||
/// </summary>
|
||||
public ulong MountImageSize;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Size
|
||||
/// </summary>
|
||||
public ulong PKGSize;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Signed Size
|
||||
/// </summary>
|
||||
public uint PKGSignedSize;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Signed Size
|
||||
/// </summary>
|
||||
public uint PKGCacheSize;
|
||||
|
||||
/// <summary>
|
||||
/// SHA256 for PFS Image
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
|
||||
public byte[]? PFSImageSHA256;
|
||||
|
||||
/// <summary>
|
||||
/// SHA256 for PFS Signed
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
|
||||
public byte[]? PFSSignedSHA256;
|
||||
|
||||
/// <summary>
|
||||
/// PFS Split Size nth 0
|
||||
/// </summary>
|
||||
public ulong PFSSplitSize0;
|
||||
|
||||
/// <summary>
|
||||
/// PFS Split Size nth 1
|
||||
/// </summary>
|
||||
public ulong PFSSplitSize1;
|
||||
|
||||
/// <summary>
|
||||
/// PKG Padding Section 3
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xB50)]
|
||||
public byte[]? Zeroes3;
|
||||
|
||||
/// <summary>
|
||||
/// SHA256 for PKG
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
|
||||
public byte[]? PKGSHA256;
|
||||
}
|
||||
}
|
||||
11
SabreTools.Models/PlayStation4/Constants.cs
Normal file
11
SabreTools.Models/PlayStation4/Constants.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace SabreTools.Models.PlayStation4
|
||||
{
|
||||
/// <see href="https://www.psdevwiki.com/ps4/PKG_files"/>
|
||||
public class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifying bytes for app.pkg file, "\7FCNT"
|
||||
/// </summary>
|
||||
public const uint AppPkgMagic = 0x7F434E54;
|
||||
}
|
||||
}
|
||||
@@ -2,17 +2,19 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<NoWarn>CS0618</NoWarn>
|
||||
<NoWarn>CS0618;NETSDK1215</NoWarn>
|
||||
<Nullable>enable</Nullable>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>1.5.5</Version>
|
||||
<Version>1.6.0</Version>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Description>Common models used by other SabreTools projects</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2022-2024</Copyright>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2022-2025</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryUrl>https://github.com/SabreTools/SabreTools.Models</RepositoryUrl>
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.Models.SafeDisc
|
||||
namespace SabreTools.Models.SafeDisc
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
|
||||
122
SabreTools.Models/SecuROM/Constants.cs
Normal file
122
SabreTools.Models/SecuROM/Constants.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
|
||||
namespace SabreTools.Models.SecuROM
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
#region DFA
|
||||
|
||||
public static readonly string DFAMagicString = "SDFA" + (char)0x04 + (char)0x00 + (char)0x00 + (char)0x00;
|
||||
|
||||
public static readonly byte[] DFAMagicBytes = [0x53, 0x44, 0x46, 0x41, 0x04, 0x00, 0x00, 0x00];
|
||||
|
||||
#region Keys
|
||||
|
||||
/// <summary>
|
||||
/// 128-bit value, possibly a GUID
|
||||
/// </summary>
|
||||
public const string COID = "COID";
|
||||
|
||||
/// <summary>
|
||||
/// 128-bit value, possibly a GUID
|
||||
/// </summary>
|
||||
/// <remarks>Only a value of D0 A2 25 C7 16 20 B7 43 99 74 2A BB 39 6B C3 57 has been found</remarks>
|
||||
public const string CUID = "CUID";
|
||||
|
||||
/// <summary>
|
||||
/// Encrypted data section
|
||||
/// </summary>
|
||||
public const string DATA = "DATA";
|
||||
|
||||
/// <summary>
|
||||
/// Header version (?)
|
||||
/// </summary>
|
||||
/// <remarks>Only a value of 0C 00 00 00 has been found</remarks>
|
||||
public const string HVER = "HVER";
|
||||
|
||||
/// <summary>
|
||||
/// Unknown value
|
||||
/// </summary>
|
||||
public const string INVE = "INVE";
|
||||
|
||||
/// <summary>
|
||||
/// Unknown key value
|
||||
/// </summary>
|
||||
public const string KEYB = "KEYB";
|
||||
|
||||
/// <summary>
|
||||
/// Unknown key value
|
||||
/// </summary>
|
||||
public const string KEYL = "KEYL";
|
||||
|
||||
/// <summary>
|
||||
/// MAC address (?)
|
||||
/// </summary>
|
||||
public const string MAC1 = "MAC1";
|
||||
|
||||
/// <summary>
|
||||
/// MAC address (?)
|
||||
/// </summary>
|
||||
public const string MAC2 = "MAC2";
|
||||
|
||||
/// <summary>
|
||||
/// Padding section
|
||||
/// </summary>
|
||||
/// <remarks>Only a length of 832 has been found</remarks>
|
||||
public const string PAD1 = "PAD1";
|
||||
|
||||
/// <summary>
|
||||
/// Private key ID (?)
|
||||
/// </summary>
|
||||
public const string PKID = "PKID";
|
||||
|
||||
/// <summary>
|
||||
/// Private key name (?)
|
||||
/// </summary>
|
||||
/// <remarks>Seemingly a UTF-16 string</remarks>
|
||||
public const string PKNA = "PKNA";
|
||||
|
||||
/// <summary>
|
||||
/// Size of the decrypted executable
|
||||
/// </summary>
|
||||
public const string RAWS = "RAWS";
|
||||
|
||||
/// <summary>
|
||||
/// 128-bit value, possibly a GUID
|
||||
/// </summary>
|
||||
/// <remarks>Only a value of all zeroes has been found</remarks>
|
||||
public const string SCID = "SCID";
|
||||
|
||||
/// <summary>
|
||||
/// Time stored in NTFS filetime
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sysinfo/file-times"/>
|
||||
public const string TIME = "TIME";
|
||||
|
||||
/// <summary>
|
||||
/// First URL to connect to
|
||||
/// </summary>
|
||||
public const string UR01 = "UR01";
|
||||
|
||||
/// <summary>
|
||||
/// Second URL to connect to
|
||||
/// </summary>
|
||||
public const string UR02 = "UR02";
|
||||
|
||||
/// <summary>
|
||||
/// Unknown value
|
||||
/// </summary>
|
||||
public const string XSPF = "XSPF";
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Matroshka
|
||||
|
||||
public const string MatroshkaMagicString = "MatR";
|
||||
|
||||
public static readonly byte[] MatroshkaMagicBytes = [0x4D, 0x61, 0x74, 0x52];
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
24
SabreTools.Models/SecuROM/DFAEntry.cs
Normal file
24
SabreTools.Models/SecuROM/DFAEntry.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace SabreTools.Models.SecuROM
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single key-length-value tuple in a
|
||||
/// SecuROM DFA file
|
||||
/// </summary>
|
||||
public class DFAEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Entry name, always 4 ASCII characters
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of the value in bytes
|
||||
/// </summary>
|
||||
public uint Length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Value of the entry whose length is given by <see cref="Length"/>
|
||||
/// </summary>
|
||||
public byte[]? Value { get; set; }
|
||||
}
|
||||
}
|
||||
27
SabreTools.Models/SecuROM/DFAFile.cs
Normal file
27
SabreTools.Models/SecuROM/DFAFile.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
namespace SabreTools.Models.SecuROM
|
||||
{
|
||||
/// <remarks>
|
||||
/// Most DFA-protected files seem to also have additional encryption,
|
||||
/// possibly SecuROM DFE. Only early RC-encrypted executables can be
|
||||
/// parsed beyond the initial header.
|
||||
/// </remarks>
|
||||
public class DFAFile
|
||||
{
|
||||
/// <summary>
|
||||
/// "SDFA" 0x04 0x00 0x00 0x00
|
||||
/// </summary>
|
||||
/// <remarks>8 bytes</remarks>
|
||||
public byte[]? Signature { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unknown value, possibly a block or header size
|
||||
/// </summary>
|
||||
/// <remarks>Only a value of 0x400 has been found</remarks>
|
||||
public uint BlockOrHeaderSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// All entries in the file
|
||||
/// </summary>
|
||||
public DFAEntry[]? Entries { get; set; }
|
||||
}
|
||||
}
|
||||
36
SabreTools.Models/SecuROM/Enums.cs
Normal file
36
SabreTools.Models/SecuROM/Enums.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace SabreTools.Models.SecuROM
|
||||
{
|
||||
public enum MatroshkaEntryType : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper or activation executable
|
||||
/// </summary>
|
||||
Helper = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// Main executable, usually one of the following:
|
||||
/// - RC-encrypted executable to be decrypted later
|
||||
/// - Main game program executable
|
||||
/// - Revoker executable
|
||||
/// </summary>
|
||||
/// <remarks>Usually the second entry</remarks>
|
||||
Main = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// Required libraries for the main executable
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Examples include:
|
||||
/// - DFA.dll for RC-encrypted executables
|
||||
/// - paul.dll for PA-protected games
|
||||
/// - remover.exe for revocation
|
||||
/// executables.
|
||||
/// </remarks>
|
||||
Dependency = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// Similar use to <see cref="Dependency"/>
|
||||
/// </summary>
|
||||
Unknown0x08 = 0x08,
|
||||
}
|
||||
}
|
||||
59
SabreTools.Models/SecuROM/MatroshkaEntry.cs
Normal file
59
SabreTools.Models/SecuROM/MatroshkaEntry.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
namespace SabreTools.Models.SecuROM
|
||||
{
|
||||
public class MatroshkaEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// File entry path, either 256 or 512 bytes
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Versions without a key prefix are 256 bytes.
|
||||
/// Versions with key values either are 256 or 512 bytes.
|
||||
/// </remarks>
|
||||
public byte[]? Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Type of the entry data
|
||||
/// </summary>
|
||||
public MatroshkaEntryType EntryType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Data size
|
||||
/// </summary>
|
||||
public uint Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Data offset within the package
|
||||
/// </summary>
|
||||
public uint Offset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unknown value only seen in later versions
|
||||
/// </summary>
|
||||
/// <remarks>Possibly indicates that the offset is a 64-bit value</remarks>
|
||||
public uint? Unknown { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File modification time, stored in NTFS filetime.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sysinfo/file-times"/>
|
||||
public ulong ModifiedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File creation time, stored in NTFS filetime.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sysinfo/file-times"/>
|
||||
public ulong CreatedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File access time, stored in NTFS filetime.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sysinfo/file-times"/>
|
||||
public ulong AccessedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// MD5 hash of the data
|
||||
/// </summary>
|
||||
/// <remarks>16 bytes</remarks>
|
||||
public byte[]? MD5 { get; set; }
|
||||
}
|
||||
}
|
||||
79
SabreTools.Models/SecuROM/MatroshkaPackage.cs
Normal file
79
SabreTools.Models/SecuROM/MatroshkaPackage.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
namespace SabreTools.Models.SecuROM
|
||||
{
|
||||
/// <summary>
|
||||
/// Securom Matroschka Package PE section
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Offered by SecuROM, its main purpose seems to be managing some sort
|
||||
/// of SecuROM-related operation involving multiple temporary files
|
||||
/// contained within the package. Observed in Release Control executables,
|
||||
/// Product Activation Revocation executables, and in some regular
|
||||
/// Product-Activation-protected releases (such as the digital download
|
||||
/// releases of Neverwinter Nights 2 and Test Drive Unlimited) where the
|
||||
/// game executable, paul.dll and other PA-related files are stored in
|
||||
/// the matroschka package.
|
||||
/// </remarks>
|
||||
public class MatroshkaPackage
|
||||
{
|
||||
/// <summary>
|
||||
/// "MatR"
|
||||
/// </summary>
|
||||
/// <remarks>4 bytes</remarks>
|
||||
public string? Signature { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of internal entries
|
||||
/// </summary>
|
||||
public uint EntryCount { get; set; }
|
||||
|
||||
#region Release Control only
|
||||
|
||||
// The combination of the 3 following values have only been seen in
|
||||
// one of 3 distinct patterns. The meaning of these patterns is unknown.
|
||||
// - 0 0 1
|
||||
// - 0 1 1
|
||||
// - 1 1 1
|
||||
// These values do not seem to have a link to whether the paths included
|
||||
// in entries are 256- or 512-byte. There also do not seem to be any links
|
||||
// between these values and the hex string values.
|
||||
|
||||
/// <summary>
|
||||
/// One of four unknown values only observed on RC matroschka sections
|
||||
/// </summary>
|
||||
/// <remarks>Only values of 0 or 1 have been found</remarks>
|
||||
public uint? UnknownRCValue1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// One of four unknown values only observed on RC matroschka sections
|
||||
/// </summary>
|
||||
/// <remarks>Only values of 0 or 1 have been found</remarks>
|
||||
public uint? UnknownRCValue2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// One of four unknown values only observed on RC matroschka sections
|
||||
/// </summary>
|
||||
/// <remarks>Only a value of 1 has been found</remarks>
|
||||
public uint? UnknownRCValue3 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 32-character hex string
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Due to encryption on later DFA-encrypted RC executables, this is the
|
||||
/// most reliable way to identify which executables are using the same key.
|
||||
/// </remarks>
|
||||
public string? KeyHexString { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Padding for alignment, always 0x00000000
|
||||
/// </summary>
|
||||
public uint? Padding { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Entries array whose length is given by <see cref="EntryCount"/>
|
||||
/// </summary>
|
||||
public MatroshkaEntry[]? Entries { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user