Compare commits

...

128 Commits
2.0.2 ... 2.1.0

Author SHA1 Message Date
Matt Nadareski
281c18e21d Bump version 2025-11-06 08:08:10 -05:00
Matt Nadareski
1a9c8b5392 Scaffolding for the future 2025-11-06 08:01:04 -05:00
Deterous
831a272f4b Final ISO9660 fix (#41)
* debug

* using

* Test fix

* Final fix
2025-11-05 20:26:42 -05:00
Matt Nadareski
f47e68b9ba Add Mode0 and Mode2 formless models 2025-11-05 09:49:32 -05:00
Matt Nadareski
eaabd2ee77 Add static readers for CD-ROM sector types 2025-11-05 09:37:56 -05:00
Matt Nadareski
a269edd6ea Missed one explicit type 2025-11-05 09:20:48 -05:00
Matt Nadareski
3bb501ce0c Separate out some helper methods 2025-11-05 09:14:37 -05:00
Deterous
d0006a4653 Custom ISO Stream for full CDROM support (#40)
* Implement custom ISO stream for CDROM support

* Delete old files

* Delete old test

* Leaner CDROM wrapper

* Fix custom stream

* WrapperBase using ISO stream

* Reset stream after deserializing

* Fix SeekOrigin

* Return to cached position

* CDROM Constants

* correct ns

* fix href
2025-11-05 08:20:34 -05:00
Matt Nadareski
c48a1394bc Be descriptive about types 2025-11-04 14:15:39 -05:00
Matt Nadareski
fcf7fcfd44 Be descriptive about types 2025-11-04 10:49:03 -05:00
Matt Nadareski
cca08e7103 Use consistent naming 2025-11-04 10:27:00 -05:00
Matt Nadareski
b908732f5c Fix logical block extension 2025-11-04 10:25:55 -05:00
Matt Nadareski
4ee4a6e85f Slight extension cleanup 2025-11-04 10:07:57 -05:00
Matt Nadareski
7990f11bab Remove unnecessary null checks 2025-11-04 09:54:24 -05:00
Matt Nadareski
427f7c9136 Remove unnecessary null checks 2025-11-04 09:46:03 -05:00
Matt Nadareski
f938f1593d Formatting update for readability 2025-11-04 09:15:12 -05:00
Matt Nadareski
480a1834ed Logic inversion and slight cleanup 2025-11-03 20:16:54 -05:00
Matt Nadareski
df5acc648c Minor cleanup 2025-11-03 10:31:30 -05:00
Matt Nadareski
10569e6aa1 Add tests for CDROM 2025-11-03 10:29:52 -05:00
Matt Nadareski
e5103b4830 Fix format comment for ExtractionTool 2025-11-03 09:27:57 -05:00
Matt Nadareski
513646fc53 Fix ExtractionTool publish 2025-11-03 09:03:45 -05:00
Matt Nadareski
27f723bf2f CascLibSharp isn't used and can be removed 2025-11-03 08:53:04 -05:00
Matt Nadareski
6511ecb5ad Merge pull request #39 from SabreTools/storm
Directly include StormLibSharp
2025-11-03 08:39:47 -05:00
Matt Nadareski
7bf6e6f344 Code cleanup and slight modernization 2025-11-03 08:36:12 -05:00
Matt Nadareski
d3e340ae39 Add and use MPQ filename constants 2025-11-02 23:21:29 -05:00
Matt Nadareski
22167a9617 Recursion isn't needed now 2025-11-02 22:27:02 -05:00
Matt Nadareski
48bea55133 Enable extraction on all .NET versions (not OSes) 2025-11-02 22:20:21 -05:00
Matt Nadareski
42239919e5 Enable StormLib for all .NET versions 2025-11-02 22:07:40 -05:00
Matt Nadareski
4840d9df6e Remove NoWarn and fix issues 2025-11-02 21:41:58 -05:00
Matt Nadareski
1378b87ea6 Directly include StormLibSharp code 2025-11-02 21:11:39 -05:00
Matt Nadareski
6b48164b97 Remove StormLibSharp as submodule 2025-11-02 21:07:51 -05:00
Matt Nadareski
50b09aa249 Automated cleanup 2025-11-02 19:28:16 -05:00
Deterous
ecbd147f6d CD-ROM (Volume Descriptor Set) support (#37)
* CD-ROM Wrapper

* Fix CDROMVolume Reader

* Fix SectorMode enum
2025-11-02 19:21:19 -05:00
HeroponRikiBestest
c13df79848 Fix extraction of recent MPF-zipped logs (#38)
* Fix extraction of recent MPF-zipped logs

* Use greater than or equal to

* corrected logic
2025-11-02 08:35:02 -05:00
Deterous
48bcc1de5b ISO9660: Skip interleaved files and other fixes (#35)
* Skip interleaved files

* Fix warning logic

* Refactor

* Fix extraction

* Multi extent

* review
2025-11-01 22:52:41 -04:00
Matt Nadareski
d082f5de25 Auto formatting cleanup 2025-10-31 21:07:13 -04:00
Deterous
c2321669b6 Support ISO9660 Extended Attribute Record (#34)
* Support ISO9660 Extended Attribute Record

* fix

* Fix

* Don't extract multi-extent files

* ReadUInt16LittleEndian

* debug

* Fix

* Skip EAR when extracting files

* Add comment about EAR

* Fix same-name extraction

* Safer directory parsing

* even safer

* return null

* more directory record checks

* not nullable nullable

* init system use

* valid records should pass

* review

* remove empty case
2025-10-31 21:04:45 -04:00
Matt Nadareski
e382635b85 Fix accidental recursion 2025-10-31 14:01:25 -04:00
Matt Nadareski
b4e02d7f8c Ensure default values in models when not optional 2025-10-31 13:59:28 -04:00
Matt Nadareski
0dc8a0b6c0 One missed explicit endian read 2025-10-31 09:36:28 -04:00
Matt Nadareski
171834986d Fix build from previous cleanup 2025-10-31 00:01:35 -04:00
Matt Nadareski
97af686b73 ZSTD model cleanup 2025-10-30 23:59:25 -04:00
Matt Nadareski
7d627ffc6f XZP model cleanup 2025-10-30 23:59:08 -04:00
Matt Nadareski
d924f25eb2 XZ model cleanup 2025-10-30 23:57:15 -04:00
Matt Nadareski
abd8ef3b1f Xbox model cleanup 2025-10-30 23:55:08 -04:00
Matt Nadareski
e9b8dba3a6 WiseInstaller model cleanup 2025-10-30 23:54:22 -04:00
Matt Nadareski
aaff7e7332 WAD3 model cleanup 2025-10-30 23:50:44 -04:00
Matt Nadareski
2fa00d1a16 VPK model cleanup 2025-10-30 23:48:26 -04:00
Matt Nadareski
8a2a2ecd12 TAR model cleanup 2025-10-30 23:45:14 -04:00
Matt Nadareski
98517bdd8c StarForce model cleanup 2025-10-30 23:43:06 -04:00
Matt Nadareski
dfe76f7e7e SpoonInstaller model cleanup 2025-10-30 23:41:40 -04:00
Matt Nadareski
a2e24b1f5f SGA model cleanup 2025-10-30 23:40:45 -04:00
Matt Nadareski
6a4e76e245 SevenZip model cleanup 2025-10-30 23:34:20 -04:00
Matt Nadareski
1ebec97e0e SecuROM model cleanup 2025-10-30 23:34:06 -04:00
Matt Nadareski
b9f03b02f0 RealArcade model cleanup 2025-10-30 23:31:19 -04:00
Matt Nadareski
2c06760778 RAR model cleanup 2025-10-30 23:31:01 -04:00
Matt Nadareski
3f0ee70b71 Quantum model cleanup 2025-10-30 23:30:45 -04:00
Matt Nadareski
05b34f158b PortableExecutable model cleanup 2025-10-30 23:29:24 -04:00
Matt Nadareski
e08db935b4 PlayStation4 model cleanup 2025-10-30 23:07:12 -04:00
Matt Nadareski
47da068bd3 PlayStation3 model cleanup 2025-10-30 23:06:46 -04:00
Matt Nadareski
9de669606d PlayJ model cleanup 2025-10-30 23:05:24 -04:00
Matt Nadareski
a02d50e61d PKZIP model cleanup 2025-10-30 23:01:55 -04:00
Matt Nadareski
069dab7fba PIC model cleanup 2025-10-30 22:58:02 -04:00
Matt Nadareski
d65edadbbb PFF model cleanup 2025-10-30 22:56:23 -04:00
Matt Nadareski
6307a51c0a PAK model cleanup 2025-10-30 22:54:37 -04:00
Matt Nadareski
d27c602bdf OLE model cleanup 2025-10-30 22:52:56 -04:00
Matt Nadareski
59fe9cb113 Nitro model cleanup 2025-10-30 22:51:16 -04:00
Matt Nadareski
b4b7ba75cb NewExecutable model cleanup 2025-10-30 22:47:17 -04:00
Matt Nadareski
d02e0c16c4 NCF model cleanup 2025-10-30 22:39:08 -04:00
Matt Nadareski
4aa0eb54b7 N3DS model cleanup 2025-10-30 22:36:21 -04:00
Matt Nadareski
c4f73abcb6 MSDOS model cleanup 2025-10-30 22:15:10 -04:00
Matt Nadareski
73dec51a4d MoPaQ model cleanup 2025-10-30 22:12:06 -04:00
Matt Nadareski
b7c3c094ae MicrosoftCabinet model cleanup 2025-10-30 22:07:29 -04:00
Matt Nadareski
97702ab3d5 LZ model cleanup 2025-10-30 22:03:22 -04:00
Matt Nadareski
a9b5fe706c LinearExecutable model cleanup 2025-10-30 22:00:42 -04:00
Matt Nadareski
198d48610c LDSCRYPT model cleanup 2025-10-30 21:55:01 -04:00
Matt Nadareski
c0e0344914 IRD model cleanup 2025-10-30 21:54:27 -04:00
Matt Nadareski
d49b2f1b60 InstallShieldExecutable model cleanup 2025-10-30 21:52:20 -04:00
Matt Nadareski
ec7172466b InstallShieldCabinet model cleanup 2025-10-30 21:51:15 -04:00
Matt Nadareski
d75a512ead InstallShieldArchiveV3 model cleanup 2025-10-30 21:43:38 -04:00
Matt Nadareski
af8b6906b6 GZIP model cleanup 2025-10-30 21:40:25 -04:00
Matt Nadareski
96bc301e6d GCF model cleanup 2025-10-30 21:38:17 -04:00
Matt Nadareski
c10749f34d DVD model cleanup 2025-10-30 21:32:21 -04:00
Matt Nadareski
0e4235c8ba Delphi model cleanup 2025-10-30 21:30:41 -04:00
Matt Nadareski
b2d31bb87e CueSheets model cleanup 2025-10-30 21:30:13 -04:00
Matt Nadareski
3ee88793da COFF model cleanup 2025-10-30 21:29:24 -04:00
Matt Nadareski
ad0f01c3ef CHD model cleanup 2025-10-30 21:27:37 -04:00
Matt Nadareski
63a96a7cf8 CFB model cleanup 2025-10-30 21:26:19 -04:00
Matt Nadareski
b8d8ca9a5c BZip2 model cleanup 2025-10-30 21:22:33 -04:00
Matt Nadareski
6b0fca31ae BSP model cleanup 2025-10-30 21:21:56 -04:00
Matt Nadareski
c147b12b10 Bitmap model cleanup 2025-10-30 20:58:03 -04:00
Matt Nadareski
7884b0b775 BFPK model cleanup 2025-10-30 20:57:35 -04:00
Matt Nadareski
9f3c263328 BDPlus model cleanup 2025-10-30 20:55:39 -04:00
Matt Nadareski
b830ce3d73 AdvancedInstaller model cleanup 2025-10-30 20:54:32 -04:00
Matt Nadareski
e8b7f33bf0 AACS model cleanup 2025-10-30 20:52:35 -04:00
Matt Nadareski
eae75c5943 Allow byte arrays to be non-null in most models 2025-10-30 20:44:16 -04:00
Matt Nadareski
c1f5ebcae1 Remove experiments 2025-10-30 19:50:03 -04:00
Matt Nadareski
acb8e98fe2 Add ImgBurn and UltraISO check extensions 2025-10-30 17:04:29 -04:00
Matt Nadareski
a24a92e97c Add unset reserved bytes extension 2025-10-30 16:22:05 -04:00
Matt Nadareski
f2d2fe97bb Override 2025-10-30 12:06:42 -04:00
Matt Nadareski
705252eec7 Unify Skeleton to ISO-9660 2025-10-30 12:03:13 -04:00
Matt Nadareski
69ae0456f0 Add skeleton printing and tests 2025-10-30 11:50:37 -04:00
Deterous
f07bd07cce Redumper skeleton support (#32)
* Skeleton support

* hide ISO extract

* Return true

* Don't inherit ISO9660

* fix

* fix2

* Skeleton
2025-10-30 11:46:45 -04:00
Matt Nadareski
9db2d2ca05 Reduce complexity of Zstd filename generation 2025-10-30 10:23:50 -04:00
Deterous
85248b0135 ISO 9660 Extraction (#31)
* ISO9660 Extraction

* Fix build

* Decode strings in Printer

* Double comment
2025-10-30 10:00:10 -04:00
Matt Nadareski
8663edc7df Fix unsynced ISO position 2025-10-30 08:20:46 -04:00
Matt Nadareski
b9cc9e40fd Changes based on a code sweep with unrelated issue 2025-10-30 07:51:08 -04:00
HeroponRikiBestest
5ce085ad2b Implement basic ZSTD detection and extraction. (#30)
* Implement basic ZSTD detection and extraction.

* Fix comment

* Remove newline

* Add newline

* Move section

* more newlines banished to the ether

* fix comment and name

* fix final i think
2025-10-29 22:01:23 -04:00
Matt Nadareski
d24f8a2fce Add ECMA link to models readme 2025-10-29 10:11:39 -04:00
Matt Nadareski
a73e830209 This extension is useful 2025-10-29 09:46:12 -04:00
Matt Nadareski
146fb42fd0 Replace remaining Seek with SeekIfPossible 2025-10-29 09:34:52 -04:00
Matt Nadareski
5b54ed719e Better integrate new printing model 2025-10-29 09:23:45 -04:00
Matt Nadareski
02d011228e IRD wrapper exists and should be used 2025-10-29 08:57:01 -04:00
Matt Nadareski
07adfd20a3 Add tests for ISO9660 2025-10-29 08:55:45 -04:00
Matt Nadareski
1d00abd6cc Make printing a wrapper extension 2025-10-29 08:53:14 -04:00
Deterous
36c2cc2f15 ISO 9660 support (#29)
* Begin defining ISO9660 models

* Fix initial models

* Improve ISO9660 models

* ISO9660 models

* Fix fields

* Nullable and enums

* Fix flags attribute

* Start ISO9660 Reader code

* semicolon

* Fix build

* Use EqualsExactly

* Fix build

* Update ISO9660.cs

* Update ISO9660.cs

* Move DirectoryRecordDateTime class

* ParseDirectoryRecordDateTime function

* ST refactoring

* fix return

* return array

* ISO9660 wrapper

* Initial printing code

* semicolon

* Fix

* orphan variable name

* fix null ref

* ISO9660 Printer

* Fix DirectoryRecord parsing

* fix

* test

* test

* Fix reader

* extractable ISO

* partial wrapper class

* namespace

* extension property

* path tables

* Cleanup

* rename directory

* fix

* fix

* typo

* fix2

* Fix

* Cleanup reader

* Count list property

* Parse Path Tables

* fix model name

* fix

* fix2

* fix3

* print path table records

* debug errors

* debug error

* debug

* undo debug

* Fix casting

* Validate path table locations

* print table numbers

* Printer cleanup

* fix printer

* printer++

* Print DecDateTime

* else if

* BootSystemUse

* Use Linq

* custom zero check

* fix

* Update ISO9660.cs

* Update ISO9660.cs

* Update ISO9660.cs

* Update ISO9660.cs

* fix

* debug

* debug2

* debug3

* debug4

* debug5

* debug6

* debug7

* debug8

* Array.TrueForAll

* Update ISO9660.cs

* fix

* cleanup

* typo

* Use BothInt numerics

* using SabreTools.Numerics

* Test nonnull

* nonnull bothint

* Print invalid BothInts

* Print directory record

* typo

* fix

* null check

* directory descriptors

* cleanup printer

* semicolon

* Fix

* flags never null

* more non nullable

* no null

* AppendLineBothEndian

* fix

* rename to Directory

* fix

* namespace

* full namespace

* fix

* cleanup

* Parse directories

* fix

* Fix

* Test parse directories

* PeekByteValue

* Revert CI changes

* Dummy extractor

* Review and fixes

* Fixes

* Final fix

* big endian directory search

* fix big endian changes

* Final fix
2025-10-29 08:46:08 -04:00
Matt Nadareski
27cf01ce84 Add printing cases for empty alongside null 2025-10-28 09:52:53 -04:00
Matt Nadareski
1e94163693 Add both-endian StringBuilder extensions
This has to use a new name for the both-endian handling because otherwise the implicit type handling will otherwise cause compilation errors.
2025-10-28 09:49:38 -04:00
Matt Nadareski
db1f94775b Convert some known Peek calls 2025-10-27 22:55:25 -04:00
Matt Nadareski
ce394eb4e9 Seek, if possible 2025-10-27 22:43:56 -04:00
Matt Nadareski
15109bed88 Update IO to 1.8.0 2025-10-27 22:15:54 -04:00
Matt Nadareski
8a18c8de34 Update rolling tag 2025-10-26 20:31:03 -04:00
HeroponRikiBestest
2f093a80c7 increase buffer size for isexe reading / writing based on deterous's … (#28)
* increase buffer size for isexe reading / writing based on deterous's input

* remove comment
2025-10-26 18:54:35 -04:00
Matt Nadareski
5df1af9c17 Minor cleanup and additions 2025-10-23 16:05:12 -04:00
HeroponRikiBestest
d5ab37a5a6 Add extraction for installshield executables. (#27)
* Add extractor for installshield executables.

* Add comment

* Fix intendation.

* Ensure PRs recursively pull

* Rebase

* Fix formatting for parsex

* newline before obj.name

* Changed while loop check to a position vs length check

* Specify type for chunkSize

* declare chunksize as a const int outside of the loop

* Open file writer with using

* Call fs.flush after every write.

* Improved chunk writing loop.

* Remove now-unecessary variable

* Properly handle extracting files of size greater than int32.

* Use long for overlay address

* create deserializer outside of loop.

* Move null check.

* Don't cache position.

---------

Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2025-10-23 15:38:51 -04:00
Matt Nadareski
ed9ecf0da9 Ensure PRs recursively pull 2025-10-23 12:08:47 -04:00
Matt Nadareski
4fc17197ca Fix inverted logic of file only flag 2025-10-19 17:59:56 -04:00
Matt Nadareski
94a9cf0c3f Minor tweak to Wise debug statements 2025-10-17 09:56:04 -04:00
873 changed files with 10726 additions and 5617 deletions

View File

@@ -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
View File

@@ -1,3 +0,0 @@
[submodule "SabreTools.Serialization/_EXTERNAL/stormlibsharp"]
path = SabreTools.Serialization/_EXTERNAL/stormlibsharp
url = https://github.com/robpaveza/stormlibsharp.git

View File

@@ -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>

View File

@@ -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:

View File

@@ -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"));

View File

@@ -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>

View File

@@ -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 |

View 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);
}
}
}

View File

@@ -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);
}
}
}

View 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);
}
}
}

