mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-02-05 05:37:46 +00:00
Compare commits
128 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
281c18e21d | ||
|
|
1a9c8b5392 | ||
|
|
831a272f4b | ||
|
|
f47e68b9ba | ||
|
|
eaabd2ee77 | ||
|
|
a269edd6ea | ||
|
|
3bb501ce0c | ||
|
|
d0006a4653 | ||
|
|
c48a1394bc | ||
|
|
fcf7fcfd44 | ||
|
|
cca08e7103 | ||
|
|
b908732f5c | ||
|
|
4ee4a6e85f | ||
|
|
7990f11bab | ||
|
|
427f7c9136 | ||
|
|
f938f1593d | ||
|
|
480a1834ed | ||
|
|
df5acc648c | ||
|
|
10569e6aa1 | ||
|
|
e5103b4830 | ||
|
|
513646fc53 | ||
|
|
27f723bf2f | ||
|
|
6511ecb5ad | ||
|
|
7bf6e6f344 | ||
|
|
d3e340ae39 | ||
|
|
22167a9617 | ||
|
|
48bea55133 | ||
|
|
42239919e5 | ||
|
|
4840d9df6e | ||
|
|
1378b87ea6 | ||
|
|
6b48164b97 | ||
|
|
50b09aa249 | ||
|
|
ecbd147f6d | ||
|
|
c13df79848 | ||
|
|
48bcc1de5b | ||
|
|
d082f5de25 | ||
|
|
c2321669b6 | ||
|
|
e382635b85 | ||
|
|
b4e02d7f8c | ||
|
|
0dc8a0b6c0 | ||
|
|
171834986d | ||
|
|
97af686b73 | ||
|
|
7d627ffc6f | ||
|
|
d924f25eb2 | ||
|
|
abd8ef3b1f | ||
|
|
e9b8dba3a6 | ||
|
|
aaff7e7332 | ||
|
|
2fa00d1a16 | ||
|
|
8a2a2ecd12 | ||
|
|
98517bdd8c | ||
|
|
dfe76f7e7e | ||
|
|
a2e24b1f5f | ||
|
|
6a4e76e245 | ||
|
|
1ebec97e0e | ||
|
|
b9f03b02f0 | ||
|
|
2c06760778 | ||
|
|
3f0ee70b71 | ||
|
|
05b34f158b | ||
|
|
e08db935b4 | ||
|
|
47da068bd3 | ||
|
|
9de669606d | ||
|
|
a02d50e61d | ||
|
|
069dab7fba | ||
|
|
d65edadbbb | ||
|
|
6307a51c0a | ||
|
|
d27c602bdf | ||
|
|
59fe9cb113 | ||
|
|
b4b7ba75cb | ||
|
|
d02e0c16c4 | ||
|
|
4aa0eb54b7 | ||
|
|
c4f73abcb6 | ||
|
|
73dec51a4d | ||
|
|
b7c3c094ae | ||
|
|
97702ab3d5 | ||
|
|
a9b5fe706c | ||
|
|
198d48610c | ||
|
|
c0e0344914 | ||
|
|
d49b2f1b60 | ||
|
|
ec7172466b | ||
|
|
d75a512ead | ||
|
|
af8b6906b6 | ||
|
|
96bc301e6d | ||
|
|
c10749f34d | ||
|
|
0e4235c8ba | ||
|
|
b2d31bb87e | ||
|
|
3ee88793da | ||
|
|
ad0f01c3ef | ||
|
|
63a96a7cf8 | ||
|
|
b8d8ca9a5c | ||
|
|
6b0fca31ae | ||
|
|
c147b12b10 | ||
|
|
7884b0b775 | ||
|
|
9f3c263328 | ||
|
|
b830ce3d73 | ||
|
|
e8b7f33bf0 | ||
|
|
eae75c5943 | ||
|
|
c1f5ebcae1 | ||
|
|
acb8e98fe2 | ||
|
|
a24a92e97c | ||
|
|
f2d2fe97bb | ||
|
|
705252eec7 | ||
|
|
69ae0456f0 | ||
|
|
f07bd07cce | ||
|
|
9db2d2ca05 | ||
|
|
85248b0135 | ||
|
|
8663edc7df | ||
|
|
b9cc9e40fd | ||
|
|
5ce085ad2b | ||
|
|
d24f8a2fce | ||
|
|
a73e830209 | ||
|
|
146fb42fd0 | ||
|
|
5b54ed719e | ||
|
|
02d011228e | ||
|
|
07adfd20a3 | ||
|
|
1d00abd6cc | ||
|
|
36c2cc2f15 | ||
|
|
27cf01ce84 | ||
|
|
1e94163693 | ||
|
|
db1f94775b | ||
|
|
ce394eb4e9 | ||
|
|
15109bed88 | ||
|
|
8a18c8de34 | ||
|
|
2f093a80c7 | ||
|
|
5df1af9c17 | ||
|
|
d5ab37a5a6 | ||
|
|
ed9ecf0da9 | ||
|
|
4fc17197ca | ||
|
|
94a9cf0c3f |
10
.github/workflows/build_and_test.yml
vendored
10
.github/workflows/build_and_test.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
@@ -27,6 +27,14 @@ jobs:
|
||||
- name: Run publish script
|
||||
run: ./publish-nix.sh -d
|
||||
|
||||
- name: Update rolling tag
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git tag -f rolling
|
||||
git push origin :refs/tags/rolling || true
|
||||
git push origin rolling --force
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "SabreTools.Serialization/_EXTERNAL/stormlibsharp"]
|
||||
path = SabreTools.Serialization/_EXTERNAL/stormlibsharp
|
||||
url = https://github.com/robpaveza/stormlibsharp.git
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>2.0.2</Version>
|
||||
<Version>2.1.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Support All Frameworks -->
|
||||
@@ -29,11 +29,6 @@
|
||||
|
||||
<!-- These are needed for dealing with native Windows DLLs -->
|
||||
<ItemGroup Condition="'$(RuntimeIdentifier)'=='win-x86'">
|
||||
<ContentWithTargetPath Include="..\SabreTools.Serialization\runtimes\win-x86\native\CascLib.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
<TargetPath>CascLib.dll</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
<ContentWithTargetPath Include="..\SabreTools.Serialization\runtimes\win-x86\native\StormLib.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
@@ -41,11 +36,6 @@
|
||||
</ContentWithTargetPath>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(RuntimeIdentifier)'=='win-x64'">
|
||||
<ContentWithTargetPath Include="..\SabreTools.Serialization\runtimes\win-x64\native\CascLib.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
<TargetPath>CascLib.dll</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
<ContentWithTargetPath Include="..\SabreTools.Serialization\runtimes\win-x64\native\StormLib.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
@@ -59,7 +49,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.3.2]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.7.6]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.8.0]" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.9" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace ExtractionTool.Features
|
||||
try
|
||||
{
|
||||
int read = stream.Read(magic, 0, 16);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
stream.SeekIfPossible(0, SeekOrigin.Begin);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -165,6 +165,11 @@ namespace ExtractionTool.Features
|
||||
bzip2.Extract(OutputPath, Debug);
|
||||
break;
|
||||
|
||||
// CD-ROM bin file
|
||||
case CDROM cdrom:
|
||||
cdrom.Extract(OutputPath, Debug);
|
||||
break;
|
||||
|
||||
// CFB
|
||||
case CFB cfb:
|
||||
cfb.Extract(OutputPath, Debug);
|
||||
@@ -190,6 +195,11 @@ namespace ExtractionTool.Features
|
||||
iscab.Extract(OutputPath, Debug);
|
||||
break;
|
||||
|
||||
// ISO 9660 volume
|
||||
case ISO9660 iso9660:
|
||||
iso9660.Extract(OutputPath, Debug);
|
||||
break;
|
||||
|
||||
// LZ-compressed file, KWAJ variant
|
||||
case LZKWAJ kwaj:
|
||||
kwaj.Extract(OutputPath, Debug);
|
||||
@@ -284,6 +294,11 @@ namespace ExtractionTool.Features
|
||||
case XZP xzp:
|
||||
xzp.Extract(OutputPath, Debug);
|
||||
break;
|
||||
|
||||
// ZSTD
|
||||
case ZSTD zstd:
|
||||
zstd.Extract(OutputPath, Debug);
|
||||
break;
|
||||
|
||||
// Everything else
|
||||
default:
|
||||
|
||||
@@ -159,8 +159,7 @@ namespace InfoPrint.Features
|
||||
using Stream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
|
||||
// Read the first 8 bytes
|
||||
byte[]? magic = stream.ReadBytes(8);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
byte[] magic = stream.PeekBytes(8);
|
||||
|
||||
// Get the file type
|
||||
string extension = Path.GetExtension(file).TrimStart('.');
|
||||
@@ -203,7 +202,7 @@ namespace InfoPrint.Features
|
||||
}
|
||||
|
||||
// Only print to console if enabled
|
||||
if (FileOnly)
|
||||
if (!FileOnly)
|
||||
Console.WriteLine(builder);
|
||||
|
||||
using var sw = new StreamWriter(File.OpenWrite($"{filenameBase}.txt"));
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>2.0.2</Version>
|
||||
<Version>2.1.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Support All Frameworks -->
|
||||
@@ -34,7 +34,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.3.2]" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="[1.5.1]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.7.6]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.8.0]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -9,7 +9,7 @@ Find the link to the Nuget package [here](https://www.nuget.org/packages/SabreTo
|
||||
The following non-project libraries (or ports thereof) are used for file handling:
|
||||
|
||||
- [GrindCore.SharpCompress](https://github.com/Nanook/GrindCore.SharpCompress) - Common archive format extraction
|
||||
- [StormLibSharp](https://github.com/robpaveza/stormlibsharp) - MoPaQ extraction [Unused in .NET Framework 2.0/3.5/4.0 and non-Windows builds due to Windows-specific libraries]
|
||||
- [StormLibSharp](https://github.com/robpaveza/stormlibsharp) - MoPaQ extraction [Unused in non-Windows builds due to Windows-specific libraries]
|
||||
|
||||
The following projects have influenced this library:
|
||||
|
||||
@@ -66,7 +66,7 @@ Options:
|
||||
| InstallShield CAB | |
|
||||
| Microsoft cabinet file | Does not support LZX or Quantum compression |
|
||||
| Microsoft LZ-compressed files | KWAJ, QBasic, and SZDD variants |
|
||||
| MoPaQ game data archive (MPQ) | Windows only. .NET Framework 4.5.2 and above |
|
||||
| MoPaQ game data archive (MPQ) | Windows only |
|
||||
| New Exectuable | Embedded archives and executables in the overlay and Wise installer |
|
||||
| NovaLogic Game Archive Format (PFF) | |
|
||||
| PKZIP and derived files (ZIP, etc.) | .NET Framework 4.6.2 and greater |
|
||||
@@ -99,8 +99,8 @@ Below is a table representing the various non-conversion interfaces that are imp
|
||||
|
||||
| Interface Name | Purpose |
|
||||
| --- | --- |
|
||||
| `SabreTools.Data.Printers.IPrinter<TModel>` | Provides a formatted output for a `TModel` |
|
||||
| `SabreTools.Serialization.Wrappers.IExtractable` | Marks a wrapper as able to be extracted |
|
||||
| `SabreTools.Serialization.Wrappers.IPrintable` | Marks a wrapper as able to print model information |
|
||||
| `SabreTools.Serialization.Wrappers.IWrapper` | Represents an item with a description and JSON serializable state, allowing for extensions |
|
||||
| `SabreTools.Serialization.Wrappers.IWrapper<TModel>` | Wraps a model with source data, allowing for extensions |
|
||||
|
||||
@@ -114,7 +114,6 @@ Below is a table of all namespaces within the library and what they represent
|
||||
| `SabreTools.Data.Extensions` | Extension methods related to models |
|
||||
| `SabreTools.Data.Models` | Models representing different file and structure types |
|
||||
| `SabreTools.Data.ObjectIdentifier` | Object Identifier (OID) parsing |
|
||||
| `SabreTools.Data.Printers` | Export model information in a formatted manner |
|
||||
| `SabreTools.Serialization.CrossModel` | Convert between models; mainly used for metadata files converting to and from a common, `Dictionary`-based model |
|
||||
| `SabreTools.Serialization.Interfaces` | Interfaces used commonly throughout the library |
|
||||
| `SabreTools.Serialization.Readers` | Convert from external sources to models |
|
||||
|
||||
73
SabreTools.Serialization.Test/Readers/ISO9660Tests.cs
Normal file
73
SabreTools.Serialization.Test/Readers/ISO9660Tests.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SabreTools.Serialization.Readers;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.Serialization.Test.Readers
|
||||
{
|
||||
public class ISO9660Tests
|
||||
{
|
||||
[Fact]
|
||||
public void NullArray_Null()
|
||||
{
|
||||
byte[]? data = null;
|
||||
int offset = 0;
|
||||
var deserializer = new ISO9660();
|
||||
|
||||
var actual = deserializer.Deserialize(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyArray_Null()
|
||||
{
|
||||
byte[]? data = [];
|
||||
int offset = 0;
|
||||
var deserializer = new ISO9660();
|
||||
|
||||
var actual = deserializer.Deserialize(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidArray_Null()
|
||||
{
|
||||
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
|
||||
int offset = 0;
|
||||
var deserializer = new ISO9660();
|
||||
|
||||
var actual = deserializer.Deserialize(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NullStream_Null()
|
||||
{
|
||||
Stream? data = null;
|
||||
var deserializer = new ISO9660();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([]);
|
||||
var deserializer = new ISO9660();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
|
||||
var deserializer = new ISO9660();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SabreTools.Serialization.Readers;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.Serialization.Test.Readers
|
||||
{
|
||||
public class InstallShieldExecutableFileTests
|
||||
{
|
||||
[Fact]
|
||||
public void NullArray_Null()
|
||||
{
|
||||
byte[]? data = null;
|
||||
int offset = 0;
|
||||
var deserializer = new InstallShieldExecutableFile();
|
||||
|
||||
var actual = deserializer.Deserialize(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyArray_Null()
|
||||
{
|
||||
byte[]? data = [];
|
||||
int offset = 0;
|
||||
var deserializer = new InstallShieldExecutableFile();
|
||||
|
||||
var actual = deserializer.Deserialize(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidArray_Null()
|
||||
{
|
||||
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
|
||||
int offset = 0;
|
||||
var deserializer = new InstallShieldExecutableFile();
|
||||
|
||||
var actual = deserializer.Deserialize(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NullStream_Null()
|
||||
{
|
||||
Stream? data = null;
|
||||
var deserializer = new InstallShieldExecutableFile();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([]);
|
||||
var deserializer = new InstallShieldExecutableFile();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
|
||||
var deserializer = new InstallShieldExecutableFile();
|
||||
|
||||
var actual = deserializer.Deserialize(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
61
SabreTools.Serialization.Test/Wrappers/CDROMTests.cs
Normal file
61
SabreTools.Serialization.Test/Wrappers/CDROMTests.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.Serialization.Test.Wrappers
|
||||
{
|
||||
public class CDROMTests
|
||||
{
|
||||
[Fact]
|
||||
public void NullArray_Null()
|
||||
{
|
||||
byte[]? data = null;
|
||||
int offset = 0;
|
||||
var actual = CDROM.Create(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyArray_Null()
|
||||
{
|
||||
byte[]? data = [];
|
||||
int offset = 0;
|
||||
var actual = CDROM.Create(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidArray_Null()
|
||||
{
|
||||
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
|
||||
int offset = 0;
|
||||
var actual = CDROM.Create(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NullStream_Null()
|
||||
{
|
||||
Stream? data = null;
|
||||
var actual = CDROM.Create(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([]);
|
||||
var actual = CDROM.Create(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
|
||||
var actual = CDROM.Create(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
61
SabreTools.Serialization.Test/Wrappers/ISO9660Tests.cs
Normal file
61
SabreTools.Serialization.Test/Wrappers/ISO9660Tests.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.Serialization.Test.Wrappers
|
||||
{
|
||||
public class ISO9660Tests
|
||||
{
|
||||
[Fact]
|
||||
public void NullArray_Null()
|
||||
{
|
||||
byte[]? data = null;
|
||||
int offset = 0;
|
||||
var actual = ISO9660.Create(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyArray_Null()
|
||||
{
|
||||
byte[]? data = [];
|
||||
int offset = 0;
|
||||
var actual = ISO9660.Create(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidArray_Null()
|
||||
{
|
||||
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
|
||||
int offset = 0;
|
||||
var actual = ISO9660.Create(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NullStream_Null()
|
||||
{
|
||||
Stream? data = null;
|
||||
var actual = ISO9660.Create(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([]);
|
||||
var actual = ISO9660.Create(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
|
||||
var actual = ISO9660.Create(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
61
SabreTools.Serialization.Test/Wrappers/SkeletonTests.cs
Normal file
61
SabreTools.Serialization.Test/Wrappers/SkeletonTests.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.Serialization.Test.Wrappers
|
||||
{
|
||||
public class SkeletonTests
|
||||
{
|
||||
[Fact]
|
||||
public void NullArray_Null()
|
||||
{
|
||||
byte[]? data = null;
|
||||
int offset = 0;
|
||||
var actual = Skeleton.Create(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyArray_Null()
|
||||
{
|
||||
byte[]? data = [];
|
||||
int offset = 0;
|
||||
var actual = Skeleton.Create(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidArray_Null()
|
||||
{
|
||||
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
|
||||
int offset = 0;
|
||||
var actual = Skeleton.Create(data, offset);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NullStream_Null()
|
||||
{
|
||||
Stream? data = null;
|
||||
var actual = Skeleton.Create(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([]);
|
||||
var actual = Skeleton.Create(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidStream_Null()
|
||||
{
|
||||
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
|
||||
var actual = Skeleton.Create(data);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
317
SabreTools.Serialization/Extensions/CDROM.cs
Normal file
317
SabreTools.Serialization/Extensions/CDROM.cs
Normal file
@@ -0,0 +1,317 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SabreTools.Data.Models.CDROM;
|
||||
using SabreTools.IO.Extensions;
|
||||
|
||||
namespace SabreTools.Data.Extensions
|
||||
{
|
||||
public static class CDROM
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the sector mode for a CD-ROM stream
|
||||
/// </summary>
|
||||
/// <param name="stream">Stream to derive the sector mode from</param>
|
||||
/// <returns>Sector mode from the stream on success, <see cref="SectorMode.UNKNOWN"/> on error</returns>
|
||||
public static SectorMode GetSectorMode(this Stream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte modeByte = stream.ReadByteValue();
|
||||
if (modeByte == 0)
|
||||
{
|
||||
return SectorMode.MODE0;
|
||||
}
|
||||
else if (modeByte == 1)
|
||||
{
|
||||
return SectorMode.MODE1;
|
||||
}
|
||||
else if (modeByte == 2)
|
||||
{
|
||||
stream.SeekIfPossible(2, SeekOrigin.Current);
|
||||
byte submode = stream.ReadByteValue();
|
||||
if ((submode & 0x20) == 0x20)
|
||||
return SectorMode.MODE2_FORM2;
|
||||
else
|
||||
return SectorMode.MODE2_FORM1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SectorMode.UNKNOWN;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore the actual error
|
||||
return SectorMode.UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the user data size for a sector mode
|
||||
/// </summary>
|
||||
/// <param name="mode">Sector mode to get a value for</param>
|
||||
/// <returns>User data size, if possible</returns>
|
||||
public static long GetUserDataSize(this SectorMode mode)
|
||||
{
|
||||
return mode switch
|
||||
{
|
||||
SectorMode.MODE0 => Constants.Mode0DataSize,
|
||||
SectorMode.MODE1 => Constants.Mode1DataSize,
|
||||
SectorMode.MODE2 => Constants.Mode0DataSize,
|
||||
SectorMode.MODE2_FORM1 => Constants.Mode2Form1DataSize,
|
||||
SectorMode.MODE2_FORM2 => Constants.Mode2Form2DataSize,
|
||||
_ => Constants.Mode0DataSize,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the user data end offset for a sector mode
|
||||
/// </summary>
|
||||
/// <param name="mode">Sector mode to get a value for</param>
|
||||
/// <returns>User data end offset, if possible</returns>
|
||||
public static long GetUserDataEnd(this SectorMode mode)
|
||||
{
|
||||
return mode switch
|
||||
{
|
||||
SectorMode.MODE0 => Constants.Mode0UserDataEnd, // TODO: Support flexible sector length (2352)
|
||||
SectorMode.MODE1 => Constants.Mode1UserDataEnd,
|
||||
SectorMode.MODE2 => Constants.Mode0UserDataEnd, // TODO: Support flexible sector length (2352)
|
||||
SectorMode.MODE2_FORM1 => Constants.Mode2Form1UserDataEnd,
|
||||
SectorMode.MODE2_FORM2 => Constants.Mode2Form2UserDataEnd, // TODO: Support flexible sector length (2348)
|
||||
_ => Constants.Mode0UserDataEnd,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the user data start offset for a sector mode
|
||||
/// </summary>
|
||||
/// <param name="mode">Sector mode to get a value for</param>
|
||||
/// <returns>User data start offset, if possible</returns>
|
||||
public static long GetUserDataStart(this SectorMode mode)
|
||||
{
|
||||
return mode switch
|
||||
{
|
||||
SectorMode.MODE0 => Constants.Mode0UserDataStart,
|
||||
SectorMode.MODE1 => Constants.Mode1UserDataStart,
|
||||
SectorMode.MODE2 => Constants.Mode0UserDataStart,
|
||||
SectorMode.MODE2_FORM1 => Constants.Mode2Form1UserDataStart,
|
||||
SectorMode.MODE2_FORM2 => Constants.Mode2Form2UserDataStart,
|
||||
_ => Constants.Mode0UserDataStart,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a stream that provides only the user data of a CDROM stream
|
||||
/// </summary>
|
||||
public class ISO9660Stream : Stream
|
||||
{
|
||||
// Base CDROM stream (2352-byte sector)
|
||||
private readonly Stream _baseStream;
|
||||
|
||||
// State variables
|
||||
private long _position = 0;
|
||||
private SectorMode _currentMode = SectorMode.UNKNOWN;
|
||||
private long _userDataStart = Constants.Mode1UserDataStart;
|
||||
private long _userDataEnd = Constants.Mode1UserDataEnd;
|
||||
private long _isoSectorSize = Constants.Mode1DataSize;
|
||||
|
||||
public ISO9660Stream(Stream inputStream)
|
||||
{
|
||||
if (!inputStream.CanSeek || !inputStream.CanRead)
|
||||
throw new ArgumentException("Stream must be readable and seekable.", nameof(inputStream));
|
||||
|
||||
_baseStream = inputStream;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool CanRead => _baseStream.CanRead;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool CanSeek => _baseStream.CanSeek;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool CanWrite => false;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Flush() => _baseStream.Flush();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_baseStream.Length / Constants.CDROMSectorSize) * _isoSectorSize;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException("Setting the length of this stream is not supported.");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException("Writing to this stream is not supported.");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
_baseStream.Dispose();
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override long Position
|
||||
{
|
||||
// Get the position of the underlying ISO9660 stream
|
||||
get
|
||||
{
|
||||
// Get the user data location based on the current sector mode
|
||||
SetState(_position);
|
||||
|
||||
// Get the number of ISO sectors before current position
|
||||
long isoPosition = (_position / Constants.CDROMSectorSize) * _isoSectorSize;
|
||||
|
||||
// Add the within-sector position
|
||||
long remainder = _position % Constants.CDROMSectorSize;
|
||||
if (remainder > _userDataEnd)
|
||||
isoPosition += _isoSectorSize;
|
||||
else if (remainder > _userDataStart)
|
||||
isoPosition += remainder - _userDataStart;
|
||||
|
||||
return isoPosition;
|
||||
}
|
||||
set
|
||||
{
|
||||
// Seek to the underlying ISO9660 position
|
||||
Seek(value, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int totalRead = 0;
|
||||
int remaining = count;
|
||||
|
||||
while (remaining > 0 && _position < _baseStream.Length)
|
||||
{
|
||||
// Determine location of current sector
|
||||
long baseStreamOffset = _position - (_position % Constants.CDROMSectorSize);
|
||||
|
||||
// Set the current sector's mode and user data location
|
||||
SetState(baseStreamOffset);
|
||||
|
||||
// Deal with case where base position is not in ISO stream
|
||||
long remainder = _position % Constants.CDROMSectorSize;
|
||||
long sectorOffset = remainder - _userDataStart;
|
||||
if (remainder < _userDataStart)
|
||||
{
|
||||
baseStreamOffset += _userDataStart;
|
||||
sectorOffset = 0;
|
||||
_position += _userDataStart;
|
||||
}
|
||||
else if (remainder >= _userDataEnd)
|
||||
{
|
||||
baseStreamOffset += Constants.CDROMSectorSize;
|
||||
sectorOffset = 0;
|
||||
_position += Constants.CDROMSectorSize - _userDataEnd + _userDataStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
baseStreamOffset += remainder;
|
||||
}
|
||||
|
||||
// Sanity check on read location before seeking
|
||||
if (baseStreamOffset < 0 || baseStreamOffset > _baseStream.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(offset), "Attempted to seek outside the stream boundaries.");
|
||||
|
||||
// Seek to target position in base CDROM stream
|
||||
_baseStream.SeekIfPossible(baseStreamOffset, SeekOrigin.Begin);
|
||||
|
||||
// Read the remaining bytes, up to max of one ISO sector (2048 bytes)
|
||||
int bytesToRead = (int)Math.Min(remaining, _isoSectorSize - sectorOffset);
|
||||
|
||||
// Don't overshoot end of stream
|
||||
bytesToRead = (int)Math.Min(bytesToRead, _baseStream.Length - _position);
|
||||
|
||||
// Finish reading if no more bytes to be read
|
||||
if (bytesToRead <= 0)
|
||||
break;
|
||||
|
||||
// Read up to 2048 bytes from base CDROM stream
|
||||
int bytesRead = _baseStream.Read(buffer, offset + totalRead, bytesToRead);
|
||||
|
||||
// Update state for base stream
|
||||
_position = _baseStream.Position;
|
||||
if (bytesToRead == (_isoSectorSize - sectorOffset))
|
||||
_position += (Constants.CDROMSectorSize - _userDataEnd) + _userDataStart;
|
||||
|
||||
// Update state for ISO stream
|
||||
totalRead += bytesRead;
|
||||
remaining -= bytesRead;
|
||||
|
||||
if (bytesRead == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
// Get the intended position for the ISO9660 stream
|
||||
long targetPosition = origin switch
|
||||
{
|
||||
SeekOrigin.Begin => offset,
|
||||
SeekOrigin.Current => Position + offset,
|
||||
SeekOrigin.End => Length + offset,
|
||||
_ => throw new ArgumentException("Invalid SeekOrigin.", nameof(origin)),
|
||||
};
|
||||
|
||||
// Get the number of ISO sectors before current position
|
||||
long newPosition = (targetPosition / _isoSectorSize) * Constants.CDROMSectorSize;
|
||||
|
||||
// Set the current sector's mode and user data location
|
||||
SetState(newPosition);
|
||||
|
||||
// Add the within-sector position
|
||||
newPosition += _userDataStart + (targetPosition % _isoSectorSize);
|
||||
if (newPosition < 0 || newPosition > _baseStream.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(offset), "Attempted to seek outside the stream boundaries.");
|
||||
|
||||
_position = _baseStream.SeekIfPossible(newPosition, SeekOrigin.Begin);
|
||||
return Position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the current stream state based on the location
|
||||
/// </summary>
|
||||
/// <param name="sectorLocation">Sector location to update from</param>
|
||||
private void SetState(long sectorLocation)
|
||||
{
|
||||
long current = _baseStream.Position;
|
||||
long modePosition = sectorLocation - (sectorLocation % Constants.CDROMSectorSize) + 15;
|
||||
|
||||
// Get the current sector mode
|
||||
_baseStream.SeekIfPossible(modePosition, SeekOrigin.Begin);
|
||||
_currentMode = _baseStream.GetSectorMode();
|
||||
|
||||
// Set the user data location variables
|
||||
_userDataStart = _currentMode.GetUserDataStart();
|
||||
_userDataEnd = _currentMode.GetUserDataEnd();
|
||||
// _isoSectorSize = _currentMode.GetUserDataSize();
|
||||
|
||||
// Reset the stream position
|
||||
_baseStream.SeekIfPossible(current, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
62
SabreTools.Serialization/Extensions/ISO9660.cs
Normal file
62
SabreTools.Serialization/Extensions/ISO9660.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using SabreTools.Data.Models.ISO9660;
|
||||
using SabreTools.Numerics;
|
||||
|
||||
namespace SabreTools.Data.Extensions
|
||||
{
|
||||
public static class ISO9660
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the logical block size from a sector length
|
||||
/// </summary>
|
||||
/// <param name="vd">Volume descriptor containing block information</param>
|
||||
/// <param name="sectorLength">Defined sector length</param>
|
||||
/// <returns>Size of a logical block</returns>
|
||||
public static short GetLogicalBlockSize(this VolumeDescriptor vd, short sectorLength)
|
||||
{
|
||||
BothInt16 blockSize;
|
||||
if (vd is PrimaryVolumeDescriptor pvd)
|
||||
blockSize = pvd.LogicalBlockSize;
|
||||
else if (vd is SupplementaryVolumeDescriptor svd)
|
||||
blockSize = svd.LogicalBlockSize;
|
||||
else
|
||||
return sectorLength;
|
||||
|
||||
// If the block size is inconsistent
|
||||
if (!blockSize.IsValid)
|
||||
{
|
||||
bool leValid = BlockSizeValid(blockSize.LittleEndian, sectorLength);
|
||||
bool beValid = BlockSizeValid(blockSize.BigEndian, sectorLength);
|
||||
|
||||
if (leValid && !beValid)
|
||||
blockSize = blockSize.LittleEndian;
|
||||
else if (beValid && !leValid)
|
||||
blockSize = blockSize.BigEndian;
|
||||
else
|
||||
return sectorLength;
|
||||
}
|
||||
|
||||
// Validate logical block size
|
||||
if (!BlockSizeValid(blockSize, sectorLength))
|
||||
blockSize = sectorLength;
|
||||
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if a block size is valid
|
||||
/// </summary>
|
||||
/// <param name="blockSize">Block length to check</param>
|
||||
/// <param name="sectorLength">Defined sector length</param>
|
||||
/// <returns>True if the block length is valid, false otherwise</returns>
|
||||
private static bool BlockSizeValid(short blockSize, short sectorLength)
|
||||
=> blockSize >= 512 && blockSize <= sectorLength && (blockSize & (blockSize - 1)) == 0;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if an array contains all ASCII numeric digits
|
||||
/// </summary>
|
||||
/// TODO: Move to IO as an array extension
|
||||
public static bool IsNumericArray(this byte[] arr)
|
||||
=> Array.TrueForAll(arr, b => b >= 0x30 && b <= 0x39);
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ namespace SabreTools.Data.Extensions
|
||||
obj.Offset = data.ReadUInt32LittleEndian(ref offset);
|
||||
obj.Timestamp = data.ReadUInt32LittleEndian(ref offset);
|
||||
obj.Age = data.ReadUInt32LittleEndian(ref offset);
|
||||
obj.PdbFileName = data.ReadNullTerminatedAnsiString(ref offset);
|
||||
obj.PdbFileName = data.ReadNullTerminatedAnsiString(ref offset) ?? string.Empty;
|
||||
|
||||
return obj;
|
||||
}
|
||||
@@ -142,7 +142,7 @@ namespace SabreTools.Data.Extensions
|
||||
|
||||
obj.GUID = data.ReadGuid(ref offset);
|
||||
obj.Age = data.ReadUInt32LittleEndian(ref offset);
|
||||
obj.PathAndFileName = data.ReadNullTerminatedUTF8String(ref offset);
|
||||
obj.PathAndFileName = data.ReadNullTerminatedUTF8String(ref offset) ?? string.Empty;
|
||||
|
||||
return obj;
|
||||
}
|
||||
@@ -260,7 +260,7 @@ namespace SabreTools.Data.Extensions
|
||||
offset += sizeof(ushort);
|
||||
|
||||
// Read the menu resource as a string
|
||||
dialogTemplateExtended.MenuResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogTemplateExtended.MenuResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the WORD boundary if we're not at the end
|
||||
entry.Data.AlignToBoundary(ref offset, 2);
|
||||
@@ -292,7 +292,7 @@ namespace SabreTools.Data.Extensions
|
||||
offset += sizeof(ushort);
|
||||
|
||||
// Read the class resource as a string
|
||||
dialogTemplateExtended.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogTemplateExtended.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the WORD boundary if we're not at the end
|
||||
entry.Data.AlignToBoundary(ref offset, 2);
|
||||
@@ -319,7 +319,7 @@ namespace SabreTools.Data.Extensions
|
||||
else
|
||||
{
|
||||
// Read the title resource as a string
|
||||
dialogTemplateExtended.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogTemplateExtended.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the WORD boundary if we're not at the end
|
||||
entry.Data.AlignToBoundary(ref offset, 2);
|
||||
@@ -340,7 +340,7 @@ namespace SabreTools.Data.Extensions
|
||||
dialogTemplateExtended.Weight = entry.Data.ReadUInt16LittleEndian(ref offset);
|
||||
dialogTemplateExtended.Italic = entry.Data.ReadByte(ref offset);
|
||||
dialogTemplateExtended.CharSet = entry.Data.ReadByte(ref offset);
|
||||
dialogTemplateExtended.Typeface = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogTemplateExtended.Typeface = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
}
|
||||
|
||||
// Align to the DWORD boundary if we're not at the end
|
||||
@@ -392,7 +392,7 @@ namespace SabreTools.Data.Extensions
|
||||
offset += sizeof(ushort);
|
||||
|
||||
// Read the class resource as a string
|
||||
dialogItemTemplate.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogItemTemplate.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the WORD boundary if we're not at the end
|
||||
entry.Data.AlignToBoundary(ref offset, 2);
|
||||
@@ -418,7 +418,7 @@ namespace SabreTools.Data.Extensions
|
||||
else
|
||||
{
|
||||
// Read the title resource as a string
|
||||
dialogItemTemplate.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogItemTemplate.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the WORD boundary if we're not at the end
|
||||
entry.Data.AlignToBoundary(ref offset, 2);
|
||||
@@ -482,7 +482,7 @@ namespace SabreTools.Data.Extensions
|
||||
offset += sizeof(ushort);
|
||||
|
||||
// Read the menu resource as a string
|
||||
dialogTemplate.MenuResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogTemplate.MenuResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the WORD boundary if we're not at the end
|
||||
entry.Data.AlignToBoundary(ref offset, 2);
|
||||
@@ -518,7 +518,7 @@ namespace SabreTools.Data.Extensions
|
||||
offset += sizeof(ushort);
|
||||
|
||||
// Read the class resource as a string
|
||||
dialogTemplate.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogTemplate.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the WORD boundary if we're not at the end
|
||||
entry.Data.AlignToBoundary(ref offset, 2);
|
||||
@@ -549,7 +549,7 @@ namespace SabreTools.Data.Extensions
|
||||
else
|
||||
{
|
||||
// Read the title resource as a string
|
||||
dialogTemplate.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogTemplate.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the WORD boundary if we're not at the end
|
||||
entry.Data.AlignToBoundary(ref offset, 2);
|
||||
@@ -569,7 +569,7 @@ namespace SabreTools.Data.Extensions
|
||||
dialogTemplate.PointSizeValue = entry.Data.ReadUInt16LittleEndian(ref offset);
|
||||
|
||||
// Read the font name as a string
|
||||
dialogTemplate.Typeface = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogTemplate.Typeface = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
}
|
||||
|
||||
// Align to the DWORD boundary if we're not at the end
|
||||
@@ -620,7 +620,7 @@ namespace SabreTools.Data.Extensions
|
||||
offset += sizeof(ushort);
|
||||
|
||||
// Read the class resource as a string
|
||||
dialogItemTemplate.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogItemTemplate.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the WORD boundary if we're not at the end
|
||||
entry.Data.AlignToBoundary(ref offset, 2);
|
||||
@@ -646,7 +646,7 @@ namespace SabreTools.Data.Extensions
|
||||
else
|
||||
{
|
||||
// Read the title resource as a string
|
||||
dialogItemTemplate.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
dialogItemTemplate.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the WORD boundary if we're not at the end
|
||||
entry.Data.AlignToBoundary(ref offset, 2);
|
||||
@@ -738,8 +738,8 @@ namespace SabreTools.Data.Extensions
|
||||
dirEntry.Entry.Reserved = entry.Data.ReadUInt32LittleEndian(ref offset);
|
||||
|
||||
// TODO: Determine how to read these two? Immediately after?
|
||||
dirEntry.Entry.DeviceName = entry.Data.ReadNullTerminatedAnsiString(ref offset);
|
||||
dirEntry.Entry.FaceName = entry.Data.ReadNullTerminatedAnsiString(ref offset);
|
||||
dirEntry.Entry.DeviceName = entry.Data.ReadNullTerminatedAnsiString(ref offset) ?? string.Empty;
|
||||
dirEntry.Entry.FaceName = entry.Data.ReadNullTerminatedAnsiString(ref offset) ?? string.Empty;
|
||||
|
||||
fontGroupHeader.DE[i] = dirEntry;
|
||||
}
|
||||
@@ -878,7 +878,7 @@ namespace SabreTools.Data.Extensions
|
||||
}
|
||||
|
||||
// Message resource entries
|
||||
if (messageResourceData.Blocks != null && messageResourceData.Blocks.Length != 0)
|
||||
if (messageResourceData.Blocks.Length != 0)
|
||||
{
|
||||
var messageResourceEntries = new Dictionary<uint, MessageResourceEntry?>();
|
||||
|
||||
@@ -898,9 +898,8 @@ namespace SabreTools.Data.Extensions
|
||||
messageResourceEntry.Flags = entry.Data.ReadUInt16LittleEndian(ref offset);
|
||||
|
||||
Encoding textEncoding = messageResourceEntry.Flags == 0x0001 ? Encoding.Unicode : Encoding.ASCII;
|
||||
byte[]? textArray = entry.Data.ReadBytes(ref offset, messageResourceEntry.Length - 4);
|
||||
if (textArray != null)
|
||||
messageResourceEntry.Text = textEncoding.GetString(textArray);
|
||||
byte[] textArray = entry.Data.ReadBytes(ref offset, messageResourceEntry.Length - 4);
|
||||
messageResourceEntry.Text = textEncoding.GetString(textArray);
|
||||
|
||||
messageResourceEntries[j] = messageResourceEntry;
|
||||
}
|
||||
@@ -928,7 +927,7 @@ namespace SabreTools.Data.Extensions
|
||||
stringFileInfo.Length = data.ReadUInt16LittleEndian(ref offset);
|
||||
stringFileInfo.ValueLength = data.ReadUInt16LittleEndian(ref offset);
|
||||
stringFileInfo.ResourceType = (VersionResourceType)data.ReadUInt16LittleEndian(ref offset);
|
||||
stringFileInfo.Key = data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
stringFileInfo.Key = data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
if (stringFileInfo.Key != "StringFileInfo")
|
||||
{
|
||||
offset -= 6 + ((stringFileInfo.Key?.Length ?? 0 + 1) * 2);
|
||||
@@ -946,7 +945,7 @@ namespace SabreTools.Data.Extensions
|
||||
stringTable.Length = data.ReadUInt16LittleEndian(ref offset);
|
||||
stringTable.ValueLength = data.ReadUInt16LittleEndian(ref offset);
|
||||
stringTable.ResourceType = (VersionResourceType)data.ReadUInt16LittleEndian(ref offset);
|
||||
stringTable.Key = data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
stringTable.Key = data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the DWORD boundary if we're not at the end
|
||||
data.AlignToBoundary(ref offset, 4);
|
||||
@@ -960,7 +959,7 @@ namespace SabreTools.Data.Extensions
|
||||
stringData.Length = data.ReadUInt16LittleEndian(ref offset);
|
||||
stringData.ValueLength = data.ReadUInt16LittleEndian(ref offset);
|
||||
stringData.ResourceType = (VersionResourceType)data.ReadUInt16LittleEndian(ref offset);
|
||||
stringData.Key = data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
stringData.Key = data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
// Align to the DWORD boundary if we're not at the end
|
||||
data.AlignToBoundary(ref offset, 4);
|
||||
@@ -1007,7 +1006,7 @@ namespace SabreTools.Data.Extensions
|
||||
// Create the output table
|
||||
var stringTable = new Dictionary<int, string?>();
|
||||
|
||||
// Loop through and add
|
||||
// Loop through and add
|
||||
while (offset < entry.Data.Length)
|
||||
{
|
||||
string? stringValue = entry.Data.ReadPrefixedUnicodeString(ref offset);
|
||||
@@ -1037,7 +1036,7 @@ namespace SabreTools.Data.Extensions
|
||||
varFileInfo.Length = data.ReadUInt16LittleEndian(ref offset);
|
||||
varFileInfo.ValueLength = data.ReadUInt16LittleEndian(ref offset);
|
||||
varFileInfo.ResourceType = (VersionResourceType)data.ReadUInt16LittleEndian(ref offset);
|
||||
varFileInfo.Key = data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
varFileInfo.Key = data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
if (varFileInfo.Key != "VarFileInfo")
|
||||
return null;
|
||||
|
||||
@@ -1052,7 +1051,7 @@ namespace SabreTools.Data.Extensions
|
||||
varData.Length = data.ReadUInt16LittleEndian(ref offset);
|
||||
varData.ValueLength = data.ReadUInt16LittleEndian(ref offset);
|
||||
varData.ResourceType = (VersionResourceType)data.ReadUInt16LittleEndian(ref offset);
|
||||
varData.Key = data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
varData.Key = data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
if (varData.Key != "Translation")
|
||||
{
|
||||
offset -= 6 + ((varData.Key?.Length ?? 0 + 1) * 2);
|
||||
@@ -1102,7 +1101,7 @@ namespace SabreTools.Data.Extensions
|
||||
versionInfo.Length = entry.Data.ReadUInt16LittleEndian(ref offset);
|
||||
versionInfo.ValueLength = entry.Data.ReadUInt16LittleEndian(ref offset);
|
||||
versionInfo.ResourceType = (VersionResourceType)entry.Data.ReadUInt16LittleEndian(ref offset);
|
||||
versionInfo.Key = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
versionInfo.Key = entry.Data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
if (versionInfo.Key != "VS_VERSION_INFO")
|
||||
return null;
|
||||
|
||||
@@ -1205,7 +1204,7 @@ namespace SabreTools.Data.Extensions
|
||||
obj.State = (MenuFlags)data.ReadUInt32LittleEndian(ref offset);
|
||||
obj.ID = data.ReadUInt32LittleEndian(ref offset);
|
||||
obj.Flags = (MenuFlags)data.ReadUInt32LittleEndian(ref offset);
|
||||
obj.MenuText = data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
obj.MenuText = data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
return obj;
|
||||
}
|
||||
@@ -1254,7 +1253,7 @@ namespace SabreTools.Data.Extensions
|
||||
var obj = new NormalMenuItem();
|
||||
|
||||
obj.NormalResInfo = (MenuFlags)data.ReadUInt32LittleEndian(ref offset);
|
||||
obj.NormalMenuText = data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
obj.NormalMenuText = data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
return obj;
|
||||
}
|
||||
@@ -1273,7 +1272,7 @@ namespace SabreTools.Data.Extensions
|
||||
obj.PopupState = (MenuFlags)data.ReadUInt32LittleEndian(ref offset);
|
||||
obj.PopupID = data.ReadUInt32LittleEndian(ref offset);
|
||||
obj.PopupResInfo = (MenuFlags)data.ReadUInt32LittleEndian(ref offset);
|
||||
obj.PopupMenuText = data.ReadNullTerminatedUnicodeString(ref offset);
|
||||
obj.PopupMenuText = data.ReadNullTerminatedUnicodeString(ref offset) ?? string.Empty;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using SabreTools.Numerics;
|
||||
|
||||
namespace SabreTools.Data.Printers
|
||||
namespace SabreTools.Data.Extensions
|
||||
{
|
||||
// TODO: Add extension for printing enums, if possible
|
||||
internal static class StringBuilderExtensions
|
||||
@@ -34,6 +35,19 @@ namespace SabreTools.Data.Printers
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a potentially both-endian Int8 to a StringBuilder
|
||||
/// </summary>
|
||||
public static StringBuilder AppendLineBothEndian(this StringBuilder sb, BothInt8? value, string prefixString)
|
||||
{
|
||||
value ??= 0;
|
||||
if (value.IsValid)
|
||||
return sb.AppendLine(value, prefixString);
|
||||
|
||||
sb = sb.AppendLine(value.LittleEndian, $"{prefixString} (Little-Endian)");
|
||||
return sb.AppendLine(value.BigEndian, $"{prefixString} (Big-Endian)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a UInt8 to a StringBuilder
|
||||
/// </summary>
|
||||
@@ -44,6 +58,19 @@ namespace SabreTools.Data.Printers
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a potentially both-endian UInt8 to a StringBuilder
|
||||
/// </summary>
|
||||
public static StringBuilder AppendLineBothEndian(this StringBuilder sb, BothUInt8? value, string prefixString)
|
||||
{
|
||||
value ??= 0;
|
||||
if (value.IsValid)
|
||||
return sb.AppendLine(value, prefixString);
|
||||
|
||||
sb = sb.AppendLine(value.LittleEndian, $"{prefixString} (Little-Endian)");
|
||||
return sb.AppendLine(value.BigEndian, $"{prefixString} (Big-Endian)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a Int16 to a StringBuilder
|
||||
/// </summary>
|
||||
@@ -54,6 +81,19 @@ namespace SabreTools.Data.Printers
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a potentially both-endian Int16 to a StringBuilder
|
||||
/// </summary>
|
||||
public static StringBuilder AppendLineBothEndian(this StringBuilder sb, BothInt16? value, string prefixString)
|
||||
{
|
||||
value ??= 0;
|
||||
if (value.IsValid)
|
||||
return sb.AppendLine(value, prefixString);
|
||||
|
||||
sb = sb.AppendLine(value.LittleEndian, $"{prefixString} (Little-Endian)");
|
||||
return sb.AppendLine(value.BigEndian, $"{prefixString} (Big-Endian)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a UInt16 to a StringBuilder
|
||||
/// </summary>
|
||||
@@ -64,6 +104,19 @@ namespace SabreTools.Data.Printers
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a potentially both-endian UInt16 to a StringBuilder
|
||||
/// </summary>
|
||||
public static StringBuilder AppendLineBothEndian(this StringBuilder sb, BothUInt16? value, string prefixString)
|
||||
{
|
||||
value ??= 0;
|
||||
if (value.IsValid)
|
||||
return sb.AppendLine(value, prefixString);
|
||||
|
||||
sb = sb.AppendLine(value.LittleEndian, $"{prefixString} (Little-Endian)");
|
||||
return sb.AppendLine(value.BigEndian, $"{prefixString} (Big-Endian)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a Int32 to a StringBuilder
|
||||
/// </summary>
|
||||
@@ -74,6 +127,19 @@ namespace SabreTools.Data.Printers
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a potentially both-endian Int32 to a StringBuilder
|
||||
/// </summary>
|
||||
public static StringBuilder AppendLineBothEndian(this StringBuilder sb, BothInt32? value, string prefixString)
|
||||
{
|
||||
value ??= 0;
|
||||
if (value.IsValid)
|
||||
return sb.AppendLine(value, prefixString);
|
||||
|
||||
sb = sb.AppendLine(value.LittleEndian, $"{prefixString} (Little-Endian)");
|
||||
return sb.AppendLine(value.BigEndian, $"{prefixString} (Big-Endian)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a UInt32 to a StringBuilder
|
||||
/// </summary>
|
||||
@@ -84,6 +150,19 @@ namespace SabreTools.Data.Printers
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a potentially both-endian UInt32 to a StringBuilder
|
||||
/// </summary>
|
||||
public static StringBuilder AppendLineBothEndian(this StringBuilder sb, BothUInt32? value, string prefixString)
|
||||
{
|
||||
value ??= 0;
|
||||
if (value.IsValid)
|
||||
return sb.AppendLine(value, prefixString);
|
||||
|
||||
sb = sb.AppendLine(value.LittleEndian, $"{prefixString} (Little-Endian)");
|
||||
return sb.AppendLine(value.BigEndian, $"{prefixString} (Big-Endian)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a Single to a StringBuilder
|
||||
/// </summary>
|
||||
@@ -104,6 +183,19 @@ namespace SabreTools.Data.Printers
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a potentially both-endian Int64 to a StringBuilder
|
||||
/// </summary>
|
||||
public static StringBuilder AppendLineBothEndian(this StringBuilder sb, BothInt64? value, string prefixString)
|
||||
{
|
||||
value ??= 0;
|
||||
if (value.IsValid)
|
||||
return sb.AppendLine(value, prefixString);
|
||||
|
||||
sb = sb.AppendLine(value.LittleEndian, $"{prefixString} (Little-Endian)");
|
||||
return sb.AppendLine(value.BigEndian, $"{prefixString} (Big-Endian)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a UInt64 to a StringBuilder
|
||||
/// </summary>
|
||||
@@ -114,6 +206,19 @@ namespace SabreTools.Data.Printers
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a potentially both-endian UInt64 to a StringBuilder
|
||||
/// </summary>
|
||||
public static StringBuilder AppendLineBothEndian(this StringBuilder sb, BothUInt64? value, string prefixString)
|
||||
{
|
||||
value ??= 0;
|
||||
if (value.IsValid)
|
||||
return sb.AppendLine(value, prefixString);
|
||||
|
||||
sb = sb.AppendLine(value.LittleEndian, $"{prefixString} (Little-Endian)");
|
||||
return sb.AppendLine(value.BigEndian, $"{prefixString} (Big-Endian)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a line containing a Double to a StringBuilder
|
||||
/// </summary>
|
||||
@@ -130,6 +235,9 @@ namespace SabreTools.Data.Printers
|
||||
public static StringBuilder AppendLine(this StringBuilder sb, string? value, string prefixString)
|
||||
{
|
||||
string valueString = value ?? "[NULL]";
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -149,6 +257,9 @@ namespace SabreTools.Data.Printers
|
||||
public static StringBuilder AppendLine(this StringBuilder sb, byte[]? value, string prefixString)
|
||||
{
|
||||
string valueString = (value == null ? "[NULL]" : BitConverter.ToString(value).Replace('-', ' '));
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -158,6 +269,9 @@ namespace SabreTools.Data.Printers
|
||||
public static StringBuilder AppendLine(this StringBuilder sb, byte[]? value, string prefixString, Encoding encoding)
|
||||
{
|
||||
string valueString = (value == null ? "[NULL]" : encoding.GetString(value).Replace("\0", string.Empty));
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -173,6 +287,9 @@ namespace SabreTools.Data.Printers
|
||||
valueString = string.Join(", ", valueArr);
|
||||
}
|
||||
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -188,6 +305,9 @@ namespace SabreTools.Data.Printers
|
||||
valueString = string.Join(", ", valueArr);
|
||||
}
|
||||
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -203,6 +323,9 @@ namespace SabreTools.Data.Printers
|
||||
valueString = string.Join(", ", valueArr);
|
||||
}
|
||||
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -218,6 +341,9 @@ namespace SabreTools.Data.Printers
|
||||
valueString = string.Join(", ", valueArr);
|
||||
}
|
||||
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -233,6 +359,9 @@ namespace SabreTools.Data.Printers
|
||||
valueString = string.Join(", ", valueArr);
|
||||
}
|
||||
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -248,6 +377,9 @@ namespace SabreTools.Data.Printers
|
||||
valueString = string.Join(", ", valueArr);
|
||||
}
|
||||
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -263,6 +395,9 @@ namespace SabreTools.Data.Printers
|
||||
valueString = string.Join(", ", valueArr);
|
||||
}
|
||||
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -278,6 +413,9 @@ namespace SabreTools.Data.Printers
|
||||
valueString = string.Join(", ", valueArr);
|
||||
}
|
||||
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -293,6 +431,9 @@ namespace SabreTools.Data.Printers
|
||||
valueString = string.Join(", ", valueArr);
|
||||
}
|
||||
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
|
||||
@@ -308,6 +449,9 @@ namespace SabreTools.Data.Printers
|
||||
valueString = string.Join(", ", valueArr);
|
||||
}
|
||||
|
||||
if (valueString.Length == 0)
|
||||
return sb.AppendLine($"{prefixString}: [EMPTY]");
|
||||
|
||||
return sb.AppendLine($"{prefixString}: {valueString}");
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// Null-terminated ASCII string representing the copyright
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.LPStr)]
|
||||
public string? Copyright;
|
||||
public string Copyright = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// case of a non-zero Range value).
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
|
||||
public byte[]? DriveID;
|
||||
public byte[] DriveID = new byte[6];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// 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
|
||||
@@ -21,6 +21,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// <summary>
|
||||
/// Revocation list entries
|
||||
/// </summary>
|
||||
public DriveRevocationSignatureBlock[]? SignatureBlocks { get; set; }
|
||||
public DriveRevocationSignatureBlock[] SignatureBlocks { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// 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 { get; set; }
|
||||
public DriveRevocationListEntry[] EntryFields { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// determines that the signature does not verify or is omitted, it
|
||||
/// must refuse to use the Media Key.
|
||||
/// </summary>
|
||||
public byte[]? SignatureData { get; set; }
|
||||
/// <remarks><see cref="RecordLength"/>-4 bytes</remarks>
|
||||
public byte[] SignatureData { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,4 +66,4 @@ namespace SabreTools.Data.Models.AACS
|
||||
VerifyMediaKey_AACS2 = 0x86,
|
||||
EmptyRecord0xF8_AACS2 = 0xF8,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// <summary>
|
||||
/// In this record, each subset-difference is encoded with 5 bytes.
|
||||
/// </summary>
|
||||
public SubsetDifference[]? SubsetDifferences { get; set; }
|
||||
public SubsetDifference[] SubsetDifferences { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// <summary>
|
||||
/// Unparsed data comprising the record after the header
|
||||
/// </summary>
|
||||
public byte[]? Data { get; set; }
|
||||
public byte[] Data { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// Range value).
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
|
||||
public byte[]? HostID;
|
||||
public byte[] HostID = new byte[6];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// <summary>
|
||||
/// Revocation list entries
|
||||
/// </summary>
|
||||
public HostRevocationSignatureBlock[]? SignatureBlocks { get; set; }
|
||||
public HostRevocationSignatureBlock[] SignatureBlocks { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// 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 { get; set; }
|
||||
public HostRevocationListEntry[] EntryFields { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// <summary>
|
||||
/// Records
|
||||
/// </summary>
|
||||
public Record[]? Records { get; set; }
|
||||
public Record[] Records { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// record. This 16 bytes is the ciphertext value C in the media
|
||||
/// key calculation.
|
||||
/// </summary>
|
||||
public byte[][]? MediaKeyData { get; set; }
|
||||
public byte[][] MediaKeyData { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ namespace SabreTools.Data.Models.AACS
|
||||
{
|
||||
/// <summary>
|
||||
/// Each Record begins with a one-byte Record Type field, followed by a
|
||||
/// three-byte Record Length field.
|
||||
///
|
||||
/// 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
|
||||
@@ -25,4 +25,4 @@ namespace SabreTools.Data.Models.AACS
|
||||
// <remarks>UInt24 not UInt32</remarks>
|
||||
public uint RecordLength { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,4 +20,4 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// </summary>
|
||||
public uint Number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,6 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// Subset-Difference record, with 0 being the start of the record.
|
||||
/// </summary>
|
||||
// <remarks>UInt24 not UInt32</remarks>
|
||||
public uint[]? Offsets { get; set; }
|
||||
public uint[] Offsets { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,4 +29,4 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// </summary>
|
||||
public uint VersionNumber { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace SabreTools.Data.Models.AACS
|
||||
/// where 0xXXXXXXXXXXXXXXXX is an arbitrary 8-byte value, and Km is
|
||||
/// the correct final Media Key value.
|
||||
/// </summary>
|
||||
public byte[]? CiphertextValue { get; set; }
|
||||
/// <remarks>0x10 bytes</remarks>
|
||||
public byte[] CiphertextValue { get; set; } = new byte[0x10];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ namespace SabreTools.Data.Models.AdvancedInstaller
|
||||
|
||||
public const string SignatureString = "ADVINSTSFX";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,6 @@ namespace SabreTools.Data.Models.AdvancedInstaller
|
||||
/// <summary>
|
||||
/// Unicode-encoded file name
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace SabreTools.Data.Models.AdvancedInstaller
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only seen when the preceeding two fields exist
|
||||
///
|
||||
///
|
||||
/// Observed values:
|
||||
/// - 01 00 00 00
|
||||
/// </remarks>
|
||||
@@ -80,7 +80,7 @@ namespace SabreTools.Data.Models.AdvancedInstaller
|
||||
/// Hex string that looks like a key or other identifier
|
||||
/// </summary>
|
||||
/// <remarks>32 bytes</remarks>
|
||||
public string? HexString { get; set; }
|
||||
public string HexString { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Unknown
|
||||
@@ -89,7 +89,7 @@ namespace SabreTools.Data.Models.AdvancedInstaller
|
||||
/// Offset pointer to <see cref="FileDataStart"/>
|
||||
/// relative to the end of the signature if no filename
|
||||
/// exists.
|
||||
///
|
||||
///
|
||||
/// Observed values:
|
||||
/// - 32 00 00 00 (No original filename)
|
||||
/// - 13 02 00 00 (Original filename)
|
||||
@@ -99,7 +99,7 @@ namespace SabreTools.Data.Models.AdvancedInstaller
|
||||
/// <summary>
|
||||
/// "ADVINSTSFX"
|
||||
/// </summary>
|
||||
public string? Signature { get; set; }
|
||||
public string Signature { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Unknown, always 0? Padding?
|
||||
|
||||
@@ -5,12 +5,12 @@ namespace SabreTools.Data.Models.AdvancedInstaller
|
||||
/// Advanced Installer SFX file. These SFX files store
|
||||
/// all files uncompressed sequentially in the overlay
|
||||
/// of an executable.
|
||||
///
|
||||
///
|
||||
/// The design is similar to the end of central directory
|
||||
/// in a PKZIP file. The footer needs to be read before
|
||||
/// the entry table as both the pointer to the start of
|
||||
/// the table as well as the entry count are included there.
|
||||
///
|
||||
///
|
||||
/// The layout of this is derived from the layout in the
|
||||
/// physical file.
|
||||
/// </summary>
|
||||
@@ -19,11 +19,11 @@ namespace SabreTools.Data.Models.AdvancedInstaller
|
||||
/// <summary>
|
||||
/// Set of file entries
|
||||
/// </summary>
|
||||
public FileEntry[]? Entries { get; set; }
|
||||
public FileEntry[] Entries { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Footer representing the central directory
|
||||
/// </summary>
|
||||
public Footer? Footer { get; set; }
|
||||
public Footer Footer { get; set; } = new();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ namespace SabreTools.Data.Models.BDPlus
|
||||
|
||||
public const string SignatureString = "BDSVM_CC";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@ namespace SabreTools.Data.Models.BDPlus
|
||||
/// "BDSVM_CC"
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
|
||||
public string? Signature;
|
||||
public string Signature = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Unknown data
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
|
||||
public byte[]? Unknown1 = new byte[5];
|
||||
public byte[] Unknown1 = new byte[5];
|
||||
|
||||
/// <summary>
|
||||
/// Version year
|
||||
@@ -43,8 +43,8 @@ namespace SabreTools.Data.Models.BDPlus
|
||||
public uint Length;
|
||||
|
||||
/// <summary>
|
||||
/// Length bytes of data
|
||||
/// <see cref="Length"> bytes of data
|
||||
/// </summary>
|
||||
public byte[]? Data { get; set; }
|
||||
public byte[] Data { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
/// <summary>
|
||||
/// Header
|
||||
/// </summary>
|
||||
public Header? Header { get; set; }
|
||||
public Header Header { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Files
|
||||
/// </summary>
|
||||
public FileEntry[]? Files { get; set; }
|
||||
public FileEntry[] Files { get; set; } = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,4 +8,4 @@ namespace SabreTools.Data.Models.BFPK
|
||||
|
||||
public const uint SignatureUInt32 = 0x4b504642;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
/// <summary>
|
||||
/// Name
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Uncompressed size
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace SabreTools.Data.Models.BFPK
|
||||
/// "BFPK"
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
|
||||
public string? Magic;
|
||||
public string Magic = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Version
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Indicies
|
||||
/// </summary>
|
||||
public LeafAmbientIndex[]? Indicies { get; set; }
|
||||
public LeafAmbientIndex[] Indicies { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Lightings
|
||||
/// </summary>
|
||||
public LeafAmbientLighting[]? Lightings { get; set; }
|
||||
public LeafAmbientLighting[] Lightings { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,4 +30,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
public VbspContents Contents;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Brushes
|
||||
/// </summary>
|
||||
public Brush[]? Brushes { get; set; }
|
||||
public Brush[] Brushes { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// references into the texture and displacement info lumps.
|
||||
/// Bevel is zero for normal brush sides, but 1 if the side is
|
||||
/// a bevel plane (which seem to be used for collision detection).
|
||||
///
|
||||
///
|
||||
/// Unlike the face array, brushsides are not culled (removed)
|
||||
/// where they touch the void. Void-facing sides do however have
|
||||
/// their texinfo entry changed to the tools/toolsnodraw texture
|
||||
@@ -17,7 +17,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// entries which are used to render that brush. Brushsides are
|
||||
/// used by the engine to calculate all player physics collision
|
||||
/// with world brushes. (Vphysics objects use lump 29 instead.)
|
||||
///
|
||||
///
|
||||
/// The maximum number of brushsides is 65536 (MAX_MAP_BRUSHSIDES).
|
||||
/// The maximum number of brushsides on a single brush is 128 (MAX_BRUSH_SIDES).
|
||||
/// </summary>
|
||||
@@ -45,4 +45,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
public short Bevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Brushsides
|
||||
/// </summary>
|
||||
public Brushside[]? Brushsides { get; set; }
|
||||
public Brushside[] Brushsides { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <summary>
|
||||
/// The face lump contains the surfaces of the scene.
|
||||
///
|
||||
///
|
||||
/// The first number of this data structure is an index into
|
||||
/// the planes lump giving a plane which is parallel to this
|
||||
/// face (meaning they share the same normal). The second
|
||||
@@ -22,7 +22,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// an offset in byes giving the beginning of the binary lightmap
|
||||
/// data of this face in the lighting lump.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class BspFace
|
||||
{
|
||||
@@ -55,7 +55,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// Specify lighting styles
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public byte[]? LightingStyles = new byte[4];
|
||||
public byte[] LightingStyles = new byte[4];
|
||||
|
||||
/// <summary>
|
||||
/// Offsets into the raw lightmap data; if less than zero,
|
||||
@@ -63,4 +63,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
public int LightmapOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
public sealed class BspFacesLump : Lump
|
||||
{
|
||||
/// <summary>
|
||||
/// Faces
|
||||
/// </summary>
|
||||
public BspFace[]? Faces { get; set; }
|
||||
public BspFace[] Faces { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,85 +10,85 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Header data
|
||||
/// </summary>
|
||||
public BspHeader? Header { get; set; }
|
||||
public BspHeader Header { get; set; } = new();
|
||||
|
||||
#region Lumps
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_ENTITIES [0]
|
||||
/// </summary>
|
||||
public EntitiesLump? Entities { get; set; }
|
||||
public EntitiesLump Entities { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_PLANES [1]
|
||||
/// </summary>
|
||||
public PlanesLump? PlanesLump { get; set; }
|
||||
public PlanesLump PlanesLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_TEXTURES [2]
|
||||
/// </summary>
|
||||
public TextureLump? TextureLump { get; set; }
|
||||
public TextureLump TextureLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_VERTICES [3]
|
||||
/// </summary>
|
||||
public VerticesLump? VerticesLump { get; set; }
|
||||
public VerticesLump VerticesLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_VISIBILITY [4]
|
||||
/// </summary>
|
||||
public VisibilityLump? VisibilityLump { get; set; }
|
||||
public VisibilityLump VisibilityLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_NODES [5]
|
||||
/// </summary>
|
||||
public BspNodesLump? NodesLump { get; set; }
|
||||
public BspNodesLump NodesLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_TEXINFO [6]
|
||||
/// </summary>
|
||||
public BspTexinfoLump? TexinfoLump { get; set; }
|
||||
public BspTexinfoLump TexinfoLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_FACES [7]
|
||||
/// </summary>
|
||||
public BspFacesLump? FacesLump { get; set; }
|
||||
public BspFacesLump FacesLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_LIGHTING [8]
|
||||
/// </summary>
|
||||
public LightmapLump? LightmapLump { get; set; }
|
||||
public LightmapLump LightmapLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_CLIPNODES [9]
|
||||
/// </summary>s
|
||||
public ClipnodesLump? ClipnodesLump { get; set; }
|
||||
public ClipnodesLump ClipnodesLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_LEAVES [10]
|
||||
/// </summary>
|
||||
public BspLeavesLump? LeavesLump { get; set; }
|
||||
public BspLeavesLump LeavesLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_MARKSURFACES [11]
|
||||
/// </summary>
|
||||
public MarksurfacesLump? MarksurfacesLump { get; set; }
|
||||
public MarksurfacesLump MarksurfacesLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_EDGES [12]
|
||||
/// </summary>
|
||||
public EdgesLump? EdgesLump { get; set; }
|
||||
public EdgesLump EdgesLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_SURFEDGES [13]
|
||||
/// </summary>
|
||||
public SurfedgesLump? SurfedgesLump { get; set; }
|
||||
public SurfedgesLump SurfedgesLump { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// LUMP_MODELS [14]
|
||||
/// </summary>
|
||||
public BspModelsLump? ModelsLump { get; set; }
|
||||
public BspModelsLump ModelsLump { get; set; } = new();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
/// <remarks>15 entries</remarks>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.BSP_HEADER_LUMPS)]
|
||||
public BspLumpEntry[]? Lumps;
|
||||
public BspLumpEntry[] Lumps = new BspLumpEntry[Constants.BSP_HEADER_LUMPS];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <summary>
|
||||
/// The leaves lump contains the leaves of the BSP tree.
|
||||
///
|
||||
///
|
||||
/// The first entry of this struct is the type of the content
|
||||
/// of this leaf. It can be one of the predefined values, found
|
||||
/// in the compiler source codes, and is litte relevant for the
|
||||
@@ -22,7 +22,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// specify the volume of ambient sounds in Quake, but are unused in
|
||||
/// GoldSrc.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class BspLeaf
|
||||
{
|
||||
@@ -62,6 +62,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// Ambient sound levels
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public byte[]? AmbientLevels = new byte[4];
|
||||
public byte[] AmbientLevels = new byte[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
public sealed class BspLeavesLump : Lump
|
||||
{
|
||||
/// <summary>
|
||||
/// Leaves
|
||||
/// </summary>
|
||||
public BspLeaf[]? Leaves { get; set; }
|
||||
public BspLeaf[] Leaves { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
public int Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,32 +18,32 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// clipnodes, but I am not sure about this. The meaning of the
|
||||
/// next value is also somehow unclear to me. Finally their are
|
||||
/// direct indexes into the faces array, not taking the redirecting
|
||||
/// by the marksurfaces.
|
||||
/// by the marksurfaces.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class BspModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines bounding box
|
||||
/// </summary>
|
||||
public Vector3D? Mins;
|
||||
public Vector3D Mins = new();
|
||||
|
||||
/// <summary>
|
||||
/// Defines bounding box
|
||||
/// </summary>
|
||||
public Vector3D? Maxs;
|
||||
public Vector3D Maxs = new();
|
||||
|
||||
/// <summary>
|
||||
/// Coordinates to move the coordinate system
|
||||
/// </summary>
|
||||
public Vector3D? OriginVector;
|
||||
public Vector3D OriginVector = new();
|
||||
|
||||
/// <summary>
|
||||
/// Index into nodes array
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.MAX_MAP_HULLS)]
|
||||
public int[]? HeadnodesIndex = new int[Constants.MAX_MAP_HULLS];
|
||||
public int[] HeadnodesIndex = new int[Constants.MAX_MAP_HULLS];
|
||||
|
||||
/// <summary>
|
||||
/// ???
|
||||
@@ -60,4 +60,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
public int FacesCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
public sealed class BspModelsLump : Lump
|
||||
{
|
||||
/// <summary>
|
||||
/// Model
|
||||
/// </summary>
|
||||
public BspModel[]? Models { get; set; }
|
||||
public BspModel[] Models { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// This lump is simple again and contains an array of binary
|
||||
/// structures, the nodes, which are a major part of the BSP tree.
|
||||
///
|
||||
///
|
||||
/// Every BSPNODE structure represents a node in the BSP tree and
|
||||
/// every node equals more or less a division step of the BSP algorithm.
|
||||
/// Therefore, each node has an index (iPlane) referring to a plane
|
||||
@@ -20,8 +20,8 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// Finally firstFace indexes into the face lump and spezifies the
|
||||
/// first of nFaces surfaces contained in this node.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class BspNode
|
||||
{
|
||||
@@ -59,4 +59,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
public ushort FaceCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
public sealed class BspNodesLump : Lump
|
||||
{
|
||||
/// <summary>
|
||||
/// Nodes
|
||||
/// </summary>
|
||||
public BspNode[]? Nodes { get; set; }
|
||||
public BspNode[] Nodes { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// The texinfo lump contains informations about how textures are
|
||||
/// applied to surfaces. The lump itself is an array of binary data
|
||||
/// structures.
|
||||
///
|
||||
///
|
||||
/// This struct is mainly responsible for the calculation of the texture
|
||||
/// coordinates (vS, fSShift, vT, fTShift). This values determine the
|
||||
/// position of the texture on the surface. The iMiptex integer refers
|
||||
@@ -22,7 +22,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// S-vector
|
||||
/// </summary>
|
||||
public Vector3D? SVector;
|
||||
public Vector3D SVector = new();
|
||||
|
||||
/// <summary>
|
||||
/// Texture shift in the S direction
|
||||
@@ -32,7 +32,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// T-vector
|
||||
/// </summary>
|
||||
public Vector3D? TVector;
|
||||
public Vector3D TVector = new();
|
||||
|
||||
/// <summary>
|
||||
/// Texture shift in the T direction
|
||||
@@ -49,4 +49,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
public TextureFlag Flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
public sealed class BspTexinfoLump : Lump
|
||||
{
|
||||
/// <summary>
|
||||
/// Texinfos
|
||||
/// </summary>
|
||||
public BspTexinfo[]? Texinfos { get; set; }
|
||||
public BspTexinfo[] Texinfos { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/sp/src/public/bspfile.h#L600"/>
|
||||
/// <see href="https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/sp/src/public/bspfile.h#L600"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class CDispCornerNeighbors
|
||||
{
|
||||
@@ -14,4 +14,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
|
||||
public byte NeighborCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/sp/src/public/bspfile.h#L583"/>
|
||||
/// <see href="https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/sp/src/public/bspfile.h#L583"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class CDispNeighbor
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public CDispSubNeighbor[]? SubNeighbors = new CDispSubNeighbor[2];
|
||||
public CDispSubNeighbor[] SubNeighbors = new CDispSubNeighbor[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/sp/src/public/bspfile.h#L557"/>
|
||||
/// <see href="https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/sp/src/public/bspfile.h#L557"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class CDispSubNeighbor
|
||||
{
|
||||
@@ -29,4 +29,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
public byte NeighborSpan;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// This lump contains the so-called clipnodes, which build a second
|
||||
/// BSP tree used only for collision detection.
|
||||
///
|
||||
///
|
||||
/// This structure is a reduced form of the BSPNODE struct from the
|
||||
/// nodes lump. Also the BSP tree built by the clipnodes is simpler
|
||||
/// than the one described by the BSPNODEs to accelerate collision calculations.
|
||||
/// than the one described by the BSPNODEs to accelerate collision calculations.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class Clipnode
|
||||
{
|
||||
@@ -23,6 +23,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// Negative numbers are contents
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public short[]? ChildrenIndices = new short[2];
|
||||
public short[] ChildrenIndices = new short[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
public sealed class ClipnodesLump : Lump
|
||||
{
|
||||
/// <summary>
|
||||
/// Clipnodes
|
||||
/// </summary>
|
||||
public Clipnode[]? Clipnodes { get; set; }
|
||||
public Clipnode[] Clipnodes { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// 4-byte lightmap structure
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ColorRGBExp32
|
||||
{
|
||||
@@ -17,4 +17,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
|
||||
public sbyte Exponent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// The lighting data for each sample is represented by an array
|
||||
/// of 6 ColorRGBExp32
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class CompressedLightCube
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
|
||||
public ColorRGBExp32[]? Colors;
|
||||
public ColorRGBExp32[] Colors = new ColorRGBExp32[6];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
public static class Constants
|
||||
{
|
||||
#region Header
|
||||
@@ -45,7 +45,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
public const int MAX_MAP_PORTALS = 65536;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Entities
|
||||
|
||||
public const int MAX_KEY = 32;
|
||||
@@ -61,7 +61,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
public const int MIPLEVELS = 4;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region VBSP
|
||||
|
||||
public static readonly byte[] SignatureBytes = [0x56, 0x42, 0x53, 0x50];
|
||||
@@ -79,15 +79,15 @@ namespace SabreTools.Data.Models.BSP
|
||||
public const string LzmaHeaderString = "LZMA";
|
||||
|
||||
public const uint LzmaHeaderUInt32 = 0x414D5A4C;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Overlay
|
||||
|
||||
public const int OVERLAY_BSP_FACE_COUNT = 64;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Worldlights
|
||||
|
||||
/// <summary>
|
||||
@@ -97,4 +97,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,16 +9,16 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// is resolution of the cubemap, specified as 2^(size-1) pixels
|
||||
/// square. If set as 0, the default size of 6 (32x32 pixels) is
|
||||
/// used. There can be a maximum of 1024 (MAX_MAP_CUBEMAPSAMPLES)
|
||||
/// cubemaps in a file.
|
||||
///
|
||||
/// cubemaps in a file.
|
||||
///
|
||||
/// When the "buildcubemaps" console command is performed, six
|
||||
/// snapshots of the map (one for each direction) are taken at the
|
||||
/// location of each env_cubemap entity. These snapshots are stored
|
||||
/// in a multi-frame texture (vtf) file, which is added to the
|
||||
/// Pakfile lump (see above). The textures are named cX_Y_Z.vtf,
|
||||
/// where (X,Y,Z) are the (integer) coordinates of the corresponding
|
||||
/// cubemap.
|
||||
///
|
||||
/// cubemap.
|
||||
///
|
||||
/// Faces containing materials that are environment mapped (e.g.
|
||||
/// shiny textures) reference their assigned cubemap through their
|
||||
/// material name. A face with a material named (e.g.) walls/shiny.vmt
|
||||
@@ -26,11 +26,11 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// to a renamed material maps/mapname/walls/shiny_X_Y_Z.vmt, where
|
||||
/// (X,Y,Z) are the cubemap coordinates as before. This .vmt file
|
||||
/// is also stored in the Pakfile, and references the cubemap .vtf
|
||||
/// file through its $envmap property.
|
||||
///
|
||||
/// file through its $envmap property.
|
||||
///
|
||||
/// Version 20 files contain extra cX_Y_Z.hdr.vtf files in the
|
||||
/// Pakfile lump, containing HDR texture files in RGBA16161616F
|
||||
/// (16-bit per channel) format.
|
||||
/// (16-bit per channel) format.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -40,11 +40,11 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// Position of light snapped to the nearest integer
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public int[]? Origin = new int[3];
|
||||
public int[] Origin = new int[3];
|
||||
|
||||
/// <summary>
|
||||
/// Resolution of cubemap, 0 - default
|
||||
/// </summary>
|
||||
public int Size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Cubemaps
|
||||
/// </summary>
|
||||
public Cubemap[]? Cubemaps { get; set; }
|
||||
public Cubemap[] Cubemaps { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// This face is used to set the texture and overall physical location
|
||||
/// and boundaries of the displacement.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class DispInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Start position used for orientation
|
||||
/// </summary>
|
||||
public Vector3D? StartPosition;
|
||||
public Vector3D StartPosition = new();
|
||||
|
||||
/// <summary>
|
||||
/// Index into LUMP_DISP_VERTS.
|
||||
@@ -76,18 +76,18 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// Indexed by NEIGHBOREDGE_ defines.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public CDispNeighbor[]? EdgeNeighbors = new CDispNeighbor[4];
|
||||
public CDispNeighbor[] EdgeNeighbors = new CDispNeighbor[4];
|
||||
|
||||
/// <summary>
|
||||
/// Indexed by CORNER_ defines.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public CDispCornerNeighbors[]? CornerNeighbors = new CDispCornerNeighbors[4];
|
||||
public CDispCornerNeighbors[] CornerNeighbors = new CDispCornerNeighbors[4];
|
||||
|
||||
/// <summary>
|
||||
/// Active verticies
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
|
||||
public uint[]? AllowedVerts = new uint[10];
|
||||
public uint[] AllowedVerts = new uint[10];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Infos
|
||||
/// </summary>
|
||||
public DispInfo[]? Infos { get; set; }
|
||||
public DispInfo[] Infos { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Tris
|
||||
/// </summary>
|
||||
public DispTri[]? Tris { get; set; }
|
||||
public DispTri[] Tris { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,18 +7,18 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// vec is the normalized vector of the offset of each displacement vertex from
|
||||
/// its original (flat) position; dist is the distance the offset has taken
|
||||
/// place; and alpha is the alpha-blending of the texture at that vertex.
|
||||
///
|
||||
///
|
||||
/// A displacement of power p references (2^p + 1)^2 dispverts in the array,
|
||||
/// starting from the DispVertStart index.
|
||||
/// starting from the DispVertStart index.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class DispVert
|
||||
{
|
||||
/// <summary>
|
||||
/// Vector field defining displacement volume.
|
||||
/// </summary>
|
||||
public Vector3D? Vec;
|
||||
public Vector3D Vec = new();
|
||||
|
||||
/// <summary>
|
||||
/// Displacement distances.
|
||||
@@ -30,4 +30,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
public float Alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Verts
|
||||
/// </summary>
|
||||
public DispVert[]? Verts { get; set; }
|
||||
public DispVert[] Verts { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <summary>
|
||||
/// The edges delimit the face and further refer to the vertices of the
|
||||
/// face. Each edge is pointing to the start and end vertex of the edge.
|
||||
/// face. Each edge is pointing to the start and end vertex of the edge.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class Edge
|
||||
@@ -15,6 +15,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// Indices into vertex array
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public ushort[]? VertexIndices = new ushort[2];
|
||||
public ushort[] VertexIndices = new ushort[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
public sealed class EdgesLump : Lump
|
||||
{
|
||||
/// <summary>
|
||||
/// Edge
|
||||
/// </summary>
|
||||
public Edge[]? Edges { get; set; }
|
||||
public Edge[] Edges { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
public sealed class EntitiesLump : Lump
|
||||
{
|
||||
/// <summary>
|
||||
/// Entities
|
||||
/// </summary>
|
||||
public Entity[]? Entities { get; set; }
|
||||
public Entity[] Entities { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,22 +7,22 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// It consists of the string representations of all entities,
|
||||
/// which are copied directly from the input file to the output
|
||||
/// BSP file by the compiler.
|
||||
///
|
||||
///
|
||||
/// Every entity begins and ends with curly brackets. In between
|
||||
/// there are the attributes of the entity, one in each line,
|
||||
/// which are pairs of strings enclosed by quotes. The first
|
||||
/// string is the name of the attribute (the key), the second one
|
||||
/// its value. The attribute "classname" is mandatory for every
|
||||
/// entity specifiying its type and therefore, how it is
|
||||
/// interpreted by the engine.
|
||||
/// interpreted by the engine.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
public sealed class Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity attributes
|
||||
/// </summary>
|
||||
public List<KeyValuePair<string, string>>? Attributes { get; set; }
|
||||
public List<KeyValuePair<string, string>> Attributes { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
public enum BspContents : int
|
||||
{
|
||||
CONTENTS_EMPTY = -1,
|
||||
@@ -22,7 +22,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
CONTENTS_TRANSLUCENT = -15,
|
||||
}
|
||||
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_flags_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_flags_(Source)"/>
|
||||
[Flags]
|
||||
public enum VbspContents : uint
|
||||
{
|
||||
@@ -32,7 +32,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
CONTENTS_EMPTY = 0x00000000,
|
||||
|
||||
/// <summary>
|
||||
/// An eye is never valid in a solid
|
||||
/// An eye is never valid in a solid
|
||||
/// </summary>
|
||||
CONTENTS_SOLID = 0x00000001,
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
CONTENTS_MIST = 0x00000040,
|
||||
|
||||
/// <summary>
|
||||
/// Block AI line of sight
|
||||
/// Block AI line of sight
|
||||
/// </summary>
|
||||
CONTENTS_BLOCKLOS = 0x00000040,
|
||||
|
||||
@@ -101,13 +101,13 @@ namespace SabreTools.Data.Models.BSP
|
||||
|
||||
/// <summary>
|
||||
/// Per team contents used to differentiate collisions
|
||||
/// between players and objects on different teams
|
||||
/// between players and objects on different teams
|
||||
/// </summary>
|
||||
CONTENTS_TEAM1 = 0x00000800,
|
||||
|
||||
/// <summary>
|
||||
/// Per team contents used to differentiate collisions
|
||||
/// between players and objects on different teams
|
||||
/// between players and objects on different teams
|
||||
/// </summary>
|
||||
CONTENTS_TEAM2 = 0x00001000,
|
||||
|
||||
@@ -215,12 +215,12 @@ namespace SabreTools.Data.Models.BSP
|
||||
CONTENTS_LADDER = 0x20000000,
|
||||
|
||||
/// <summary>
|
||||
/// Use accurate hitboxes on trace
|
||||
/// Use accurate hitboxes on trace
|
||||
/// </summary>
|
||||
CONTENTS_HITBOX = 0x40000000,
|
||||
}
|
||||
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
[Flags]
|
||||
public enum DispTriTag : ushort
|
||||
{
|
||||
@@ -231,7 +231,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
DISPTRI_FLAG_SURFPROP2 = 0x10,
|
||||
}
|
||||
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
public enum EmitType
|
||||
{
|
||||
/// <summary>
|
||||
@@ -267,8 +267,8 @@ namespace SabreTools.Data.Models.BSP
|
||||
EMIT_SKYAMBIENT,
|
||||
}
|
||||
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
public enum LumpType : int
|
||||
{
|
||||
#region BSP and VBSP
|
||||
@@ -292,14 +292,14 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// The texture lump is somehow a bit more complex then the
|
||||
/// other lumps, because it is possible to save textures
|
||||
/// directly within the BSP file instead of storing them in
|
||||
/// external WAD files.
|
||||
/// external WAD files.
|
||||
/// </summary>
|
||||
/// <remarks>LUMP_TEXDATA in VBSP</remarks>
|
||||
LUMP_TEXTURES = 2,
|
||||
|
||||
/// <summary>
|
||||
/// This lump simply consists of all vertices of the BSP tree.
|
||||
/// They are stored as a primitve array of triples of floats.
|
||||
/// They are stored as a primitve array of triples of floats.
|
||||
/// </summary>
|
||||
/// <remarks>LUMP_VERTEXES in VBSP</remarks>
|
||||
LUMP_VERTICES = 3,
|
||||
@@ -312,20 +312,20 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// Potentially Visible Sets (PVS) (also called VIS lists) in the
|
||||
/// same amout of leaves of the tree, the user can enter (often
|
||||
/// referred to as VisLeaves). The visiblilty lists are stored as
|
||||
/// sequences of bitfields, which are run-length encoded.
|
||||
/// sequences of bitfields, which are run-length encoded.
|
||||
/// </summary>
|
||||
LUMP_VISIBILITY = 4,
|
||||
|
||||
/// <summary>
|
||||
/// This lump is simple again and contains an array of binary
|
||||
/// structures, the nodes, which are a major part of the BSP tree.
|
||||
/// structures, the nodes, which are a major part of the BSP tree.
|
||||
/// </summary>
|
||||
LUMP_NODES = 5,
|
||||
|
||||
/// <summary>
|
||||
/// The texinfo lump contains informations about how textures are
|
||||
/// applied to surfaces. The lump itself is an array of binary data
|
||||
/// structures.
|
||||
/// structures.
|
||||
/// </summary>
|
||||
LUMP_TEXINFO = 6,
|
||||
|
||||
@@ -338,13 +338,13 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// This is one of the largest lumps in the BSP file. The lightmap
|
||||
/// lump stores all lightmaps used in the entire map. The lightmaps
|
||||
/// are arrays of triples of bytes (3 channel color, RGB) and stored
|
||||
/// continuously.
|
||||
/// continuously.
|
||||
/// </summary>
|
||||
LUMP_LIGHTING = 8,
|
||||
|
||||
/// <summary>
|
||||
/// This lump contains the so-called clipnodes, which build a second
|
||||
/// BSP tree used only for collision detection.
|
||||
/// BSP tree used only for collision detection.
|
||||
/// </summary>
|
||||
/// <remarks>LUMP_OCCLUSION in VBSP</remarks>
|
||||
LUMP_CLIPNODES = 9,
|
||||
@@ -363,7 +363,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
|
||||
/// <summary>
|
||||
/// The edges delimit the face and further refer to the vertices of the
|
||||
/// face. Each edge is pointing to the start and end vertex of the edge.
|
||||
/// face. Each edge is pointing to the start and end vertex of the edge.
|
||||
/// </summary>
|
||||
LUMP_EDGES = 12,
|
||||
|
||||
@@ -375,7 +375,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// or negative. If the value of the surfedge is positive, the first vertex
|
||||
/// of the edge is used as vertex for rendering the face, otherwise, the
|
||||
/// value is multiplied by -1 and the second vertex of the indexed edge is
|
||||
/// used.
|
||||
/// used.
|
||||
/// </summary>
|
||||
LUMP_SURFEDGES = 13,
|
||||
|
||||
@@ -711,7 +711,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
public enum PlaneType : int
|
||||
{
|
||||
// Plane is perpendicular to given axis
|
||||
@@ -725,7 +725,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
PLANE_ANYZ = 5,
|
||||
}
|
||||
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)/Static_prop_flags"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)/Static_prop_flags"/>
|
||||
[Flags]
|
||||
public enum StaticPropFlags : uint
|
||||
{
|
||||
@@ -787,7 +787,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
STATIC_PROP_NO_PER_TEXEL_LIGHTING = 0x100,
|
||||
}
|
||||
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)/Static_prop_flags"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)/Static_prop_flags"/>
|
||||
[Flags]
|
||||
public enum StaticPropFlagsEx : uint
|
||||
{
|
||||
@@ -807,7 +807,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
STATIC_PROP_FLAGS_EX_ENABLE_LIGHT_BOUNCE = 0x00000004,
|
||||
}
|
||||
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_flags_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_flags_(Source)"/>
|
||||
[Flags]
|
||||
public enum SurfaceFlag : uint
|
||||
{
|
||||
@@ -908,12 +908,12 @@ namespace SabreTools.Data.Models.BSP
|
||||
SURF_NOCHOP = 0x4000,
|
||||
|
||||
/// <summary>
|
||||
/// Surface is part of a hitbox
|
||||
/// Surface is part of a hitbox
|
||||
/// </summary>
|
||||
SURF_HITBOX = 0x8000,
|
||||
}
|
||||
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
[Flags]
|
||||
public enum TextureFlag : uint
|
||||
{
|
||||
@@ -923,4 +923,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <remarks>Used by sky and liquids</remarks>
|
||||
DisableLightmaps = 0x01,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,11 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Number of game lumps
|
||||
/// </summary>
|
||||
public int LumpCount;
|
||||
public int LumpCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="LumpCount"/>
|
||||
/// <see cref="LumpCount"/>
|
||||
/// </summary>
|
||||
public GameLumpDirectory[]? Directories;
|
||||
public GameLumpDirectory[] Directories { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,4 +37,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
public int FileLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,4 +14,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
|
||||
public ushort FirstAmbientSample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class LeafAmbientLighting
|
||||
{
|
||||
public CompressedLightCube? Cube;
|
||||
public CompressedLightCube Cube = new();
|
||||
|
||||
/// <summary>
|
||||
/// Fixed point fraction of leaf bounds
|
||||
@@ -38,4 +38,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// </summary>
|
||||
public byte Pad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Map
|
||||
/// </summary>
|
||||
public ushort[]? Map { get; set; }
|
||||
public ushort[] Map { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Map
|
||||
/// </summary>
|
||||
public ushort[]? Map { get; set; }
|
||||
public ushort[] Map { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,15 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// This is one of the largest lumps in the BSP file. The lightmap
|
||||
/// lump stores all lightmaps used in the entire map. The lightmaps
|
||||
/// are arrays of triples of bytes (3 channel color, RGB) and stored
|
||||
/// continuously.
|
||||
/// continuously.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
public sealed class LightmapLump : Lump
|
||||
{
|
||||
/// <summary>
|
||||
/// Lightmap RGB values
|
||||
/// </summary>
|
||||
/// <remarks>Array of 3-byte values</remarks>
|
||||
public byte[][]? Lightmap { get; set; }
|
||||
public byte[][] Lightmap { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Represents a common Lump type
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
public abstract class Lump
|
||||
{
|
||||
// No shared fields between types
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// In this case, the lump data starts with the following header
|
||||
/// (from public/tier1/lzmaDecoder.h), which is used in place of
|
||||
/// the standard 13-byte LZMA header.
|
||||
///
|
||||
///
|
||||
/// lzmaSize denotes the size (in bytes) of compressed data, it
|
||||
/// is equal to the size of a lump minus 17 bytes (lzma header).
|
||||
/// actualSize denotes the size of decompressed data. properties[5]
|
||||
/// field are used solely for LZMA decoding.
|
||||
///
|
||||
///
|
||||
/// There are two special cases for compression: LUMP_PAKFILE is never
|
||||
/// compressed as a lump (the contents of the zip are compressed instead)
|
||||
/// and each of the game lumps in LUMP_GAME_LUMP are compressed individually.
|
||||
@@ -35,6 +35,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
public uint LzmaSize;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
|
||||
public byte[]? Properties = new byte[5];
|
||||
public byte[] Properties = new byte[5];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,18 @@ namespace SabreTools.Data.Models.BSP
|
||||
{
|
||||
/// <summary>
|
||||
/// The marksurfaces lump is a simple array of short integers.
|
||||
///
|
||||
///
|
||||
/// This lump is a simple table for redirecting the marksurfaces
|
||||
/// indexes in the leafs to the actial face indexes. A leaf inserts
|
||||
/// it's marksurface indexes into this array and gets the associated
|
||||
/// faces contained within this leaf.
|
||||
/// faces contained within this leaf.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
public sealed class MarksurfacesLump : Lump
|
||||
{
|
||||
/// <summary>
|
||||
/// Marksurfaces
|
||||
/// </summary>
|
||||
public ushort[]? Marksurfaces { get; set; }
|
||||
public ushort[] Marksurfaces { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// texture lump relative to the beginning of it's BSPMIPTEX struct.
|
||||
/// </summary>
|
||||
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class MipTexture
|
||||
{
|
||||
@@ -23,8 +23,8 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// Name of texture
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.MAXTEXTURENAME)]
|
||||
public string? Name;
|
||||
|
||||
public string Name = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Extends of the texture
|
||||
/// </summary>
|
||||
@@ -39,6 +39,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// Offsets to texture mipmaps BSPMIPTEX
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.MIPLEVELS)]
|
||||
public uint[]? Offsets;
|
||||
public uint[] Offsets = new uint[Constants.MIPLEVELS];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,14 +27,14 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Minima of all vertices
|
||||
/// </summary>
|
||||
public Vector3D? Mins;
|
||||
public Vector3D Mins = new();
|
||||
|
||||
/// <summary>
|
||||
/// Maxima of all vertices
|
||||
/// </summary>
|
||||
public Vector3D? Maxs;
|
||||
public Vector3D Maxs = new();
|
||||
|
||||
/// <remarks>Since v1</remarks>
|
||||
public int Area;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,4 +26,4 @@ namespace SabreTools.Data.Models.BSP
|
||||
|
||||
public int PlanEnum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// Brush sides textured with tools/toolsoccluder or tools/toolstrigger
|
||||
/// are then stored together with the occluder keys and some additional
|
||||
/// info in this lump.
|
||||
///
|
||||
///
|
||||
/// The lump is divided into three parts and begins with a integer value
|
||||
/// with the total number of occluders, followed by an array of
|
||||
/// doccluderdata_t fields of the same size. The next part begins with
|
||||
@@ -27,20 +27,20 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// <see cref="Count">
|
||||
/// </summary>
|
||||
public OccluderData[]? Data;
|
||||
|
||||
public OccluderData[] Data { get; set; } = [];
|
||||
|
||||
public int PolyDataCount;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="PolyDataCount">
|
||||
/// </summary>
|
||||
public OccluderPolyData[]? PolyData;
|
||||
public OccluderPolyData[] PolyData { get; set; } = [];
|
||||
|
||||
public int VertexIndexCount;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="VertexIndexCount">
|
||||
/// </summary>
|
||||
public int[]? VertexIndicies;
|
||||
public int[] VertexIndicies { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Unlike the simpler decals (infodecal entities), info_overlays
|
||||
/// are removed from the entity lump and stored separately in the
|
||||
/// Overlay lump (Lump 45).
|
||||
///
|
||||
/// Overlay lump (Lump 45).
|
||||
///
|
||||
/// The FaceCountAndRenderOrder member is split into two parts;
|
||||
/// the lower 14 bits are the number of faces that the overlay
|
||||
/// appears on, with the top 2 bits being the render order of
|
||||
@@ -17,7 +17,7 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// scale, and orientation of the overlay decal. There is no
|
||||
/// enforced limit on overlays inside the engine. VBSP enforces
|
||||
/// a limit of 512 (MAX_MAP_OVERLAYS, 1024 in Counter-Strike:
|
||||
/// Global Offensive), but custom compilers can circumvent this.
|
||||
/// Global Offensive), but custom compilers can circumvent this.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -30,19 +30,19 @@ namespace SabreTools.Data.Models.BSP
|
||||
public ushort FaceCountAndRenderOrder;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.OVERLAY_BSP_FACE_COUNT)]
|
||||
public int[]? Ofaces = new int[Constants.OVERLAY_BSP_FACE_COUNT];
|
||||
public int[] Ofaces = new int[Constants.OVERLAY_BSP_FACE_COUNT];
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public float[]? U = new float[2];
|
||||
public float[] U = new float[2];
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public float[]? V = new float[2];
|
||||
public float[] V = new float[2];
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public Vector3D[]? UVPoints = new Vector3D[4];
|
||||
public Vector3D[] UVPoints = new Vector3D[4];
|
||||
|
||||
public Vector3D? Origin;
|
||||
public Vector3D Origin = new();
|
||||
|
||||
public Vector3D? BasisNormal;
|
||||
public Vector3D BasisNormal = new();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// <summary>
|
||||
/// Overlays
|
||||
/// </summary>
|
||||
public Overlay[]? Overlays { get; set; }
|
||||
public Overlay[] Overlays { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,31 +13,31 @@ namespace SabreTools.Data.Models.BSP
|
||||
/// These files are integrated into the game engine's file system
|
||||
/// and will be loaded preferentially before externally located
|
||||
/// files are used.
|
||||
///
|
||||
///
|
||||
/// The format of the Pakfile lump is identical to that used by the
|
||||
/// Zip compression utility when no compression is specified (i.e.,
|
||||
/// the individual files are stored in uncompressed format). In some
|
||||
/// branches, such as , LZMA compression can be used as well. If the
|
||||
/// Pakfile lump is extracted and written to a file, it can therefore
|
||||
/// be opened with WinZip and similar programs.
|
||||
///
|
||||
///
|
||||
/// The header public/zip_uncompressed.h defines the structures
|
||||
/// present in the Pakfile lump. The last element in the lump is a
|
||||
/// ZIP_EndOfCentralDirRecord structure. This points to an array of
|
||||
/// ZIP_FileHeader structures immediately preceeding it, one for each
|
||||
/// file present in the Pak. Each of these headers then point to
|
||||
/// ZIP_LocalFileHeader structures that are followed by that file's
|
||||
/// data.
|
||||
///
|
||||
/// data.
|
||||
///
|
||||
/// The Pakfile lump is usually the last element of the bsp file.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(Source)"/>
|
||||
public sealed class PakfileLump
|
||||
{
|
||||
/// <summary>
|
||||
/// Pakfile data
|
||||
/// </summary>
|
||||
/// TODO: Split and/or decompress data?
|
||||
public byte[]? Data;
|
||||
public byte[] Data { get; set; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user