mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-11-15 17:00:38 +00:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de17b0c59c | ||
|
|
1663345195 | ||
|
|
5c3184baa7 | ||
|
|
9e39a0cf16 | ||
|
|
36a67139d9 | ||
|
|
33caf06bc1 | ||
|
|
f639f7ac24 | ||
|
|
11f9bf9fd9 | ||
|
|
373cf2d752 | ||
|
|
dc18951d0b | ||
|
|
29b9d27c33 | ||
|
|
f6ade446c6 | ||
|
|
6238fcbb46 | ||
|
|
2f6698edac | ||
|
|
04e8751f9b | ||
|
|
7262f74f7f | ||
|
|
0b6af978ff | ||
|
|
2cacaac9fd | ||
|
|
d39d8f9b61 | ||
|
|
09fd38e776 | ||
|
|
db2a6f63ff | ||
|
|
d9dd16fbb9 | ||
|
|
3c0c31cf10 | ||
|
|
d9bf16deef | ||
|
|
3798dbcb47 | ||
|
|
2a70a9a20e | ||
|
|
6f92f85f5d | ||
|
|
b7851601a4 | ||
|
|
cb2a96c413 | ||
|
|
69c0843a0d | ||
|
|
0171ea9da7 | ||
|
|
e493af25e0 | ||
|
|
62427576e9 | ||
|
|
e80ea00872 | ||
|
|
ce1cd15978 | ||
|
|
2a604bd73a | ||
|
|
bcc0a5bd1e | ||
|
|
32d9e8a09d | ||
|
|
d0f5ac322d | ||
|
|
05c86e4c24 | ||
|
|
1d76967a08 | ||
|
|
b9ffd61252 | ||
|
|
b4e1f6b729 |
1
.github/workflows/build_and_test.yml
vendored
1
.github/workflows/build_and_test.yml
vendored
@@ -20,6 +20,7 @@ jobs:
|
|||||||
8.0.x
|
8.0.x
|
||||||
9.0.x
|
9.0.x
|
||||||
10.0.x
|
10.0.x
|
||||||
|
11.0.x
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: dotnet test
|
run: dotnet test
|
||||||
|
|||||||
1
.github/workflows/check_pr.yml
vendored
1
.github/workflows/check_pr.yml
vendored
@@ -15,6 +15,7 @@ jobs:
|
|||||||
8.0.x
|
8.0.x
|
||||||
9.0.x
|
9.0.x
|
||||||
10.0.x
|
10.0.x
|
||||||
|
11.0.x
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: dotnet build
|
run: dotnet build
|
||||||
|
|||||||
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@@ -10,7 +10,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "build",
|
"preLaunchTask": "build",
|
||||||
// If you have changed target frameworks, make sure to update the program path.
|
// If you have changed target frameworks, make sure to update the program path.
|
||||||
"program": "${workspaceFolder}/ExtractionTool/bin/Debug/net10.0/ExtractionTool.dll",
|
"program": "${workspaceFolder}/ExtractionTool/bin/Debug/net11.0/ExtractionTool.dll",
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "build",
|
"preLaunchTask": "build",
|
||||||
// If you have changed target frameworks, make sure to update the program path.
|
// If you have changed target frameworks, make sure to update the program path.
|
||||||
"program": "${workspaceFolder}/InfoPrint/bin/Debug/net10.0/InfoPrint.dll",
|
"program": "${workspaceFolder}/InfoPrint/bin/Debug/net11.0/InfoPrint.dll",
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Version>3.0.1</Version>
|
<Version>3.3.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Support All Frameworks -->
|
<!-- Support All Frameworks -->
|
||||||
@@ -20,11 +20,11 @@
|
|||||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`)) OR $(TargetFramework.StartsWith(`net10`))">
|
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`)) OR $(TargetFramework.StartsWith(`net10`)) OR $(TargetFramework.StartsWith(`net11`))">
|
||||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
||||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- These are needed for dealing with native Windows DLLs -->
|
<!-- These are needed for dealing with native Windows DLLs -->
|
||||||
@@ -48,9 +48,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
|
<PackageReference Include="SabreTools.CommandLine" Version="1.6.0" />
|
||||||
<PackageReference Include="SabreTools.IO" Version="[2.1.0]" />
|
<PackageReference Include="SabreTools.IO" Version="2.4.0" />
|
||||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="10.0.8" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="11.0.0" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Version>3.0.1</Version>
|
<Version>3.3.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Support All Frameworks -->
|
<!-- Support All Frameworks -->
|
||||||
@@ -20,11 +20,11 @@
|
|||||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`)) OR $(TargetFramework.StartsWith(`net10`))">
|
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`)) OR $(TargetFramework.StartsWith(`net10`)) OR $(TargetFramework.StartsWith(`net11`))">
|
||||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
||||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -32,9 +32,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
|
<PackageReference Include="SabreTools.CommandLine" Version="1.6.0" />
|
||||||
<PackageReference Include="SabreTools.Hashing" Version="[2.0.0]" />
|
<PackageReference Include="SabreTools.Hashing" Version="2.2.0" />
|
||||||
<PackageReference Include="SabreTools.IO" Version="[2.1.0]" />
|
<PackageReference Include="SabreTools.IO" Version="2.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -361,6 +361,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -380,6 +381,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -406,6 +408,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -424,6 +427,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -449,6 +453,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -467,6 +472,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -493,6 +499,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -510,6 +517,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -536,6 +544,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -554,6 +563,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -580,6 +590,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -598,6 +609,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -624,6 +636,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -642,6 +655,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -668,6 +682,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -686,6 +701,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -712,6 +728,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -730,6 +747,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -756,6 +774,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -774,6 +793,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -800,6 +820,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -818,6 +839,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -844,6 +866,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -862,6 +885,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -888,6 +912,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -906,6 +931,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -932,6 +958,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -950,6 +977,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -976,6 +1004,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -994,6 +1023,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -1020,6 +1050,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1038,6 +1069,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -1064,6 +1096,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1082,6 +1115,53 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
|
};
|
||||||
|
|
||||||
|
bool actual = self.PartialEquals(other);
|
||||||
|
Assert.True(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PartialEquals_Rom_PartialBLAKE3_True()
|
||||||
|
{
|
||||||
|
var self = new Rom
|
||||||
|
{
|
||||||
|
Name = "name1",
|
||||||
|
Size = 12345,
|
||||||
|
CRC16 = string.Empty,
|
||||||
|
CRC32 = string.Empty,
|
||||||
|
CRC64 = string.Empty,
|
||||||
|
MD2 = string.Empty,
|
||||||
|
MD4 = string.Empty,
|
||||||
|
MD5 = string.Empty,
|
||||||
|
RIPEMD128 = string.Empty,
|
||||||
|
RIPEMD160 = string.Empty,
|
||||||
|
SHA1 = string.Empty,
|
||||||
|
SHA256 = string.Empty,
|
||||||
|
SHA384 = string.Empty,
|
||||||
|
SHA512 = string.Empty,
|
||||||
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = "blake3",
|
||||||
|
};
|
||||||
|
var other = new Rom
|
||||||
|
{
|
||||||
|
Name = "name2",
|
||||||
|
Size = 12345,
|
||||||
|
CRC16 = "crc16",
|
||||||
|
CRC32 = "crc32",
|
||||||
|
CRC64 = "crc64",
|
||||||
|
MD2 = "md2",
|
||||||
|
MD4 = "md4",
|
||||||
|
MD5 = "md5",
|
||||||
|
RIPEMD128 = "ripemd128",
|
||||||
|
RIPEMD160 = "ripemd160",
|
||||||
|
SHA1 = "sha1",
|
||||||
|
SHA256 = "sha256",
|
||||||
|
SHA384 = "sha384",
|
||||||
|
SHA512 = "sha512",
|
||||||
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -1108,6 +1188,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
var other = new Rom
|
var other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1126,6 +1207,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.PartialEquals(other);
|
bool actual = self.PartialEquals(other);
|
||||||
@@ -1392,6 +1474,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1408,6 +1491,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1432,6 +1516,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1448,6 +1533,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1472,6 +1558,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1488,6 +1575,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1512,6 +1600,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1528,6 +1617,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1552,6 +1642,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1568,6 +1659,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1592,6 +1684,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1608,6 +1701,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1632,6 +1726,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1648,6 +1743,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1672,6 +1768,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1688,6 +1785,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1712,6 +1810,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1728,6 +1827,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1752,6 +1852,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1768,6 +1869,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1792,6 +1894,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1808,6 +1911,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1832,6 +1936,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1848,6 +1953,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1872,6 +1978,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1888,6 +1995,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1912,6 +2020,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1928,6 +2037,49 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
|
};
|
||||||
|
|
||||||
|
bool actual = self.HashMatch(other);
|
||||||
|
Assert.True(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HashMatch_Rom_PartialBLAKE3_True()
|
||||||
|
{
|
||||||
|
Rom self = new Rom
|
||||||
|
{
|
||||||
|
CRC16 = string.Empty,
|
||||||
|
CRC32 = string.Empty,
|
||||||
|
CRC64 = string.Empty,
|
||||||
|
MD2 = string.Empty,
|
||||||
|
MD4 = string.Empty,
|
||||||
|
MD5 = string.Empty,
|
||||||
|
RIPEMD128 = string.Empty,
|
||||||
|
RIPEMD160 = string.Empty,
|
||||||
|
SHA1 = string.Empty,
|
||||||
|
SHA256 = string.Empty,
|
||||||
|
SHA384 = string.Empty,
|
||||||
|
SHA512 = string.Empty,
|
||||||
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = "blake3",
|
||||||
|
};
|
||||||
|
Rom other = new Rom
|
||||||
|
{
|
||||||
|
CRC16 = "crc16",
|
||||||
|
CRC32 = "crc32",
|
||||||
|
CRC64 = "crc64",
|
||||||
|
MD2 = "md2",
|
||||||
|
MD4 = "md4",
|
||||||
|
MD5 = "md5",
|
||||||
|
RIPEMD128 = "ripemd128",
|
||||||
|
RIPEMD160 = "ripemd160",
|
||||||
|
SHA1 = "sha1",
|
||||||
|
SHA256 = "sha256",
|
||||||
|
SHA384 = "sha384",
|
||||||
|
SHA512 = "sha512",
|
||||||
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -1952,6 +2104,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
Rom other = new Rom
|
Rom other = new Rom
|
||||||
{
|
{
|
||||||
@@ -1968,6 +2121,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HashMatch(other);
|
bool actual = self.HashMatch(other);
|
||||||
@@ -2162,6 +2316,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2186,6 +2341,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2210,6 +2366,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2234,6 +2391,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2258,6 +2416,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2282,6 +2441,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2306,6 +2466,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2330,6 +2491,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2354,6 +2516,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2378,6 +2541,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2402,6 +2566,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2426,6 +2591,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = HashType.SHA384.ZeroString,
|
SHA384 = HashType.SHA384.ZeroString,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2450,6 +2616,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = HashType.SHA512.ZeroString,
|
SHA512 = HashType.SHA512.ZeroString,
|
||||||
SpamSum = string.Empty,
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2474,6 +2641,32 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = HashType.SpamSum.ZeroString,
|
SpamSum = HashType.SpamSum.ZeroString,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool actual = self.HasZeroHash();
|
||||||
|
Assert.True(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HasZeroHash_Rom_ZeroBLAKE3_True()
|
||||||
|
{
|
||||||
|
var self = new Rom
|
||||||
|
{
|
||||||
|
CRC16 = string.Empty,
|
||||||
|
CRC32 = string.Empty,
|
||||||
|
CRC64 = string.Empty,
|
||||||
|
MD2 = string.Empty,
|
||||||
|
MD4 = string.Empty,
|
||||||
|
MD5 = string.Empty,
|
||||||
|
RIPEMD128 = string.Empty,
|
||||||
|
RIPEMD160 = string.Empty,
|
||||||
|
SHA1 = string.Empty,
|
||||||
|
SHA256 = string.Empty,
|
||||||
|
SHA384 = string.Empty,
|
||||||
|
SHA512 = string.Empty,
|
||||||
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = HashType.BLAKE3.ZeroString,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2498,6 +2691,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = HashType.SHA384.ZeroString,
|
SHA384 = HashType.SHA384.ZeroString,
|
||||||
SHA512 = HashType.SHA512.ZeroString,
|
SHA512 = HashType.SHA512.ZeroString,
|
||||||
SpamSum = HashType.SpamSum.ZeroString,
|
SpamSum = HashType.SpamSum.ZeroString,
|
||||||
|
BLAKE3 = HashType.BLAKE3.ZeroString,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -2583,6 +2777,7 @@ namespace SabreTools.Data.Extensions.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
self.FillMissingHashes(other);
|
self.FillMissingHashes(other);
|
||||||
|
|||||||
@@ -1,17 +1,24 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
<TargetFrameworks>net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="coverlet.collector" Version="10.0.0" />
|
<PackageReference Include="coverlet.collector" Version="10.1.0">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.11.1" />
|
||||||
<PackageReference Include="xunit" Version="2.9.3" />
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
274
SabreTools.Data.Extensions.Test/UDFExtensionsTests.cs
Normal file
274
SabreTools.Data.Extensions.Test/UDFExtensionsTests.cs
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
using SabreTools.Data.Models.UDF;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace SabreTools.Data.Extensions.Test
|
||||||
|
{
|
||||||
|
public class UDFExtensionsTests
|
||||||
|
{
|
||||||
|
#region DecodeDCharacters
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DecodeDCharacters_Null_Empty()
|
||||||
|
{
|
||||||
|
byte[]? data = null;
|
||||||
|
Assert.Equal(string.Empty, data.DecodeDCharacters());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DecodeDCharacters_8Bit_Decoded()
|
||||||
|
{
|
||||||
|
byte[] data = [8, 0x41, 0x62, 0xE4];
|
||||||
|
Assert.Equal("Abä", data.DecodeDCharacters());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DecodeDCharacters_16Bit_Decoded()
|
||||||
|
{
|
||||||
|
byte[] data = [16, 0x00, 0x41, 0x30, 0x42];
|
||||||
|
Assert.Equal("Aあ", data.DecodeDCharacters());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DecodeDCharacters_UnknownCompression_Null()
|
||||||
|
{
|
||||||
|
byte[] data = [1, 0x41];
|
||||||
|
Assert.Null(data.DecodeDCharacters());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DecodeDString_UsesLengthByte()
|
||||||
|
{
|
||||||
|
byte[] data = [8, 0x41, 0x42, 0x43, 0x00, 3];
|
||||||
|
Assert.Equal("AB", data.DecodeDString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DecodeDString_ZeroLength_Empty()
|
||||||
|
{
|
||||||
|
byte[] data = [8, 0x41, 0x00, 0];
|
||||||
|
Assert.Equal(string.Empty, data.DecodeDString());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region TryGetSector
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetSector_Type1_StartPlusBlock()
|
||||||
|
{
|
||||||
|
var volume = CreateVolume(new Type1PartitionMap { PartitionNumber = 0 });
|
||||||
|
bool actual = volume.TryGetSector(UDFExtensions.GetKey(0, 10), out long sector);
|
||||||
|
Assert.True(actual);
|
||||||
|
Assert.Equal(1010, sector);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetSector_Type1_OutsidePartition_False()
|
||||||
|
{
|
||||||
|
var volume = CreateVolume(new Type1PartitionMap { PartitionNumber = 0 });
|
||||||
|
bool actual = volume.TryGetSector(UDFExtensions.GetKey(0, 100), out _);
|
||||||
|
Assert.False(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetSector_UnknownPartitionReference_False()
|
||||||
|
{
|
||||||
|
var volume = CreateVolume(new Type1PartitionMap { PartitionNumber = 0 });
|
||||||
|
bool actual = volume.TryGetSector(UDFExtensions.GetKey(1, 0), out _);
|
||||||
|
Assert.False(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetSector_Metadata_ThroughMetadataFile()
|
||||||
|
{
|
||||||
|
// Metadata File at block 5 of partition 0: blocks 0-1 of the metadata partition are blocks 20-21,
|
||||||
|
// blocks 2-3 are blocks 40-41
|
||||||
|
var volume = CreateVolume(
|
||||||
|
new Type1PartitionMap { PartitionNumber = 0 },
|
||||||
|
new MetadataPartitionMap { PartitionNumber = 0, MetadataFileLocation = 5, MetadataMirrorFileLocation = 6 });
|
||||||
|
volume.FileEntries[UDFExtensions.GetKey(0, 5)] = CreateShortAdEntry((4096, 20), (4096, 40));
|
||||||
|
|
||||||
|
Assert.True(volume.TryGetSector(UDFExtensions.GetKey(1, 1), out long first));
|
||||||
|
Assert.Equal(1021, first);
|
||||||
|
Assert.True(volume.TryGetSector(UDFExtensions.GetKey(1, 2), out long second));
|
||||||
|
Assert.Equal(1040, second);
|
||||||
|
Assert.False(volume.TryGetSector(UDFExtensions.GetKey(1, 4), out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetSector_Metadata_FallsBackToMirror()
|
||||||
|
{
|
||||||
|
var volume = CreateVolume(
|
||||||
|
new Type1PartitionMap { PartitionNumber = 0 },
|
||||||
|
new MetadataPartitionMap { PartitionNumber = 0, MetadataFileLocation = 5, MetadataMirrorFileLocation = 6 });
|
||||||
|
volume.FileEntries[UDFExtensions.GetKey(0, 6)] = CreateShortAdEntry((2048, 30));
|
||||||
|
|
||||||
|
Assert.True(volume.TryGetSector(UDFExtensions.GetKey(1, 0), out long sector));
|
||||||
|
Assert.Equal(1030, sector);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region GetAllocationDescriptors
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetAllocationDescriptors_Embedded_Empty()
|
||||||
|
{
|
||||||
|
var entry = new FileEntry();
|
||||||
|
entry.ICBTag.Flags = (ushort)AllocationDescriptorType.EMBEDDED;
|
||||||
|
entry.AllocationDescriptors = [1, 2, 3];
|
||||||
|
|
||||||
|
var actual = new Volume().GetAllocationDescriptors(0, entry);
|
||||||
|
Assert.NotNull(actual);
|
||||||
|
Assert.Empty(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetAllocationDescriptors_ZeroLengthTerminates()
|
||||||
|
{
|
||||||
|
var entry = CreateShortAdEntry((2048, 20), (0, 99), (2048, 40));
|
||||||
|
|
||||||
|
var actual = new Volume().GetAllocationDescriptors(UDFExtensions.GetKey(2, 7), entry);
|
||||||
|
Assert.NotNull(actual);
|
||||||
|
var ad = Assert.Single(actual);
|
||||||
|
Assert.Equal(20u, ad.ExtentLocation.LogicalBlockNumber);
|
||||||
|
Assert.Equal((ushort)2, ad.ExtentLocation.PartitionReferenceNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetAllocationDescriptors_MissingAllocationExtent_NullWithKey()
|
||||||
|
{
|
||||||
|
var entry = CreateShortAdEntry((2048, 20), ((3u << 30) | 2048, 50));
|
||||||
|
|
||||||
|
var actual = new Volume().GetAllocationDescriptors(UDFExtensions.GetKey(0, 7), entry, out long missingKey);
|
||||||
|
Assert.Null(actual);
|
||||||
|
Assert.Equal(UDFExtensions.GetKey(0, 50), missingKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetAllocationDescriptors_AllocationExtentLoop_Null()
|
||||||
|
{
|
||||||
|
var volume = new Volume();
|
||||||
|
var entry = CreateShortAdEntry(((3u << 30) | 2048, 50));
|
||||||
|
volume.AllocationExtentDescriptors[UDFExtensions.GetKey(0, 50)] = new AllocationExtentDescriptor
|
||||||
|
{
|
||||||
|
AllocationDescriptors = CreateShortAdEntry(((3u << 30) | 2048, 50)).AllocationDescriptors,
|
||||||
|
};
|
||||||
|
|
||||||
|
var actual = volume.GetAllocationDescriptors(UDFExtensions.GetKey(0, 7), entry);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IsValidDescriptor
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(2)]
|
||||||
|
[InlineData(3)]
|
||||||
|
public void IsValidDescriptor_Valid_True(byte version)
|
||||||
|
{
|
||||||
|
byte[] data = CreateDescriptor(version);
|
||||||
|
Assert.True(data.IsValidDescriptor(0, data.Length, 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsValidDescriptor_WrongChecksum_False()
|
||||||
|
{
|
||||||
|
byte[] data = CreateDescriptor(2);
|
||||||
|
data[4]++;
|
||||||
|
Assert.False(data.IsValidDescriptor(0, data.Length, 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsValidDescriptor_UnknownVersion_False()
|
||||||
|
{
|
||||||
|
byte[] data = CreateDescriptor(4);
|
||||||
|
Assert.False(data.IsValidDescriptor(0, data.Length, 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsValidDescriptor_WrongCrc_False()
|
||||||
|
{
|
||||||
|
byte[] data = CreateDescriptor(2);
|
||||||
|
data[16] ^= 0x01;
|
||||||
|
Assert.False(data.IsValidDescriptor(0, data.Length, 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsValidDescriptor_CrcPastAvailable_NotChecked()
|
||||||
|
{
|
||||||
|
byte[] data = CreateDescriptor(2);
|
||||||
|
data[16] ^= 0x01;
|
||||||
|
Assert.True(data.IsValidDescriptor(0, 16, 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsValidDescriptor_WrongLocation_False()
|
||||||
|
{
|
||||||
|
byte[] data = CreateDescriptor(2);
|
||||||
|
Assert.False(data.IsValidDescriptor(0, data.Length, 21));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Descriptor with tag location 20 whose 3 bytes after the tag have the CRC #3299 (ECMA-167 3/7.2.6)
|
||||||
|
/// </summary>
|
||||||
|
private static byte[] CreateDescriptor(byte version)
|
||||||
|
{
|
||||||
|
byte[] data = new byte[19];
|
||||||
|
data[0] = 1;
|
||||||
|
data[2] = version;
|
||||||
|
data[8] = 0x99;
|
||||||
|
data[9] = 0x32;
|
||||||
|
data[10] = 3;
|
||||||
|
data[12] = 20;
|
||||||
|
data[16] = 0x70;
|
||||||
|
data[17] = 0x6A;
|
||||||
|
data[18] = 0x77;
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if (i != 4)
|
||||||
|
data[4] += data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Volume with partition 0 at sector 1000 (length 50) and the given partition maps
|
||||||
|
/// </summary>
|
||||||
|
private static Volume CreateVolume(params PartitionMap[] maps)
|
||||||
|
{
|
||||||
|
return new Volume
|
||||||
|
{
|
||||||
|
VolumeDescriptorSequence =
|
||||||
|
[
|
||||||
|
new PartitionDescriptor { PartitionNumber = 0, PartitionStartingLocation = 1000, PartitionLength = 50 },
|
||||||
|
new LogicalVolumeDescriptor { LogicalBlockSize = 2048, PartitionMaps = maps },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File Entry with the given short allocation descriptors (extent length, position)
|
||||||
|
/// </summary>
|
||||||
|
private static FileEntry CreateShortAdEntry(params (uint Length, uint Position)[] extents)
|
||||||
|
{
|
||||||
|
var data = new byte[extents.Length * 8];
|
||||||
|
for (int i = 0; i < extents.Length; i++)
|
||||||
|
{
|
||||||
|
for (int b = 0; b < 4; b++)
|
||||||
|
{
|
||||||
|
data[(i * 8) + b] = (byte)(extents[i].Length >> (8 * b));
|
||||||
|
data[(i * 8) + 4 + b] = (byte)(extents[i].Position >> (8 * b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var entry = new FileEntry { AllocationDescriptors = data };
|
||||||
|
entry.ICBTag.Flags = (ushort)AllocationDescriptorType.SHORT;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -296,6 +296,10 @@ namespace SabreTools.Data.Extensions
|
|||||||
string? otherSpamSum = other.SpamSum;
|
string? otherSpamSum = other.SpamSum;
|
||||||
bool conditionalSpamSum = ConditionalHashEquals(selfSpamSum, otherSpamSum);
|
bool conditionalSpamSum = ConditionalHashEquals(selfSpamSum, otherSpamSum);
|
||||||
|
|
||||||
|
string? selfBlake3 = self.BLAKE3;
|
||||||
|
string? otherBlake3 = other.BLAKE3;
|
||||||
|
bool conditionalBlake3 = ConditionalHashEquals(selfBlake3, otherBlake3);
|
||||||
|
|
||||||
return conditionalCrc16
|
return conditionalCrc16
|
||||||
&& conditionalCrc
|
&& conditionalCrc
|
||||||
&& conditionalCrc64
|
&& conditionalCrc64
|
||||||
@@ -308,7 +312,8 @@ namespace SabreTools.Data.Extensions
|
|||||||
&& conditionalSha256
|
&& conditionalSha256
|
||||||
&& conditionalSha384
|
&& conditionalSha384
|
||||||
&& conditionalSha512
|
&& conditionalSha512
|
||||||
&& conditionalSpamSum;
|
&& conditionalSpamSum
|
||||||
|
&& conditionalBlake3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -357,6 +362,7 @@ namespace SabreTools.Data.Extensions
|
|||||||
bool sha384Null = string.IsNullOrEmpty(rom.SHA384);
|
bool sha384Null = string.IsNullOrEmpty(rom.SHA384);
|
||||||
bool sha512Null = string.IsNullOrEmpty(rom.SHA512);
|
bool sha512Null = string.IsNullOrEmpty(rom.SHA512);
|
||||||
bool spamsumNull = string.IsNullOrEmpty(rom.SpamSum);
|
bool spamsumNull = string.IsNullOrEmpty(rom.SpamSum);
|
||||||
|
bool blake3Null = string.IsNullOrEmpty(rom.BLAKE3);
|
||||||
|
|
||||||
return !crc16Null
|
return !crc16Null
|
||||||
|| !crc32Null
|
|| !crc32Null
|
||||||
@@ -370,7 +376,8 @@ namespace SabreTools.Data.Extensions
|
|||||||
|| !sha256Null
|
|| !sha256Null
|
||||||
|| !sha384Null
|
|| !sha384Null
|
||||||
|| !sha512Null
|
|| !sha512Null
|
||||||
|| !spamsumNull;
|
|| !spamsumNull
|
||||||
|
|| !blake3Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -455,6 +462,9 @@ namespace SabreTools.Data.Extensions
|
|||||||
string? spamsum = rom.SpamSum;
|
string? spamsum = rom.SpamSum;
|
||||||
bool spamsumNull = string.IsNullOrEmpty(spamsum) || string.Equals(spamsum, HashType.SpamSum.ZeroString, StringComparison.OrdinalIgnoreCase);
|
bool spamsumNull = string.IsNullOrEmpty(spamsum) || string.Equals(spamsum, HashType.SpamSum.ZeroString, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
string? blake3 = rom.BLAKE3;
|
||||||
|
bool blake3Null = string.IsNullOrEmpty(blake3) || string.Equals(blake3, HashType.BLAKE3.ZeroString, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
return crc16Null
|
return crc16Null
|
||||||
&& crc32Null
|
&& crc32Null
|
||||||
&& crc64Null
|
&& crc64Null
|
||||||
@@ -467,7 +477,8 @@ namespace SabreTools.Data.Extensions
|
|||||||
&& sha256Null
|
&& sha256Null
|
||||||
&& sha384Null
|
&& sha384Null
|
||||||
&& sha512Null
|
&& sha512Null
|
||||||
&& spamsumNull;
|
&& spamsumNull
|
||||||
|
&& blake3Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -552,6 +563,9 @@ namespace SabreTools.Data.Extensions
|
|||||||
bool spamsumNull = string.IsNullOrEmpty(self.SpamSum);
|
bool spamsumNull = string.IsNullOrEmpty(self.SpamSum);
|
||||||
spamsumNull ^= string.IsNullOrEmpty(other.SpamSum);
|
spamsumNull ^= string.IsNullOrEmpty(other.SpamSum);
|
||||||
|
|
||||||
|
bool blake3Null = string.IsNullOrEmpty(self.BLAKE3);
|
||||||
|
blake3Null ^= string.IsNullOrEmpty(other.BLAKE3);
|
||||||
|
|
||||||
return !crc16Null
|
return !crc16Null
|
||||||
|| !crc32Null
|
|| !crc32Null
|
||||||
|| !crc64Null
|
|| !crc64Null
|
||||||
@@ -564,7 +578,8 @@ namespace SabreTools.Data.Extensions
|
|||||||
|| !sha256Null
|
|| !sha256Null
|
||||||
|| !sha384Null
|
|| !sha384Null
|
||||||
|| !sha512Null
|
|| !sha512Null
|
||||||
|| !spamsumNull;
|
|| !spamsumNull
|
||||||
|
|| !blake3Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -696,6 +711,11 @@ namespace SabreTools.Data.Extensions
|
|||||||
string? otherSpamSum = other.SpamSum;
|
string? otherSpamSum = other.SpamSum;
|
||||||
if (string.IsNullOrEmpty(selfSpamSum) && !string.IsNullOrEmpty(otherSpamSum))
|
if (string.IsNullOrEmpty(selfSpamSum) && !string.IsNullOrEmpty(otherSpamSum))
|
||||||
self.SpamSum = otherSpamSum;
|
self.SpamSum = otherSpamSum;
|
||||||
|
|
||||||
|
string? selfBlake3 = self.BLAKE3;
|
||||||
|
string? otherBlake3 = other.BLAKE3;
|
||||||
|
if (string.IsNullOrEmpty(selfBlake3) && !string.IsNullOrEmpty(otherBlake3))
|
||||||
|
self.BLAKE3 = otherBlake3;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Assembly Properties -->
|
<!-- Assembly Properties -->
|
||||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;net11.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Version>3.0.1</Version>
|
<Version>3.3.0</Version>
|
||||||
|
|
||||||
<!-- Package Properties -->
|
<!-- Package Properties -->
|
||||||
<Authors>Matt Nadareski</Authors>
|
<Authors>Matt Nadareski</Authors>
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="NetLegacySupport.Numerics" Version="1.0.1" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`))" />
|
<PackageReference Include="NetLegacySupport.Numerics" Version="1.0.1" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`))" />
|
||||||
<PackageReference Include="SabreTools.IO" Version="[2.1.0]" />
|
<PackageReference Include="SabreTools.IO" Version="2.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
417
SabreTools.Data.Extensions/UDFExtensions.cs
Normal file
417
SabreTools.Data.Extensions/UDFExtensions.cs
Normal file
@@ -0,0 +1,417 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using SabreTools.Data.Models.UDF;
|
||||||
|
using SabreTools.Numerics.Extensions;
|
||||||
|
|
||||||
|
namespace SabreTools.Data.Extensions
|
||||||
|
{
|
||||||
|
public static class UDFExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of Allocation Extent Descriptors followed for one File Entry
|
||||||
|
/// </summary>
|
||||||
|
private const int MaximumAllocationExtents = 1024;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CRC-ITU-T (CCITT, polynomial 0x1021) table for descriptor CRCs
|
||||||
|
/// </summary>
|
||||||
|
private static readonly ushort[] CrcTable = CreateCrcTable();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the dictionary key of a logical block address
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Logical block address</param>
|
||||||
|
/// <returns>((long)PartitionReferenceNumber << 32) | LogicalBlockNumber</returns>
|
||||||
|
public static long GetKey(this LogicalBlockAddress address)
|
||||||
|
=> GetKey(address.PartitionReferenceNumber, address.LogicalBlockNumber);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the dictionary key of a logical block address
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="partitionReferenceNumber">Index of the partition map</param>
|
||||||
|
/// <param name="logicalBlockNumber">Logical block number within the partition</param>
|
||||||
|
/// <returns>((long)partitionReferenceNumber << 32) | logicalBlockNumber</returns>
|
||||||
|
public static long GetKey(ushort partitionReferenceNumber, uint logicalBlockNumber)
|
||||||
|
=> ((long)partitionReferenceNumber << 32) | logicalBlockNumber;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the extent type from an allocation descriptor's extent length
|
||||||
|
/// </summary>
|
||||||
|
public static ExtentType GetExtentType(uint extentLength)
|
||||||
|
=> (ExtentType)(extentLength >> Constants.ExtentTypeShift);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the extent length in bytes from an allocation descriptor's extent length
|
||||||
|
/// </summary>
|
||||||
|
public static uint GetExtentLength(uint extentLength)
|
||||||
|
=> extentLength & Constants.ExtentLengthMask;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the type of the allocation descriptors of an ICB
|
||||||
|
/// </summary>
|
||||||
|
public static AllocationDescriptorType GetAllocationDescriptorType(this ICBTag tag)
|
||||||
|
=> (AllocationDescriptorType)(tag.Flags & Constants.AllocationDescriptorTypeMask);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the prevailing Logical Volume Descriptor (highest Volume Descriptor Sequence Number)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="volume">Volume to search</param>
|
||||||
|
/// <returns>Logical Volume Descriptor on success, null if none was recorded</returns>
|
||||||
|
public static LogicalVolumeDescriptor? GetLogicalVolumeDescriptor(this Volume volume)
|
||||||
|
{
|
||||||
|
LogicalVolumeDescriptor? prevailing = null;
|
||||||
|
foreach (var descriptor in volume.VolumeDescriptorSequence)
|
||||||
|
{
|
||||||
|
if (descriptor is LogicalVolumeDescriptor lvd
|
||||||
|
&& (prevailing is null || lvd.VolumeDescriptorSequenceNumber > prevailing.VolumeDescriptorSequenceNumber))
|
||||||
|
{
|
||||||
|
prevailing = lvd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prevailing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the prevailing Partition Descriptor of a partition (highest Volume Descriptor Sequence Number)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="volume">Volume to search</param>
|
||||||
|
/// <param name="partitionNumber">Partition number</param>
|
||||||
|
/// <returns>Partition Descriptor on success, null if none was recorded</returns>
|
||||||
|
public static PartitionDescriptor? GetPartitionDescriptor(this Volume volume, ushort partitionNumber)
|
||||||
|
{
|
||||||
|
PartitionDescriptor? prevailing = null;
|
||||||
|
foreach (var descriptor in volume.VolumeDescriptorSequence)
|
||||||
|
{
|
||||||
|
if (descriptor is PartitionDescriptor pd
|
||||||
|
&& pd.PartitionNumber == partitionNumber
|
||||||
|
&& (prevailing is null || pd.VolumeDescriptorSequenceNumber > prevailing.VolumeDescriptorSequenceNumber))
|
||||||
|
{
|
||||||
|
prevailing = pd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prevailing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the partition reference number of the Type 1 partition map for a partition number
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lvd">Logical Volume Descriptor holding the partition maps</param>
|
||||||
|
/// <param name="partitionNumber">Partition number</param>
|
||||||
|
/// <returns>Partition reference number on success, -1 if there is no such map</returns>
|
||||||
|
public static int GetType1PartitionReference(this LogicalVolumeDescriptor lvd, ushort partitionNumber)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < lvd.PartitionMaps.Length; i++)
|
||||||
|
{
|
||||||
|
if (lvd.PartitionMaps[i] is Type1PartitionMap map && map.PartitionNumber == partitionNumber)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Map a logical block of a partition to a logical sector of the volume
|
||||||
|
/// Supports Type 1 partitions and Metadata Partitions (the Metadata File's File Entry must be in FileEntries)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="volume">Volume containing the Volume Descriptor Sequence</param>
|
||||||
|
/// <param name="key">Logical block address key, see GetKey</param>
|
||||||
|
/// <param name="sector">Logical sector on success</param>
|
||||||
|
/// <returns>True if the block could be mapped, false otherwise</returns>
|
||||||
|
public static bool TryGetSector(this Volume volume, long key, out long sector)
|
||||||
|
{
|
||||||
|
sector = -1;
|
||||||
|
|
||||||
|
var lvd = volume.GetLogicalVolumeDescriptor();
|
||||||
|
if (lvd is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int partitionReference = (int)(key >> 32);
|
||||||
|
uint block = (uint)key;
|
||||||
|
if (partitionReference < 0 || partitionReference >= lvd.PartitionMaps.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var map = lvd.PartitionMaps[partitionReference];
|
||||||
|
if (map is Type1PartitionMap type1)
|
||||||
|
{
|
||||||
|
var pd = volume.GetPartitionDescriptor(type1.PartitionNumber);
|
||||||
|
if (pd is null || block >= pd.PartitionLength)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sector = (long)pd.PartitionStartingLocation + block;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (map is MetadataPartitionMap metadata)
|
||||||
|
{
|
||||||
|
// The Metadata File (or its mirror) is recorded in the Type 1 partition of the same partition number
|
||||||
|
int physical = lvd.GetType1PartitionReference(metadata.PartitionNumber);
|
||||||
|
if (physical < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryGetMetadataFileBlock(volume, lvd, GetKey((ushort)physical, metadata.MetadataFileLocation), block, out long physicalKey)
|
||||||
|
&& !TryGetMetadataFileBlock(volume, lvd, GetKey((ushort)physical, metadata.MetadataMirrorFileLocation), block, out physicalKey))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return volume.TryGetSector(physicalKey, out sector);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Virtual and Sparable partitions are not supported
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Map a logical block of a Metadata Partition through the Metadata File's allocation descriptors
|
||||||
|
/// </summary>
|
||||||
|
private static bool TryGetMetadataFileBlock(Volume volume, LogicalVolumeDescriptor lvd, long fileKey, uint block, out long physicalKey)
|
||||||
|
{
|
||||||
|
physicalKey = -1;
|
||||||
|
if (!volume.FileEntries.TryGetValue(fileKey, out var fileEntry))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var descriptors = volume.GetAllocationDescriptors(fileKey, fileEntry);
|
||||||
|
if (descriptors is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint blockSize = lvd.LogicalBlockSize;
|
||||||
|
long first = 0;
|
||||||
|
foreach (var ad in descriptors)
|
||||||
|
{
|
||||||
|
long blocks = (GetExtentLength(ad.ExtentLength) + blockSize - 1) / blockSize;
|
||||||
|
if (block < first + blocks)
|
||||||
|
{
|
||||||
|
if (GetExtentType(ad.ExtentLength) != ExtentType.RECORDED_AND_ALLOCATED)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
physicalKey = GetKey(ad.ExtentLocation.PartitionReferenceNumber, (uint)(ad.ExtentLocation.LogicalBlockNumber + (block - first)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
first += blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the allocation descriptors of a File Entry, including those continued in Allocation Extent Descriptors,
|
||||||
|
/// as long allocation descriptors (short allocation descriptors get the partition of the File Entry)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="volume">Volume containing the Allocation Extent Descriptors</param>
|
||||||
|
/// <param name="key">Logical block address key of the File Entry</param>
|
||||||
|
/// <param name="fileEntry">File Entry</param>
|
||||||
|
/// <returns>Allocation descriptors (empty for embedded data), null if they are not supported or incomplete</returns>
|
||||||
|
public static List<LongAllocationDescriptor>? GetAllocationDescriptors(this Volume volume, long key, FileEntry fileEntry)
|
||||||
|
=> volume.GetAllocationDescriptors(key, fileEntry, out _);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the allocation descriptors of a File Entry, including those continued in Allocation Extent Descriptors,
|
||||||
|
/// as long allocation descriptors (short allocation descriptors get the partition of the File Entry)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="volume">Volume containing the Allocation Extent Descriptors</param>
|
||||||
|
/// <param name="key">Logical block address key of the File Entry</param>
|
||||||
|
/// <param name="fileEntry">File Entry</param>
|
||||||
|
/// <param name="missingKey">Key of the first Allocation Extent Descriptor that is not in the volume, -1 if none</param>
|
||||||
|
/// <returns>Allocation descriptors (empty for embedded data), null if they are not supported or incomplete</returns>
|
||||||
|
public static List<LongAllocationDescriptor>? GetAllocationDescriptors(this Volume volume, long key, FileEntry fileEntry, out long missingKey)
|
||||||
|
{
|
||||||
|
missingKey = -1;
|
||||||
|
|
||||||
|
var type = fileEntry.ICBTag.GetAllocationDescriptorType();
|
||||||
|
if (type == AllocationDescriptorType.EMBEDDED)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
// Extended allocation descriptors are not allowed by UDF
|
||||||
|
if (type != AllocationDescriptorType.SHORT && type != AllocationDescriptorType.LONG)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
List<LongAllocationDescriptor> result = [];
|
||||||
|
ushort partition = (ushort)(key >> 32);
|
||||||
|
byte[] descriptors = fileEntry.AllocationDescriptors;
|
||||||
|
int length = descriptors.Length;
|
||||||
|
|
||||||
|
for (int extents = 0; extents <= MaximumAllocationExtents; extents++)
|
||||||
|
{
|
||||||
|
long nextKey = -1;
|
||||||
|
int size = type == AllocationDescriptorType.SHORT ? 8 : 16;
|
||||||
|
for (int offset = 0; offset + size <= length; offset += size)
|
||||||
|
{
|
||||||
|
var ad = new LongAllocationDescriptor();
|
||||||
|
ad.ExtentLength = descriptors.ToUInt32LittleEndian(offset);
|
||||||
|
if (type == AllocationDescriptorType.SHORT)
|
||||||
|
{
|
||||||
|
ad.ExtentLocation.LogicalBlockNumber = descriptors.ToUInt32LittleEndian(offset + 4);
|
||||||
|
ad.ExtentLocation.PartitionReferenceNumber = partition;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ad.ExtentLocation.LogicalBlockNumber = descriptors.ToUInt32LittleEndian(offset + 4);
|
||||||
|
ad.ExtentLocation.PartitionReferenceNumber = descriptors.ToUInt16LittleEndian(offset + 8);
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
ad.ImplementationUse[i] = descriptors[offset + 10 + i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A zero length terminates the allocation descriptors
|
||||||
|
if (GetExtentLength(ad.ExtentLength) == 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (GetExtentType(ad.ExtentLength) == ExtentType.NEXT_EXTENT)
|
||||||
|
{
|
||||||
|
nextKey = ad.ExtentLocation.GetKey();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Add(ad);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextKey < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (!volume.AllocationExtentDescriptors.TryGetValue(nextKey, out var aed))
|
||||||
|
{
|
||||||
|
missingKey = nextKey;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
partition = (ushort)(nextKey >> 32);
|
||||||
|
descriptors = aed.AllocationDescriptors;
|
||||||
|
length = descriptors.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Too many continuation extents, assume a loop
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check a descriptor tag: checksum, version, CRC (when it fits into the data) and location
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>ECMA-167 3/7.2; receiving systems allow descriptor version 2 or 3 (3/7.2.2)</remarks>
|
||||||
|
/// <param name="data">Data holding the descriptor</param>
|
||||||
|
/// <param name="offset">Offset of the descriptor</param>
|
||||||
|
/// <param name="available">Number of bytes of the descriptor available from the offset</param>
|
||||||
|
/// <param name="location">Expected tag location (logical sector or logical block number)</param>
|
||||||
|
/// <returns>True if the tag is valid, false otherwise</returns>
|
||||||
|
public static bool IsValidDescriptor(this byte[] data, int offset, int available, uint location)
|
||||||
|
{
|
||||||
|
byte checksum = 0;
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if (i != 4)
|
||||||
|
checksum += data[offset + i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checksum != data[offset + 4])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ushort version = data.ToUInt16LittleEndian(offset + 2);
|
||||||
|
if (version != 2 && version != 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ushort crcLength = data.ToUInt16LittleEndian(offset + 10);
|
||||||
|
if (16 + crcLength <= available)
|
||||||
|
{
|
||||||
|
if (ComputeCrc(data, offset + 16, crcLength) != data.ToUInt16LittleEndian(offset + 8))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.ToUInt32LittleEndian(offset + 12) == location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decode OSTA Compressed Unicode d-characters (first byte = compression ID)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">Encoded characters</param>
|
||||||
|
/// <returns>Decoded string, empty for no characters, null for an unknown compression ID</returns>
|
||||||
|
public static string? DecodeDCharacters(this byte[]? data)
|
||||||
|
=> DecodeDCharacters(data, data?.Length ?? 0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decode an OSTA Compressed Unicode dstring (last byte = number of used bytes)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">Encoded dstring field</param>
|
||||||
|
/// <returns>Decoded string, empty for no characters, null for an unknown compression ID</returns>
|
||||||
|
public static string? DecodeDString(this byte[]? data)
|
||||||
|
{
|
||||||
|
if (data is null || data.Length == 0)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
int length = data[data.Length - 1];
|
||||||
|
if (length > data.Length - 1)
|
||||||
|
length = data.Length - 1;
|
||||||
|
|
||||||
|
return DecodeDCharacters(data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decode the first length bytes of OSTA Compressed Unicode d-characters
|
||||||
|
/// </summary>
|
||||||
|
private static string? DecodeDCharacters(byte[]? data, int length)
|
||||||
|
{
|
||||||
|
if (data is null || length == 0)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
// 254 and 255 are the same encodings, used by UDF for deleted entries
|
||||||
|
byte compressionId = data[0];
|
||||||
|
var builder = new StringBuilder(length);
|
||||||
|
if (compressionId == Constants.CompressionId8 || compressionId == 254)
|
||||||
|
{
|
||||||
|
for (int i = 1; i < length; i++)
|
||||||
|
{
|
||||||
|
builder.Append((char)data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (compressionId == Constants.CompressionId16 || compressionId == 255)
|
||||||
|
{
|
||||||
|
for (int i = 1; i + 1 < length; i += 2)
|
||||||
|
{
|
||||||
|
builder.Append((char)data.ToUInt16BigEndian(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Replace with CRC-16/XMODEM from Hashing once its CRC code is faster
|
||||||
|
/// <summary>
|
||||||
|
/// Compute the CRC-ITU-T of a range of bytes
|
||||||
|
/// </summary>
|
||||||
|
private static ushort ComputeCrc(byte[] data, int offset, int length)
|
||||||
|
{
|
||||||
|
ushort crc = 0;
|
||||||
|
for (int i = offset; i < offset + length; i++)
|
||||||
|
{
|
||||||
|
crc = (ushort)(CrcTable[((crc >> 8) ^ data[i]) & 0xFF] ^ (crc << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create the CRC-ITU-T table
|
||||||
|
/// </summary>
|
||||||
|
private static ushort[] CreateCrcTable()
|
||||||
|
{
|
||||||
|
var table = new ushort[256];
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
ushort crc = (ushort)(i << 8);
|
||||||
|
for (int bit = 0; bit < 8; bit++)
|
||||||
|
{
|
||||||
|
crc = (crc & 0x8000) != 0 ? (ushort)((crc << 1) ^ 0x1021) : (ushort)(crc << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table[i] = crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -68,6 +68,9 @@ namespace SabreTools.Data.Models.ClrMamePro
|
|||||||
/// <remarks>spamsum; Appears after SHA512</remarks>
|
/// <remarks>spamsum; Appears after SHA512</remarks>
|
||||||
public string? SpamSum { get; set; }
|
public string? SpamSum { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>blake3; Appears after SHA512</remarks>
|
||||||
|
public string? BLAKE3 { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region DiscImgeCreator Extensions
|
#region DiscImgeCreator Extensions
|
||||||
|
|||||||
15
SabreTools.Data.Models/Hashfile/BLAKE3.cs
Normal file
15
SabreTools.Data.Models/Hashfile/BLAKE3.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
namespace SabreTools.Data.Models.Hashfile
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// BLAKE3 File
|
||||||
|
/// </summary>
|
||||||
|
public class BLAKE3
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string? Hash { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string? File { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,5 +24,7 @@ namespace SabreTools.Data.Models.Hashfile
|
|||||||
public SHA512[]? SHA512 { get; set; }
|
public SHA512[]? SHA512 { get; set; }
|
||||||
|
|
||||||
public SpamSum[]? SpamSum { get; set; }
|
public SpamSum[]? SpamSum { get; set; }
|
||||||
|
|
||||||
|
public BLAKE3[]? BLAKE3 { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ namespace SabreTools.Data.Models.Logiqx
|
|||||||
[XmlAttribute("runnable")]
|
[XmlAttribute("runnable")]
|
||||||
public Runnable? Runnable { get; set; }
|
public Runnable? Runnable { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>(dir|zip|7z), RomVault extension</remarks>
|
||||||
|
/// TODO: Turn this into an enum like the other flags
|
||||||
|
[XmlAttribute("type")]
|
||||||
|
public string? SetType { get; set; }
|
||||||
|
|
||||||
[XmlElement("comment")]
|
[XmlElement("comment")]
|
||||||
public string[]? Comment { get; set; }
|
public string[]? Comment { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ namespace SabreTools.Data.Models.Logiqx
|
|||||||
[XmlElement("comment")]
|
[XmlElement("comment")]
|
||||||
public string? Comment { get; set; }
|
public string? Comment { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>RomVault extension</remarks>
|
||||||
|
[XmlElement("subset")]
|
||||||
|
public string? Subset { get; set; }
|
||||||
|
|
||||||
/// <remarks>Trurip extension</remarks>
|
/// <remarks>Trurip extension</remarks>
|
||||||
[XmlElement("type")]
|
[XmlElement("type")]
|
||||||
public string? Type { get; set; }
|
public string? Type { get; set; }
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ namespace SabreTools.Data.Models.Logiqx
|
|||||||
[XmlAttribute("spamsum")]
|
[XmlAttribute("spamsum")]
|
||||||
public string? SpamSum { get; set; }
|
public string? SpamSum { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>Hash extension</remarks>
|
||||||
|
[XmlAttribute("blake3")]
|
||||||
|
public string? BLAKE3 { get; set; }
|
||||||
|
|
||||||
/// <remarks>DiscImgeCreator extension</remarks>
|
/// <remarks>DiscImgeCreator extension</remarks>
|
||||||
[XmlAttribute("xxh3_64")]
|
[XmlAttribute("xxh3_64")]
|
||||||
public string? xxHash364 { get; set; }
|
public string? xxHash364 { get; set; }
|
||||||
|
|||||||
@@ -21,5 +21,10 @@ namespace SabreTools.Data.Models.Logiqx
|
|||||||
/// <remarks>(zip|unzip) "zip"</remarks>
|
/// <remarks>(zip|unzip) "zip"</remarks>
|
||||||
[XmlAttribute("forcepacking")]
|
[XmlAttribute("forcepacking")]
|
||||||
public PackingFlag ForcePacking { get; set; }
|
public PackingFlag ForcePacking { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>(noautodir|nogame)</remarks>
|
||||||
|
/// TODO: Turn this into an enum like the other flags
|
||||||
|
[XmlAttribute("dir")]
|
||||||
|
public string? Dir { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
|
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
|
public string? DirHandling { get; set; }
|
||||||
|
|
||||||
public string? Email { get; set; }
|
public string? Email { get; set; }
|
||||||
|
|
||||||
public string? EmulatorVersion { get; set; }
|
public string? EmulatorVersion { get; set; }
|
||||||
@@ -108,6 +110,8 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
/// TODO: This needs an internal model OR mapping to fields
|
/// TODO: This needs an internal model OR mapping to fields
|
||||||
public OfflineList.Search? Search { get; set; }
|
public OfflineList.Search? Search { get; set; }
|
||||||
|
|
||||||
|
public string? Subset { get; set; }
|
||||||
|
|
||||||
public string? System { get; set; }
|
public string? System { get; set; }
|
||||||
|
|
||||||
public string? Timestamp { get; set; }
|
public string? Timestamp { get; set; }
|
||||||
@@ -135,6 +139,7 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
obj.DatVersion = DatVersion;
|
obj.DatVersion = DatVersion;
|
||||||
obj.Debug = Debug;
|
obj.Debug = Debug;
|
||||||
obj.Description = Description;
|
obj.Description = Description;
|
||||||
|
obj.DirHandling = DirHandling;
|
||||||
obj.Email = Email;
|
obj.Email = Email;
|
||||||
obj.EmulatorVersion = EmulatorVersion;
|
obj.EmulatorVersion = EmulatorVersion;
|
||||||
obj.FileName = FileName;
|
obj.FileName = FileName;
|
||||||
@@ -166,6 +171,7 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
obj.ScreenshotsHeight = ScreenshotsHeight;
|
obj.ScreenshotsHeight = ScreenshotsHeight;
|
||||||
obj.ScreenshotsWidth = ScreenshotsWidth;
|
obj.ScreenshotsWidth = ScreenshotsWidth;
|
||||||
obj.Search = Search;
|
obj.Search = Search;
|
||||||
|
obj.Subset = Subset;
|
||||||
obj.System = System;
|
obj.System = System;
|
||||||
obj.Timestamp = Timestamp;
|
obj.Timestamp = Timestamp;
|
||||||
obj.Type = Type;
|
obj.Type = Type;
|
||||||
@@ -224,6 +230,11 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
else if (Description is not null && !Description.Equals(other.Description, StringComparison.OrdinalIgnoreCase))
|
else if (Description is not null && !Description.Equals(other.Description, StringComparison.OrdinalIgnoreCase))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if ((DirHandling is null) ^ (other.DirHandling is null))
|
||||||
|
return false;
|
||||||
|
else if (DirHandling is not null && !DirHandling.Equals(other.DirHandling, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return false;
|
||||||
|
|
||||||
if ((Email is null) ^ (other.Email is null))
|
if ((Email is null) ^ (other.Email is null))
|
||||||
return false;
|
return false;
|
||||||
else if (Email is not null && !Email.Equals(other.Email, StringComparison.OrdinalIgnoreCase))
|
else if (Email is not null && !Email.Equals(other.Email, StringComparison.OrdinalIgnoreCase))
|
||||||
@@ -336,6 +347,11 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
else if (ScreenshotsWidth is not null && !ScreenshotsWidth.Equals(other.ScreenshotsWidth, StringComparison.OrdinalIgnoreCase))
|
else if (ScreenshotsWidth is not null && !ScreenshotsWidth.Equals(other.ScreenshotsWidth, StringComparison.OrdinalIgnoreCase))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if ((Subset is null) ^ (other.Subset is null))
|
||||||
|
return false;
|
||||||
|
else if (Subset is not null && !Subset.Equals(other.Subset, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return false;
|
||||||
|
|
||||||
if ((System is null) ^ (other.System is null))
|
if ((System is null) ^ (other.System is null))
|
||||||
return false;
|
return false;
|
||||||
else if (System is not null && !System.Equals(other.System, StringComparison.OrdinalIgnoreCase))
|
else if (System is not null && !System.Equals(other.System, StringComparison.OrdinalIgnoreCase))
|
||||||
|
|||||||
@@ -159,6 +159,9 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
|
|
||||||
public string? Serial { get; set; }
|
public string? Serial { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>(dir|zip|7z), RomVault extension</remarks>
|
||||||
|
public string? SetType { get; set; }
|
||||||
|
|
||||||
public SharedFeat[]? SharedFeat { get; set; }
|
public SharedFeat[]? SharedFeat { get; set; }
|
||||||
|
|
||||||
public Slot[]? Slot { get; set; }
|
public Slot[]? Slot { get; set; }
|
||||||
@@ -298,6 +301,7 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
obj.SaveType = SaveType;
|
obj.SaveType = SaveType;
|
||||||
obj.Score = Score;
|
obj.Score = Score;
|
||||||
obj.Serial = Serial;
|
obj.Serial = Serial;
|
||||||
|
obj.SetType = SetType;
|
||||||
if (SharedFeat is not null)
|
if (SharedFeat is not null)
|
||||||
obj.SharedFeat = Array.ConvertAll(SharedFeat, i => (SharedFeat)i.Clone());
|
obj.SharedFeat = Array.ConvertAll(SharedFeat, i => (SharedFeat)i.Clone());
|
||||||
if (Slot is not null)
|
if (Slot is not null)
|
||||||
@@ -569,6 +573,11 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
else if (Serial is not null && !Serial.Equals(other.Serial, StringComparison.OrdinalIgnoreCase))
|
else if (Serial is not null && !Serial.Equals(other.Serial, StringComparison.OrdinalIgnoreCase))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if ((SetType is null) ^ (other.SetType is null))
|
||||||
|
return false;
|
||||||
|
else if (SetType is not null && !SetType.Equals(other.SetType, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return false;
|
||||||
|
|
||||||
if ((Source is null) ^ (other.Source is null))
|
if ((Source is null) ^ (other.Source is null))
|
||||||
return false;
|
return false;
|
||||||
else if (Source is not null && !Source.Equals(other.Source, StringComparison.OrdinalIgnoreCase))
|
else if (Source is not null && !Source.Equals(other.Source, StringComparison.OrdinalIgnoreCase))
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
/// <remarks>ArchiveDotOrg.File</remarks>
|
/// <remarks>ArchiveDotOrg.File</remarks>
|
||||||
public string? BitTorrentMagnetHash { get; set; }
|
public string? BitTorrentMagnetHash { get; set; }
|
||||||
|
|
||||||
|
public string? BLAKE3 { get; set; }
|
||||||
|
|
||||||
/// <remarks>ArchiveDotOrg.File</remarks>
|
/// <remarks>ArchiveDotOrg.File</remarks>
|
||||||
public string? ClothCoverDetectionModuleVersion { get; set; }
|
public string? ClothCoverDetectionModuleVersion { get; set; }
|
||||||
|
|
||||||
@@ -190,6 +192,9 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
/// <remarks>(baddump|nodump|good|verified) "good"</remarks>
|
/// <remarks>(baddump|nodump|good|verified) "good"</remarks>
|
||||||
public ItemStatus? Status { get; set; }
|
public ItemStatus? Status { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>Possibly enum; OpenMSX.RomBase</remarks>
|
||||||
|
public string? StatusMisc { get; set; }
|
||||||
|
|
||||||
/// <remarks>ArchiveDotOrg.File</remarks>
|
/// <remarks>ArchiveDotOrg.File</remarks>
|
||||||
public string? Summation { get; set; }
|
public string? Summation { get; set; }
|
||||||
|
|
||||||
@@ -293,6 +298,7 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
obj.Bios = Bios;
|
obj.Bios = Bios;
|
||||||
obj.Bitrate = Bitrate;
|
obj.Bitrate = Bitrate;
|
||||||
obj.BitTorrentMagnetHash = BitTorrentMagnetHash;
|
obj.BitTorrentMagnetHash = BitTorrentMagnetHash;
|
||||||
|
obj.BLAKE3 = BLAKE3;
|
||||||
obj.ClothCoverDetectionModuleVersion = ClothCoverDetectionModuleVersion;
|
obj.ClothCoverDetectionModuleVersion = ClothCoverDetectionModuleVersion;
|
||||||
obj.CollectionCatalogNumber = CollectionCatalogNumber;
|
obj.CollectionCatalogNumber = CollectionCatalogNumber;
|
||||||
obj.Comment = Comment;
|
obj.Comment = Comment;
|
||||||
@@ -350,6 +356,7 @@ namespace SabreTools.Data.Models.Metadata
|
|||||||
obj.SpamSum = SpamSum;
|
obj.SpamSum = SpamSum;
|
||||||
obj.Start = Start;
|
obj.Start = Start;
|
||||||
obj.Status = Status;
|
obj.Status = Status;
|
||||||
|
obj.StatusMisc = StatusMisc;
|
||||||
obj.Summation = Summation;
|
obj.Summation = Summation;
|
||||||
obj.TesseractOCR = TesseractOCR;
|
obj.TesseractOCR = TesseractOCR;
|
||||||
obj.TesseractOCRConverted = TesseractOCRConverted;
|
obj.TesseractOCRConverted = TesseractOCRConverted;
|
||||||
|
|||||||
@@ -8,17 +8,37 @@ namespace SabreTools.Data.Models.OpenMSX
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class RomBase
|
public abstract class RomBase
|
||||||
{
|
{
|
||||||
[XmlElement("start")]
|
/// <remarks>
|
||||||
public string? Start { get; set; }
|
/// "hash" in older versions, "sha1" in newer versions
|
||||||
|
/// </remarks>
|
||||||
|
[XmlAttribute("sha1")]
|
||||||
|
[XmlElement("hash")]
|
||||||
|
public string? SHA1 { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// Element in older versions and DTD, attribute in newer versions
|
||||||
|
/// </remarks>
|
||||||
|
[XmlAttribute("type")]
|
||||||
[XmlElement("type")]
|
[XmlElement("type")]
|
||||||
public string? Type { get; set; }
|
public string? Type { get; set; }
|
||||||
|
|
||||||
/// <remarks>SHA-1 hash</remarks>
|
/// <remarks>
|
||||||
[XmlElement("hash")]
|
/// Only present in newer versions
|
||||||
public string? Hash { get; set; }
|
/// </remarks>
|
||||||
|
[XmlAttribute("status")]
|
||||||
|
public string? Status { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// Element in older versions and DTD, attribute in newer versions
|
||||||
|
/// </remarks>
|
||||||
|
[XmlAttribute("remark")]
|
||||||
[XmlElement("remark")]
|
[XmlElement("remark")]
|
||||||
public string? Remark { get; set; }
|
public string? Remark { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// Only present in older versions
|
||||||
|
/// </remarks>
|
||||||
|
[XmlElement("start")]
|
||||||
|
public string? Start { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,30 +6,63 @@ namespace SabreTools.Data.Models.OpenMSX
|
|||||||
[XmlRoot("software")]
|
[XmlRoot("software")]
|
||||||
public class Software
|
public class Software
|
||||||
{
|
{
|
||||||
|
/// <remarks>
|
||||||
|
/// Element in older versions and DTD, attribute in newer versions
|
||||||
|
/// </remarks>
|
||||||
[Required]
|
[Required]
|
||||||
|
[XmlAttribute("title")]
|
||||||
[XmlElement("title")]
|
[XmlElement("title")]
|
||||||
public string? Title { get; set; }
|
public string? Title { get; set; }
|
||||||
|
|
||||||
[XmlElement("genmsxid")]
|
/// <remarks>
|
||||||
public string? GenMSXID { get; set; }
|
/// Element in older versions and DTD, attribute in newer versions
|
||||||
|
/// </remarks>
|
||||||
[Required]
|
[Required]
|
||||||
|
[XmlAttribute("system")]
|
||||||
[XmlElement("system")]
|
[XmlElement("system")]
|
||||||
public string? System { get; set; }
|
public string? System { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// Element in older versions and DTD, attribute in newer versions
|
||||||
|
/// </remarks>
|
||||||
[Required]
|
[Required]
|
||||||
|
[XmlAttribute("company")]
|
||||||
[XmlElement("company")]
|
[XmlElement("company")]
|
||||||
public string? Company { get; set; }
|
public string? Company { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// Element in older versions and DTD, attribute in newer versions
|
||||||
|
/// </remarks>
|
||||||
[Required]
|
[Required]
|
||||||
|
[XmlAttribute("year")]
|
||||||
[XmlElement("year")]
|
[XmlElement("year")]
|
||||||
public string? Year { get; set; }
|
public string? Year { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// Element in older versions and DTD, attribute in newer versions
|
||||||
|
/// </remarks>
|
||||||
[Required]
|
[Required]
|
||||||
|
[XmlAttribute("country")]
|
||||||
[XmlElement("country")]
|
[XmlElement("country")]
|
||||||
public string? Country { get; set; }
|
public string? Country { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// Element in older versions and DTD, attribute in newer versions
|
||||||
|
/// </remarks>
|
||||||
|
[XmlAttribute("genmsxid")]
|
||||||
|
[XmlElement("genmsxid")]
|
||||||
|
public string? GenMSXID { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// Present in older versions
|
||||||
|
/// </remarks>
|
||||||
[XmlElement("dump")]
|
[XmlElement("dump")]
|
||||||
public Dump[]? Dump { get; set; }
|
public Dump[]? Dump { get; set; }
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// Present in newer versions
|
||||||
|
/// </remarks>
|
||||||
|
[XmlElement("rom")]
|
||||||
|
public RomBase[]? Rom { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,13 @@ namespace SabreTools.Data.Models.PKZIP
|
|||||||
/// File data, appears after the encryption header
|
/// File data, appears after the encryption header
|
||||||
/// if it exists or after the local file header otherwise
|
/// if it exists or after the local file header otherwise
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[] FileData { get; set; } = [];
|
/// Not read into the model, see <see cref="FileDataOffset"/>
|
||||||
|
// public byte[] FileData { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Offset of the file data in the stream
|
||||||
|
/// </summary>
|
||||||
|
public long FileDataOffset { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Data descriptors, appears after the file data
|
/// Data descriptors, appears after the file data
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Assembly Properties -->
|
<!-- Assembly Properties -->
|
||||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;net11.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Version>3.0.1</Version>
|
<Version>3.3.0</Version>
|
||||||
|
|
||||||
<!-- Package Properties -->
|
<!-- Package Properties -->
|
||||||
<Authors>Matt Nadareski</Authors>
|
<Authors>Matt Nadareski</Authors>
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||||
<PackageReference Include="SabreTools.IO" Version="[2.1.0]" />
|
<PackageReference Include="SabreTools.IO" Version="2.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
24
SabreTools.Data.Models/UDF/AllocationExtentDescriptor.cs
Normal file
24
SabreTools.Data.Models/UDF/AllocationExtentDescriptor.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Allocation Extent Descriptor (4/14.5), continues the allocation descriptors of a File Entry
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class AllocationExtentDescriptor : Descriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Logical block of the previous allocation extent
|
||||||
|
/// </summary>
|
||||||
|
public uint PreviousAllocationExtentLocation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the allocation descriptors in bytes
|
||||||
|
/// </summary>
|
||||||
|
public uint LengthOfAllocationDescriptors { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allocation descriptors, of the type given in the owning File Entry's ICB tag flags
|
||||||
|
/// </summary>
|
||||||
|
public byte[] AllocationDescriptors { get; set; } = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
24
SabreTools.Data.Models/UDF/AnchorVolumeDescriptorPointer.cs
Normal file
24
SabreTools.Data.Models/UDF/AnchorVolumeDescriptorPointer.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Anchor Volume Descriptor Pointer (3/10.2), recorded at sector 256 (and at the end of the volume)
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class AnchorVolumeDescriptorPointer : Descriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extent of the Main Volume Descriptor Sequence
|
||||||
|
/// </summary>
|
||||||
|
public ExtentDescriptor MainVolumeDescriptorSequenceExtent { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extent of the Reserve Volume Descriptor Sequence
|
||||||
|
/// </summary>
|
||||||
|
public ExtentDescriptor ReserveVolumeDescriptorSequenceExtent { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved, 480 bytes of 0x00
|
||||||
|
/// </summary>
|
||||||
|
public byte[] Reserved { get; set; } = new byte[480];
|
||||||
|
}
|
||||||
|
}
|
||||||
20
SabreTools.Data.Models/UDF/CharacterSetSpecification.cs
Normal file
20
SabreTools.Data.Models/UDF/CharacterSetSpecification.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Character Set Specification (charspec, 1/7.2.1)
|
||||||
|
/// UDF requires CS0 with the information "OSTA Compressed Unicode"
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class CharacterSetSpecification
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Character set type (0 = CS0)
|
||||||
|
/// </summary>
|
||||||
|
public byte CharacterSetType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Character set information, padded with 0x00
|
||||||
|
/// </summary>
|
||||||
|
public byte[] CharacterSetInformation { get; set; } = new byte[63];
|
||||||
|
}
|
||||||
|
}
|
||||||
126
SabreTools.Data.Models/UDF/Constants.cs
Normal file
126
SabreTools.Data.Models/UDF/Constants.cs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF / ECMA-167 constant values and arrays
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
/// <see href="http://www.osta.org/specs/pdf/udf260.pdf"/>
|
||||||
|
public static class Constants
|
||||||
|
{
|
||||||
|
#region Volume Recognition Constants
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Size of a logical sector on optical media
|
||||||
|
/// </summary>
|
||||||
|
public const int SectorSize = 2048;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sector of the first Volume Structure Descriptor (after the 32KiB System Area)
|
||||||
|
/// </summary>
|
||||||
|
public const int VolumeRecognitionSequenceSector = 16;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sector of the first Anchor Volume Descriptor Pointer
|
||||||
|
/// </summary>
|
||||||
|
public const int AnchorVolumeDescriptorPointerSector = 256;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Beginning Extended Area Descriptor identifier, "BEA01"
|
||||||
|
/// </summary>
|
||||||
|
public static readonly byte[] BeginningExtendedAreaDescriptor = [0x42, 0x45, 0x41, 0x30, 0x31];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NSR Descriptor identifier for ECMA-167 2nd edition (UDF 1.02 to 1.50), "NSR02"
|
||||||
|
/// </summary>
|
||||||
|
public static readonly byte[] NSR02 = [0x4E, 0x53, 0x52, 0x30, 0x32];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NSR Descriptor identifier for ECMA-167 3rd edition (UDF 2.00 and later), "NSR03"
|
||||||
|
/// </summary>
|
||||||
|
public static readonly byte[] NSR03 = [0x4E, 0x53, 0x52, 0x30, 0x33];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Terminating Extended Area Descriptor identifier, "TEA01"
|
||||||
|
/// </summary>
|
||||||
|
public static readonly byte[] TerminatingExtendedAreaDescriptor = [0x54, 0x45, 0x41, 0x30, 0x31];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ISO 9660 volume descriptor identifier, "CD001" (bridge discs)
|
||||||
|
/// </summary>
|
||||||
|
public static readonly byte[] CD001 = [0x43, 0x44, 0x30, 0x30, 0x31];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Boot Descriptor identifier, "BOOT2"
|
||||||
|
/// </summary>
|
||||||
|
public static readonly byte[] BOOT2 = [0x42, 0x4F, 0x4F, 0x54, 0x32];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ECMA-168 volume descriptor identifier, "CDW02"
|
||||||
|
/// </summary>
|
||||||
|
public static readonly byte[] CDW02 = [0x43, 0x44, 0x57, 0x30, 0x32];
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Partition Map Constants
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Type 1 Partition Map type
|
||||||
|
/// </summary>
|
||||||
|
public const byte Type1PartitionMap = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Type 2 Partition Map type
|
||||||
|
/// </summary>
|
||||||
|
public const byte Type2PartitionMap = 2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition type identifier of a UDF Metadata Partition (UDF 2.50 and later)
|
||||||
|
/// </summary>
|
||||||
|
public const string MetadataPartitionIdentifier = "*UDF Metadata Partition";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition type identifier of a UDF Sparable Partition
|
||||||
|
/// </summary>
|
||||||
|
public const string SparablePartitionIdentifier = "*UDF Sparable Partition";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition type identifier of a UDF Virtual Partition
|
||||||
|
/// </summary>
|
||||||
|
public const string VirtualPartitionIdentifier = "*UDF Virtual Partition";
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Character Set Constants
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OSTA Compressed Unicode, 8 bits per character
|
||||||
|
/// </summary>
|
||||||
|
public const byte CompressionId8 = 8;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OSTA Compressed Unicode, 16 bits per character (big-endian)
|
||||||
|
/// </summary>
|
||||||
|
public const byte CompressionId16 = 16;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Allocation Descriptor Constants
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mask of the extent length in an allocation descriptor (the top two bits hold the extent type)
|
||||||
|
/// </summary>
|
||||||
|
public const uint ExtentLengthMask = 0x3FFFFFFF;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shift of the extent type in an allocation descriptor's extent length
|
||||||
|
/// </summary>
|
||||||
|
public const int ExtentTypeShift = 30;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mask of the allocation descriptor type in an ICB tag's flags
|
||||||
|
/// </summary>
|
||||||
|
public const ushort AllocationDescriptorTypeMask = 0x0007;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
14
SabreTools.Data.Models/UDF/Descriptor.cs
Normal file
14
SabreTools.Data.Models/UDF/Descriptor.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Abstract UDF tagged descriptor, all start with a Descriptor Tag
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public abstract class Descriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Descriptor tag
|
||||||
|
/// </summary>
|
||||||
|
public DescriptorTag DescriptorTag { get; set; } = new();
|
||||||
|
}
|
||||||
|
}
|
||||||
50
SabreTools.Data.Models/UDF/DescriptorTag.cs
Normal file
50
SabreTools.Data.Models/UDF/DescriptorTag.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Descriptor Tag (3/7.2), the first 16 bytes of every tagged descriptor
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class DescriptorTag
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Type of the descriptor
|
||||||
|
/// </summary>
|
||||||
|
public TagIdentifier TagIdentifier { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Version of the descriptor, 2 (ECMA-167 2nd edition) or 3 (3rd edition)
|
||||||
|
/// </summary>
|
||||||
|
public ushort DescriptorVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sum modulo 256 of bytes 0-3 and 5-15 of the tag
|
||||||
|
/// </summary>
|
||||||
|
public byte TagChecksum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved, 0x00
|
||||||
|
/// </summary>
|
||||||
|
public byte Reserved { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identification of a set of descriptors
|
||||||
|
/// </summary>
|
||||||
|
public ushort TagSerialNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CRC-CCITT of the DescriptorCRCLength bytes following the tag
|
||||||
|
/// </summary>
|
||||||
|
public ushort DescriptorCRC { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of bytes after the tag covered by the DescriptorCRC
|
||||||
|
/// </summary>
|
||||||
|
public ushort DescriptorCRCLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of the logical sector (volume structures) or logical block (file structures)
|
||||||
|
/// in which the descriptor is recorded
|
||||||
|
/// </summary>
|
||||||
|
public uint TagLocation { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
24
SabreTools.Data.Models/UDF/EntityIdentifier.cs
Normal file
24
SabreTools.Data.Models/UDF/EntityIdentifier.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Entity Identifier (regid, 1/7.4)
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class EntityIdentifier
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Flags (bit 0: dirty, bit 1: protected)
|
||||||
|
/// </summary>
|
||||||
|
public byte Flags { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifier, padded with 0x00
|
||||||
|
/// </summary>
|
||||||
|
public byte[] Identifier { get; set; } = new byte[23];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifier suffix (UDF domain identifiers: revision as a little-endian ushort, then domain flags)
|
||||||
|
/// </summary>
|
||||||
|
public byte[] IdentifierSuffix { get; set; } = new byte[8];
|
||||||
|
}
|
||||||
|
}
|
||||||
306
SabreTools.Data.Models/UDF/Enums.cs
Normal file
306
SabreTools.Data.Models/UDF/Enums.cs
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enum for DescriptorTag.TagIdentifier
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public enum TagIdentifier : ushort
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Primary Volume Descriptor (3/10.1)
|
||||||
|
/// </summary>
|
||||||
|
PRIMARY_VOLUME_DESCRIPTOR = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Anchor Volume Descriptor Pointer (3/10.2)
|
||||||
|
/// </summary>
|
||||||
|
ANCHOR_VOLUME_DESCRIPTOR_POINTER = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Volume Descriptor Pointer (3/10.3)
|
||||||
|
/// </summary>
|
||||||
|
VOLUME_DESCRIPTOR_POINTER = 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation Use Volume Descriptor (3/10.4)
|
||||||
|
/// </summary>
|
||||||
|
IMPLEMENTATION_USE_VOLUME_DESCRIPTOR = 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition Descriptor (3/10.5)
|
||||||
|
/// </summary>
|
||||||
|
PARTITION_DESCRIPTOR = 5,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical Volume Descriptor (3/10.6)
|
||||||
|
/// </summary>
|
||||||
|
LOGICAL_VOLUME_DESCRIPTOR = 6,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unallocated Space Descriptor (3/10.8)
|
||||||
|
/// </summary>
|
||||||
|
UNALLOCATED_SPACE_DESCRIPTOR = 7,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Terminating Descriptor (3/10.9)
|
||||||
|
/// </summary>
|
||||||
|
TERMINATING_DESCRIPTOR = 8,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical Volume Integrity Descriptor (3/10.10)
|
||||||
|
/// </summary>
|
||||||
|
LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR = 9,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File Set Descriptor (4/14.1)
|
||||||
|
/// </summary>
|
||||||
|
FILE_SET_DESCRIPTOR = 256,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File Identifier Descriptor (4/14.4)
|
||||||
|
/// </summary>
|
||||||
|
FILE_IDENTIFIER_DESCRIPTOR = 257,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allocation Extent Descriptor (4/14.5)
|
||||||
|
/// </summary>
|
||||||
|
ALLOCATION_EXTENT_DESCRIPTOR = 258,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indirect Entry (4/14.7)
|
||||||
|
/// </summary>
|
||||||
|
INDIRECT_ENTRY = 259,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Terminal Entry (4/14.8)
|
||||||
|
/// </summary>
|
||||||
|
TERMINAL_ENTRY = 260,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File Entry (4/14.9)
|
||||||
|
/// </summary>
|
||||||
|
FILE_ENTRY = 261,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extended Attribute Header Descriptor (4/14.10.1)
|
||||||
|
/// </summary>
|
||||||
|
EXTENDED_ATTRIBUTE_HEADER_DESCRIPTOR = 262,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unallocated Space Entry (4/14.11)
|
||||||
|
/// </summary>
|
||||||
|
UNALLOCATED_SPACE_ENTRY = 263,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Space Bitmap Descriptor (4/14.12)
|
||||||
|
/// </summary>
|
||||||
|
SPACE_BITMAP_DESCRIPTOR = 264,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition Integrity Entry (4/14.13)
|
||||||
|
/// </summary>
|
||||||
|
PARTITION_INTEGRITY_ENTRY = 265,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extended File Entry (4/14.17)
|
||||||
|
/// </summary>
|
||||||
|
EXTENDED_FILE_ENTRY = 266,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enum for FileIdentifierDescriptor.FileCharacteristics (4/14.4.3)
|
||||||
|
/// Bits 5-7: Reserved: 0
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
[Flags]
|
||||||
|
public enum FileCharacteristics : byte
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// No characteristics set
|
||||||
|
/// </summary>
|
||||||
|
NONE = 0x00,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The existence of the file shall not be made known to the user (hidden)
|
||||||
|
/// </summary>
|
||||||
|
EXISTENCE = 0x01,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The file is a directory
|
||||||
|
/// </summary>
|
||||||
|
DIRECTORY = 0x02,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The descriptor shall be ignored (deleted)
|
||||||
|
/// </summary>
|
||||||
|
DELETED = 0x04,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ICB identifies the parent directory
|
||||||
|
/// </summary>
|
||||||
|
PARENT = 0x08,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The file contains implementation use data (UDF: stream directory metadata)
|
||||||
|
/// </summary>
|
||||||
|
METADATA = 0x10,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enum for ICBTag.FileType (4/14.6.6, UDF 2.3.5.4)
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public enum FileType : byte
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Not specified
|
||||||
|
/// </summary>
|
||||||
|
UNSPECIFIED = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unallocated Space Entry
|
||||||
|
/// </summary>
|
||||||
|
UNALLOCATED_SPACE_ENTRY = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition Integrity Entry
|
||||||
|
/// </summary>
|
||||||
|
PARTITION_INTEGRITY_ENTRY = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indirect Entry
|
||||||
|
/// </summary>
|
||||||
|
INDIRECT_ENTRY = 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Directory
|
||||||
|
/// </summary>
|
||||||
|
DIRECTORY = 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sequence of bytes (a regular file)
|
||||||
|
/// </summary>
|
||||||
|
FILE = 5,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Block special device
|
||||||
|
/// </summary>
|
||||||
|
BLOCK_DEVICE = 6,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Character special device
|
||||||
|
/// </summary>
|
||||||
|
CHARACTER_DEVICE = 7,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extended attributes
|
||||||
|
/// </summary>
|
||||||
|
EXTENDED_ATTRIBUTES = 8,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// FIFO file
|
||||||
|
/// </summary>
|
||||||
|
FIFO = 9,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Socket
|
||||||
|
/// </summary>
|
||||||
|
SOCKET = 10,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Terminal Entry
|
||||||
|
/// </summary>
|
||||||
|
TERMINAL_ENTRY = 11,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Symbolic link
|
||||||
|
/// </summary>
|
||||||
|
SYMBOLIC_LINK = 12,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stream directory
|
||||||
|
/// </summary>
|
||||||
|
STREAM_DIRECTORY = 13,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Virtual Allocation Table
|
||||||
|
/// </summary>
|
||||||
|
VIRTUAL_ALLOCATION_TABLE = 248,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Real-Time file
|
||||||
|
/// </summary>
|
||||||
|
REAL_TIME_FILE = 249,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Metadata File
|
||||||
|
/// </summary>
|
||||||
|
METADATA_FILE = 250,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Metadata Mirror File
|
||||||
|
/// </summary>
|
||||||
|
METADATA_MIRROR_FILE = 251,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Metadata Bitmap File
|
||||||
|
/// </summary>
|
||||||
|
METADATA_BITMAP_FILE = 252,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enum for the allocation descriptor type in ICBTag.Flags (4/14.6.8)
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public enum AllocationDescriptorType : byte
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Short Allocation Descriptors (4/14.14.1)
|
||||||
|
/// </summary>
|
||||||
|
SHORT = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Long Allocation Descriptors (4/14.14.2)
|
||||||
|
/// </summary>
|
||||||
|
LONG = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extended Allocation Descriptors (4/14.14.3)
|
||||||
|
/// </summary>
|
||||||
|
EXTENDED = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The file data is embedded in the allocation descriptors field
|
||||||
|
/// </summary>
|
||||||
|
EMBEDDED = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enum for the extent type in the top two bits of an allocation descriptor's extent length (4/14.14.1.1)
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public enum ExtentType : byte
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extent recorded and allocated
|
||||||
|
/// </summary>
|
||||||
|
RECORDED_AND_ALLOCATED = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extent not recorded but allocated
|
||||||
|
/// </summary>
|
||||||
|
NOT_RECORDED_BUT_ALLOCATED = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extent not recorded and not allocated
|
||||||
|
/// </summary>
|
||||||
|
NOT_RECORDED_NOT_ALLOCATED = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The extent is the next extent of allocation descriptors
|
||||||
|
/// </summary>
|
||||||
|
NEXT_EXTENT = 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
30
SabreTools.Data.Models/UDF/ExtendedFileEntry.cs
Normal file
30
SabreTools.Data.Models/UDF/ExtendedFileEntry.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Extended File Entry (4/14.17, UDF 2.00 and later), a File Entry with object size,
|
||||||
|
/// creation time and a stream directory
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class ExtendedFileEntry : FileEntry
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Size of the file and its streams in bytes
|
||||||
|
/// </summary>
|
||||||
|
public ulong ObjectSize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creation date and time
|
||||||
|
/// </summary>
|
||||||
|
public Timestamp CreationDateAndTime { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved, 0x00000000
|
||||||
|
/// </summary>
|
||||||
|
public uint Reserved { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ICB of the stream directory, length 0 if none
|
||||||
|
/// </summary>
|
||||||
|
public LongAllocationDescriptor StreamDirectoryICB { get; set; } = new();
|
||||||
|
}
|
||||||
|
}
|
||||||
19
SabreTools.Data.Models/UDF/ExtentDescriptor.cs
Normal file
19
SabreTools.Data.Models/UDF/ExtentDescriptor.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Extent Descriptor (extent_ad, 3/7.1), an extent of logical sectors
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class ExtentDescriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the extent in bytes
|
||||||
|
/// </summary>
|
||||||
|
public uint ExtentLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical sector number of the start of the extent
|
||||||
|
/// </summary>
|
||||||
|
public uint ExtentLocation { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
115
SabreTools.Data.Models/UDF/FileEntry.cs
Normal file
115
SabreTools.Data.Models/UDF/FileEntry.cs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF File Entry (4/14.9), the ICB describing a file or directory and where its data is recorded
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public class FileEntry : Descriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ICB tag
|
||||||
|
/// </summary>
|
||||||
|
public ICBTag ICBTag { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// User ID
|
||||||
|
/// </summary>
|
||||||
|
public uint Uid { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Group ID
|
||||||
|
/// </summary>
|
||||||
|
public uint Gid { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Permissions
|
||||||
|
/// </summary>
|
||||||
|
public uint Permissions { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of File Identifier Descriptors identifying this ICB
|
||||||
|
/// </summary>
|
||||||
|
public ushort FileLinkCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Record format
|
||||||
|
/// </summary>
|
||||||
|
public byte RecordFormat { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Record display attributes
|
||||||
|
/// </summary>
|
||||||
|
public byte RecordDisplayAttributes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Record length
|
||||||
|
/// </summary>
|
||||||
|
public uint RecordLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Size of the file in bytes
|
||||||
|
/// </summary>
|
||||||
|
public ulong InformationLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of recorded logical blocks
|
||||||
|
/// </summary>
|
||||||
|
public ulong LogicalBlocksRecorded { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Access date and time
|
||||||
|
/// </summary>
|
||||||
|
public Timestamp AccessDateAndTime { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modification date and time
|
||||||
|
/// </summary>
|
||||||
|
public Timestamp ModificationDateAndTime { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attribute date and time
|
||||||
|
/// </summary>
|
||||||
|
public Timestamp AttributeDateAndTime { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checkpoint
|
||||||
|
/// </summary>
|
||||||
|
public uint Checkpoint { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ICB of the extended attributes, length 0 if none
|
||||||
|
/// </summary>
|
||||||
|
public LongAllocationDescriptor ExtendedAttributeICB { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation identifier
|
||||||
|
/// </summary>
|
||||||
|
public EntityIdentifier ImplementationIdentifier { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unique ID
|
||||||
|
/// </summary>
|
||||||
|
public ulong UniqueID { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the extended attributes in bytes
|
||||||
|
/// </summary>
|
||||||
|
public uint LengthOfExtendedAttributes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the allocation descriptors in bytes
|
||||||
|
/// </summary>
|
||||||
|
public uint LengthOfAllocationDescriptors { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extended attributes
|
||||||
|
/// </summary>
|
||||||
|
public byte[] ExtendedAttributes { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allocation descriptors of the type given in the ICB tag flags,
|
||||||
|
/// or the file data itself if the type is AllocationDescriptorType.EMBEDDED
|
||||||
|
/// </summary>
|
||||||
|
public byte[] AllocationDescriptors { get; set; } = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
49
SabreTools.Data.Models/UDF/FileIdentifierDescriptor.cs
Normal file
49
SabreTools.Data.Models/UDF/FileIdentifierDescriptor.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF File Identifier Descriptor (4/14.4), a directory entry naming a file or directory and pointing to its ICB
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class FileIdentifierDescriptor : Descriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// File version number
|
||||||
|
/// </summary>
|
||||||
|
public ushort FileVersionNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File characteristics
|
||||||
|
/// </summary>
|
||||||
|
public FileCharacteristics FileCharacteristics { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the file identifier in bytes
|
||||||
|
/// </summary>
|
||||||
|
public byte LengthOfFileIdentifier { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ICB of the file or directory
|
||||||
|
/// </summary>
|
||||||
|
public LongAllocationDescriptor ICB { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the implementation use in bytes
|
||||||
|
/// </summary>
|
||||||
|
public ushort LengthOfImplementationUse { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation use
|
||||||
|
/// </summary>
|
||||||
|
public byte[] ImplementationUse { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File identifier, d-characters (first byte = compression ID), empty for the parent directory
|
||||||
|
/// </summary>
|
||||||
|
public byte[] FileIdentifier { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Padding to a multiple of 4 bytes
|
||||||
|
/// </summary>
|
||||||
|
public byte[] Padding { get; set; } = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
99
SabreTools.Data.Models/UDF/FileSetDescriptor.cs
Normal file
99
SabreTools.Data.Models/UDF/FileSetDescriptor.cs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF File Set Descriptor (4/14.1), the location of the root directory
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class FileSetDescriptor : Descriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Recording date and time
|
||||||
|
/// </summary>
|
||||||
|
public Timestamp RecordingDateAndTime { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interchange level
|
||||||
|
/// </summary>
|
||||||
|
public ushort InterchangeLevel { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum interchange level
|
||||||
|
/// </summary>
|
||||||
|
public ushort MaximumInterchangeLevel { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Character set list
|
||||||
|
/// </summary>
|
||||||
|
public uint CharacterSetList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum character set list
|
||||||
|
/// </summary>
|
||||||
|
public uint MaximumCharacterSetList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File set number
|
||||||
|
/// </summary>
|
||||||
|
public uint FileSetNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File Set Descriptor number
|
||||||
|
/// </summary>
|
||||||
|
public uint FileSetDescriptorNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical volume identifier character set
|
||||||
|
/// </summary>
|
||||||
|
public CharacterSetSpecification LogicalVolumeIdentifierCharacterSet { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical volume identifier, dstring (last byte = length)
|
||||||
|
/// </summary>
|
||||||
|
public byte[] LogicalVolumeIdentifier { get; set; } = new byte[128];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File set character set
|
||||||
|
/// </summary>
|
||||||
|
public CharacterSetSpecification FileSetCharacterSet { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File set identifier, dstring (last byte = length)
|
||||||
|
/// </summary>
|
||||||
|
public byte[] FileSetIdentifier { get; set; } = new byte[32];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copyright file identifier, dstring (last byte = length)
|
||||||
|
/// </summary>
|
||||||
|
public byte[] CopyrightFileIdentifier { get; set; } = new byte[32];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Abstract file identifier, dstring (last byte = length)
|
||||||
|
/// </summary>
|
||||||
|
public byte[] AbstractFileIdentifier { get; set; } = new byte[32];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ICB of the root directory
|
||||||
|
/// </summary>
|
||||||
|
public LongAllocationDescriptor RootDirectoryICB { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Domain identifier
|
||||||
|
/// </summary>
|
||||||
|
public EntityIdentifier DomainIdentifier { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Next extent of File Set Descriptors, length 0 if none
|
||||||
|
/// </summary>
|
||||||
|
public LongAllocationDescriptor NextExtent { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ICB of the system stream directory (ECMA-167 3rd edition), length 0 if none
|
||||||
|
/// </summary>
|
||||||
|
public LongAllocationDescriptor SystemStreamDirectoryICB { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved, 32 bytes of 0x00
|
||||||
|
/// </summary>
|
||||||
|
public byte[] Reserved { get; set; } = new byte[32];
|
||||||
|
}
|
||||||
|
}
|
||||||
15
SabreTools.Data.Models/UDF/GenericDescriptor.cs
Normal file
15
SabreTools.Data.Models/UDF/GenericDescriptor.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF tagged descriptor of a type that is not parsed further
|
||||||
|
/// (e.g. Implementation Use Volume Descriptor, Unallocated Space Descriptor, Terminating Descriptor)
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class GenericDescriptor : Descriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contents of the descriptor after the tag, up to the end of the logical sector
|
||||||
|
/// </summary>
|
||||||
|
public byte[] Data { get; set; } = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
49
SabreTools.Data.Models/UDF/ICBTag.cs
Normal file
49
SabreTools.Data.Models/UDF/ICBTag.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Information Control Block Tag (icbtag, 4/14.6)
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class ICBTag
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Prior recorded number of direct entries
|
||||||
|
/// </summary>
|
||||||
|
public uint PriorRecordedNumberOfDirectEntries { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Strategy type (UDF: 4, or 4096 for write-once media)
|
||||||
|
/// </summary>
|
||||||
|
public ushort StrategyType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Strategy parameter, 2 bytes
|
||||||
|
/// </summary>
|
||||||
|
public byte[] StrategyParameter { get; set; } = new byte[2];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of entries
|
||||||
|
/// </summary>
|
||||||
|
public ushort MaximumNumberOfEntries { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved, 0x00
|
||||||
|
/// </summary>
|
||||||
|
public byte Reserved { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File type
|
||||||
|
/// </summary>
|
||||||
|
public FileType FileType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parent ICB location
|
||||||
|
/// </summary>
|
||||||
|
public LogicalBlockAddress ParentICBLocation { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flags, the lower 3 bits hold the AllocationDescriptorType
|
||||||
|
/// </summary>
|
||||||
|
public ushort Flags { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
19
SabreTools.Data.Models/UDF/LogicalBlockAddress.cs
Normal file
19
SabreTools.Data.Models/UDF/LogicalBlockAddress.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Recorded Address (lb_addr, 4/7.1), a logical block within a partition
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class LogicalBlockAddress
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Logical block number, relative to the start of the partition
|
||||||
|
/// </summary>
|
||||||
|
public uint LogicalBlockNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Index of the partition map in the Logical Volume Descriptor
|
||||||
|
/// </summary>
|
||||||
|
public ushort PartitionReferenceNumber { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
69
SabreTools.Data.Models/UDF/LogicalVolumeDescriptor.cs
Normal file
69
SabreTools.Data.Models/UDF/LogicalVolumeDescriptor.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Logical Volume Descriptor (3/10.6), block size, partition maps and the location of the File Set Descriptor
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class LogicalVolumeDescriptor : Descriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Volume Descriptor Sequence Number, the highest number prevails
|
||||||
|
/// </summary>
|
||||||
|
public uint VolumeDescriptorSequenceNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Descriptor character set
|
||||||
|
/// </summary>
|
||||||
|
public CharacterSetSpecification DescriptorCharacterSet { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical volume identifier, dstring (last byte = length)
|
||||||
|
/// </summary>
|
||||||
|
public byte[] LogicalVolumeIdentifier { get; set; } = new byte[128];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Size of a logical block in bytes
|
||||||
|
/// </summary>
|
||||||
|
public uint LogicalBlockSize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Domain identifier ("*OSTA UDF Compliant", suffix holds the UDF revision)
|
||||||
|
/// </summary>
|
||||||
|
public EntityIdentifier DomainIdentifier { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical volume contents use (UDF: extent of the File Set Descriptor)
|
||||||
|
/// </summary>
|
||||||
|
public LongAllocationDescriptor LogicalVolumeContentsUse { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the partition maps in bytes
|
||||||
|
/// </summary>
|
||||||
|
public uint MapTableLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of partition maps
|
||||||
|
/// </summary>
|
||||||
|
public uint NumberOfPartitionMaps { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation identifier
|
||||||
|
/// </summary>
|
||||||
|
public EntityIdentifier ImplementationIdentifier { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation use, 128 bytes
|
||||||
|
/// </summary>
|
||||||
|
public byte[] ImplementationUse { get; set; } = new byte[128];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extent of the Logical Volume Integrity Sequence
|
||||||
|
/// </summary>
|
||||||
|
public ExtentDescriptor IntegritySequenceExtent { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition maps, a partition reference number is the index into this array
|
||||||
|
/// </summary>
|
||||||
|
public PartitionMap[] PartitionMaps { get; set; } = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
25
SabreTools.Data.Models/UDF/LongAllocationDescriptor.cs
Normal file
25
SabreTools.Data.Models/UDF/LongAllocationDescriptor.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Long Allocation Descriptor (long_ad, 4/14.14.2), an extent within any partition of the logical volume
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class LongAllocationDescriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the extent in bytes (lower 30 bits) and the ExtentType (upper 2 bits)
|
||||||
|
/// A length of 0 terminates a sequence of allocation descriptors
|
||||||
|
/// </summary>
|
||||||
|
public uint ExtentLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical block address of the start of the extent
|
||||||
|
/// </summary>
|
||||||
|
public LogicalBlockAddress ExtentLocation { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation use (UDF: flags and unique ID bits)
|
||||||
|
/// </summary>
|
||||||
|
public byte[] ImplementationUse { get; set; } = new byte[6];
|
||||||
|
}
|
||||||
|
}
|
||||||
45
SabreTools.Data.Models/UDF/MetadataPartitionMap.cs
Normal file
45
SabreTools.Data.Models/UDF/MetadataPartitionMap.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Metadata Partition Map (UDF 2.2.10, UDF 2.50 and later), a partition whose logical blocks
|
||||||
|
/// are the contents of the Metadata File recorded in the underlying partition
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="http://www.osta.org/specs/pdf/udf260.pdf"/>
|
||||||
|
public sealed class MetadataPartitionMap : Type2PartitionMap
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Logical block of the Metadata File's File Entry in the underlying partition
|
||||||
|
/// </summary>
|
||||||
|
public uint MetadataFileLocation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical block of the Metadata Mirror File's File Entry in the underlying partition
|
||||||
|
/// </summary>
|
||||||
|
public uint MetadataMirrorFileLocation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical block of the Metadata Bitmap File's File Entry, 0xFFFFFFFF if not recorded
|
||||||
|
/// </summary>
|
||||||
|
public uint MetadataBitmapFileLocation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allocation unit size in logical blocks
|
||||||
|
/// </summary>
|
||||||
|
public uint AllocationUnitSize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Alignment unit size in logical blocks
|
||||||
|
/// </summary>
|
||||||
|
public ushort AlignmentUnitSize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flags (bit 0: duplicate metadata flag)
|
||||||
|
/// </summary>
|
||||||
|
public byte Flags { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved, 5 bytes of 0x00
|
||||||
|
/// </summary>
|
||||||
|
public byte[] Reserved2 { get; set; } = new byte[5];
|
||||||
|
}
|
||||||
|
}
|
||||||
64
SabreTools.Data.Models/UDF/PartitionDescriptor.cs
Normal file
64
SabreTools.Data.Models/UDF/PartitionDescriptor.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Partition Descriptor (3/10.5), the physical location of a partition
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class PartitionDescriptor : Descriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Volume Descriptor Sequence Number, the highest number prevails
|
||||||
|
/// </summary>
|
||||||
|
public uint VolumeDescriptorSequenceNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition flags (bit 0: space is allocated)
|
||||||
|
/// </summary>
|
||||||
|
public ushort PartitionFlags { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition number, referenced by the partition maps
|
||||||
|
/// </summary>
|
||||||
|
public ushort PartitionNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition contents ("+NSR02" or "+NSR03" for UDF)
|
||||||
|
/// </summary>
|
||||||
|
public EntityIdentifier PartitionContents { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition contents use (Partition Header Descriptor for NSR), 128 bytes
|
||||||
|
/// </summary>
|
||||||
|
public byte[] PartitionContentsUse { get; set; } = new byte[128];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Access type (1 = read-only, 2 = write-once, 3 = rewritable, 4 = overwritable)
|
||||||
|
/// </summary>
|
||||||
|
public uint AccessType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical sector number of the first sector of the partition
|
||||||
|
/// </summary>
|
||||||
|
public uint PartitionStartingLocation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the partition in logical sectors
|
||||||
|
/// </summary>
|
||||||
|
public uint PartitionLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation identifier
|
||||||
|
/// </summary>
|
||||||
|
public EntityIdentifier ImplementationIdentifier { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation use, 128 bytes
|
||||||
|
/// </summary>
|
||||||
|
public byte[] ImplementationUse { get; set; } = new byte[128];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved, 156 bytes of 0x00
|
||||||
|
/// </summary>
|
||||||
|
public byte[] Reserved { get; set; } = new byte[156];
|
||||||
|
}
|
||||||
|
}
|
||||||
19
SabreTools.Data.Models/UDF/PartitionMap.cs
Normal file
19
SabreTools.Data.Models/UDF/PartitionMap.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Abstract UDF Partition Map (3/10.7)
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public abstract class PartitionMap
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Partition map type (1 or 2)
|
||||||
|
/// </summary>
|
||||||
|
public byte PartitionMapType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the partition map in bytes
|
||||||
|
/// </summary>
|
||||||
|
public byte PartitionMapLength { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
114
SabreTools.Data.Models/UDF/PrimaryVolumeDescriptor.cs
Normal file
114
SabreTools.Data.Models/UDF/PrimaryVolumeDescriptor.cs
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Primary Volume Descriptor (3/10.1)
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class PrimaryVolumeDescriptor : Descriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Volume Descriptor Sequence Number, the highest number prevails
|
||||||
|
/// </summary>
|
||||||
|
public uint VolumeDescriptorSequenceNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Primary Volume Descriptor Number
|
||||||
|
/// </summary>
|
||||||
|
public uint PrimaryVolumeDescriptorNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Volume identifier, dstring (last byte = length)
|
||||||
|
/// </summary>
|
||||||
|
public byte[] VolumeIdentifier { get; set; } = new byte[32];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Volume sequence number
|
||||||
|
/// </summary>
|
||||||
|
public ushort VolumeSequenceNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum volume sequence number
|
||||||
|
/// </summary>
|
||||||
|
public ushort MaximumVolumeSequenceNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interchange level
|
||||||
|
/// </summary>
|
||||||
|
public ushort InterchangeLevel { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum interchange level
|
||||||
|
/// </summary>
|
||||||
|
public ushort MaximumInterchangeLevel { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Character set list
|
||||||
|
/// </summary>
|
||||||
|
public uint CharacterSetList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum character set list
|
||||||
|
/// </summary>
|
||||||
|
public uint MaximumCharacterSetList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Volume set identifier, dstring (last byte = length)
|
||||||
|
/// </summary>
|
||||||
|
public byte[] VolumeSetIdentifier { get; set; } = new byte[128];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Descriptor character set
|
||||||
|
/// </summary>
|
||||||
|
public CharacterSetSpecification DescriptorCharacterSet { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Explanatory character set
|
||||||
|
/// </summary>
|
||||||
|
public CharacterSetSpecification ExplanatoryCharacterSet { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extent of the volume abstract
|
||||||
|
/// </summary>
|
||||||
|
public ExtentDescriptor VolumeAbstract { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extent of the volume copyright notice
|
||||||
|
/// </summary>
|
||||||
|
public ExtentDescriptor VolumeCopyrightNotice { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Application identifier
|
||||||
|
/// </summary>
|
||||||
|
public EntityIdentifier ApplicationIdentifier { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recording date and time
|
||||||
|
/// </summary>
|
||||||
|
public Timestamp RecordingDateAndTime { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation identifier
|
||||||
|
/// </summary>
|
||||||
|
public EntityIdentifier ImplementationIdentifier { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation use, 64 bytes
|
||||||
|
/// </summary>
|
||||||
|
public byte[] ImplementationUse { get; set; } = new byte[64];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Predecessor Volume Descriptor Sequence location
|
||||||
|
/// </summary>
|
||||||
|
public uint PredecessorVolumeDescriptorSequenceLocation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flags (bit 0: volume set identification is common to all volumes of the set)
|
||||||
|
/// </summary>
|
||||||
|
public ushort Flags { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved, 22 bytes of 0x00
|
||||||
|
/// </summary>
|
||||||
|
public byte[] Reserved { get; set; } = new byte[22];
|
||||||
|
}
|
||||||
|
}
|
||||||
20
SabreTools.Data.Models/UDF/ShortAllocationDescriptor.cs
Normal file
20
SabreTools.Data.Models/UDF/ShortAllocationDescriptor.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Short Allocation Descriptor (short_ad, 4/14.14.1), an extent within the partition of the descriptor
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class ShortAllocationDescriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the extent in bytes (lower 30 bits) and the ExtentType (upper 2 bits)
|
||||||
|
/// A length of 0 terminates a sequence of allocation descriptors
|
||||||
|
/// </summary>
|
||||||
|
public uint ExtentLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical block number of the start of the extent
|
||||||
|
/// </summary>
|
||||||
|
public uint ExtentPosition { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
60
SabreTools.Data.Models/UDF/Timestamp.cs
Normal file
60
SabreTools.Data.Models/UDF/Timestamp.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Timestamp (1/7.3)
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class Timestamp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Type (upper 4 bits, 1 = local time) and time zone offset from UTC in minutes
|
||||||
|
/// (lower 12 bits, signed, -2047 = not specified)
|
||||||
|
/// </summary>
|
||||||
|
public ushort TypeAndTimezone { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Year, 1 to 9999
|
||||||
|
/// </summary>
|
||||||
|
public short Year { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Month, 1 to 12
|
||||||
|
/// </summary>
|
||||||
|
public byte Month { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Day, 1 to 31
|
||||||
|
/// </summary>
|
||||||
|
public byte Day { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hour, 0 to 23
|
||||||
|
/// </summary>
|
||||||
|
public byte Hour { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Minute, 0 to 59
|
||||||
|
/// </summary>
|
||||||
|
public byte Minute { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Second, 0 to 59
|
||||||
|
/// </summary>
|
||||||
|
public byte Second { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Centiseconds, 0 to 99
|
||||||
|
/// </summary>
|
||||||
|
public byte Centiseconds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hundreds of microseconds, 0 to 99
|
||||||
|
/// </summary>
|
||||||
|
public byte HundredsOfMicroseconds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Microseconds, 0 to 99
|
||||||
|
/// </summary>
|
||||||
|
public byte Microseconds { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
19
SabreTools.Data.Models/UDF/Type1PartitionMap.cs
Normal file
19
SabreTools.Data.Models/UDF/Type1PartitionMap.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Type 1 Partition Map (3/10.7.2), logical blocks map 1:1 onto a Partition Descriptor's sectors
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class Type1PartitionMap : PartitionMap
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Volume sequence number of the volume containing the partition
|
||||||
|
/// </summary>
|
||||||
|
public ushort VolumeSequenceNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition number of the Partition Descriptor
|
||||||
|
/// </summary>
|
||||||
|
public ushort PartitionNumber { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
37
SabreTools.Data.Models/UDF/Type2PartitionMap.cs
Normal file
37
SabreTools.Data.Models/UDF/Type2PartitionMap.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Type 2 Partition Map (3/10.7.3, UDF 2.2.8-2.2.10), a partition identified by its partition type identifier
|
||||||
|
/// (e.g. "*UDF Virtual Partition", "*UDF Sparable Partition", "*UDF Metadata Partition")
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
/// <see href="http://www.osta.org/specs/pdf/udf260.pdf"/>
|
||||||
|
public class Type2PartitionMap : PartitionMap
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved, 2 bytes of 0x00
|
||||||
|
/// </summary>
|
||||||
|
public byte[] Reserved { get; set; } = new byte[2];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition type identifier
|
||||||
|
/// </summary>
|
||||||
|
public EntityIdentifier PartitionTypeIdentifier { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Volume sequence number of the volume containing the partition
|
||||||
|
/// </summary>
|
||||||
|
public ushort VolumeSequenceNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition number of the underlying Partition Descriptor
|
||||||
|
/// </summary>
|
||||||
|
public ushort PartitionNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition type specific data after the partition number, 24 bytes
|
||||||
|
/// Empty for partition types that are parsed further (MetadataPartitionMap)
|
||||||
|
/// </summary>
|
||||||
|
public byte[] PartitionTypeData { get; set; } = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
52
SabreTools.Data.Models/UDF/Volume.cs
Normal file
52
SabreTools.Data.Models/UDF/Volume.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A volume (or disc image) with a UDF / ECMA-167 file system
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Logical sectors and logical blocks are 2048 bytes on optical media
|
||||||
|
/// File system structures are addressed by logical block address (partition reference number + logical block);
|
||||||
|
/// dictionaries are keyed by ((long)PartitionReferenceNumber << 32) | LogicalBlockNumber
|
||||||
|
/// </remarks>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
/// <see href="http://www.osta.org/specs/pdf/udf260.pdf"/>
|
||||||
|
public sealed class Volume
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Volume Recognition Sequence starting at sector 16
|
||||||
|
/// </summary>
|
||||||
|
public VolumeStructureDescriptor[] VolumeRecognitionSequence { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Anchor Volume Descriptor Pointer
|
||||||
|
/// </summary>
|
||||||
|
public AnchorVolumeDescriptorPointer? AnchorVolumeDescriptorPointer { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Volume Descriptor Sequence (Primary, Partition, Logical Volume, ... up to the Terminating Descriptor)
|
||||||
|
/// </summary>
|
||||||
|
public Descriptor[] VolumeDescriptorSequence { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File Set Descriptor
|
||||||
|
/// </summary>
|
||||||
|
public FileSetDescriptor? FileSetDescriptor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File Entries (and Extended File Entries) by logical block address
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<long, FileEntry> FileEntries { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allocation Extent Descriptors by logical block address
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<long, AllocationExtentDescriptor> AllocationExtentDescriptors { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File Identifier Descriptors of each directory, by logical block address of the directory's File Entry
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<long, FileIdentifierDescriptor[]> Directories { get; set; } = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
24
SabreTools.Data.Models/UDF/VolumeDescriptorPointer.cs
Normal file
24
SabreTools.Data.Models/UDF/VolumeDescriptorPointer.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Volume Descriptor Pointer (3/10.3), continues the Volume Descriptor Sequence in another extent
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class VolumeDescriptorPointer : Descriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Volume Descriptor Sequence Number
|
||||||
|
/// </summary>
|
||||||
|
public uint VolumeDescriptorSequenceNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extent of the next part of the Volume Descriptor Sequence
|
||||||
|
/// </summary>
|
||||||
|
public ExtentDescriptor NextVolumeDescriptorSequenceExtent { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved, 484 bytes of 0x00
|
||||||
|
/// </summary>
|
||||||
|
public byte[] Reserved { get; set; } = new byte[484];
|
||||||
|
}
|
||||||
|
}
|
||||||
30
SabreTools.Data.Models/UDF/VolumeStructureDescriptor.cs
Normal file
30
SabreTools.Data.Models/UDF/VolumeStructureDescriptor.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
namespace SabreTools.Data.Models.UDF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UDF Volume Structure Descriptor (2/9.1), one logical sector of the Volume Recognition Sequence
|
||||||
|
/// starting at sector 16, e.g. "BEA01", "NSR02"/"NSR03", "TEA01", or "CD001" on bridge discs
|
||||||
|
/// </summary>
|
||||||
|
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||||
|
public sealed class VolumeStructureDescriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Structure type
|
||||||
|
/// </summary>
|
||||||
|
public byte StructureType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Standard identifier, 5 bytes
|
||||||
|
/// </summary>
|
||||||
|
public byte[] StandardIdentifier { get; set; } = new byte[5];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Structure version
|
||||||
|
/// </summary>
|
||||||
|
public byte StructureVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Structure data, the rest of the logical sector
|
||||||
|
/// </summary>
|
||||||
|
public byte[] StructureData { get; set; } = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -212,6 +212,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
DatVersion = "datversion",
|
DatVersion = "datversion",
|
||||||
Debug = true,
|
Debug = true,
|
||||||
Description = "description",
|
Description = "description",
|
||||||
|
DirHandling = "noautodir",
|
||||||
Email = "email",
|
Email = "email",
|
||||||
EmulatorVersion = "emulatorversion",
|
EmulatorVersion = "emulatorversion",
|
||||||
FileName = "filename",
|
FileName = "filename",
|
||||||
@@ -243,6 +244,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
ScreenshotsHeight = "screenshotsheight",
|
ScreenshotsHeight = "screenshotsheight",
|
||||||
ScreenshotsWidth = "screenshotsWidth",
|
ScreenshotsWidth = "screenshotsWidth",
|
||||||
Search = search,
|
Search = search,
|
||||||
|
Subset = "subset",
|
||||||
System = "system",
|
System = "system",
|
||||||
Timestamp = "timestamp",
|
Timestamp = "timestamp",
|
||||||
Type = "type",
|
Type = "type",
|
||||||
@@ -327,6 +329,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
SaveType = "savetype",
|
SaveType = "savetype",
|
||||||
Score = "score",
|
Score = "score",
|
||||||
Serial = "serial",
|
Serial = "serial",
|
||||||
|
SetType = "dir",
|
||||||
SharedFeat = [CreateMetadataSharedFeat()],
|
SharedFeat = [CreateMetadataSharedFeat()],
|
||||||
Slot = [CreateMetadataSlot()],
|
Slot = [CreateMetadataSlot()],
|
||||||
SoftwareList = [CreateMetadataSoftwareList()],
|
SoftwareList = [CreateMetadataSoftwareList()],
|
||||||
@@ -778,6 +781,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Bios = "bios",
|
Bios = "bios",
|
||||||
Bitrate = "bitrate",
|
Bitrate = "bitrate",
|
||||||
BitTorrentMagnetHash = "btih",
|
BitTorrentMagnetHash = "btih",
|
||||||
|
BLAKE3 = HashType.BLAKE3.ZeroString,
|
||||||
ClothCoverDetectionModuleVersion = "cloth_cover_detection_module_version",
|
ClothCoverDetectionModuleVersion = "cloth_cover_detection_module_version",
|
||||||
CollectionCatalogNumber = "collection-catalog-number",
|
CollectionCatalogNumber = "collection-catalog-number",
|
||||||
Comment = "comment",
|
Comment = "comment",
|
||||||
@@ -835,6 +839,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
SpamSum = HashType.SpamSum.ZeroString,
|
SpamSum = HashType.SpamSum.ZeroString,
|
||||||
Start = "start",
|
Start = "start",
|
||||||
Status = Data.Models.Metadata.ItemStatus.Good,
|
Status = Data.Models.Metadata.ItemStatus.Good,
|
||||||
|
StatusMisc = "status",
|
||||||
Summation = "summation",
|
Summation = "summation",
|
||||||
TesseractOCR = "ocr",
|
TesseractOCR = "ocr",
|
||||||
TesseractOCRConverted = "ocr_converted",
|
TesseractOCRConverted = "ocr_converted",
|
||||||
@@ -1004,6 +1009,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal("datversion", datHeader.DatVersion);
|
Assert.Equal("datversion", datHeader.DatVersion);
|
||||||
Assert.True(datHeader.Debug);
|
Assert.True(datHeader.Debug);
|
||||||
Assert.Equal("description", datHeader.Description);
|
Assert.Equal("description", datHeader.Description);
|
||||||
|
Assert.Equal("noautodir", datHeader.DirHandling);
|
||||||
Assert.Equal("email", datHeader.Email);
|
Assert.Equal("email", datHeader.Email);
|
||||||
Assert.Equal("emulatorversion", datHeader.EmulatorVersion);
|
Assert.Equal("emulatorversion", datHeader.EmulatorVersion);
|
||||||
Assert.Equal(Data.Models.Metadata.MergingFlag.Merged, datHeader.ForceMerging);
|
Assert.Equal(Data.Models.Metadata.MergingFlag.Merged, datHeader.ForceMerging);
|
||||||
@@ -1033,6 +1039,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal("screenshotsheight", datHeader.ScreenshotsHeight);
|
Assert.Equal("screenshotsheight", datHeader.ScreenshotsHeight);
|
||||||
Assert.Equal("screenshotsWidth", datHeader.ScreenshotsWidth);
|
Assert.Equal("screenshotsWidth", datHeader.ScreenshotsWidth);
|
||||||
Assert.NotNull(datHeader.Search);
|
Assert.NotNull(datHeader.Search);
|
||||||
|
Assert.Equal("subset", datHeader.Subset);
|
||||||
Assert.Equal("system", datHeader.System);
|
Assert.Equal("system", datHeader.System);
|
||||||
Assert.Equal("timestamp", datHeader.Timestamp);
|
Assert.Equal("timestamp", datHeader.Timestamp);
|
||||||
Assert.Equal("type", datHeader.Type);
|
Assert.Equal("type", datHeader.Type);
|
||||||
@@ -1090,6 +1097,8 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal("sampleof", machine.SampleOf);
|
Assert.Equal("sampleof", machine.SampleOf);
|
||||||
Assert.Equal("savetype", machine.SaveType);
|
Assert.Equal("savetype", machine.SaveType);
|
||||||
Assert.Equal("score", machine.Score);
|
Assert.Equal("score", machine.Score);
|
||||||
|
Assert.Equal("serial", machine.Serial);
|
||||||
|
Assert.Equal("dir", machine.SetType);
|
||||||
Assert.Equal("source", machine.Source);
|
Assert.Equal("source", machine.Source);
|
||||||
Assert.Equal("sourcefile", machine.SourceFile);
|
Assert.Equal("sourcefile", machine.SourceFile);
|
||||||
Assert.Equal("sourcerom", machine.SourceRom);
|
Assert.Equal("sourcerom", machine.SourceRom);
|
||||||
@@ -1450,6 +1459,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal("bios", rom.Bios);
|
Assert.Equal("bios", rom.Bios);
|
||||||
Assert.Equal("bitrate", rom.Bitrate);
|
Assert.Equal("bitrate", rom.Bitrate);
|
||||||
Assert.Equal("btih", rom.BitTorrentMagnetHash);
|
Assert.Equal("btih", rom.BitTorrentMagnetHash);
|
||||||
|
Assert.Equal(HashType.BLAKE3.ZeroString, rom.BLAKE3);
|
||||||
Assert.Equal("cloth_cover_detection_module_version", rom.ClothCoverDetectionModuleVersion);
|
Assert.Equal("cloth_cover_detection_module_version", rom.ClothCoverDetectionModuleVersion);
|
||||||
Assert.Equal("collection-catalog-number", rom.CollectionCatalogNumber);
|
Assert.Equal("collection-catalog-number", rom.CollectionCatalogNumber);
|
||||||
Assert.Equal("comment", rom.Comment);
|
Assert.Equal("comment", rom.Comment);
|
||||||
@@ -1507,6 +1517,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal(HashType.SpamSum.ZeroString, rom.SpamSum);
|
Assert.Equal(HashType.SpamSum.ZeroString, rom.SpamSum);
|
||||||
Assert.Equal("start", rom.Start);
|
Assert.Equal("start", rom.Start);
|
||||||
Assert.Equal(Data.Models.Metadata.ItemStatus.Good, rom.Status);
|
Assert.Equal(Data.Models.Metadata.ItemStatus.Good, rom.Status);
|
||||||
|
Assert.Equal("status", rom.StatusMisc);
|
||||||
Assert.Equal("summation", rom.Summation);
|
Assert.Equal("summation", rom.Summation);
|
||||||
Assert.Equal("ocr", rom.TesseractOCR);
|
Assert.Equal("ocr", rom.TesseractOCR);
|
||||||
Assert.Equal("ocr_converted", rom.TesseractOCRConverted);
|
Assert.Equal("ocr_converted", rom.TesseractOCRConverted);
|
||||||
|
|||||||
@@ -344,6 +344,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal("datversion", header.DatVersion);
|
Assert.Equal("datversion", header.DatVersion);
|
||||||
Assert.True(header.Debug);
|
Assert.True(header.Debug);
|
||||||
Assert.Equal("description", header.Description);
|
Assert.Equal("description", header.Description);
|
||||||
|
Assert.Equal("noautodir", header.DirHandling);
|
||||||
Assert.Equal("email", header.Email);
|
Assert.Equal("email", header.Email);
|
||||||
Assert.Equal("emulatorversion", header.EmulatorVersion);
|
Assert.Equal("emulatorversion", header.EmulatorVersion);
|
||||||
Assert.Equal("filename", header.FileName);
|
Assert.Equal("filename", header.FileName);
|
||||||
@@ -374,6 +375,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal("screenshotsheight", header.ScreenshotsHeight);
|
Assert.Equal("screenshotsheight", header.ScreenshotsHeight);
|
||||||
Assert.Equal("screenshotsWidth", header.ScreenshotsWidth);
|
Assert.Equal("screenshotsWidth", header.ScreenshotsWidth);
|
||||||
Assert.NotNull(header.Search);
|
Assert.NotNull(header.Search);
|
||||||
|
Assert.Equal("subset", header.Subset);
|
||||||
Assert.Equal("system", header.System);
|
Assert.Equal("system", header.System);
|
||||||
Assert.Equal("timestamp", header.Timestamp);
|
Assert.Equal("timestamp", header.Timestamp);
|
||||||
Assert.Equal("type", header.Type);
|
Assert.Equal("type", header.Type);
|
||||||
@@ -436,6 +438,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal("savetype", machine.SaveType);
|
Assert.Equal("savetype", machine.SaveType);
|
||||||
Assert.Equal("score", machine.Score);
|
Assert.Equal("score", machine.Score);
|
||||||
Assert.Equal("serial", machine.Serial);
|
Assert.Equal("serial", machine.Serial);
|
||||||
|
Assert.Equal("dir", machine.SetType);
|
||||||
Assert.Equal("source", machine.Source);
|
Assert.Equal("source", machine.Source);
|
||||||
Assert.Equal("sourcefile", machine.SourceFile);
|
Assert.Equal("sourcefile", machine.SourceFile);
|
||||||
Assert.Equal("sourcerom", machine.SourceRom);
|
Assert.Equal("sourcerom", machine.SourceRom);
|
||||||
@@ -1005,6 +1008,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal("bios", rom.Bios);
|
Assert.Equal("bios", rom.Bios);
|
||||||
Assert.Equal("bitrate", rom.Bitrate);
|
Assert.Equal("bitrate", rom.Bitrate);
|
||||||
Assert.Equal("btih", rom.BitTorrentMagnetHash);
|
Assert.Equal("btih", rom.BitTorrentMagnetHash);
|
||||||
|
Assert.Equal(HashType.BLAKE3.ZeroString, rom.BLAKE3);
|
||||||
Assert.Equal("cloth_cover_detection_module_version", rom.ClothCoverDetectionModuleVersion);
|
Assert.Equal("cloth_cover_detection_module_version", rom.ClothCoverDetectionModuleVersion);
|
||||||
Assert.Equal("collection-catalog-number", rom.CollectionCatalogNumber);
|
Assert.Equal("collection-catalog-number", rom.CollectionCatalogNumber);
|
||||||
Assert.Equal("comment", rom.Comment);
|
Assert.Equal("comment", rom.Comment);
|
||||||
@@ -1062,6 +1066,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal(HashType.SpamSum.ZeroString, rom.SpamSum);
|
Assert.Equal(HashType.SpamSum.ZeroString, rom.SpamSum);
|
||||||
Assert.Equal("start", rom.Start);
|
Assert.Equal("start", rom.Start);
|
||||||
Assert.Equal(Data.Models.Metadata.ItemStatus.Good, rom.Status);
|
Assert.Equal(Data.Models.Metadata.ItemStatus.Good, rom.Status);
|
||||||
|
Assert.Equal("status", rom.StatusMisc);
|
||||||
Assert.Equal("summation", rom.Summation);
|
Assert.Equal("summation", rom.Summation);
|
||||||
Assert.Equal("ocr", rom.TesseractOCR);
|
Assert.Equal("ocr", rom.TesseractOCR);
|
||||||
Assert.Equal("ocr_converted", rom.TesseractOCRConverted);
|
Assert.Equal("ocr_converted", rom.TesseractOCRConverted);
|
||||||
|
|||||||
@@ -1396,7 +1396,8 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
SHA256 = "sha256",
|
SHA256 = "sha256",
|
||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum"
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
string actual = DatFile.FormatPrefixPostfix(item, machine, fix);
|
string actual = DatFile.FormatPrefixPostfix(item, machine, fix);
|
||||||
@@ -1514,7 +1515,8 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
SHA256 = "sha256",
|
SHA256 = "sha256",
|
||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum"
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
string actual = DatFile.FormatPrefixPostfix(item, machine, fix);
|
string actual = DatFile.FormatPrefixPostfix(item, machine, fix);
|
||||||
@@ -1550,6 +1552,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Null(rom.SHA384);
|
Assert.Null(rom.SHA384);
|
||||||
Assert.Null(rom.SHA512);
|
Assert.Null(rom.SHA512);
|
||||||
Assert.Null(rom.SpamSum);
|
Assert.Null(rom.SpamSum);
|
||||||
|
Assert.Null(rom.BLAKE3);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -1575,6 +1578,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Null(rom.SHA384);
|
Assert.Null(rom.SHA384);
|
||||||
Assert.Null(rom.SHA512);
|
Assert.Null(rom.SHA512);
|
||||||
Assert.Null(rom.SpamSum);
|
Assert.Null(rom.SpamSum);
|
||||||
|
Assert.Null(rom.BLAKE3);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -1594,7 +1598,8 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
SHA256 = "null",
|
SHA256 = "null",
|
||||||
SHA384 = "null",
|
SHA384 = "null",
|
||||||
SHA512 = "null",
|
SHA512 = "null",
|
||||||
SpamSum = "null"
|
SpamSum = "null",
|
||||||
|
BLAKE3 = "null",
|
||||||
};
|
};
|
||||||
|
|
||||||
DatItem actual = DatFile.ProcessNullifiedItem(item);
|
DatItem actual = DatFile.ProcessNullifiedItem(item);
|
||||||
@@ -1614,6 +1619,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal(HashType.SHA384.ZeroString, rom.SHA384);
|
Assert.Equal(HashType.SHA384.ZeroString, rom.SHA384);
|
||||||
Assert.Equal(HashType.SHA512.ZeroString, rom.SHA512);
|
Assert.Equal(HashType.SHA512.ZeroString, rom.SHA512);
|
||||||
Assert.Equal(HashType.SpamSum.ZeroString, rom.SpamSum);
|
Assert.Equal(HashType.SpamSum.ZeroString, rom.SpamSum);
|
||||||
|
Assert.Equal(HashType.BLAKE3.ZeroString, rom.BLAKE3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -1955,6 +1961,19 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal($"_{hash}", actual);
|
Assert.Equal($"_{hash}", actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetDuplicateSuffix_Rom_BLAKE3()
|
||||||
|
{
|
||||||
|
string hash = "hash";
|
||||||
|
DatItem datItem = new Rom
|
||||||
|
{
|
||||||
|
BLAKE3 = hash
|
||||||
|
};
|
||||||
|
|
||||||
|
string actual = DatFile.GetDuplicateSuffix(datItem);
|
||||||
|
Assert.Equal($"_{hash}", actual);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetDuplicateSuffix_Other_Generic()
|
public void GetDuplicateSuffix_Other_Generic()
|
||||||
{
|
{
|
||||||
@@ -2434,7 +2453,8 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
SHA256 = "crc",
|
SHA256 = "crc",
|
||||||
SHA384 = "crc",
|
SHA384 = "crc",
|
||||||
SHA512 = "crc",
|
SHA512 = "crc",
|
||||||
SpamSum = "crc"
|
SpamSum = "crc",
|
||||||
|
BLAKE3 = "crc",
|
||||||
};
|
};
|
||||||
DatFile datFile = new Logiqx(null, useGame: false);
|
DatFile datFile = new Logiqx(null, useGame: false);
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal(0, stats.GetHashCount(HashType.SHA384));
|
Assert.Equal(0, stats.GetHashCount(HashType.SHA384));
|
||||||
Assert.Equal(0, stats.GetHashCount(HashType.SHA512));
|
Assert.Equal(0, stats.GetHashCount(HashType.SHA512));
|
||||||
Assert.Equal(0, stats.GetHashCount(HashType.SpamSum));
|
Assert.Equal(0, stats.GetHashCount(HashType.SpamSum));
|
||||||
|
Assert.Equal(0, stats.GetHashCount(HashType.BLAKE3));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
||||||
@@ -88,6 +89,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal(1, stats.GetHashCount(HashType.SHA384));
|
Assert.Equal(1, stats.GetHashCount(HashType.SHA384));
|
||||||
Assert.Equal(1, stats.GetHashCount(HashType.SHA512));
|
Assert.Equal(1, stats.GetHashCount(HashType.SHA512));
|
||||||
Assert.Equal(2, stats.GetHashCount(HashType.SpamSum));
|
Assert.Equal(2, stats.GetHashCount(HashType.SpamSum));
|
||||||
|
Assert.Equal(1, stats.GetHashCount(HashType.BLAKE3));
|
||||||
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
||||||
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
||||||
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
||||||
@@ -116,6 +118,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal(0, stats.GetHashCount(HashType.SHA384));
|
Assert.Equal(0, stats.GetHashCount(HashType.SHA384));
|
||||||
Assert.Equal(0, stats.GetHashCount(HashType.SHA512));
|
Assert.Equal(0, stats.GetHashCount(HashType.SHA512));
|
||||||
Assert.Equal(0, stats.GetHashCount(HashType.SpamSum));
|
Assert.Equal(0, stats.GetHashCount(HashType.SpamSum));
|
||||||
|
Assert.Equal(0, stats.GetHashCount(HashType.BLAKE3));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
||||||
@@ -151,6 +154,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal(0, stats.GetHashCount(HashType.SHA384));
|
Assert.Equal(0, stats.GetHashCount(HashType.SHA384));
|
||||||
Assert.Equal(0, stats.GetHashCount(HashType.SHA512));
|
Assert.Equal(0, stats.GetHashCount(HashType.SHA512));
|
||||||
Assert.Equal(0, stats.GetHashCount(HashType.SpamSum));
|
Assert.Equal(0, stats.GetHashCount(HashType.SpamSum));
|
||||||
|
Assert.Equal(0, stats.GetHashCount(HashType.BLAKE3));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
||||||
@@ -179,6 +183,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal(1, stats.GetHashCount(HashType.SHA384));
|
Assert.Equal(1, stats.GetHashCount(HashType.SHA384));
|
||||||
Assert.Equal(1, stats.GetHashCount(HashType.SHA512));
|
Assert.Equal(1, stats.GetHashCount(HashType.SHA512));
|
||||||
Assert.Equal(2, stats.GetHashCount(HashType.SpamSum));
|
Assert.Equal(2, stats.GetHashCount(HashType.SpamSum));
|
||||||
|
Assert.Equal(1, stats.GetHashCount(HashType.BLAKE3));
|
||||||
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
||||||
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
||||||
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
Assert.Equal(1, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
||||||
@@ -203,6 +208,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal(0, stats.GetHashCount(HashType.SHA384));
|
Assert.Equal(0, stats.GetHashCount(HashType.SHA384));
|
||||||
Assert.Equal(0, stats.GetHashCount(HashType.SHA512));
|
Assert.Equal(0, stats.GetHashCount(HashType.SHA512));
|
||||||
Assert.Equal(0, stats.GetHashCount(HashType.SpamSum));
|
Assert.Equal(0, stats.GetHashCount(HashType.SpamSum));
|
||||||
|
Assert.Equal(0, stats.GetHashCount(HashType.BLAKE3));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Disk));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.File));
|
||||||
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
Assert.Equal(0, stats.GetItemCount(Data.Models.Metadata.ItemType.Media));
|
||||||
@@ -238,6 +244,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
Assert.Equal(1, newStats.GetHashCount(HashType.SHA384));
|
Assert.Equal(1, newStats.GetHashCount(HashType.SHA384));
|
||||||
Assert.Equal(1, newStats.GetHashCount(HashType.SHA512));
|
Assert.Equal(1, newStats.GetHashCount(HashType.SHA512));
|
||||||
Assert.Equal(1, newStats.GetHashCount(HashType.SpamSum));
|
Assert.Equal(1, newStats.GetHashCount(HashType.SpamSum));
|
||||||
|
Assert.Equal(1, newStats.GetHashCount(HashType.BLAKE3));
|
||||||
Assert.Equal(1, newStats.GetItemCount(Data.Models.Metadata.ItemType.Rom));
|
Assert.Equal(1, newStats.GetItemCount(Data.Models.Metadata.ItemType.Rom));
|
||||||
Assert.Equal(1, newStats.GetStatusCount(ItemStatus.Good));
|
Assert.Equal(1, newStats.GetStatusCount(ItemStatus.Good));
|
||||||
}
|
}
|
||||||
@@ -317,6 +324,7 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
rom.SHA384 = HashType.SHA384.ZeroString;
|
rom.SHA384 = HashType.SHA384.ZeroString;
|
||||||
rom.SHA512 = HashType.SHA512.ZeroString;
|
rom.SHA512 = HashType.SHA512.ZeroString;
|
||||||
rom.SpamSum = HashType.SpamSum.ZeroString;
|
rom.SpamSum = HashType.SpamSum.ZeroString;
|
||||||
|
rom.BLAKE3 = HashType.BLAKE3.ZeroString;
|
||||||
|
|
||||||
return rom;
|
return rom;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -700,6 +700,31 @@ namespace SabreTools.Metadata.DatFiles.Test
|
|||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Blake3File_SupportedTypes()
|
||||||
|
{
|
||||||
|
var datFile = new Blake3File(null);
|
||||||
|
var actual = datFile.SupportedTypes;
|
||||||
|
Assert.True(actual.SequenceEqual([
|
||||||
|
Data.Models.Metadata.ItemType.Rom,
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Blake3File_GetMissingRequiredFields_Rom()
|
||||||
|
{
|
||||||
|
var datItem = new Rom();
|
||||||
|
var datFile = new Blake3File(null);
|
||||||
|
|
||||||
|
var actual = datFile.GetMissingRequiredFields(datItem);
|
||||||
|
|
||||||
|
Assert.NotNull(actual);
|
||||||
|
Assert.True(actual.SequenceEqual([
|
||||||
|
nameof(Data.Models.Metadata.Rom.Name),
|
||||||
|
nameof(Data.Models.Metadata.Rom.BLAKE3),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Listrom
|
#region Listrom
|
||||||
|
|||||||
@@ -1,18 +1,25 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
<TargetFrameworks>net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="coverlet.collector" Version="10.0.0" />
|
<PackageReference Include="coverlet.collector" Version="10.1.0">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PackageReference Include="SabreTools.Hashing" Version="[2.0.0]" />
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.11.1" />
|
||||||
|
<PackageReference Include="SabreTools.Hashing" Version="2.2.0" />
|
||||||
<PackageReference Include="xunit" Version="2.9.3" />
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
Header.Debug = header.Debug;
|
Header.Debug = header.Debug;
|
||||||
if (Header.Description is null)
|
if (Header.Description is null)
|
||||||
Header.Description = header.Description;
|
Header.Description = header.Description;
|
||||||
|
if (Header.DirHandling is null)
|
||||||
|
Header.DirHandling = header.DirHandling;
|
||||||
if (Header.Email is null)
|
if (Header.Email is null)
|
||||||
Header.Email = header.Email;
|
Header.Email = header.Email;
|
||||||
if (Header.EmulatorVersion is null)
|
if (Header.EmulatorVersion is null)
|
||||||
@@ -156,6 +158,8 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
Header.ScreenshotsWidth = header.ScreenshotsWidth;
|
Header.ScreenshotsWidth = header.ScreenshotsWidth;
|
||||||
if (Header.System is null)
|
if (Header.System is null)
|
||||||
Header.System = header.System;
|
Header.System = header.System;
|
||||||
|
if (Header.Subset is null)
|
||||||
|
Header.Subset = header.Subset;
|
||||||
if (Header.Timestamp is null)
|
if (Header.Timestamp is null)
|
||||||
Header.Timestamp = header.Timestamp;
|
Header.Timestamp = header.Timestamp;
|
||||||
if (Header.Type is null)
|
if (Header.Type is null)
|
||||||
|
|||||||
@@ -593,7 +593,8 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
sha384 = string.Empty,
|
sha384 = string.Empty,
|
||||||
sha512 = string.Empty,
|
sha512 = string.Empty,
|
||||||
size = string.Empty,
|
size = string.Empty,
|
||||||
spamsum = string.Empty;
|
spamsum = string.Empty,
|
||||||
|
blake3 = string.Empty;
|
||||||
|
|
||||||
// Ensure we have the proper values for replacement
|
// Ensure we have the proper values for replacement
|
||||||
if (item is Disk disk)
|
if (item is Disk disk)
|
||||||
@@ -633,6 +634,7 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
sha512 = rom.SHA512 ?? string.Empty;
|
sha512 = rom.SHA512 ?? string.Empty;
|
||||||
size = rom.Size.ToString() ?? string.Empty;
|
size = rom.Size.ToString() ?? string.Empty;
|
||||||
spamsum = rom.SpamSum ?? string.Empty;
|
spamsum = rom.SpamSum ?? string.Empty;
|
||||||
|
blake3 = rom.BLAKE3 ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now do bulk replacement where possible
|
// Now do bulk replacement where possible
|
||||||
@@ -657,7 +659,8 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
.Replace("%sha384%", sha384)
|
.Replace("%sha384%", sha384)
|
||||||
.Replace("%sha512%", sha512)
|
.Replace("%sha512%", sha512)
|
||||||
.Replace("%size%", size)
|
.Replace("%size%", size)
|
||||||
.Replace("%spamsum%", spamsum);
|
.Replace("%spamsum%", spamsum)
|
||||||
|
.Replace("%blake3%", blake3);
|
||||||
|
|
||||||
return fix;
|
return fix;
|
||||||
}
|
}
|
||||||
@@ -681,6 +684,14 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
if (rom.CRC32 != "null")
|
if (rom.CRC32 != "null")
|
||||||
return rom;
|
return rom;
|
||||||
|
|
||||||
|
// If the item has a SHA-1 but no size
|
||||||
|
if (rom.Size is null && rom.SHA1 is not null && rom.SHA1 != "null")
|
||||||
|
return rom;
|
||||||
|
|
||||||
|
// If the item has a SHA-256 but no size
|
||||||
|
if (rom.Size is null && rom.SHA256 is not null && rom.SHA256 != "null")
|
||||||
|
return rom;
|
||||||
|
|
||||||
// If the Rom has "null" characteristics, ensure all fields
|
// If the Rom has "null" characteristics, ensure all fields
|
||||||
rom.Name = rom.Name == "null" ? "-" : rom.Name;
|
rom.Name = rom.Name == "null" ? "-" : rom.Name;
|
||||||
rom.Size = 0;
|
rom.Size = 0;
|
||||||
@@ -697,6 +708,7 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
rom.SHA384 = rom.SHA384 == "null" ? HashType.SHA384.ZeroString : null;
|
rom.SHA384 = rom.SHA384 == "null" ? HashType.SHA384.ZeroString : null;
|
||||||
rom.SHA512 = rom.SHA512 == "null" ? HashType.SHA512.ZeroString : null;
|
rom.SHA512 = rom.SHA512 == "null" ? HashType.SHA512.ZeroString : null;
|
||||||
rom.SpamSum = rom.SpamSum == "null" ? HashType.SpamSum.ZeroString : null;
|
rom.SpamSum = rom.SpamSum == "null" ? HashType.SpamSum.ZeroString : null;
|
||||||
|
rom.BLAKE3 = rom.BLAKE3 == "null" ? HashType.BLAKE3.ZeroString : null;
|
||||||
|
|
||||||
return rom;
|
return rom;
|
||||||
}
|
}
|
||||||
@@ -979,7 +991,7 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
{
|
{
|
||||||
// If we have a 0-size or blank rom, then we ignore
|
// If we have a 0-size or blank rom, then we ignore
|
||||||
long? size = rom.Size;
|
long? size = rom.Size;
|
||||||
if (size == 0 || size is null)
|
if ((size == 0 || size is null) && rom.SHA1 is null && rom.SHA256 is null)
|
||||||
{
|
{
|
||||||
string itemString = JsonConvert.SerializeObject(datItem, Formatting.None);
|
string itemString = JsonConvert.SerializeObject(datItem, Formatting.None);
|
||||||
_logger.Verbose($"Item '{itemString}' was skipped because it had an invalid size");
|
_logger.Verbose($"Item '{itemString}' was skipped because it had an invalid size");
|
||||||
@@ -1127,6 +1139,10 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
if (!string.IsNullOrEmpty(spamSum))
|
if (!string.IsNullOrEmpty(spamSum))
|
||||||
return $"_{spamSum}";
|
return $"_{spamSum}";
|
||||||
|
|
||||||
|
string? blake3 = datItem.BLAKE3;
|
||||||
|
if (!string.IsNullOrEmpty(blake3))
|
||||||
|
return $"_{blake3}";
|
||||||
|
|
||||||
return "_1";
|
return "_1";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,12 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
set => _internal.Description = value;
|
set => _internal.Description = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string? DirHandling
|
||||||
|
{
|
||||||
|
get => _internal.DirHandling;
|
||||||
|
set => _internal.DirHandling = value;
|
||||||
|
}
|
||||||
|
|
||||||
public string? Email
|
public string? Email
|
||||||
{
|
{
|
||||||
get => _internal.Email;
|
get => _internal.Email;
|
||||||
@@ -282,6 +288,12 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public bool SearchSpecified => Search is not null;
|
public bool SearchSpecified => Search is not null;
|
||||||
|
|
||||||
|
public string? Subset
|
||||||
|
{
|
||||||
|
get => _internal.Subset;
|
||||||
|
set => _internal.Subset = value;
|
||||||
|
}
|
||||||
|
|
||||||
public string? System
|
public string? System
|
||||||
{
|
{
|
||||||
get => _internal.System;
|
get => _internal.System;
|
||||||
|
|||||||
@@ -353,6 +353,12 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
ModifyHashCount(HashType.SHA384, string.IsNullOrEmpty(rom.SHA384) ? 0 : 1);
|
ModifyHashCount(HashType.SHA384, string.IsNullOrEmpty(rom.SHA384) ? 0 : 1);
|
||||||
ModifyHashCount(HashType.SHA512, string.IsNullOrEmpty(rom.SHA512) ? 0 : 1);
|
ModifyHashCount(HashType.SHA512, string.IsNullOrEmpty(rom.SHA512) ? 0 : 1);
|
||||||
ModifyHashCount(HashType.SpamSum, string.IsNullOrEmpty(rom.SpamSum) ? 0 : 1);
|
ModifyHashCount(HashType.SpamSum, string.IsNullOrEmpty(rom.SpamSum) ? 0 : 1);
|
||||||
|
#if NET7_0_OR_GREATER
|
||||||
|
ModifyHashCount(HashType.BLAKE3, string.IsNullOrEmpty(rom.BLAKE3) ? 0 : 1);
|
||||||
|
#else
|
||||||
|
// HACK because BLAKE3 is not supported below .NET 7
|
||||||
|
ModifyHashCount(HashType.CRC1_ZERO, string.IsNullOrEmpty(rom.BLAKE3) ? 0 : 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ModifyStatusCount(ItemStatus.BadDump, status == ItemStatus.BadDump ? 1 : 0);
|
ModifyStatusCount(ItemStatus.BadDump, status == ItemStatus.BadDump ? 1 : 0);
|
||||||
@@ -430,6 +436,12 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
ModifyHashCount(HashType.SHA384, string.IsNullOrEmpty(rom.SHA384) ? 0 : -1);
|
ModifyHashCount(HashType.SHA384, string.IsNullOrEmpty(rom.SHA384) ? 0 : -1);
|
||||||
ModifyHashCount(HashType.SHA512, string.IsNullOrEmpty(rom.SHA512) ? 0 : -1);
|
ModifyHashCount(HashType.SHA512, string.IsNullOrEmpty(rom.SHA512) ? 0 : -1);
|
||||||
ModifyHashCount(HashType.SpamSum, string.IsNullOrEmpty(rom.SpamSum) ? 0 : -1);
|
ModifyHashCount(HashType.SpamSum, string.IsNullOrEmpty(rom.SpamSum) ? 0 : -1);
|
||||||
|
#if NET7_0_OR_GREATER
|
||||||
|
ModifyHashCount(HashType.BLAKE3, string.IsNullOrEmpty(rom.BLAKE3) ? 0 : -1);
|
||||||
|
#else
|
||||||
|
// HACK because BLAKE3 is not supported below .NET 7
|
||||||
|
ModifyHashCount(HashType.CRC1_ZERO, string.IsNullOrEmpty(rom.BLAKE3) ? 0 : -1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ModifyStatusCount(ItemStatus.BadDump, status == ItemStatus.BadDump ? -1 : 0);
|
ModifyStatusCount(ItemStatus.BadDump, status == ItemStatus.BadDump ? -1 : 0);
|
||||||
|
|||||||
@@ -169,6 +169,11 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
RedumpSpamSum,
|
RedumpSpamSum,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// BLAKE3 hash list
|
||||||
|
/// </summary>
|
||||||
|
RedumpBLAKE3,
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
56
SabreTools.Metadata.DatFiles/Formats/Blake3File.cs
Normal file
56
SabreTools.Metadata.DatFiles/Formats/Blake3File.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using SabreTools.Hashing;
|
||||||
|
using SabreTools.Metadata.DatItems;
|
||||||
|
using SabreTools.Metadata.DatItems.Formats;
|
||||||
|
|
||||||
|
namespace SabreTools.Metadata.DatFiles.Formats
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an BLAKE3 hashfile
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Blake3File : Hashfile
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override Data.Models.Metadata.ItemType[] SupportedTypes
|
||||||
|
=> [
|
||||||
|
Data.Models.Metadata.ItemType.Rom,
|
||||||
|
];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor designed for casting a base DatFile
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="datFile">Parent DatFile to copy from</param>
|
||||||
|
public Blake3File(DatFile? datFile) : base(datFile)
|
||||||
|
{
|
||||||
|
#if NET7_0_OR_GREATER
|
||||||
|
_hash = HashType.BLAKE3;
|
||||||
|
#else
|
||||||
|
// HACK because BLAKE3 is not supported below .NET 7
|
||||||
|
_hash = HashType.CRC1_ZERO;
|
||||||
|
#endif
|
||||||
|
Header.DatFormat = DatFormat.RedumpBLAKE3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected internal override List<string>? GetMissingRequiredFields(DatItem datItem)
|
||||||
|
{
|
||||||
|
List<string> missingFields = [];
|
||||||
|
|
||||||
|
switch (datItem)
|
||||||
|
{
|
||||||
|
case Rom rom:
|
||||||
|
if (string.IsNullOrEmpty(rom.Name))
|
||||||
|
missingFields.Add(nameof(Data.Models.Metadata.Rom.Name));
|
||||||
|
if (string.IsNullOrEmpty(rom.BLAKE3))
|
||||||
|
missingFields.Add(nameof(Data.Models.Metadata.Rom.BLAKE3));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Item type is not supported
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return missingFields;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -88,9 +88,12 @@ namespace SabreTools.Metadata.DatFiles.Formats
|
|||||||
case Rom rom:
|
case Rom rom:
|
||||||
if (string.IsNullOrEmpty(rom.Name))
|
if (string.IsNullOrEmpty(rom.Name))
|
||||||
missingFields.Add(nameof(Data.Models.Metadata.Rom.Name));
|
missingFields.Add(nameof(Data.Models.Metadata.Rom.Name));
|
||||||
if (rom.Size is null || rom.Size < 0)
|
if ((rom.Size is null || rom.Size < 0)
|
||||||
|
&& (rom.SHA1 is null || rom.SHA1 == "null")
|
||||||
|
&& (rom.SHA256 is null || rom.SHA1 == "null"))
|
||||||
missingFields.Add(nameof(Data.Models.Metadata.Rom.Size));
|
missingFields.Add(nameof(Data.Models.Metadata.Rom.Size));
|
||||||
if (string.IsNullOrEmpty(rom.CRC16)
|
if (string.IsNullOrEmpty(rom.BLAKE3)
|
||||||
|
&& string.IsNullOrEmpty(rom.CRC16)
|
||||||
&& string.IsNullOrEmpty(rom.CRC32)
|
&& string.IsNullOrEmpty(rom.CRC32)
|
||||||
&& string.IsNullOrEmpty(rom.CRC64)
|
&& string.IsNullOrEmpty(rom.CRC64)
|
||||||
&& string.IsNullOrEmpty(rom.MD2)
|
&& string.IsNullOrEmpty(rom.MD2)
|
||||||
|
|||||||
@@ -282,9 +282,12 @@ namespace SabreTools.Metadata.DatFiles.Formats
|
|||||||
case Rom rom:
|
case Rom rom:
|
||||||
if (string.IsNullOrEmpty(rom.Name))
|
if (string.IsNullOrEmpty(rom.Name))
|
||||||
missingFields.Add(nameof(Data.Models.Metadata.Rom.Name));
|
missingFields.Add(nameof(Data.Models.Metadata.Rom.Name));
|
||||||
if (rom.Size is null || rom.Size < 0)
|
if ((rom.Size is null || rom.Size < 0)
|
||||||
|
&& (rom.SHA1 is null || rom.SHA1 == "null")
|
||||||
|
&& (rom.SHA256 is null || rom.SHA1 == "null"))
|
||||||
missingFields.Add(nameof(Data.Models.Metadata.Rom.Size));
|
missingFields.Add(nameof(Data.Models.Metadata.Rom.Size));
|
||||||
if (string.IsNullOrEmpty(rom.CRC16)
|
if (string.IsNullOrEmpty(rom.BLAKE3)
|
||||||
|
&& string.IsNullOrEmpty(rom.CRC16)
|
||||||
&& string.IsNullOrEmpty(rom.CRC32)
|
&& string.IsNullOrEmpty(rom.CRC32)
|
||||||
&& string.IsNullOrEmpty(rom.CRC64)
|
&& string.IsNullOrEmpty(rom.CRC64)
|
||||||
&& string.IsNullOrEmpty(rom.MD2)
|
&& string.IsNullOrEmpty(rom.MD2)
|
||||||
|
|||||||
@@ -29,17 +29,22 @@ namespace SabreTools.Metadata.DatFiles.Formats
|
|||||||
<![CDATA[
|
<![CDATA[
|
||||||
The softwaredb.xml file contains information about rom mapper types
|
The softwaredb.xml file contains information about rom mapper types
|
||||||
|
|
||||||
- Copyright 2003 Nicolas Beyaert (Initial Database)
|
Copyright 2003 Nicolas Beyaert (Initial Database)
|
||||||
- Copyright 2004-2013 BlueMSX Team
|
Copyright 2004-2013 BlueMSX Team
|
||||||
- Copyright 2005-2023 openMSX Team
|
Copyright 2005-2026 openMSX Team
|
||||||
- Generation MSXIDs by www.generation-msx.nl
|
|
||||||
|
|
||||||
- Thanks go out to:
|
Generation MSXIDs by www.generation-msx.nl
|
||||||
- - Generation MSX/Sylvester for the incredible source of information
|
|
||||||
- p_gimeno and diedel for their help adding and valdiating ROM additions
|
Thanks go out to:
|
||||||
|
- Generation MSX / Sylvester for the incredible source of information
|
||||||
|
- p_gimeno and diedel for their help adding and validating ROM additions
|
||||||
- GDX for additional ROM info and validations and corrections
|
- GDX for additional ROM info and validations and corrections
|
||||||
|
- TFH / Filehunter for his sharing of information
|
||||||
|
- MP83 for deep dives into software and corrections
|
||||||
|
- bsittler for preservation and sharing of information
|
||||||
|
|
||||||
|
Important: This file is auto generated using a database.
|
||||||
|
The Database is located at https://romdb.vampier.net/
|
||||||
]]>";
|
]]>";
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -93,7 +93,9 @@ namespace SabreTools.Metadata.DatFiles.Formats
|
|||||||
case Rom rom:
|
case Rom rom:
|
||||||
if (string.IsNullOrEmpty(rom.Name))
|
if (string.IsNullOrEmpty(rom.Name))
|
||||||
missingFields.Add(nameof(Data.Models.Metadata.Rom.Name));
|
missingFields.Add(nameof(Data.Models.Metadata.Rom.Name));
|
||||||
if (rom.Size is null || rom.Size < 0)
|
if ((rom.Size is null || rom.Size < 0)
|
||||||
|
&& (rom.SHA1 is null || rom.SHA1 == "null")
|
||||||
|
&& (rom.SHA256 is null || rom.SHA1 == "null"))
|
||||||
missingFields.Add(nameof(Data.Models.Metadata.Rom.Size));
|
missingFields.Add(nameof(Data.Models.Metadata.Rom.Size));
|
||||||
if (string.IsNullOrEmpty(rom.CRC32)
|
if (string.IsNullOrEmpty(rom.CRC32)
|
||||||
&& string.IsNullOrEmpty(rom.MD5)
|
&& string.IsNullOrEmpty(rom.MD5)
|
||||||
|
|||||||
@@ -482,6 +482,7 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
rom.SHA384 = null; // HashType.SHA384.ZeroString;
|
rom.SHA384 = null; // HashType.SHA384.ZeroString;
|
||||||
rom.SHA512 = null; // HashType.SHA512.ZeroString;
|
rom.SHA512 = null; // HashType.SHA512.ZeroString;
|
||||||
rom.SpamSum = null; // HashType.SpamSum.ZeroString;
|
rom.SpamSum = null; // HashType.SpamSum.ZeroString;
|
||||||
|
rom.BLAKE3 = null; // HashType.BLAKE3.ZeroString;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the file has no size and it's not the above case, skip and log
|
// If the file has no size and it's not the above case, skip and log
|
||||||
|
|||||||
@@ -40,6 +40,15 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
private readonly Dictionary<string, List<DatItem>?> _items = [];
|
private readonly Dictionary<string, List<DatItem>?> _items = [];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Internal dictionary for the class
|
||||||
|
/// </summary>
|
||||||
|
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
|
||||||
|
private readonly ConcurrentDictionary<string, object> _itemsLocks = [];
|
||||||
|
#else
|
||||||
|
private readonly Dictionary<string, object> _itemsLocks = [];
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logging object
|
/// Logging object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -163,6 +172,7 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
rom.SHA384 = null; // HashType.SHA384.ZeroString;
|
rom.SHA384 = null; // HashType.SHA384.ZeroString;
|
||||||
rom.SHA512 = null; // HashType.SHA512.ZeroString;
|
rom.SHA512 = null; // HashType.SHA512.ZeroString;
|
||||||
rom.SpamSum = null; // HashType.SpamSum.ZeroString;
|
rom.SpamSum = null; // HashType.SpamSum.ZeroString;
|
||||||
|
rom.BLAKE3 = null; // HashType.BLAKE3.ZeroString;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the file has no size and it's not the above case, skip and log
|
// If the file has no size and it's not the above case, skip and log
|
||||||
@@ -190,7 +200,14 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
// If only adding statistics, we add an empty key for games and then just item stats
|
// If only adding statistics, we add an empty key for games and then just item stats
|
||||||
if (statsOnly)
|
if (statsOnly)
|
||||||
{
|
{
|
||||||
EnsureBucketingKey(key);
|
// Add an empty key
|
||||||
|
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
|
||||||
|
_items.GetOrAdd(key, []);
|
||||||
|
#else
|
||||||
|
if (!_items.ContainsKey(key))
|
||||||
|
_items[key] = [];
|
||||||
|
#endif
|
||||||
|
|
||||||
DatStatistics.AddItemStatistics(item);
|
DatStatistics.AddItemStatistics(item);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -293,7 +310,16 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
public bool RemoveItem(string key, DatItem value, int index)
|
public bool RemoveItem(string key, DatItem value, int index)
|
||||||
{
|
{
|
||||||
// Explicit lock for some weird corner cases
|
// Explicit lock for some weird corner cases
|
||||||
lock (key)
|
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
|
||||||
|
object lockObj = _itemsLocks.GetOrAdd(key, _ => new object());
|
||||||
|
#else
|
||||||
|
if (!_itemsLocks.ContainsKey(key))
|
||||||
|
_itemsLocks[key] = new object();
|
||||||
|
|
||||||
|
object lockObj = _itemsLocks[key];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lock (lockObj)
|
||||||
{
|
{
|
||||||
// If the key doesn't exist, return
|
// If the key doesn't exist, return
|
||||||
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
|
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
|
||||||
@@ -337,10 +363,24 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
internal void AddItem(string key, DatItem value)
|
internal void AddItem(string key, DatItem value)
|
||||||
{
|
{
|
||||||
// Explicit lock for some weird corner cases
|
// Explicit lock for some weird corner cases
|
||||||
lock (key)
|
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
|
||||||
|
object lockObj = _itemsLocks.GetOrAdd(key, _ => new object());
|
||||||
|
#else
|
||||||
|
if (!_itemsLocks.ContainsKey(key))
|
||||||
|
_itemsLocks[key] = new object();
|
||||||
|
|
||||||
|
object lockObj = _itemsLocks[key];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lock (lockObj)
|
||||||
{
|
{
|
||||||
// Ensure the key exists
|
// Ensure the key exists
|
||||||
EnsureBucketingKey(key);
|
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
|
||||||
|
_items.GetOrAdd(key, []);
|
||||||
|
#else
|
||||||
|
if (!_items.ContainsKey(key))
|
||||||
|
_items[key] = [];
|
||||||
|
#endif
|
||||||
|
|
||||||
// If item is null, don't add it
|
// If item is null, don't add it
|
||||||
if (value is null)
|
if (value is null)
|
||||||
@@ -639,21 +679,6 @@ namespace SabreTools.Metadata.DatFiles
|
|||||||
return roms.FindIndex(datItem.Equals) > -1;
|
return roms.FindIndex(datItem.Equals) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Ensure the key exists in the items dictionary
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key">Key to ensure</param>
|
|
||||||
private void EnsureBucketingKey(string key)
|
|
||||||
{
|
|
||||||
// If the key is missing from the dictionary, add it
|
|
||||||
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
|
|
||||||
_items.GetOrAdd(key, []);
|
|
||||||
#else
|
|
||||||
if (!_items.ContainsKey(key))
|
|
||||||
_items[key] = [];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the highest-order Field value that represents the statistics
|
/// Get the highest-order Field value that represents the statistics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Assembly Properties -->
|
<!-- Assembly Properties -->
|
||||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;net11.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Version>3.0.1</Version>
|
<Version>3.3.0</Version>
|
||||||
|
|
||||||
<!-- Package Properties -->
|
<!-- Package Properties -->
|
||||||
<Authors>Matt Nadareski</Authors>
|
<Authors>Matt Nadareski</Authors>
|
||||||
@@ -46,8 +46,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MinValueTupleBridge" Version="0.2.1" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`))" />
|
<PackageReference Include="MinValueTupleBridge" Version="0.2.1" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`))" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||||
<PackageReference Include="SabreTools.Hashing" Version="[2.0.0]" />
|
<PackageReference Include="SabreTools.Hashing" Version="2.2.0" />
|
||||||
<PackageReference Include="SabreTools.IO" Version="[2.1.0]" />
|
<PackageReference Include="SabreTools.IO" Version="2.4.0" />
|
||||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" Condition="$(TargetFramework.StartsWith(`net40`)) OR $(TargetFramework.StartsWith(`net45`))" />
|
<PackageReference Include="System.ValueTuple" Version="4.5.0" Condition="$(TargetFramework.StartsWith(`net40`)) OR $(TargetFramework.StartsWith(`net45`))" />
|
||||||
<PackageReference Include="System.ValueTuple" Version="4.6.2" Condition="$(TargetFramework.StartsWith(`net46`)) OR $(TargetFramework.StartsWith(`net47`)) OR $(TargetFramework.StartsWith(`net48`))" />
|
<PackageReference Include="System.ValueTuple" Version="4.6.2" Condition="$(TargetFramework.StartsWith(`net46`)) OR $(TargetFramework.StartsWith(`net47`)) OR $(TargetFramework.StartsWith(`net48`))" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -290,6 +290,10 @@ namespace SabreTools.Metadata.DatItems.Test
|
|||||||
[InlineData(ItemKey.SpamSum, false, true, "3::")]
|
[InlineData(ItemKey.SpamSum, false, true, "3::")]
|
||||||
[InlineData(ItemKey.SpamSum, true, false, "3::")]
|
[InlineData(ItemKey.SpamSum, true, false, "3::")]
|
||||||
[InlineData(ItemKey.SpamSum, true, true, "3::")]
|
[InlineData(ItemKey.SpamSum, true, true, "3::")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, false, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, true, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, false, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, true, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
public void GetKeyDB_DefaultImplementation(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
public void GetKeyDB_DefaultImplementation(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
||||||
{
|
{
|
||||||
Source source = new Source(0);
|
Source source = new Source(0);
|
||||||
@@ -363,6 +367,10 @@ namespace SabreTools.Metadata.DatItems.Test
|
|||||||
[InlineData(ItemKey.SpamSum, false, true, "BASE64")]
|
[InlineData(ItemKey.SpamSum, false, true, "BASE64")]
|
||||||
[InlineData(ItemKey.SpamSum, true, false, "base64")]
|
[InlineData(ItemKey.SpamSum, true, false, "base64")]
|
||||||
[InlineData(ItemKey.SpamSum, true, true, "base64")]
|
[InlineData(ItemKey.SpamSum, true, true, "base64")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, false, "DEADBEEF")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, true, "DEADBEEF")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, false, "deadbeef")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, true, "deadbeef")]
|
||||||
public void GetKeyDB_CustomImplementation(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
public void GetKeyDB_CustomImplementation(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
||||||
{
|
{
|
||||||
Source source = new Source(0);
|
Source source = new Source(0);
|
||||||
@@ -383,7 +391,8 @@ namespace SabreTools.Metadata.DatItems.Test
|
|||||||
SHA256 = "DEADBEEF",
|
SHA256 = "DEADBEEF",
|
||||||
SHA384 = "DEADBEEF",
|
SHA384 = "DEADBEEF",
|
||||||
SHA512 = "DEADBEEF",
|
SHA512 = "DEADBEEF",
|
||||||
SpamSum = "BASE64"
|
SpamSum = "BASE64",
|
||||||
|
BLAKE3 = "DEADBEEF",
|
||||||
};
|
};
|
||||||
|
|
||||||
string actual = datItem.GetKey(bucketedBy, machine, source, lower, norename);
|
string actual = datItem.GetKey(bucketedBy, machine, source, lower, norename);
|
||||||
|
|||||||
@@ -260,6 +260,10 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
[InlineData(ItemKey.SpamSum, false, true, "3::")]
|
[InlineData(ItemKey.SpamSum, false, true, "3::")]
|
||||||
[InlineData(ItemKey.SpamSum, true, false, "3::")]
|
[InlineData(ItemKey.SpamSum, true, false, "3::")]
|
||||||
[InlineData(ItemKey.SpamSum, true, true, "3::")]
|
[InlineData(ItemKey.SpamSum, true, true, "3::")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, false, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, true, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, false, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, true, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
public void GetKeyDBTest(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
public void GetKeyDBTest(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
||||||
{
|
{
|
||||||
Source source = new Source(0);
|
Source source = new Source(0);
|
||||||
|
|||||||
@@ -337,6 +337,10 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
[InlineData(ItemKey.SpamSum, false, true, "3::")]
|
[InlineData(ItemKey.SpamSum, false, true, "3::")]
|
||||||
[InlineData(ItemKey.SpamSum, true, false, "3::")]
|
[InlineData(ItemKey.SpamSum, true, false, "3::")]
|
||||||
[InlineData(ItemKey.SpamSum, true, true, "3::")]
|
[InlineData(ItemKey.SpamSum, true, true, "3::")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, false, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, true, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, false, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, true, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
public void GetKeyDBTest(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
public void GetKeyDBTest(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
||||||
{
|
{
|
||||||
Source source = new Source(0);
|
Source source = new Source(0);
|
||||||
|
|||||||
@@ -330,6 +330,10 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
[InlineData(ItemKey.SpamSum, false, true, "DEADBEEF")]
|
[InlineData(ItemKey.SpamSum, false, true, "DEADBEEF")]
|
||||||
[InlineData(ItemKey.SpamSum, true, false, "deadbeef")]
|
[InlineData(ItemKey.SpamSum, true, false, "deadbeef")]
|
||||||
[InlineData(ItemKey.SpamSum, true, true, "deadbeef")]
|
[InlineData(ItemKey.SpamSum, true, true, "deadbeef")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, false, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, true, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, false, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, true, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
public void GetKeyDBTest(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
public void GetKeyDBTest(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
||||||
{
|
{
|
||||||
Source source = new Source(0);
|
Source source = new Source(0);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
Assert.Null(self.SHA384);
|
Assert.Null(self.SHA384);
|
||||||
Assert.Null(self.SHA512);
|
Assert.Null(self.SHA512);
|
||||||
Assert.Null(self.SpamSum);
|
Assert.Null(self.SpamSum);
|
||||||
|
Assert.Null(self.BLAKE3);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -49,7 +50,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = "sha256",
|
SHA256 = "sha256",
|
||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum"
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
self.FillMissingInformation(other);
|
self.FillMissingInformation(other);
|
||||||
@@ -67,6 +69,7 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
Assert.Equal("sha384", self.SHA384);
|
Assert.Equal("sha384", self.SHA384);
|
||||||
Assert.Equal("sha512", self.SHA512);
|
Assert.Equal("sha512", self.SHA512);
|
||||||
Assert.Equal("spamsum", self.SpamSum);
|
Assert.Equal("spamsum", self.SpamSum);
|
||||||
|
Assert.Equal("blake3", self.BLAKE3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -98,7 +101,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -122,7 +126,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -146,7 +151,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -170,7 +176,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -194,7 +201,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -218,7 +226,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -242,7 +251,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -266,7 +276,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -290,7 +301,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -314,7 +326,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = "sha256",
|
SHA256 = "sha256",
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -338,7 +351,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -362,7 +376,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -386,7 +401,33 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = "spamsum"
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool actual = self.HasHashes();
|
||||||
|
Assert.True(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HasHashes_BLAKE3_True()
|
||||||
|
{
|
||||||
|
Rom self = new Rom
|
||||||
|
{
|
||||||
|
CRC16 = string.Empty,
|
||||||
|
CRC32 = string.Empty,
|
||||||
|
CRC64 = string.Empty,
|
||||||
|
MD2 = string.Empty,
|
||||||
|
MD4 = string.Empty,
|
||||||
|
MD5 = string.Empty,
|
||||||
|
RIPEMD128 = string.Empty,
|
||||||
|
RIPEMD160 = string.Empty,
|
||||||
|
SHA1 = string.Empty,
|
||||||
|
SHA256 = string.Empty,
|
||||||
|
SHA384 = string.Empty,
|
||||||
|
SHA512 = string.Empty,
|
||||||
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -410,7 +451,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = "sha256",
|
SHA256 = "sha256",
|
||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum"
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasHashes();
|
bool actual = self.HasHashes();
|
||||||
@@ -446,7 +488,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = "sha256",
|
SHA256 = "sha256",
|
||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum"
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -470,7 +513,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -494,7 +538,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -518,7 +563,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -542,7 +588,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -566,7 +613,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -590,7 +638,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -614,7 +663,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -638,7 +688,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -662,7 +713,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -686,7 +738,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = HashType.SHA256.ZeroString,
|
SHA256 = HashType.SHA256.ZeroString,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -710,7 +763,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = HashType.SHA384.ZeroString,
|
SHA384 = HashType.SHA384.ZeroString,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -734,7 +788,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = HashType.SHA512.ZeroString,
|
SHA512 = HashType.SHA512.ZeroString,
|
||||||
SpamSum = string.Empty
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -758,7 +813,33 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = string.Empty,
|
SHA256 = string.Empty,
|
||||||
SHA384 = string.Empty,
|
SHA384 = string.Empty,
|
||||||
SHA512 = string.Empty,
|
SHA512 = string.Empty,
|
||||||
SpamSum = HashType.SpamSum.ZeroString
|
SpamSum = HashType.SpamSum.ZeroString,
|
||||||
|
BLAKE3 = string.Empty,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool actual = self.HasZeroHash();
|
||||||
|
Assert.True(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HasZeroHash_ZeroBLAKE3_True()
|
||||||
|
{
|
||||||
|
Rom self = new Rom
|
||||||
|
{
|
||||||
|
CRC16 = string.Empty,
|
||||||
|
CRC32 = string.Empty,
|
||||||
|
CRC64 = string.Empty,
|
||||||
|
MD2 = string.Empty,
|
||||||
|
MD4 = string.Empty,
|
||||||
|
MD5 = string.Empty,
|
||||||
|
RIPEMD128 = string.Empty,
|
||||||
|
RIPEMD160 = string.Empty,
|
||||||
|
SHA1 = string.Empty,
|
||||||
|
SHA256 = string.Empty,
|
||||||
|
SHA384 = string.Empty,
|
||||||
|
SHA512 = string.Empty,
|
||||||
|
SpamSum = string.Empty,
|
||||||
|
BLAKE3 = HashType.BLAKE3.ZeroString,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -782,7 +863,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = HashType.SHA256.ZeroString,
|
SHA256 = HashType.SHA256.ZeroString,
|
||||||
SHA384 = HashType.SHA384.ZeroString,
|
SHA384 = HashType.SHA384.ZeroString,
|
||||||
SHA512 = HashType.SHA512.ZeroString,
|
SHA512 = HashType.SHA512.ZeroString,
|
||||||
SpamSum = HashType.SpamSum.ZeroString
|
SpamSum = HashType.SpamSum.ZeroString,
|
||||||
|
BLAKE3 = HashType.BLAKE3.ZeroString,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool actual = self.HasZeroHash();
|
bool actual = self.HasZeroHash();
|
||||||
@@ -855,6 +937,10 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
[InlineData(ItemKey.SpamSum, false, true, "DEADBEEF")]
|
[InlineData(ItemKey.SpamSum, false, true, "DEADBEEF")]
|
||||||
[InlineData(ItemKey.SpamSum, true, false, "deadbeef")]
|
[InlineData(ItemKey.SpamSum, true, false, "deadbeef")]
|
||||||
[InlineData(ItemKey.SpamSum, true, true, "deadbeef")]
|
[InlineData(ItemKey.SpamSum, true, true, "deadbeef")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, false, "DEADBEEF")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, false, true, "DEADBEEF")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, false, "deadbeef")]
|
||||||
|
[InlineData(ItemKey.BLAKE3, true, true, "deadbeef")]
|
||||||
public void GetKeyDBTest(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
public void GetKeyDBTest(ItemKey bucketedBy, bool lower, bool norename, string expected)
|
||||||
{
|
{
|
||||||
Source source = new Source(0);
|
Source source = new Source(0);
|
||||||
@@ -875,7 +961,8 @@ namespace SabreTools.Metadata.DatItems.Formats.Test
|
|||||||
SHA256 = "DEADBEEF",
|
SHA256 = "DEADBEEF",
|
||||||
SHA384 = "DEADBEEF",
|
SHA384 = "DEADBEEF",
|
||||||
SHA512 = "DEADBEEF",
|
SHA512 = "DEADBEEF",
|
||||||
SpamSum = "DEADBEEF"
|
SpamSum = "DEADBEEF",
|
||||||
|
BLAKE3 = "DEADBEEF",
|
||||||
};
|
};
|
||||||
|
|
||||||
string actual = datItem.GetKey(bucketedBy, machine, source, lower, norename);
|
string actual = datItem.GetKey(bucketedBy, machine, source, lower, norename);
|
||||||
|
|||||||
@@ -1,18 +1,25 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
<TargetFrameworks>net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="coverlet.collector" Version="10.0.0" />
|
<PackageReference Include="coverlet.collector" Version="10.1.0">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PackageReference Include="SabreTools.Hashing" Version="[2.0.0]" />
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.11.1" />
|
||||||
|
<PackageReference Include="SabreTools.Hashing" Version="2.2.0" />
|
||||||
<PackageReference Include="xunit" Version="2.9.3" />
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -191,6 +191,10 @@ namespace SabreTools.Metadata.DatItems
|
|||||||
// Now determine what the key should be based on the bucketedBy value
|
// Now determine what the key should be based on the bucketedBy value
|
||||||
switch (bucketedBy)
|
switch (bucketedBy)
|
||||||
{
|
{
|
||||||
|
case ItemKey.BLAKE3:
|
||||||
|
key = HashType.BLAKE3.ZeroString;
|
||||||
|
break;
|
||||||
|
|
||||||
case ItemKey.CRC16:
|
case ItemKey.CRC16:
|
||||||
key = HashType.CRC16.ZeroString;
|
key = HashType.CRC16.ZeroString;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace SabreTools.Metadata.DatItems
|
|||||||
|
|
||||||
Machine,
|
Machine,
|
||||||
|
|
||||||
|
BLAKE3,
|
||||||
CRC16,
|
CRC16,
|
||||||
CRC32,
|
CRC32,
|
||||||
CRC64,
|
CRC64,
|
||||||
|
|||||||
@@ -74,6 +74,12 @@ namespace SabreTools.Metadata.DatItems.Formats
|
|||||||
set => _internal.BitTorrentMagnetHash = value;
|
set => _internal.BitTorrentMagnetHash = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string? BLAKE3
|
||||||
|
{
|
||||||
|
get => _internal.BLAKE3;
|
||||||
|
set => _internal.BLAKE3 = value;
|
||||||
|
}
|
||||||
|
|
||||||
public string? ClothCoverDetectionModuleVersion
|
public string? ClothCoverDetectionModuleVersion
|
||||||
{
|
{
|
||||||
get => _internal.ClothCoverDetectionModuleVersion;
|
get => _internal.ClothCoverDetectionModuleVersion;
|
||||||
@@ -436,6 +442,12 @@ namespace SabreTools.Metadata.DatItems.Formats
|
|||||||
set => _internal.Status = value;
|
set => _internal.Status = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string? StatusMisc
|
||||||
|
{
|
||||||
|
get => _internal.StatusMisc;
|
||||||
|
set => _internal.StatusMisc = value;
|
||||||
|
}
|
||||||
|
|
||||||
public string? Summation
|
public string? Summation
|
||||||
{
|
{
|
||||||
get => _internal.Summation;
|
get => _internal.Summation;
|
||||||
@@ -858,6 +870,10 @@ namespace SabreTools.Metadata.DatItems.Formats
|
|||||||
// Now determine what the key should be based on the bucketedBy value
|
// Now determine what the key should be based on the bucketedBy value
|
||||||
switch (bucketedBy)
|
switch (bucketedBy)
|
||||||
{
|
{
|
||||||
|
case ItemKey.BLAKE3:
|
||||||
|
key = BLAKE3;
|
||||||
|
break;
|
||||||
|
|
||||||
case ItemKey.CRC16:
|
case ItemKey.CRC16:
|
||||||
key = CRC16;
|
key = CRC16;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -320,6 +320,12 @@ namespace SabreTools.Metadata.DatItems
|
|||||||
set => _internal.Serial = value;
|
set => _internal.Serial = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string? SetType
|
||||||
|
{
|
||||||
|
get => _internal.SetType;
|
||||||
|
set => _internal.SetType = value;
|
||||||
|
}
|
||||||
|
|
||||||
public string? Source
|
public string? Source
|
||||||
{
|
{
|
||||||
get => _internal.Source;
|
get => _internal.Source;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Assembly Properties -->
|
<!-- Assembly Properties -->
|
||||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;net11.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Version>3.0.1</Version>
|
<Version>3.3.0</Version>
|
||||||
|
|
||||||
<!-- Package Properties -->
|
<!-- Package Properties -->
|
||||||
<Authors>Matt Nadareski</Authors>
|
<Authors>Matt Nadareski</Authors>
|
||||||
@@ -32,8 +32,8 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||||
<PackageReference Include="SabreTools.Hashing" Version="[2.0.0]" />
|
<PackageReference Include="SabreTools.Hashing" Version="2.2.0" />
|
||||||
<PackageReference Include="SabreTools.IO" Version="[2.1.0]" />
|
<PackageReference Include="SabreTools.IO" Version="2.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
using SabreTools.Data.Models.Metadata;
|
using SabreTools.Data.Models.Metadata;
|
||||||
using SabreTools.Hashing;
|
using SabreTools.Hashing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@@ -1022,6 +1023,20 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
Assert.True(actual);
|
Assert.True(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("en-US")]
|
||||||
|
[InlineData("de-DE")]
|
||||||
|
[InlineData("fr-FR")]
|
||||||
|
public void Matches_DisplayRefresh_CurrentCultureIgnored(string culture)
|
||||||
|
{
|
||||||
|
CultureInfo.CurrentCulture = new CultureInfo(culture);
|
||||||
|
var filter = new FilterObject("display.refresh", "123.45", Operation.Equals);
|
||||||
|
Display obj = new Display { Refresh = 123.45 };
|
||||||
|
|
||||||
|
bool actual = filter.Matches(obj);
|
||||||
|
Assert.True(actual);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Driver
|
#region Driver
|
||||||
@@ -1103,6 +1118,7 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
[InlineData("header.datversion", "datversion")]
|
[InlineData("header.datversion", "datversion")]
|
||||||
[InlineData("header.debug", "yes")]
|
[InlineData("header.debug", "yes")]
|
||||||
[InlineData("header.description", "description")]
|
[InlineData("header.description", "description")]
|
||||||
|
[InlineData("header.dir", "noautodir")]
|
||||||
[InlineData("header.email", "email")]
|
[InlineData("header.email", "email")]
|
||||||
[InlineData("header.emulatorversion", "emulatorversion")]
|
[InlineData("header.emulatorversion", "emulatorversion")]
|
||||||
[InlineData("header.filename", "filename")]
|
[InlineData("header.filename", "filename")]
|
||||||
@@ -1131,6 +1147,7 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
[InlineData("header.schemalocation", "schemalocation")]
|
[InlineData("header.schemalocation", "schemalocation")]
|
||||||
[InlineData("header.screenshotsheight", "screenshotsheight")]
|
[InlineData("header.screenshotsheight", "screenshotsheight")]
|
||||||
[InlineData("header.screenshotswidth", "screenshotswidth")]
|
[InlineData("header.screenshotswidth", "screenshotswidth")]
|
||||||
|
[InlineData("header.subset", "subset")]
|
||||||
[InlineData("header.system", "system")]
|
[InlineData("header.system", "system")]
|
||||||
[InlineData("header.timestamp", "timestamp")]
|
[InlineData("header.timestamp", "timestamp")]
|
||||||
[InlineData("header.type", "type")]
|
[InlineData("header.type", "type")]
|
||||||
@@ -1150,6 +1167,7 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
DatVersion = "datversion",
|
DatVersion = "datversion",
|
||||||
Debug = true,
|
Debug = true,
|
||||||
Description = "description",
|
Description = "description",
|
||||||
|
DirHandling = "noautodir",
|
||||||
Email = "email",
|
Email = "email",
|
||||||
EmulatorVersion = "emulatorversion",
|
EmulatorVersion = "emulatorversion",
|
||||||
FileName = "filename",
|
FileName = "filename",
|
||||||
@@ -1176,6 +1194,7 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
SchemaLocation = "schemalocation",
|
SchemaLocation = "schemalocation",
|
||||||
ScreenshotsHeight = "screenshotsheight",
|
ScreenshotsHeight = "screenshotsheight",
|
||||||
ScreenshotsWidth = "screenshotswidth",
|
ScreenshotsWidth = "screenshotswidth",
|
||||||
|
Subset = "subset",
|
||||||
System = "system",
|
System = "system",
|
||||||
Timestamp = "timestamp",
|
Timestamp = "timestamp",
|
||||||
Type = "type",
|
Type = "type",
|
||||||
@@ -1290,6 +1309,8 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
[InlineData("machine.sampleof", "sampleof")]
|
[InlineData("machine.sampleof", "sampleof")]
|
||||||
[InlineData("machine.savetype", "savetype")]
|
[InlineData("machine.savetype", "savetype")]
|
||||||
[InlineData("machine.score", "score")]
|
[InlineData("machine.score", "score")]
|
||||||
|
[InlineData("machine.serial", "serial")]
|
||||||
|
[InlineData("machine.settype", "dir")]
|
||||||
[InlineData("machine.source", "source")]
|
[InlineData("machine.source", "source")]
|
||||||
[InlineData("machine.sourcefile", "sourcefile")]
|
[InlineData("machine.sourcefile", "sourcefile")]
|
||||||
[InlineData("machine.sourcerom", "sourcerom")]
|
[InlineData("machine.sourcerom", "sourcerom")]
|
||||||
@@ -1360,6 +1381,7 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
SaveType = "savetype",
|
SaveType = "savetype",
|
||||||
Score = "score",
|
Score = "score",
|
||||||
Serial = "serial",
|
Serial = "serial",
|
||||||
|
SetType = "dir",
|
||||||
Source = "source",
|
Source = "source",
|
||||||
SourceFile = "sourcefile",
|
SourceFile = "sourcefile",
|
||||||
SourceRom = "sourcerom",
|
SourceRom = "sourcerom",
|
||||||
@@ -1582,6 +1604,7 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
[InlineData("rom.bitrate", "bitrate")]
|
[InlineData("rom.bitrate", "bitrate")]
|
||||||
[InlineData("rom.bittorrentmagnethash", "btih")]
|
[InlineData("rom.bittorrentmagnethash", "btih")]
|
||||||
[InlineData("rom.btih", "btih")]
|
[InlineData("rom.btih", "btih")]
|
||||||
|
[InlineData("rom.blake3", "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")]
|
||||||
[InlineData("rom.cloth_cover_detection_module_version", "cloth_cover_detection_module_version")]
|
[InlineData("rom.cloth_cover_detection_module_version", "cloth_cover_detection_module_version")]
|
||||||
[InlineData("rom.clothcoverdetectionmoduleversion", "cloth_cover_detection_module_version")]
|
[InlineData("rom.clothcoverdetectionmoduleversion", "cloth_cover_detection_module_version")]
|
||||||
[InlineData("rom.collection-catalog-number", "collection-catalog-number")]
|
[InlineData("rom.collection-catalog-number", "collection-catalog-number")]
|
||||||
@@ -1653,6 +1676,7 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
[InlineData("rom.spamsum", "3::")]
|
[InlineData("rom.spamsum", "3::")]
|
||||||
[InlineData("rom.start", "start")]
|
[InlineData("rom.start", "start")]
|
||||||
[InlineData("rom.status", "good")]
|
[InlineData("rom.status", "good")]
|
||||||
|
[InlineData("rom.status_misc", "status")]
|
||||||
[InlineData("rom.summation", "summation")]
|
[InlineData("rom.summation", "summation")]
|
||||||
[InlineData("rom.ocr", "ocr")]
|
[InlineData("rom.ocr", "ocr")]
|
||||||
[InlineData("rom.tesseractocr", "ocr")]
|
[InlineData("rom.tesseractocr", "ocr")]
|
||||||
@@ -1719,6 +1743,7 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
Bios = "bios",
|
Bios = "bios",
|
||||||
Bitrate = "bitrate",
|
Bitrate = "bitrate",
|
||||||
BitTorrentMagnetHash = "btih",
|
BitTorrentMagnetHash = "btih",
|
||||||
|
BLAKE3 = HashType.BLAKE3.ZeroString,
|
||||||
ClothCoverDetectionModuleVersion = "cloth_cover_detection_module_version",
|
ClothCoverDetectionModuleVersion = "cloth_cover_detection_module_version",
|
||||||
CollectionCatalogNumber = "collection-catalog-number",
|
CollectionCatalogNumber = "collection-catalog-number",
|
||||||
Comment = "comment",
|
Comment = "comment",
|
||||||
@@ -1776,6 +1801,7 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
SpamSum = HashType.SpamSum.ZeroString,
|
SpamSum = HashType.SpamSum.ZeroString,
|
||||||
Start = "start",
|
Start = "start",
|
||||||
Status = ItemStatus.Good,
|
Status = ItemStatus.Good,
|
||||||
|
StatusMisc = "status",
|
||||||
Summation = "summation",
|
Summation = "summation",
|
||||||
TesseractOCR = "ocr",
|
TesseractOCR = "ocr",
|
||||||
TesseractOCRConverted = "ocr_converted",
|
TesseractOCRConverted = "ocr_converted",
|
||||||
@@ -2074,6 +2100,20 @@ namespace SabreTools.Metadata.Filter.Test
|
|||||||
Assert.True(actual);
|
Assert.True(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("en-US")]
|
||||||
|
[InlineData("de-DE")]
|
||||||
|
[InlineData("fr-FR")]
|
||||||
|
public void Matches_VideoRefresh_CurrentCultureIgnored(string culture)
|
||||||
|
{
|
||||||
|
CultureInfo.CurrentCulture = new CultureInfo(culture);
|
||||||
|
var filter = new FilterObject("video.refresh", "123.45", Operation.Equals);
|
||||||
|
Video obj = new Video { Refresh = 123.45 };
|
||||||
|
|
||||||
|
bool actual = filter.Matches(obj);
|
||||||
|
Assert.True(actual);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
<TargetFrameworks>net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -18,10 +19,16 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="coverlet.collector" Version="10.0.0" />
|
<PackageReference Include="coverlet.collector" Version="10.1.0">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.9.0" />
|
||||||
<PackageReference Include="xunit" Version="2.9.3" />
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -309,6 +309,8 @@ namespace SabreTools.Metadata.Filter
|
|||||||
"datversion",
|
"datversion",
|
||||||
"debug",
|
"debug",
|
||||||
"description",
|
"description",
|
||||||
|
"dir",
|
||||||
|
"dirhandling",
|
||||||
"email",
|
"email",
|
||||||
"emulatorversion",
|
"emulatorversion",
|
||||||
"filename",
|
"filename",
|
||||||
@@ -337,6 +339,7 @@ namespace SabreTools.Metadata.Filter
|
|||||||
"screenshotsheight",
|
"screenshotsheight",
|
||||||
"screenshotswidth",
|
"screenshotswidth",
|
||||||
"skipper",
|
"skipper",
|
||||||
|
"subset",
|
||||||
"system",
|
"system",
|
||||||
"timestamp",
|
"timestamp",
|
||||||
"type",
|
"type",
|
||||||
@@ -421,6 +424,8 @@ namespace SabreTools.Metadata.Filter
|
|||||||
"sampleof",
|
"sampleof",
|
||||||
"savetype",
|
"savetype",
|
||||||
"score",
|
"score",
|
||||||
|
"serial",
|
||||||
|
"settype",
|
||||||
"source",
|
"source",
|
||||||
"sourcefile",
|
"sourcefile",
|
||||||
"sourcerom",
|
"sourcerom",
|
||||||
@@ -540,6 +545,7 @@ namespace SabreTools.Metadata.Filter
|
|||||||
"bitrate",
|
"bitrate",
|
||||||
"bittorrentmagnethash",
|
"bittorrentmagnethash",
|
||||||
"btih",
|
"btih",
|
||||||
|
"blake3",
|
||||||
"cloth_cover_detection_module_version",
|
"cloth_cover_detection_module_version",
|
||||||
"clothcoverdetectionmoduleversion",
|
"clothcoverdetectionmoduleversion",
|
||||||
"collection-catalog-number",
|
"collection-catalog-number",
|
||||||
@@ -619,6 +625,7 @@ namespace SabreTools.Metadata.Filter
|
|||||||
"spamsum",
|
"spamsum",
|
||||||
"start",
|
"start",
|
||||||
"status",
|
"status",
|
||||||
|
"status_misc",
|
||||||
"summation",
|
"summation",
|
||||||
"tesseractocr",
|
"tesseractocr",
|
||||||
"tesseractocrconverted",
|
"tesseractocrconverted",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using SabreTools.Data.Extensions;
|
using SabreTools.Data.Extensions;
|
||||||
using SabreTools.Data.Models.Metadata;
|
using SabreTools.Data.Models.Metadata;
|
||||||
@@ -1134,7 +1135,7 @@ namespace SabreTools.Metadata.Filter
|
|||||||
return true;
|
return true;
|
||||||
case "refresh":
|
case "refresh":
|
||||||
case "freq":
|
case "freq":
|
||||||
checkValue = obj.Refresh?.ToString();
|
checkValue = obj.Refresh?.ToString(CultureInfo.InvariantCulture);
|
||||||
return true;
|
return true;
|
||||||
case "rotate":
|
case "rotate":
|
||||||
case "orientation":
|
case "orientation":
|
||||||
@@ -1280,6 +1281,10 @@ namespace SabreTools.Metadata.Filter
|
|||||||
case "description":
|
case "description":
|
||||||
checkValue = obj.Description;
|
checkValue = obj.Description;
|
||||||
return true;
|
return true;
|
||||||
|
case "dir":
|
||||||
|
case "dirhandling":
|
||||||
|
checkValue = obj.DirHandling;
|
||||||
|
return true;
|
||||||
case "email":
|
case "email":
|
||||||
checkValue = obj.Email;
|
checkValue = obj.Email;
|
||||||
return true;
|
return true;
|
||||||
@@ -1365,6 +1370,9 @@ namespace SabreTools.Metadata.Filter
|
|||||||
checkValue = obj.ScreenshotsWidth;
|
checkValue = obj.ScreenshotsWidth;
|
||||||
return true;
|
return true;
|
||||||
// Header.Search is intentionally skipped
|
// Header.Search is intentionally skipped
|
||||||
|
case "subset":
|
||||||
|
checkValue = obj.Subset;
|
||||||
|
return true;
|
||||||
case "system":
|
case "system":
|
||||||
checkValue = obj.System;
|
checkValue = obj.System;
|
||||||
return true;
|
return true;
|
||||||
@@ -1603,6 +1611,9 @@ namespace SabreTools.Metadata.Filter
|
|||||||
case "serial":
|
case "serial":
|
||||||
checkValue = obj.Serial;
|
checkValue = obj.Serial;
|
||||||
return true;
|
return true;
|
||||||
|
case "settype":
|
||||||
|
checkValue = obj.SetType;
|
||||||
|
return true;
|
||||||
case "source":
|
case "source":
|
||||||
checkValue = obj.Source;
|
checkValue = obj.Source;
|
||||||
return true;
|
return true;
|
||||||
@@ -1901,6 +1912,9 @@ namespace SabreTools.Metadata.Filter
|
|||||||
case "bittorrentmagnethash":
|
case "bittorrentmagnethash":
|
||||||
checkValue = obj.BitTorrentMagnetHash;
|
checkValue = obj.BitTorrentMagnetHash;
|
||||||
return true;
|
return true;
|
||||||
|
case "blake3":
|
||||||
|
checkValue = obj.BLAKE3;
|
||||||
|
return true;
|
||||||
case "cloth_cover_detection_module_version":
|
case "cloth_cover_detection_module_version":
|
||||||
case "clothcoverdetectionmoduleversion":
|
case "clothcoverdetectionmoduleversion":
|
||||||
checkValue = obj.ClothCoverDetectionModuleVersion;
|
checkValue = obj.ClothCoverDetectionModuleVersion;
|
||||||
@@ -2086,6 +2100,9 @@ namespace SabreTools.Metadata.Filter
|
|||||||
case "status":
|
case "status":
|
||||||
checkValue = obj.Status?.AsStringValue();
|
checkValue = obj.Status?.AsStringValue();
|
||||||
return true;
|
return true;
|
||||||
|
case "status_misc":
|
||||||
|
checkValue = obj.StatusMisc;
|
||||||
|
return true;
|
||||||
case "summation":
|
case "summation":
|
||||||
checkValue = obj.Summation;
|
checkValue = obj.Summation;
|
||||||
return true;
|
return true;
|
||||||
@@ -2496,7 +2513,7 @@ namespace SabreTools.Metadata.Filter
|
|||||||
return true;
|
return true;
|
||||||
case "refresh":
|
case "refresh":
|
||||||
case "freq":
|
case "freq":
|
||||||
checkValue = obj.Refresh?.ToString();
|
checkValue = obj.Refresh?.ToString(CultureInfo.InvariantCulture);
|
||||||
return true;
|
return true;
|
||||||
case "displaytype":
|
case "displaytype":
|
||||||
case "screen":
|
case "screen":
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Assembly Properties -->
|
<!-- Assembly Properties -->
|
||||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;net11.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Version>3.0.1</Version>
|
<Version>3.3.0</Version>
|
||||||
|
|
||||||
<!-- Package Properties -->
|
<!-- Package Properties -->
|
||||||
<Authors>Matt Nadareski</Authors>
|
<Authors>Matt Nadareski</Authors>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SabreTools.IO" Version="[2.1.0]" />
|
<PackageReference Include="SabreTools.IO" Version="2.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Assembly Properties -->
|
<!-- Assembly Properties -->
|
||||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;net11.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Version>3.0.1</Version>
|
<Version>3.3.0</Version>
|
||||||
|
|
||||||
<!-- Package Properties -->
|
<!-- Package Properties -->
|
||||||
<Authors>Matt Nadareski</Authors>
|
<Authors>Matt Nadareski</Authors>
|
||||||
@@ -37,8 +37,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SabreTools.Hashing" Version="[2.0.0]" />
|
<PackageReference Include="SabreTools.Hashing" Version="2.2.0" />
|
||||||
<PackageReference Include="SabreTools.IO" Version="[2.1.0]" />
|
<PackageReference Include="SabreTools.IO" Version="2.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,17 +1,23 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
<TargetFrameworks>net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="coverlet.collector" Version="10.0.0" />
|
<PackageReference Include="coverlet.collector" Version="10.1.0">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.11.1" />
|
||||||
<PackageReference Include="xunit" Version="2.9.3" />
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Assembly Properties -->
|
<!-- Assembly Properties -->
|
||||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;net11.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Version>3.0.1</Version>
|
<Version>3.3.0</Version>
|
||||||
|
|
||||||
<!-- Package Properties -->
|
<!-- Package Properties -->
|
||||||
<Authors>Matt Nadareski</Authors>
|
<Authors>Matt Nadareski</Authors>
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
xxHash364 = "xxhash364",
|
xxHash364 = "xxhash364",
|
||||||
xxHash3128 = "xxhash3128",
|
xxHash3128 = "xxhash3128",
|
||||||
Region = "region",
|
Region = "region",
|
||||||
@@ -378,6 +379,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
Assert.Equal("sha384", rom.SHA384);
|
Assert.Equal("sha384", rom.SHA384);
|
||||||
Assert.Equal("sha512", rom.SHA512);
|
Assert.Equal("sha512", rom.SHA512);
|
||||||
Assert.Equal("spamsum", rom.SpamSum);
|
Assert.Equal("spamsum", rom.SpamSum);
|
||||||
|
Assert.Equal("blake3", rom.BLAKE3);
|
||||||
Assert.Equal("xxhash364", rom.xxHash364);
|
Assert.Equal("xxhash364", rom.xxHash364);
|
||||||
Assert.Equal("xxhash3128", rom.xxHash3128);
|
Assert.Equal("xxhash3128", rom.xxHash3128);
|
||||||
Assert.Equal("region", rom.Region);
|
Assert.Equal("region", rom.Region);
|
||||||
|
|||||||
@@ -213,6 +213,29 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
Validate(newSpamsum);
|
Validate(newSpamsum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RoundTripBLAKE3Test()
|
||||||
|
{
|
||||||
|
// Get the cross-model serializer
|
||||||
|
var serializer = new Hashfile();
|
||||||
|
|
||||||
|
// Build the data
|
||||||
|
Data.Models.Hashfile.Hashfile hf = Build(HashType.BLAKE3);
|
||||||
|
|
||||||
|
// Serialize to generic model
|
||||||
|
Data.Models.Metadata.MetadataFile? metadata = serializer.Serialize(hf);
|
||||||
|
Assert.NotNull(metadata);
|
||||||
|
|
||||||
|
// Serialize back to original model
|
||||||
|
Data.Models.Hashfile.Hashfile? newHf = serializer.Deserialize(metadata, HashType.BLAKE3);
|
||||||
|
|
||||||
|
// Validate the data
|
||||||
|
Assert.NotNull(newHf);
|
||||||
|
Assert.NotNull(newHf.BLAKE3);
|
||||||
|
var newBlake3 = Assert.Single(newHf.BLAKE3);
|
||||||
|
Validate(newBlake3);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Build model for serialization and deserialization
|
/// Build model for serialization and deserialization
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -236,6 +259,8 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
return new Data.Models.Hashfile.Hashfile { SHA512 = [new Data.Models.Hashfile.SHA512 { Hash = "hash", File = "file" }] };
|
return new Data.Models.Hashfile.Hashfile { SHA512 = [new Data.Models.Hashfile.SHA512 { Hash = "hash", File = "file" }] };
|
||||||
else if (hashType == HashType.SpamSum)
|
else if (hashType == HashType.SpamSum)
|
||||||
return new Data.Models.Hashfile.Hashfile { SpamSum = [new Data.Models.Hashfile.SpamSum { Hash = "hash", File = "file" }] };
|
return new Data.Models.Hashfile.Hashfile { SpamSum = [new Data.Models.Hashfile.SpamSum { Hash = "hash", File = "file" }] };
|
||||||
|
else if (hashType == HashType.BLAKE3)
|
||||||
|
return new Data.Models.Hashfile.Hashfile { BLAKE3 = [new Data.Models.Hashfile.BLAKE3 { Hash = "hash", File = "file" }] };
|
||||||
else
|
else
|
||||||
throw new ArgumentOutOfRangeException(nameof(hashType));
|
throw new ArgumentOutOfRangeException(nameof(hashType));
|
||||||
}
|
}
|
||||||
@@ -329,5 +354,15 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
Assert.Equal("hash", spamsum.Hash);
|
Assert.Equal("hash", spamsum.Hash);
|
||||||
Assert.Equal("file", spamsum.File);
|
Assert.Equal("file", spamsum.File);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validate a BLAKE3
|
||||||
|
/// </summary>
|
||||||
|
private static void Validate(Data.Models.Hashfile.BLAKE3? blake3)
|
||||||
|
{
|
||||||
|
Assert.NotNull(blake3);
|
||||||
|
Assert.Equal("hash", blake3.Hash);
|
||||||
|
Assert.Equal("file", blake3.File);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
ForceMerging = Data.Models.Metadata.MergingFlag.Merged,
|
ForceMerging = Data.Models.Metadata.MergingFlag.Merged,
|
||||||
ForceNodump = Data.Models.Metadata.NodumpFlag.Required,
|
ForceNodump = Data.Models.Metadata.NodumpFlag.Required,
|
||||||
ForcePacking = Data.Models.Metadata.PackingFlag.Zip,
|
ForcePacking = Data.Models.Metadata.PackingFlag.Zip,
|
||||||
|
Dir = "noautodir",
|
||||||
};
|
};
|
||||||
|
|
||||||
var clrmamepro = new Data.Models.Logiqx.ClrMamePro
|
var clrmamepro = new Data.Models.Logiqx.ClrMamePro
|
||||||
@@ -115,6 +116,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
Url = "url",
|
Url = "url",
|
||||||
Comment = "comment",
|
Comment = "comment",
|
||||||
Type = "type",
|
Type = "type",
|
||||||
|
Subset = "subset",
|
||||||
RomVault = romvault,
|
RomVault = romvault,
|
||||||
ClrMamePro = clrmamepro,
|
ClrMamePro = clrmamepro,
|
||||||
RomCenter = romcenter,
|
RomCenter = romcenter,
|
||||||
@@ -171,6 +173,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
SHA384 = "sha384",
|
SHA384 = "sha384",
|
||||||
SHA512 = "sha512",
|
SHA512 = "sha512",
|
||||||
SpamSum = "spamsum",
|
SpamSum = "spamsum",
|
||||||
|
BLAKE3 = "blake3",
|
||||||
xxHash364 = "xxhash364",
|
xxHash364 = "xxhash364",
|
||||||
xxHash3128 = "xxhash3128",
|
xxHash3128 = "xxhash3128",
|
||||||
Merge = "merge",
|
Merge = "merge",
|
||||||
@@ -252,6 +255,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
gameBase.Id = "id";
|
gameBase.Id = "id";
|
||||||
gameBase.CloneOfId = "cloneofid";
|
gameBase.CloneOfId = "cloneofid";
|
||||||
gameBase.Runnable = Data.Models.Metadata.Runnable.Yes;
|
gameBase.Runnable = Data.Models.Metadata.Runnable.Yes;
|
||||||
|
gameBase.SetType = "dir";
|
||||||
gameBase.Comment = ["comment"];
|
gameBase.Comment = ["comment"];
|
||||||
gameBase.Description = "description";
|
gameBase.Description = "description";
|
||||||
gameBase.Year = "year";
|
gameBase.Year = "year";
|
||||||
@@ -314,6 +318,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
Assert.Equal("url", header.Url);
|
Assert.Equal("url", header.Url);
|
||||||
Assert.Equal("comment", header.Comment);
|
Assert.Equal("comment", header.Comment);
|
||||||
Assert.Equal("type", header.Type);
|
Assert.Equal("type", header.Type);
|
||||||
|
Assert.Equal("subset", header.Subset);
|
||||||
Validate(header.RomVault);
|
Validate(header.RomVault);
|
||||||
Validate(header.ClrMamePro);
|
Validate(header.ClrMamePro);
|
||||||
Validate(header.RomCenter);
|
Validate(header.RomCenter);
|
||||||
@@ -329,6 +334,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
Assert.Equal(Data.Models.Metadata.MergingFlag.Merged, rv.ForceMerging);
|
Assert.Equal(Data.Models.Metadata.MergingFlag.Merged, rv.ForceMerging);
|
||||||
Assert.Equal(Data.Models.Metadata.NodumpFlag.Required, rv.ForceNodump);
|
Assert.Equal(Data.Models.Metadata.NodumpFlag.Required, rv.ForceNodump);
|
||||||
Assert.Equal(Data.Models.Metadata.PackingFlag.Zip, rv.ForcePacking);
|
Assert.Equal(Data.Models.Metadata.PackingFlag.Zip, rv.ForcePacking);
|
||||||
|
Assert.Equal("noautodir", rv.Dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -380,6 +386,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
Assert.Equal("id", gb.Id);
|
Assert.Equal("id", gb.Id);
|
||||||
Assert.Equal("cloneofid", gb.CloneOfId);
|
Assert.Equal("cloneofid", gb.CloneOfId);
|
||||||
Assert.Equal(Data.Models.Metadata.Runnable.Yes, gb.Runnable);
|
Assert.Equal(Data.Models.Metadata.Runnable.Yes, gb.Runnable);
|
||||||
|
Assert.Equal("dir", gb.SetType);
|
||||||
|
|
||||||
Assert.NotNull(gb.Comment);
|
Assert.NotNull(gb.Comment);
|
||||||
string comment = Assert.Single(gb.Comment);
|
string comment = Assert.Single(gb.Comment);
|
||||||
@@ -504,6 +511,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
Assert.Equal("sha384", rom.SHA384);
|
Assert.Equal("sha384", rom.SHA384);
|
||||||
Assert.Equal("sha512", rom.SHA512);
|
Assert.Equal("sha512", rom.SHA512);
|
||||||
Assert.Equal("spamsum", rom.SpamSum);
|
Assert.Equal("spamsum", rom.SpamSum);
|
||||||
|
Assert.Equal("blake3", rom.BLAKE3);
|
||||||
Assert.Equal("xxhash364", rom.xxHash364);
|
Assert.Equal("xxhash364", rom.xxHash364);
|
||||||
Assert.Equal("xxhash3128", rom.xxHash3128);
|
Assert.Equal("xxhash3128", rom.xxHash3128);
|
||||||
Assert.Equal("merge", rom.Merge);
|
Assert.Equal("merge", rom.Merge);
|
||||||
|
|||||||
@@ -40,11 +40,19 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
Content = "content",
|
Content = "content",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var standalone_rom = new Data.Models.OpenMSX.Rom
|
||||||
|
{
|
||||||
|
SHA1 = "sha1",
|
||||||
|
Type = "type",
|
||||||
|
Status = "status",
|
||||||
|
Remark = "remark",
|
||||||
|
};
|
||||||
|
|
||||||
var rom = new Data.Models.OpenMSX.Rom
|
var rom = new Data.Models.OpenMSX.Rom
|
||||||
{
|
{
|
||||||
Start = "start",
|
Start = "start",
|
||||||
Type = "type",
|
Type = "type",
|
||||||
Hash = "hash",
|
SHA1 = "hash",
|
||||||
Remark = "remark",
|
Remark = "remark",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -59,7 +67,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
{
|
{
|
||||||
Start = "start",
|
Start = "start",
|
||||||
Type = "type",
|
Type = "type",
|
||||||
Hash = "hash",
|
SHA1 = "hash",
|
||||||
Remark = "remark",
|
Remark = "remark",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -74,7 +82,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
{
|
{
|
||||||
Start = "start",
|
Start = "start",
|
||||||
Type = "type",
|
Type = "type",
|
||||||
Hash = "hash",
|
SHA1 = "hash",
|
||||||
Remark = "remark",
|
Remark = "remark",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -94,6 +102,7 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
Year = "year",
|
Year = "year",
|
||||||
Country = "country",
|
Country = "country",
|
||||||
Dump = [dump_rom, dump_megarom, dump_sccpluscart],
|
Dump = [dump_rom, dump_megarom, dump_sccpluscart],
|
||||||
|
Rom = [standalone_rom],
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Data.Models.OpenMSX.SoftwareDb
|
return new Data.Models.OpenMSX.SoftwareDb
|
||||||
@@ -122,6 +131,10 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
{
|
{
|
||||||
Validate(dump);
|
Validate(dump);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assert.NotNull(software.Rom);
|
||||||
|
var rom = Assert.Single(software.Rom);
|
||||||
|
ValidateStandalone(rom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -154,7 +167,19 @@ namespace SabreTools.Serialization.CrossModel.Test
|
|||||||
Assert.NotNull(rombase);
|
Assert.NotNull(rombase);
|
||||||
Assert.Equal("start", rombase.Start);
|
Assert.Equal("start", rombase.Start);
|
||||||
Assert.Equal("type", rombase.Type);
|
Assert.Equal("type", rombase.Type);
|
||||||
Assert.Equal("hash", rombase.Hash);
|
Assert.Equal("hash", rombase.SHA1);
|
||||||
|
Assert.Equal("remark", rombase.Remark);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validate a RomBase
|
||||||
|
/// </summary>
|
||||||
|
private static void ValidateStandalone(Data.Models.OpenMSX.RomBase? rombase)
|
||||||
|
{
|
||||||
|
Assert.NotNull(rombase);
|
||||||
|
Assert.Equal("sha1", rombase.SHA1);
|
||||||
|
Assert.Equal("type", rombase.Type);
|
||||||
|
Assert.Equal("status", rombase.Status);
|
||||||
Assert.Equal("remark", rombase.Remark);
|
Assert.Equal("remark", rombase.Remark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,25 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
<TargetFrameworks>net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="coverlet.collector" Version="10.0.0" />
|
<PackageReference Include="coverlet.collector" Version="10.1.0">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PackageReference Include="SabreTools.Hashing" Version="[2.0.0]" />
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.11.1" />
|
||||||
|
<PackageReference Include="SabreTools.Hashing" Version="2.2.0" />
|
||||||
<PackageReference Include="xunit" Version="2.9.3" />
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -290,6 +290,7 @@ namespace SabreTools.Serialization.CrossModel
|
|||||||
SHA384 = item.SHA384,
|
SHA384 = item.SHA384,
|
||||||
SHA512 = item.SHA512,
|
SHA512 = item.SHA512,
|
||||||
SpamSum = item.SpamSum,
|
SpamSum = item.SpamSum,
|
||||||
|
BLAKE3 = item.BLAKE3,
|
||||||
xxHash364 = item.xxHash364,
|
xxHash364 = item.xxHash364,
|
||||||
xxHash3128 = item.xxHash3128,
|
xxHash3128 = item.xxHash3128,
|
||||||
Merge = item.Merge,
|
Merge = item.Merge,
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ namespace SabreTools.Serialization.CrossModel
|
|||||||
SHA384 = item.SHA384,
|
SHA384 = item.SHA384,
|
||||||
SHA512 = item.SHA512,
|
SHA512 = item.SHA512,
|
||||||
SpamSum = item.SpamSum,
|
SpamSum = item.SpamSum,
|
||||||
|
BLAKE3 = item.BLAKE3,
|
||||||
xxHash364 = item.xxHash364,
|
xxHash364 = item.xxHash364,
|
||||||
xxHash3128 = item.xxHash3128,
|
xxHash3128 = item.xxHash3128,
|
||||||
Merge = item.Merge,
|
Merge = item.Merge,
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ namespace SabreTools.Serialization.CrossModel
|
|||||||
var sha384s = new List<SHA384>();
|
var sha384s = new List<SHA384>();
|
||||||
var sha512s = new List<SHA512>();
|
var sha512s = new List<SHA512>();
|
||||||
var spamsums = new List<SpamSum>();
|
var spamsums = new List<SpamSum>();
|
||||||
|
var blake3s = new List<BLAKE3>();
|
||||||
|
|
||||||
foreach (var hashfile in hashfiles)
|
foreach (var hashfile in hashfiles)
|
||||||
{
|
{
|
||||||
@@ -61,6 +62,8 @@ namespace SabreTools.Serialization.CrossModel
|
|||||||
sha512s.AddRange(hashfile.SHA512);
|
sha512s.AddRange(hashfile.SHA512);
|
||||||
if (hashfile.SpamSum is not null && hashfile.SpamSum.Length > 0)
|
if (hashfile.SpamSum is not null && hashfile.SpamSum.Length > 0)
|
||||||
spamsums.AddRange(hashfile.SpamSum);
|
spamsums.AddRange(hashfile.SpamSum);
|
||||||
|
if (hashfile.BLAKE3 is not null && hashfile.BLAKE3.Length > 0)
|
||||||
|
blake3s.AddRange(hashfile.BLAKE3);
|
||||||
}
|
}
|
||||||
|
|
||||||
var hashfileItem = new Data.Models.Hashfile.Hashfile();
|
var hashfileItem = new Data.Models.Hashfile.Hashfile();
|
||||||
@@ -87,6 +90,8 @@ namespace SabreTools.Serialization.CrossModel
|
|||||||
hashfileItem.SHA512 = [.. sha512s];
|
hashfileItem.SHA512 = [.. sha512s];
|
||||||
if (spamsums.Count > 0)
|
if (spamsums.Count > 0)
|
||||||
hashfileItem.SpamSum = [.. spamsums];
|
hashfileItem.SpamSum = [.. spamsums];
|
||||||
|
if (blake3s.Count > 0)
|
||||||
|
hashfileItem.BLAKE3 = [.. blake3s];
|
||||||
|
|
||||||
return hashfileItem;
|
return hashfileItem;
|
||||||
}
|
}
|
||||||
@@ -135,6 +140,14 @@ namespace SabreTools.Serialization.CrossModel
|
|||||||
SpamSum = hash == HashType.SpamSum
|
SpamSum = hash == HashType.SpamSum
|
||||||
? Array.ConvertAll(roms, ConvertToSpamSum)
|
? Array.ConvertAll(roms, ConvertToSpamSum)
|
||||||
: null,
|
: null,
|
||||||
|
#if NET7_0_OR_GREATER
|
||||||
|
BLAKE3 = hash == HashType.BLAKE3
|
||||||
|
#else
|
||||||
|
// HACK because BLAKE3 is not supported below .NET 7
|
||||||
|
BLAKE3 = hash == HashType.CRC1_ZERO
|
||||||
|
#endif
|
||||||
|
? Array.ConvertAll(roms, ConvertToBLAKE3)
|
||||||
|
: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,5 +293,18 @@ namespace SabreTools.Serialization.CrossModel
|
|||||||
};
|
};
|
||||||
return spamsum;
|
return spamsum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert from <see cref="Models.Metadata.Rom"/> to <see cref="BLAKE3"/>
|
||||||
|
/// </summary>
|
||||||
|
private static BLAKE3 ConvertToBLAKE3(Data.Models.Metadata.Rom item)
|
||||||
|
{
|
||||||
|
var spamsum = new BLAKE3
|
||||||
|
{
|
||||||
|
Hash = item.BLAKE3,
|
||||||
|
File = item.Name,
|
||||||
|
};
|
||||||
|
return spamsum;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user