View 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);
}
}
}

View 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);
}
}
}

View 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);
}
}
}
}

View 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);
}
}

View File

@@ -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;
}

View File

@@ -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}");
}
}

View File

@@ -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;
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -66,4 +66,4 @@ namespace SabreTools.Data.Models.AACS
VerifyMediaKey_AACS2 = 0x86,
EmptyRecord0xF8_AACS2 = 0xF8,
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -24,6 +24,6 @@ namespace SabreTools.Data.Models.AACS
/// <summary>
/// Revocation list entries
/// </summary>
public HostRevocationSignatureBlock[]? SignatureBlocks { get; set; }
public HostRevocationSignatureBlock[] SignatureBlocks { get; set; } = [];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -9,6 +9,6 @@ namespace SabreTools.Data.Models.AACS
/// <summary>
/// Records
/// </summary>
public Record[]? Records { get; set; }
public Record[] Records { get; set; } = [];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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; }
}
}
}

View File

@@ -20,4 +20,4 @@ namespace SabreTools.Data.Models.AACS
/// </summary>
public uint Number;
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -29,4 +29,4 @@ namespace SabreTools.Data.Models.AACS
/// </summary>
public uint VersionNumber { get; set; }
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -6,4 +6,4 @@ namespace SabreTools.Data.Models.AdvancedInstaller
public const string SignatureString = "ADVINSTSFX";
}
}
}

View File

@@ -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;
}
}

View File

@@ -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?

View File

@@ -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();
}
}

View File

@@ -6,4 +6,4 @@ namespace SabreTools.Data.Models.BDPlus
public const string SignatureString = "BDSVM_CC";
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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; } = [];
}
}

View File

@@ -8,4 +8,4 @@ namespace SabreTools.Data.Models.BFPK
public const uint SignatureUInt32 = 0x4b504642;
}
}
}

View File

@@ -14,7 +14,7 @@
/// <summary>
/// Name
/// </summary>
public string? Name { get; set; }
public string Name { get; set; } = string.Empty;
/// <summary>
/// Uncompressed size

View File

@@ -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

View File

@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
/// <summary>
/// Indicies
/// </summary>
public LeafAmbientIndex[]? Indicies { get; set; }
public LeafAmbientIndex[] Indicies { get; set; } = [];
}
}
}

View File

@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
/// <summary>
/// Lightings
/// </summary>
public LeafAmbientLighting[]? Lightings { get; set; }
public LeafAmbientLighting[] Lightings { get; set; } = [];
}
}
}

View File

@@ -30,4 +30,4 @@ namespace SabreTools.Data.Models.BSP
/// </summary>
public VbspContents Contents;
}
}
}

View File

@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
/// <summary>
/// Brushes
/// </summary>
public Brush[]? Brushes { get; set; }
public Brush[] Brushes { get; set; } = [];
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
/// <summary>
/// Brushsides
/// </summary>
public Brushside[]? Brushsides { get; set; }
public Brushside[] Brushsides { get; set; } = [];
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -17,4 +17,4 @@ namespace SabreTools.Data.Models.BSP
/// </summary>
public int Length;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -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
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
/// <summary>
/// Cubemaps
/// </summary>
public Cubemap[]? Cubemaps { get; set; }
public Cubemap[] Cubemaps { get; set; } = [];
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
/// <summary>
/// Infos
/// </summary>
public DispInfo[]? Infos { get; set; }
public DispInfo[] Infos { get; set; } = [];
}
}
}

View File

@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
/// <summary>
/// Tris
/// </summary>
public DispTri[]? Tris { get; set; }
public DispTri[] Tris { get; set; } = [];
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
/// <summary>
/// Verts
/// </summary>
public DispVert[]? Verts { get; set; }
public DispVert[] Verts { get; set; } = [];
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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,
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -37,4 +37,4 @@ namespace SabreTools.Data.Models.BSP
/// </summary>
public int FileLength;
}
}
}

View File

@@ -14,4 +14,4 @@ namespace SabreTools.Data.Models.BSP
public ushort FirstAmbientSample;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -11,6 +11,6 @@ namespace SabreTools.Data.Models.BSP
/// <summary>
/// Map
/// </summary>
public ushort[]? Map { get; set; }
public ushort[] Map { get; set; } = [];
}
}
}

View File

@@ -11,6 +11,6 @@ namespace SabreTools.Data.Models.BSP
/// <summary>
/// Map
/// </summary>
public ushort[]? Map { get; set; }
public ushort[] Map { get; set; } = [];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -26,4 +26,4 @@ namespace SabreTools.Data.Models.BSP
public int PlanEnum;
}
}
}

View File

@@ -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; } = [];
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -6,6 +6,6 @@ namespace SabreTools.Data.Models.BSP
/// <summary>
/// Overlays
/// </summary>
public Overlay[]? Overlays { get; set; }
public Overlay[] Overlays { get; set; } = [];
}
}
}

View File

@@ -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