Compare commits

...

23 Commits
1.7.1 ... 1.8.0

Author SHA1 Message Date
Matt Nadareski
c6832a5c2d Bump version 2025-10-22 08:58:57 -04:00
Matt Nadareski
77d922a9bc Minor collection cleanup in tests 2025-10-22 08:50:18 -04:00
Matt Nadareski
7b590e9bba Separate out sections to new files for maintainability 2025-10-22 08:41:57 -04:00
Matt Nadareski
0968bfe786 Ensure adding IDs only after 2025-10-21 18:41:53 -04:00
Matt Nadareski
5acb6ee128 Minor fixes 2025-10-21 18:36:15 -04:00
Matt Nadareski
5dc9ef27ef Update gitignore 2025-10-21 18:32:30 -04:00
Matt Nadareski
d5ccc0c65c Simplify downloader creation 2025-10-21 18:29:04 -04:00
Matt Nadareski
0ef9c6f87a Add console writes on failure cases 2025-10-21 18:11:20 -04:00
Matt Nadareski
638630ccab Disallow some fields from being null 2025-10-21 17:44:15 -04:00
Matt Nadareski
6c3afd25d4 Formatting pass 2025-10-21 17:33:12 -04:00
Matt Nadareski
02572c75fc Make timeout configurable by implementer 2025-10-21 17:30:31 -04:00
Matt Nadareski
cb5b42166d Reduce tab-to-space size to 2 2025-10-16 08:02:09 -04:00
Matt Nadareski
97ea30228e Bump version 2025-10-12 09:00:39 -04:00
Deterous
675af1a619 Add XboxOne/SX TitleID (#12) 2025-10-12 08:56:09 -04:00
Matt Nadareski
28c3f54cc5 Update test packages 2025-10-07 16:21:47 -04:00
Matt Nadareski
51486950fa Bump version 2025-09-24 13:35:03 -04:00
Matt Nadareski
1b1ba94247 Remove reliance on Models library 2025-09-24 13:33:42 -04:00
Matt Nadareski
c4345d0c34 Bump version 2025-09-22 18:00:58 -04:00
Matt Nadareski
b88b877672 Update Nuget packages 2025-09-22 17:58:12 -04:00
Matt Nadareski
f0c5375ac5 There 2025-09-10 21:53:06 -04:00
Matt Nadareski
1f4cca7fa0 Bump version 2025-09-05 10:14:28 -04:00
Matt Nadareski
5161913d96 Update Nuget packages 2025-09-05 09:45:00 -04:00
Deterous
c10b21a485 Add Polymega system (#11)
* Add Polymega system

* Polymega detected by windows
2025-08-31 01:22:51 -04:00
31 changed files with 1082 additions and 849 deletions

296
.gitignore vendored
View File

@@ -1,15 +1,7 @@
*.swp
*.*~
project.lock.json
.DS_Store
*.pyc
nupkg/
# Visual Studio Code
.vscode
# Rider
.idea
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
@@ -17,6 +9,9 @@ nupkg/
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
@@ -24,15 +19,280 @@ nupkg/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
msbuild.log
msbuild.err
msbuild.wrn
[Ll]og/
# Visual Studio 2015
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

22
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,22 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/RedumpTool/bin/Debug/net9.0/RedumpTool.dll",
"args": [],
"cwd": "${workspaceFolder}/RedumpTool",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false,
"justMyCode": false
}
]
}

24
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,24 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "shell",
"args": [
"build",
// Ask dotnet build to generate full paths for file names.
"/property:GenerateFullPaths=true",
// Do not generate summary otherwise it leads to duplicate errors in Problems panel
"/consoleloggerparameters:NoSummary"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
}
]
}

7
LICENSE Normal file
View File

@@ -0,0 +1,7 @@
Copyright (c) 2018-2025 Matt Nadareski
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -12,6 +12,7 @@ namespace RedumpTool
// Show help if nothing is input
if (args == null || args.Length == 0)
{
Console.WriteLine("At least one argument is required");
ShowHelp();
return;
}
@@ -20,6 +21,7 @@ namespace RedumpTool
Feature feature = DeriveFeature(args[0]);
if (feature == Feature.NONE)
{
Console.WriteLine("The feature could not be derived");
ShowHelp();
return;
}
@@ -28,6 +30,7 @@ namespace RedumpTool
var downloader = CreateDownloader(feature, args);
if (downloader == null)
{
Console.WriteLine("A downloader could not be created from the inputs");
ShowHelp();
return;
}
@@ -45,6 +48,7 @@ namespace RedumpTool
}
else if (downloaderResult.Count == 0 && downloader.Feature != Feature.Packs)
{
Console.WriteLine("No results were found");
ShowHelp();
}
}
@@ -76,20 +80,8 @@ namespace RedumpTool
/// <returns>Initialized Downloader on success, null otherwise</returns>
private static Downloader? CreateDownloader(Feature feature, string[] args)
{
// Set temporary internal variables
string? outDir = null;
string? username = null;
string? password = null;
int minimumId = -1;
int maximumId = -1;
string? queryString = null;
bool useSubfolders = false;
bool onlyNew = false;
bool onlyList = false;
bool noSlash = false;
bool force = false;
// Now loop through all of the arguments
// Loop through all of the arguments
var downloader = new Downloader() { Feature = feature };
try
{
for (int i = 1; i < args.Length; i++)
@@ -99,69 +91,73 @@ namespace RedumpTool
// Output directory
case "-o":
case "--output":
outDir = args[++i].Trim('"');
downloader.OutDir = args[++i].Trim('"');
break;
// Username
case "-u":
case "--username":
username = args[++i];
downloader.Username = args[++i];
break;
// Password
case "-p":
case "--password":
password = args[++i];
downloader.Password = args[++i];
break;
// Minimum Redump ID
case "-min":
case "--minimum":
if (!int.TryParse(args[++i], out minimumId))
if (!int.TryParse(args[++i], out int minimumId))
minimumId = -1;
downloader.MinimumId = minimumId;
break;
// Maximum Redump ID
case "-max":
case "--maximum":
if (!int.TryParse(args[++i], out maximumId))
if (!int.TryParse(args[++i], out int maximumId))
maximumId = -1;
downloader.MaximumId = maximumId;
break;
// Quicksearch text
case "-q":
case "--query":
queryString = args[++i];
downloader.QueryString = args[++i];
break;
// Packs subfolders
case "-s":
case "--subfolders":
useSubfolders = true;
downloader.UseSubfolders = true;
break;
// Use last modified
case "-n":
case "--onlynew":
onlyNew = true;
downloader.OnlyNew = true;
break;
// List instead of download
case "-l":
case "--list":
onlyList = true;
downloader.OnlyList = true;
break;
// Don't filter forward slashes from queries
case "-ns":
case "--noslash":
noSlash = true;
downloader.NoSlash = true;
break;
// Force continuation
case "-f":
case "--force":
force = true;
downloader.Force = true;
break;
// Everything else
@@ -178,18 +174,18 @@ namespace RedumpTool
}
// Output directory validation
if (!onlyList && string.IsNullOrEmpty(outDir))
if (!downloader.OnlyList && string.IsNullOrEmpty(downloader.OutDir))
{
Console.WriteLine("No output directory set!");
return null;
}
else if (!onlyList && !string.IsNullOrEmpty(outDir))
else if (!downloader.OnlyList && !string.IsNullOrEmpty(downloader.OutDir))
{
// Create the output directory, if it doesn't exist
try
{
if (!Directory.Exists(outDir))
Directory.CreateDirectory(outDir);
if (!Directory.Exists(downloader.OutDir))
Directory.CreateDirectory(downloader.OutDir!);
}
catch (Exception ex)
{
@@ -199,40 +195,25 @@ namespace RedumpTool
}
// Range verification
if (feature == Feature.Site && !onlyNew && (minimumId < 0 || maximumId < 0))
if (feature == Feature.Site && !downloader.OnlyNew && (downloader.MinimumId < 0 || downloader.MaximumId < 0))
{
Console.WriteLine("Please enter a valid range of Redump IDs");
return null;
}
else if (feature == Feature.WIP && !onlyNew && (minimumId < 0 || maximumId < 0))
else if (feature == Feature.WIP && !downloader.OnlyNew && (downloader.MinimumId < 0 || downloader.MaximumId < 0))
{
Console.WriteLine("Please enter a valid range of WIP IDs");
return null;
}
// Query verification (and cleanup)
if (feature == Feature.Quicksearch && string.IsNullOrEmpty(queryString))
if (feature == Feature.Quicksearch && string.IsNullOrEmpty(downloader.QueryString))
{
Console.WriteLine("Please enter a query for searching");
return null;
}
// Create and return the downloader
var downloader = new Downloader()
{
Feature = feature,
MinimumId = minimumId,
MaximumId = maximumId,
QueryString = queryString,
OutDir = outDir,
UseSubfolders = useSubfolders,
OnlyNew = onlyNew,
OnlyList = onlyList,
Force = force,
NoSlash = noSlash,
Username = username,
Password = password,
};
// Return the downloader
return downloader;
}

View File

@@ -9,7 +9,7 @@
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.7.1</Version>
<Version>1.8.0</Version>
</PropertyGroup>
<!-- Support All Frameworks -->
@@ -30,4 +30,4 @@
<ProjectReference Include="..\SabreTools.RedumpLib\SabreTools.RedumpLib.csproj" />
</ItemGroup>
</Project>
</Project>

View File

@@ -26,102 +26,6 @@ namespace SabreTools.RedumpLib.Test
Assert.Equal(expectNull, si == null);
}
[Fact]
public void EnsureAllSections_Null_Filled()
{
SubmissionInfo? si = null;
var actual = Builder.EnsureAllSections(si);
Assert.NotNull(actual);
Assert.NotNull(actual.CommonDiscInfo);
Assert.NotNull(actual.CommonDiscInfo.CommentsSpecialFields);
Assert.NotNull(actual.CommonDiscInfo.ContentsSpecialFields);
Assert.NotNull(actual.VersionAndEditions);
Assert.NotNull(actual.EDC);
Assert.NotNull(actual.ParentCloneRelationship);
Assert.NotNull(actual.Extras);
Assert.NotNull(actual.CopyProtection);
Assert.NotNull(actual.DumpersAndStatus);
Assert.NotNull(actual.TracksAndWriteOffsets);
Assert.NotNull(actual.SizeAndChecksums);
Assert.NotNull(actual.DumpingInfo);
Assert.NotNull(actual.Artifacts);
}
[Fact]
public void EnsureAllSections_Empty_Filled()
{
SubmissionInfo? si = new SubmissionInfo
{
CommonDiscInfo = null,
VersionAndEditions = null,
EDC = null,
ParentCloneRelationship = null,
Extras = null,
CopyProtection = null,
DumpersAndStatus = null,
TracksAndWriteOffsets = null,
SizeAndChecksums = null,
DumpingInfo = null,
Artifacts = null,
};
var actual = Builder.EnsureAllSections(si);
Assert.NotNull(actual);
Assert.NotNull(actual.CommonDiscInfo);
Assert.NotNull(actual.CommonDiscInfo.CommentsSpecialFields);
Assert.NotNull(actual.CommonDiscInfo.ContentsSpecialFields);
Assert.NotNull(actual.VersionAndEditions);
Assert.NotNull(actual.EDC);
Assert.NotNull(actual.ParentCloneRelationship);
Assert.NotNull(actual.Extras);
Assert.NotNull(actual.CopyProtection);
Assert.NotNull(actual.DumpersAndStatus);
Assert.NotNull(actual.TracksAndWriteOffsets);
Assert.NotNull(actual.SizeAndChecksums);
Assert.NotNull(actual.DumpingInfo);
Assert.NotNull(actual.Artifacts);
}
[Fact]
public void EnsureAllSections_Filled_Filled()
{
SubmissionInfo? si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection
{
CommentsSpecialFields = [],
ContentsSpecialFields = [],
},
VersionAndEditions = new VersionAndEditionsSection(),
EDC = new EDCSection(),
ParentCloneRelationship = new ParentCloneRelationshipSection(),
Extras = new ExtrasSection(),
CopyProtection = new CopyProtectionSection(),
DumpersAndStatus = new DumpersAndStatusSection(),
TracksAndWriteOffsets = new TracksAndWriteOffsetsSection(),
SizeAndChecksums = new SizeAndChecksumsSection(),
DumpingInfo = new DumpingInfoSection(),
Artifacts = [],
};
var actual = Builder.EnsureAllSections(si);
Assert.NotNull(actual);
Assert.NotNull(actual.CommonDiscInfo);
Assert.NotNull(actual.CommonDiscInfo.CommentsSpecialFields);
Assert.NotNull(actual.CommonDiscInfo.ContentsSpecialFields);
Assert.NotNull(actual.VersionAndEditions);
Assert.NotNull(actual.EDC);
Assert.NotNull(actual.ParentCloneRelationship);
Assert.NotNull(actual.Extras);
Assert.NotNull(actual.CopyProtection);
Assert.NotNull(actual.DumpersAndStatus);
Assert.NotNull(actual.TracksAndWriteOffsets);
Assert.NotNull(actual.SizeAndChecksums);
Assert.NotNull(actual.DumpingInfo);
Assert.NotNull(actual.Artifacts);
}
[Fact]
public void InjectSubmissionInformation_BothNull_Null()
{
@@ -188,4 +92,4 @@ namespace SabreTools.RedumpLib.Test
Assert.Equal(expected, actual);
}
}
}
}

View File

@@ -720,6 +720,7 @@ namespace SabreTools.RedumpLib.Test.Data
SiteCode.Series,
SiteCode.SSHash,
SiteCode.SSVersion,
SiteCode.TitleID,
SiteCode.UniversalHash,
SiteCode.VCD,
SiteCode.VFCCode,
@@ -1187,6 +1188,7 @@ namespace SabreTools.RedumpLib.Test.Data
[RedumpSystem.NintendoWiiU] = SystemCategory.DiscBasedConsole,
[RedumpSystem.Panasonic3DOInteractiveMultiplayer] = SystemCategory.DiscBasedConsole,
[RedumpSystem.PhilipsCDi] = SystemCategory.DiscBasedConsole,
[RedumpSystem.PlaymajiPolymega] = SystemCategory.DiscBasedConsole,
[RedumpSystem.PioneerLaserActive] = SystemCategory.DiscBasedConsole,
[RedumpSystem.SegaDreamcast] = SystemCategory.DiscBasedConsole,
[RedumpSystem.SegaMegaCDSegaCD] = SystemCategory.DiscBasedConsole,
@@ -1537,6 +1539,7 @@ namespace SabreTools.RedumpLib.Test.Data
RedumpSystem.NECPCEngineCDTurboGrafxCD,
RedumpSystem.NECPCFXPCFXGA,
RedumpSystem.NintendoSonySuperNESCDROMSystem,
RedumpSystem.PlaymajiPolymega,
RedumpSystem.SegaDreamcast,
RedumpSystem.SegaMegaCDSegaCD,
RedumpSystem.SegaSaturn,

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.Data.Sections;
using Xunit;
namespace SabreTools.RedumpLib.Test
@@ -556,7 +557,7 @@ namespace SabreTools.RedumpLib.Test
string? expected = "BD-ROM-66";
MediaType? mediaType = MediaType.BluRay;
string? picIdentifier = Models.PIC.Constants.DiscTypeIdentifierROMUltra;
string? picIdentifier = "BDU";
long? size = null;
long? layerbreak = 12345;
long? layerbreak2 = null;
@@ -622,7 +623,7 @@ namespace SabreTools.RedumpLib.Test
string? expected = "BD-ROM-33";
MediaType? mediaType = MediaType.BluRay;
string? picIdentifier = Models.PIC.Constants.DiscTypeIdentifierROMUltra;
string? picIdentifier = "BDU";
long? size = null;
long? layerbreak = null;
long? layerbreak2 = null;
@@ -874,4 +875,4 @@ namespace SabreTools.RedumpLib.Test
#endregion
}
}
}

View File

@@ -24,11 +24,11 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeCoverage" Version="17.14.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Microsoft.CodeCoverage" Version="18.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
<PackageReference Include="xunit.analyzers" Version="1.23.0" />
<PackageReference Include="xunit.analyzers" Version="1.24.0" />
<PackageReference Include="xunit.assert" Version="2.9.3" />
<PackageReference Include="xunit.core" Version="2.9.3" />
<PackageReference Include="xunit.extensibility.core" Version="2.9.3" />
@@ -37,7 +37,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3">
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.Data.Sections;
using Xunit;
namespace SabreTools.RedumpLib.Test
@@ -57,8 +58,8 @@ namespace SabreTools.RedumpLib.Test
DiscTitle = "Install Disc",
Category = DiscCategory.Games,
Region = Region.World,
Languages = new Language?[] { Language.English, Language.Spanish, Language.French },
LanguageSelection = new LanguageSelection?[] { LanguageSelection.BiosSettings },
Languages = [Language.English, Language.Spanish, Language.French],
LanguageSelection = [LanguageSelection.BiosSettings],
Serial = "Disc Serial",
Layer0MasteringRing = "L0 Mastering Ring",
Layer0MasteringSID = "L0 Mastering SID",
@@ -96,7 +97,7 @@ namespace SabreTools.RedumpLib.Test
{
Version = "Original",
VersionDatfile = "Alt",
CommonEditions = new string[] { "Taikenban" },
CommonEditions = ["Taikenban"],
OtherEditions = "Rerelease",
},
@@ -134,7 +135,7 @@ namespace SabreTools.RedumpLib.Test
DumpersAndStatus = new DumpersAndStatusSection()
{
Status = DumpStatus.TwoOrMoreGreen,
Dumpers = new string[] { "Dumper1", "Dumper2" },
Dumpers = ["Dumper1", "Dumper2"],
OtherDumpers = "Dumper3",
},
@@ -142,7 +143,7 @@ namespace SabreTools.RedumpLib.Test
{
ClrMameProData = "Datfile",
Cuesheet = "Cuesheet",
CommonWriteOffsets = new int[] { 0, 12, -12 },
CommonWriteOffsets = [0, 12, -12],
OtherWriteOffsets = "-2",
},

View File

@@ -1,4 +1,5 @@
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.Data.Sections;
using Xunit;
namespace SabreTools.RedumpLib.Test
@@ -28,7 +29,7 @@ namespace SabreTools.RedumpLib.Test
SubmissionInfo si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = DiscType.CD },
SizeAndChecksums = null,
SizeAndChecksums = new(),
};
Validator.NormalizeDiscType(si);
@@ -143,7 +144,7 @@ namespace SabreTools.RedumpLib.Test
SizeAndChecksums = new SizeAndChecksumsSection
{
Layerbreak = 12345,
PICIdentifier = Models.PIC.Constants.DiscTypeIdentifierROMUltra,
PICIdentifier = "BDU",
},
};
@@ -213,7 +214,7 @@ namespace SabreTools.RedumpLib.Test
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection
{
PICIdentifier = Models.PIC.Constants.DiscTypeIdentifierROMUltra,
PICIdentifier = "BDU",
},
};
@@ -301,4 +302,4 @@ namespace SabreTools.RedumpLib.Test
Assert.Equal(expected, si.CommonDiscInfo.Media);
}
}
}
}

View File

@@ -10,6 +10,7 @@ using System.Threading.Tasks;
using System.Xml;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.Data.Sections;
using SabreTools.RedumpLib.Web;
namespace SabreTools.RedumpLib
@@ -253,8 +254,6 @@ namespace SabreTools.RedumpLib
/// <param name="includeAllData">True to include all pullable information, false to do bare minimum</param>
public async static Task<bool> FillFromId(RedumpClient rc, SubmissionInfo info, int id, bool includeAllData)
{
// Ensure that required sections exist
info = EnsureAllSections(info);
var discData = await rc.DownloadSingleSiteID(id);
if (string.IsNullOrEmpty(discData))
return false;
@@ -605,35 +604,6 @@ namespace SabreTools.RedumpLib
return true;
}
/// <summary>
/// Ensure all required sections in a submission info exist
/// </summary>
/// <param name="info">SubmissionInfo object to verify</param>
public static SubmissionInfo EnsureAllSections(SubmissionInfo? info)
{
// If there's no info, create one
info ??= new SubmissionInfo();
// Ensure all sections
info.CommonDiscInfo ??= new CommonDiscInfoSection();
info.VersionAndEditions ??= new VersionAndEditionsSection();
info.EDC ??= new EDCSection();
info.ParentCloneRelationship ??= new ParentCloneRelationshipSection();
info.Extras ??= new ExtrasSection();
info.CopyProtection ??= new CopyProtectionSection();
info.DumpersAndStatus ??= new DumpersAndStatusSection();
info.TracksAndWriteOffsets ??= new TracksAndWriteOffsetsSection();
info.SizeAndChecksums ??= new SizeAndChecksumsSection();
info.DumpingInfo ??= new DumpingInfoSection();
info.Artifacts ??= [];
// Ensure special dictionaries
info.CommonDiscInfo.CommentsSpecialFields ??= [];
info.CommonDiscInfo.ContentsSpecialFields ??= [];
return info;
}
/// <summary>
/// Inject information from a seed SubmissionInfo into the existing one
/// </summary>
@@ -645,62 +615,52 @@ namespace SabreTools.RedumpLib
if (seed == null)
return info;
// Ensure that required sections exist
info = EnsureAllSections(info);
// Otherwise, inject information as necessary
if (info.CommonDiscInfo != null && seed.CommonDiscInfo != null)
{
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Title)) info.CommonDiscInfo.Title = seed.CommonDiscInfo.Title;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.ForeignTitleNonLatin)) info.CommonDiscInfo.ForeignTitleNonLatin = seed.CommonDiscInfo.ForeignTitleNonLatin;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.DiscNumberLetter)) info.CommonDiscInfo.DiscNumberLetter = seed.CommonDiscInfo.DiscNumberLetter;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.DiscTitle)) info.CommonDiscInfo.DiscTitle = seed.CommonDiscInfo.DiscTitle;
if (seed.CommonDiscInfo.Category != null) info.CommonDiscInfo.Category = seed.CommonDiscInfo.Category;
if (seed.CommonDiscInfo.Region != null) info.CommonDiscInfo.Region = seed.CommonDiscInfo.Region;
if (seed.CommonDiscInfo.Languages != null) info.CommonDiscInfo.Languages = seed.CommonDiscInfo.Languages;
if (seed.CommonDiscInfo.LanguageSelection != null) info.CommonDiscInfo.LanguageSelection = seed.CommonDiscInfo.LanguageSelection;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Serial)) info.CommonDiscInfo.Serial = seed.CommonDiscInfo.Serial;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Barcode)) info.CommonDiscInfo.Barcode = seed.CommonDiscInfo.Barcode;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Comments)) info.CommonDiscInfo.Comments = seed.CommonDiscInfo.Comments;
if (seed.CommonDiscInfo.CommentsSpecialFields != null) info.CommonDiscInfo.CommentsSpecialFields = seed.CommonDiscInfo.CommentsSpecialFields;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Contents)) info.CommonDiscInfo.Contents = seed.CommonDiscInfo.Contents;
if (seed.CommonDiscInfo.ContentsSpecialFields != null) info.CommonDiscInfo.ContentsSpecialFields = seed.CommonDiscInfo.ContentsSpecialFields;
info ??= new SubmissionInfo();
// Info that always overwrites
info.CommonDiscInfo.Layer0MasteringRing = seed.CommonDiscInfo.Layer0MasteringRing;
info.CommonDiscInfo.Layer0MasteringSID = seed.CommonDiscInfo.Layer0MasteringSID;
info.CommonDiscInfo.Layer0ToolstampMasteringCode = seed.CommonDiscInfo.Layer0ToolstampMasteringCode;
info.CommonDiscInfo.Layer0MouldSID = seed.CommonDiscInfo.Layer0MouldSID;
info.CommonDiscInfo.Layer0AdditionalMould = seed.CommonDiscInfo.Layer0AdditionalMould;
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Title)) info.CommonDiscInfo.Title = seed.CommonDiscInfo.Title;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.ForeignTitleNonLatin)) info.CommonDiscInfo.ForeignTitleNonLatin = seed.CommonDiscInfo.ForeignTitleNonLatin;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.DiscNumberLetter)) info.CommonDiscInfo.DiscNumberLetter = seed.CommonDiscInfo.DiscNumberLetter;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.DiscTitle)) info.CommonDiscInfo.DiscTitle = seed.CommonDiscInfo.DiscTitle;
if (seed.CommonDiscInfo.Category != null) info.CommonDiscInfo.Category = seed.CommonDiscInfo.Category;
if (seed.CommonDiscInfo.Region != null) info.CommonDiscInfo.Region = seed.CommonDiscInfo.Region;
if (seed.CommonDiscInfo.Languages != null) info.CommonDiscInfo.Languages = seed.CommonDiscInfo.Languages;
if (seed.CommonDiscInfo.LanguageSelection != null) info.CommonDiscInfo.LanguageSelection = seed.CommonDiscInfo.LanguageSelection;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Serial)) info.CommonDiscInfo.Serial = seed.CommonDiscInfo.Serial;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Barcode)) info.CommonDiscInfo.Barcode = seed.CommonDiscInfo.Barcode;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Comments)) info.CommonDiscInfo.Comments = seed.CommonDiscInfo.Comments;
if (seed.CommonDiscInfo.CommentsSpecialFields != null) info.CommonDiscInfo.CommentsSpecialFields = seed.CommonDiscInfo.CommentsSpecialFields;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Contents)) info.CommonDiscInfo.Contents = seed.CommonDiscInfo.Contents;
if (seed.CommonDiscInfo.ContentsSpecialFields != null) info.CommonDiscInfo.ContentsSpecialFields = seed.CommonDiscInfo.ContentsSpecialFields;
info.CommonDiscInfo.Layer1MasteringRing = seed.CommonDiscInfo.Layer1MasteringRing;
info.CommonDiscInfo.Layer1MasteringSID = seed.CommonDiscInfo.Layer1MasteringSID;
info.CommonDiscInfo.Layer1ToolstampMasteringCode = seed.CommonDiscInfo.Layer1ToolstampMasteringCode;
info.CommonDiscInfo.Layer1MouldSID = seed.CommonDiscInfo.Layer1MouldSID;
info.CommonDiscInfo.Layer1AdditionalMould = seed.CommonDiscInfo.Layer1AdditionalMould;
// Info that always overwrites
info.CommonDiscInfo.Layer0MasteringRing = seed.CommonDiscInfo.Layer0MasteringRing;
info.CommonDiscInfo.Layer0MasteringSID = seed.CommonDiscInfo.Layer0MasteringSID;
info.CommonDiscInfo.Layer0ToolstampMasteringCode = seed.CommonDiscInfo.Layer0ToolstampMasteringCode;
info.CommonDiscInfo.Layer0MouldSID = seed.CommonDiscInfo.Layer0MouldSID;
info.CommonDiscInfo.Layer0AdditionalMould = seed.CommonDiscInfo.Layer0AdditionalMould;
info.CommonDiscInfo.Layer2MasteringRing = seed.CommonDiscInfo.Layer2MasteringRing;
info.CommonDiscInfo.Layer2MasteringSID = seed.CommonDiscInfo.Layer2MasteringSID;
info.CommonDiscInfo.Layer2ToolstampMasteringCode = seed.CommonDiscInfo.Layer2ToolstampMasteringCode;
info.CommonDiscInfo.Layer1MasteringRing = seed.CommonDiscInfo.Layer1MasteringRing;
info.CommonDiscInfo.Layer1MasteringSID = seed.CommonDiscInfo.Layer1MasteringSID;
info.CommonDiscInfo.Layer1ToolstampMasteringCode = seed.CommonDiscInfo.Layer1ToolstampMasteringCode;
info.CommonDiscInfo.Layer1MouldSID = seed.CommonDiscInfo.Layer1MouldSID;
info.CommonDiscInfo.Layer1AdditionalMould = seed.CommonDiscInfo.Layer1AdditionalMould;
info.CommonDiscInfo.Layer3MasteringRing = seed.CommonDiscInfo.Layer3MasteringRing;
info.CommonDiscInfo.Layer3MasteringSID = seed.CommonDiscInfo.Layer3MasteringSID;
info.CommonDiscInfo.Layer3ToolstampMasteringCode = seed.CommonDiscInfo.Layer3ToolstampMasteringCode;
}
info.CommonDiscInfo.Layer2MasteringRing = seed.CommonDiscInfo.Layer2MasteringRing;
info.CommonDiscInfo.Layer2MasteringSID = seed.CommonDiscInfo.Layer2MasteringSID;
info.CommonDiscInfo.Layer2ToolstampMasteringCode = seed.CommonDiscInfo.Layer2ToolstampMasteringCode;
if (info.VersionAndEditions != null && seed.VersionAndEditions != null)
{
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.VersionAndEditions.Version)) info.VersionAndEditions.Version = seed.VersionAndEditions.Version;
if (!string.IsNullOrEmpty(seed.VersionAndEditions.OtherEditions)) info.VersionAndEditions.OtherEditions = seed.VersionAndEditions.OtherEditions;
}
info.CommonDiscInfo.Layer3MasteringRing = seed.CommonDiscInfo.Layer3MasteringRing;
info.CommonDiscInfo.Layer3MasteringSID = seed.CommonDiscInfo.Layer3MasteringSID;
info.CommonDiscInfo.Layer3ToolstampMasteringCode = seed.CommonDiscInfo.Layer3ToolstampMasteringCode;
if (info.CopyProtection != null && seed.CopyProtection != null)
{
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.CopyProtection.Protection)) info.CopyProtection.Protection = seed.CopyProtection.Protection;
}
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.VersionAndEditions.Version)) info.VersionAndEditions.Version = seed.VersionAndEditions.Version;
if (!string.IsNullOrEmpty(seed.VersionAndEditions.OtherEditions)) info.VersionAndEditions.OtherEditions = seed.VersionAndEditions.OtherEditions;
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.CopyProtection.Protection)) info.CopyProtection.Protection = seed.CopyProtection.Protection;
return info;
}
@@ -733,6 +693,7 @@ namespace SabreTools.RedumpLib
// Microsoft Xbox One and Series X/S
SiteCode.Filename => true,
SiteCode.TitleID => true,
// Nintendo Gamecube
SiteCode.InternalName => true,

View File

@@ -2008,6 +2008,9 @@ namespace SabreTools.RedumpLib.Data
[System(Category = SystemCategory.DiscBasedConsole, LongName = "Philips CD-i", ShortName = "cdi", HasCues = true, HasDat = true)]
PhilipsCDi,
[System(Category = SystemCategory.DiscBasedConsole, Available = false, LongName = "Playmaji Polymega")]
PlaymajiPolymega,
[System(Category = SystemCategory.DiscBasedConsole, Available = false, LongName = "Pioneer LaserActive")]
PioneerLaserActive,
@@ -2478,7 +2481,7 @@ namespace SabreTools.RedumpLib.Data
/// </summary>
/// <remarks>
/// https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
///
///
/// Because of how Redump stores region IDs, the second letter of each
/// code is lower-cased. In any other system, both letters would be
/// capitalized properly.
@@ -3379,7 +3382,7 @@ namespace SabreTools.RedumpLib.Data
[HumanReadable(LongName = "Thailand", ShortName = "Th")]
Thailand,
// East Timor was "Tp"
// East Timor was "Tp"
[HumanReadable(LongName = "Timor-Leste (East Timor)", ShortName = "Tl")]
TimorLeste,
@@ -3728,6 +3731,10 @@ namespace SabreTools.RedumpLib.Data
[HumanReadable(ShortName = "[T:TD]", LongName = "<b>Tech Demos</b>:")]
TechDemos,
// This doesn't have a site tag yet
[HumanReadable(ShortName = "<b>Title ID</b>:", LongName = "<b>Title ID</b>:")]
TitleID,
[HumanReadable(ShortName = "[T:UID]", LongName = "<b>Ubisoft ID</b>:")]
UbisoftID,

View File

@@ -159,6 +159,12 @@ namespace SabreTools.RedumpLib.Data
types.Add(MediaType.CDROM);
break;
// https://en.wikipedia.org/wiki/Polymega
case RedumpSystem.PlaymajiPolymega:
types.Add(MediaType.CDROM);
types.Add(MediaType.DVD);
break;
// https://en.wikipedia.org/wiki/LaserActive
case RedumpSystem.PioneerLaserActive:
types.Add(MediaType.CDROM);
@@ -1271,6 +1277,7 @@ namespace SabreTools.RedumpLib.Data
SiteCode.Series => true,
SiteCode.SSHash => true,
SiteCode.SSVersion => true,
SiteCode.TitleID => true,
SiteCode.UniversalHash => true,
SiteCode.VCD => true,
SiteCode.VFCCode => true,

View File

@@ -0,0 +1,202 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Converters;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Common disc info section of New Disc Form
/// </summary>
public class CommonDiscInfoSection : ICloneable
{
// Name not defined by Redump
[JsonProperty(PropertyName = "d_system", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(SystemConverter))]
public RedumpSystem? System { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_media", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(DiscTypeConverter))]
public DiscType? Media { get; set; }
[JsonProperty(PropertyName = "d_title", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Title { get; set; }
[JsonProperty(PropertyName = "d_title_foreign", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string? ForeignTitleNonLatin { get; set; }
[JsonProperty(PropertyName = "d_number", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscNumberLetter { get; set; }
[JsonProperty(PropertyName = "d_label", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscTitle { get; set; }
[JsonProperty(PropertyName = "d_category", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(DiscCategoryConverter))]
public DiscCategory? Category { get; set; }
[JsonProperty(PropertyName = "d_region", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(RegionConverter))]
public Region? Region { get; set; }
[JsonProperty(PropertyName = "d_languages", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(LanguageConverter))]
public Language?[]? Languages { get; set; }
[JsonProperty(PropertyName = "d_languages_selection", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
[JsonConverter(typeof(LanguageSelectionConverter))]
public LanguageSelection?[]? LanguageSelection { get; set; }
[JsonProperty(PropertyName = "d_serial", NullValueHandling = NullValueHandling.Ignore)]
public string? Serial { get; set; }
[JsonProperty(PropertyName = "d_ring", NullValueHandling = NullValueHandling.Ignore)]
public string? Ring { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_id", NullValueHandling = NullValueHandling.Ignore)]
public string? RingId { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_ma1", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer0MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma1_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts1", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo1_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0MouldSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo1", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0AdditionalMould { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma2", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer1MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma2_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts2", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo2_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1MouldSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo2", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1AdditionalMould { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma3", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer2MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma3_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer2MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts3", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer2ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma4", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer3MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma4_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer3MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts4", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer3ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_offsets", NullValueHandling = NullValueHandling.Ignore)]
public string RingOffsetsHidden { get { return "1"; } }
[JsonProperty(PropertyName = "d_ring_0_0_id", NullValueHandling = NullValueHandling.Ignore)]
public string? RingZeroId { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_0_density", NullValueHandling = NullValueHandling.Ignore)]
public string? RingZeroDensity { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_0_value", NullValueHandling = NullValueHandling.Ignore)]
public string? RingWriteOffset { get; set; }
[JsonProperty(PropertyName = "d_ring_count", NullValueHandling = NullValueHandling.Ignore)]
public string RingCount { get { return "1"; } }
[JsonProperty(PropertyName = "d_barcode", NullValueHandling = NullValueHandling.Ignore)]
public string? Barcode { get; set; }
[JsonProperty(PropertyName = "d_date", NullValueHandling = NullValueHandling.Ignore)]
public string? EXEDateBuildDate { get; set; }
[JsonProperty(PropertyName = "d_errors", NullValueHandling = NullValueHandling.Ignore)]
public string? ErrorsCount { get; set; }
[JsonProperty(PropertyName = "d_comments", NullValueHandling = NullValueHandling.Ignore)]
public string? Comments { get; set; }
[JsonIgnore]
public Dictionary<SiteCode, string> CommentsSpecialFields { get; set; } = [];
[JsonProperty(PropertyName = "d_contents", NullValueHandling = NullValueHandling.Ignore)]
public string? Contents { get; set; }
[JsonIgnore]
public Dictionary<SiteCode, string> ContentsSpecialFields { get; set; } = [];
public object Clone()
{
Dictionary<SiteCode, string> commentsSpecialFields = [];
foreach (var kvp in this.CommentsSpecialFields)
{
commentsSpecialFields[kvp.Key] = kvp.Value;
}
Dictionary<SiteCode, string> contentsSpecialFields = [];
foreach (var kvp in this.ContentsSpecialFields)
{
contentsSpecialFields[kvp.Key] = kvp.Value;
}
return new CommonDiscInfoSection
{
System = this.System,
Media = this.Media,
Title = this.Title,
ForeignTitleNonLatin = this.ForeignTitleNonLatin,
DiscNumberLetter = this.DiscNumberLetter,
DiscTitle = this.DiscTitle,
Category = this.Category,
Region = this.Region,
Languages = this.Languages?.Clone() as Language?[],
LanguageSelection = this.LanguageSelection?.Clone() as LanguageSelection?[],
Serial = this.Serial,
Ring = this.Ring,
RingId = this.RingId,
Layer0MasteringRing = this.Layer0MasteringRing,
Layer0MasteringSID = this.Layer0MasteringSID,
Layer0ToolstampMasteringCode = this.Layer0ToolstampMasteringCode,
Layer0MouldSID = this.Layer0MouldSID,
Layer0AdditionalMould = this.Layer0AdditionalMould,
Layer1MasteringRing = this.Layer1MasteringRing,
Layer1MasteringSID = this.Layer1MasteringSID,
Layer1ToolstampMasteringCode = this.Layer1ToolstampMasteringCode,
Layer1MouldSID = this.Layer1MouldSID,
Layer1AdditionalMould = this.Layer1AdditionalMould,
Layer2MasteringRing = this.Layer2MasteringRing,
Layer2MasteringSID = this.Layer2MasteringSID,
Layer2ToolstampMasteringCode = this.Layer2ToolstampMasteringCode,
Layer3MasteringRing = this.Layer3MasteringRing,
Layer3MasteringSID = this.Layer3MasteringSID,
Layer3ToolstampMasteringCode = this.Layer3ToolstampMasteringCode,
RingZeroId = this.RingZeroId,
RingZeroDensity = this.RingZeroDensity,
RingWriteOffset = this.RingWriteOffset,
Barcode = this.Barcode,
EXEDateBuildDate = this.EXEDateBuildDate,
ErrorsCount = this.ErrorsCount,
Comments = this.Comments,
CommentsSpecialFields = commentsSpecialFields,
Contents = this.Contents,
ContentsSpecialFields = contentsSpecialFields,
};
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Converters;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Copy protection section of New Disc form
/// </summary>
public class CopyProtectionSection : ICloneable
{
[JsonProperty(PropertyName = "d_protection_a", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? AntiModchip { get; set; }
[JsonProperty(PropertyName = "d_protection_1", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? LibCrypt { get; set; }
[JsonProperty(PropertyName = "d_libcrypt", NullValueHandling = NullValueHandling.Ignore)]
public string? LibCryptData { get; set; }
[JsonProperty(PropertyName = "d_protection", NullValueHandling = NullValueHandling.Ignore)]
public string? Protection { get; set; }
[JsonIgnore]
public Dictionary<string, List<string>?>? FullProtections { get; set; }
[JsonProperty(PropertyName = "d_securom", NullValueHandling = NullValueHandling.Ignore)]
public string? SecuROMData { get; set; }
public object Clone()
{
Dictionary<string, List<string>?>? fullProtections = null;
if (this.FullProtections != null)
{
fullProtections = new Dictionary<string, List<string>?>();
foreach (var kvp in this.FullProtections)
{
fullProtections[kvp.Key] = kvp.Value;
}
}
return new CopyProtectionSection
{
AntiModchip = this.AntiModchip,
LibCrypt = this.LibCrypt,
LibCryptData = this.LibCryptData,
Protection = this.Protection,
FullProtections = fullProtections,
SecuROMData = this.SecuROMData,
};
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Dumpers and status section of New Disc form (Moderator only)
/// </summary>
public class DumpersAndStatusSection : ICloneable
{
[JsonProperty(PropertyName = "d_status", NullValueHandling = NullValueHandling.Ignore)]
public DumpStatus Status { get; set; }
[JsonProperty(PropertyName = "d_dumpers", NullValueHandling = NullValueHandling.Ignore)]
public string[]? Dumpers { get; set; }
[JsonProperty(PropertyName = "d_dumpers_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherDumpers { get; set; }
public object Clone()
{
return new DumpersAndStatusSection
{
Status = this.Status,
Dumpers = this.Dumpers?.Clone() as string[],
OtherDumpers = this.OtherDumpers,
};
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Dumping info section for moderation
/// </summary>
public class DumpingInfoSection : ICloneable
{
// Name not defined by Redump -- Only used with MPF
[JsonProperty(PropertyName = "d_frontend_version", DefaultValueHandling = DefaultValueHandling.Include)]
public string? FrontendVersion { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_program", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingProgram { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_date", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingDate { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_params", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingParameters { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_manufacturer", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Manufacturer { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_model", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Model { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_firmware", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Firmware { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_reported_disc_type", DefaultValueHandling = DefaultValueHandling.Include)]
public string? ReportedDiscType { get; set; }
// Name not defined by Redump -- Only used with Redumper
[JsonProperty(PropertyName = "d_errors_c2", NullValueHandling = NullValueHandling.Ignore)]
public string? C2ErrorsCount { get; set; }
public object Clone()
{
return new DumpingInfoSection
{
FrontendVersion = this.FrontendVersion,
DumpingProgram = this.DumpingProgram,
DumpingDate = this.DumpingDate,
DumpingParameters = this.DumpingParameters,
Manufacturer = this.Manufacturer,
Model = this.Model,
Firmware = this.Firmware,
ReportedDiscType = this.ReportedDiscType,
C2ErrorsCount = this.C2ErrorsCount,
};
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Converters;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// EDC section of New Disc form (PSX only)
/// </summary>
public class EDCSection : ICloneable
{
[JsonProperty(PropertyName = "d_edc", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? EDC { get; set; }
public object Clone()
{
return new EDCSection
{
EDC = this.EDC,
};
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Extras section of New Disc form
/// </summary>
public class ExtrasSection : ICloneable
{
[JsonProperty(PropertyName = "d_pvd", NullValueHandling = NullValueHandling.Ignore)]
public string? PVD { get; set; }
[JsonProperty(PropertyName = "d_d1_key", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscKey { get; set; }
[JsonProperty(PropertyName = "d_d2_key", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscID { get; set; }
[JsonProperty(PropertyName = "d_pic_data", NullValueHandling = NullValueHandling.Ignore)]
public string? PIC { get; set; }
[JsonProperty(PropertyName = "d_header", NullValueHandling = NullValueHandling.Ignore)]
public string? Header { get; set; }
[JsonProperty(PropertyName = "d_bca", NullValueHandling = NullValueHandling.Ignore)]
public string? BCA { get; set; }
[JsonProperty(PropertyName = "d_ssranges", NullValueHandling = NullValueHandling.Ignore)]
public string? SecuritySectorRanges { get; set; }
public object Clone()
{
return new ExtrasSection
{
PVD = this.PVD,
DiscKey = this.DiscKey,
DiscID = this.DiscID,
PIC = this.PIC,
Header = this.Header,
BCA = this.BCA,
SecuritySectorRanges = this.SecuritySectorRanges,
};
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Parent/Clone relationship section of New Disc form
/// </summary>
public class ParentCloneRelationshipSection : ICloneable
{
[JsonProperty(PropertyName = "d_parent_id", NullValueHandling = NullValueHandling.Ignore)]
public string? ParentID { get; set; }
[JsonProperty(PropertyName = "d_is_regional_parent", NullValueHandling = NullValueHandling.Ignore)]
public bool RegionalParent { get; set; }
public object Clone()
{
return new ParentCloneRelationshipSection
{
ParentID = this.ParentID,
RegionalParent = this.RegionalParent,
};
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Size &amp; checksums section of New Disc form (DVD/BD/UMD-based)
/// </summary>
public class SizeAndChecksumsSection : ICloneable
{
[JsonProperty(PropertyName = "d_layerbreak", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak { get; set; }
[JsonProperty(PropertyName = "d_layerbreak_2", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak2 { get; set; }
[JsonProperty(PropertyName = "d_layerbreak_3", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak3 { get; set; }
[JsonProperty(PropertyName = "d_pic_identifier", NullValueHandling = NullValueHandling.Ignore)]
public string? PICIdentifier { get; set; }
[JsonProperty(PropertyName = "d_size", NullValueHandling = NullValueHandling.Ignore)]
public long Size { get; set; }
[JsonProperty(PropertyName = "d_crc32", NullValueHandling = NullValueHandling.Ignore)]
public string? CRC32 { get; set; }
[JsonProperty(PropertyName = "d_md5", NullValueHandling = NullValueHandling.Ignore)]
public string? MD5 { get; set; }
[JsonProperty(PropertyName = "d_sha1", NullValueHandling = NullValueHandling.Ignore)]
public string? SHA1 { get; set; }
public object Clone()
{
return new SizeAndChecksumsSection
{
Layerbreak = this.Layerbreak,
Layerbreak2 = this.Layerbreak2,
Layerbreak3 = this.Layerbreak3,
PICIdentifier = this.PICIdentifier,
Size = this.Size,
CRC32 = this.CRC32,
MD5 = this.MD5,
SHA1 = this.SHA1,
};
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Tracks and write offsets section of New Disc form (CD/GD-based)
/// </summary>
public class TracksAndWriteOffsetsSection : ICloneable
{
[JsonProperty(PropertyName = "d_tracks", NullValueHandling = NullValueHandling.Ignore)]
public string? ClrMameProData { get; set; }
[JsonProperty(PropertyName = "d_cue", NullValueHandling = NullValueHandling.Ignore)]
public string? Cuesheet { get; set; }
[JsonProperty(PropertyName = "d_offset", NullValueHandling = NullValueHandling.Ignore)]
public int[]? CommonWriteOffsets { get; set; }
[JsonProperty(PropertyName = "d_offset_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherWriteOffsets { get; set; }
public object Clone()
{
return new TracksAndWriteOffsetsSection
{
ClrMameProData = this.ClrMameProData,
Cuesheet = this.Cuesheet,
CommonWriteOffsets = this.CommonWriteOffsets?.Clone() as int[],
OtherWriteOffsets = this.OtherWriteOffsets,
};
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Version and editions section of New Disc form
/// </summary>
public class VersionAndEditionsSection : ICloneable
{
[JsonProperty(PropertyName = "d_version", NullValueHandling = NullValueHandling.Ignore)]
public string? Version { get; set; }
[JsonProperty(PropertyName = "d_version_datfile", NullValueHandling = NullValueHandling.Ignore)]
public string? VersionDatfile { get; set; }
[JsonProperty(PropertyName = "d_editions", NullValueHandling = NullValueHandling.Ignore)]
public string[]? CommonEditions { get; set; }
[JsonProperty(PropertyName = "d_editions_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherEditions { get; set; }
public object Clone()
{
return new VersionAndEditionsSection
{
Version = this.Version,
VersionDatfile = this.VersionDatfile,
CommonEditions = this.CommonEditions,
OtherEditions = this.OtherEditions,
};
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Converters;
using SabreTools.RedumpLib.Data.Sections;
namespace SabreTools.RedumpLib.Data
{
@@ -38,48 +38,44 @@ namespace SabreTools.RedumpLib.Data
public DateTime? LastModified { get; set; }
[JsonProperty(PropertyName = "common_disc_info", DefaultValueHandling = DefaultValueHandling.Ignore)]
public CommonDiscInfoSection? CommonDiscInfo { get; set; } = new CommonDiscInfoSection();
public CommonDiscInfoSection CommonDiscInfo { get; set; } = new CommonDiscInfoSection();
[JsonProperty(PropertyName = "versions_and_editions", DefaultValueHandling = DefaultValueHandling.Ignore)]
public VersionAndEditionsSection? VersionAndEditions { get; set; } = new VersionAndEditionsSection();
public VersionAndEditionsSection VersionAndEditions { get; set; } = new VersionAndEditionsSection();
[JsonProperty(PropertyName = "edc", DefaultValueHandling = DefaultValueHandling.Ignore)]
public EDCSection? EDC { get; set; } = new EDCSection();
public EDCSection EDC { get; set; } = new EDCSection();
[JsonProperty(PropertyName = "parent_clone_relationship", DefaultValueHandling = DefaultValueHandling.Ignore)]
public ParentCloneRelationshipSection? ParentCloneRelationship { get; set; } = new ParentCloneRelationshipSection();
public ParentCloneRelationshipSection ParentCloneRelationship { get; set; } = new ParentCloneRelationshipSection();
[JsonProperty(PropertyName = "extras", DefaultValueHandling = DefaultValueHandling.Ignore)]
public ExtrasSection? Extras { get; set; } = new ExtrasSection();
public ExtrasSection Extras { get; set; } = new ExtrasSection();
[JsonProperty(PropertyName = "copy_protection", DefaultValueHandling = DefaultValueHandling.Ignore)]
public CopyProtectionSection? CopyProtection { get; set; } = new CopyProtectionSection();
public CopyProtectionSection CopyProtection { get; set; } = new CopyProtectionSection();
[JsonProperty(PropertyName = "dumpers_and_status", DefaultValueHandling = DefaultValueHandling.Ignore)]
public DumpersAndStatusSection? DumpersAndStatus { get; set; } = new DumpersAndStatusSection();
public DumpersAndStatusSection DumpersAndStatus { get; set; } = new DumpersAndStatusSection();
[JsonProperty(PropertyName = "tracks_and_write_offsets", DefaultValueHandling = DefaultValueHandling.Ignore)]
public TracksAndWriteOffsetsSection? TracksAndWriteOffsets { get; set; } = new TracksAndWriteOffsetsSection();
public TracksAndWriteOffsetsSection TracksAndWriteOffsets { get; set; } = new TracksAndWriteOffsetsSection();
[JsonProperty(PropertyName = "size_and_checksums", DefaultValueHandling = DefaultValueHandling.Ignore)]
public SizeAndChecksumsSection? SizeAndChecksums { get; set; } = new SizeAndChecksumsSection();
public SizeAndChecksumsSection SizeAndChecksums { get; set; } = new SizeAndChecksumsSection();
[JsonProperty(PropertyName = "dumping_info", DefaultValueHandling = DefaultValueHandling.Ignore)]
public DumpingInfoSection? DumpingInfo { get; set; } = new DumpingInfoSection();
public DumpingInfoSection DumpingInfo { get; set; } = new DumpingInfoSection();
[JsonProperty(PropertyName = "artifacts", DefaultValueHandling = DefaultValueHandling.Ignore)]
public Dictionary<string, string>? Artifacts { get; set; } = [];
public Dictionary<string, string> Artifacts { get; set; } = [];
public object Clone()
{
Dictionary<string, string>? artifacts = null;
if (this.Artifacts != null)
Dictionary<string, string> artifacts = [];
foreach (var kvp in this.Artifacts)
{
artifacts = new Dictionary<string, string>();
foreach (var kvp in this.Artifacts)
{
artifacts[kvp.Key] = kvp.Value;
}
artifacts[kvp.Key] = kvp.Value;
}
return new SubmissionInfo
@@ -89,536 +85,18 @@ namespace SabreTools.RedumpLib.Data
PartiallyMatchedIDs = this.PartiallyMatchedIDs,
Added = this.Added,
LastModified = this.LastModified,
CommonDiscInfo = this.CommonDiscInfo?.Clone() as CommonDiscInfoSection,
VersionAndEditions = this.VersionAndEditions?.Clone() as VersionAndEditionsSection,
EDC = this.EDC?.Clone() as EDCSection,
ParentCloneRelationship = this.ParentCloneRelationship?.Clone() as ParentCloneRelationshipSection,
Extras = this.Extras?.Clone() as ExtrasSection,
CopyProtection = this.CopyProtection?.Clone() as CopyProtectionSection,
DumpersAndStatus = this.DumpersAndStatus?.Clone() as DumpersAndStatusSection,
TracksAndWriteOffsets = this.TracksAndWriteOffsets?.Clone() as TracksAndWriteOffsetsSection,
SizeAndChecksums = this.SizeAndChecksums?.Clone() as SizeAndChecksumsSection,
DumpingInfo = this.DumpingInfo?.Clone() as DumpingInfoSection,
CommonDiscInfo = this.CommonDiscInfo?.Clone() as CommonDiscInfoSection ?? new CommonDiscInfoSection(),
VersionAndEditions = this.VersionAndEditions?.Clone() as VersionAndEditionsSection ?? new VersionAndEditionsSection(),
EDC = this.EDC?.Clone() as EDCSection ?? new EDCSection(),
ParentCloneRelationship = this.ParentCloneRelationship?.Clone() as ParentCloneRelationshipSection ?? new ParentCloneRelationshipSection(),
Extras = this.Extras?.Clone() as ExtrasSection ?? new ExtrasSection(),
CopyProtection = this.CopyProtection?.Clone() as CopyProtectionSection ?? new CopyProtectionSection(),
DumpersAndStatus = this.DumpersAndStatus?.Clone() as DumpersAndStatusSection ?? new DumpersAndStatusSection(),
TracksAndWriteOffsets = this.TracksAndWriteOffsets?.Clone() as TracksAndWriteOffsetsSection ?? new TracksAndWriteOffsetsSection(),
SizeAndChecksums = this.SizeAndChecksums?.Clone() as SizeAndChecksumsSection ?? new SizeAndChecksumsSection(),
DumpingInfo = this.DumpingInfo?.Clone() as DumpingInfoSection ?? new DumpingInfoSection(),
Artifacts = artifacts,
};
}
}
/// <summary>
/// Common disc info section of New Disc Form
/// </summary>
public class CommonDiscInfoSection : ICloneable
{
// Name not defined by Redump
[JsonProperty(PropertyName = "d_system", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(SystemConverter))]
public RedumpSystem? System { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_media", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(DiscTypeConverter))]
public DiscType? Media { get; set; }
[JsonProperty(PropertyName = "d_title", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Title { get; set; }
[JsonProperty(PropertyName = "d_title_foreign", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string? ForeignTitleNonLatin { get; set; }
[JsonProperty(PropertyName = "d_number", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscNumberLetter { get; set; }
[JsonProperty(PropertyName = "d_label", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscTitle { get; set; }
[JsonProperty(PropertyName = "d_category", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(DiscCategoryConverter))]
public DiscCategory? Category { get; set; }
[JsonProperty(PropertyName = "d_region", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(RegionConverter))]
public Region? Region { get; set; }
[JsonProperty(PropertyName = "d_languages", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(LanguageConverter))]
public Language?[]? Languages { get; set; }
[JsonProperty(PropertyName = "d_languages_selection", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
[JsonConverter(typeof(LanguageSelectionConverter))]
public LanguageSelection?[]? LanguageSelection { get; set; }
[JsonProperty(PropertyName = "d_serial", NullValueHandling = NullValueHandling.Ignore)]
public string? Serial { get; set; }
[JsonProperty(PropertyName = "d_ring", NullValueHandling = NullValueHandling.Ignore)]
public string? Ring { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_id", NullValueHandling = NullValueHandling.Ignore)]
public string? RingId { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_ma1", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer0MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma1_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts1", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo1_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0MouldSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo1", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0AdditionalMould { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma2", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer1MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma2_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts2", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo2_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1MouldSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo2", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1AdditionalMould { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma3", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer2MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma3_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer2MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts3", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer2ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma4", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer3MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma4_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer3MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts4", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer3ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_offsets", NullValueHandling = NullValueHandling.Ignore)]
public string RingOffsetsHidden { get { return "1"; } }
[JsonProperty(PropertyName = "d_ring_0_0_id", NullValueHandling = NullValueHandling.Ignore)]
public string? RingZeroId { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_0_density", NullValueHandling = NullValueHandling.Ignore)]
public string? RingZeroDensity { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_0_value", NullValueHandling = NullValueHandling.Ignore)]
public string? RingWriteOffset { get; set; }
[JsonProperty(PropertyName = "d_ring_count", NullValueHandling = NullValueHandling.Ignore)]
public string RingCount { get { return "1"; } }
[JsonProperty(PropertyName = "d_barcode", NullValueHandling = NullValueHandling.Ignore)]
public string? Barcode { get; set; }
[JsonProperty(PropertyName = "d_date", NullValueHandling = NullValueHandling.Ignore)]
public string? EXEDateBuildDate { get; set; }
[JsonProperty(PropertyName = "d_errors", NullValueHandling = NullValueHandling.Ignore)]
public string? ErrorsCount { get; set; }
[JsonProperty(PropertyName = "d_comments", NullValueHandling = NullValueHandling.Ignore)]
public string? Comments { get; set; }
[JsonIgnore]
public Dictionary<SiteCode, string>? CommentsSpecialFields { get; set; }
[JsonProperty(PropertyName = "d_contents", NullValueHandling = NullValueHandling.Ignore)]
public string? Contents { get; set; }
[JsonIgnore]
public Dictionary<SiteCode, string>? ContentsSpecialFields { get; set; }
public object Clone()
{
Dictionary<SiteCode, string>? commentsSpecialFields = null;
if (this.CommentsSpecialFields != null)
{
commentsSpecialFields = new Dictionary<SiteCode, string>();
foreach (var kvp in this.CommentsSpecialFields)
{
commentsSpecialFields[kvp.Key] = kvp.Value;
}
}
Dictionary<SiteCode, string>? contentsSpecialFields = null;
if (this.ContentsSpecialFields != null)
{
contentsSpecialFields = new Dictionary<SiteCode, string>();
foreach (var kvp in this.ContentsSpecialFields)
{
contentsSpecialFields[kvp.Key] = kvp.Value;
}
}
return new CommonDiscInfoSection
{
System = this.System,
Media = this.Media,
Title = this.Title,
ForeignTitleNonLatin = this.ForeignTitleNonLatin,
DiscNumberLetter = this.DiscNumberLetter,
DiscTitle = this.DiscTitle,
Category = this.Category,
Region = this.Region,
Languages = this.Languages?.Clone() as Language?[],
LanguageSelection = this.LanguageSelection?.Clone() as LanguageSelection?[],
Serial = this.Serial,
Ring = this.Ring,
RingId = this.RingId,
Layer0MasteringRing = this.Layer0MasteringRing,
Layer0MasteringSID = this.Layer0MasteringSID,
Layer0ToolstampMasteringCode = this.Layer0ToolstampMasteringCode,
Layer0MouldSID = this.Layer0MouldSID,
Layer0AdditionalMould = this.Layer0AdditionalMould,
Layer1MasteringRing = this.Layer1MasteringRing,
Layer1MasteringSID = this.Layer1MasteringSID,
Layer1ToolstampMasteringCode = this.Layer1ToolstampMasteringCode,
Layer1MouldSID = this.Layer1MouldSID,
Layer1AdditionalMould = this.Layer1AdditionalMould,
Layer2MasteringRing = this.Layer2MasteringRing,
Layer2MasteringSID = this.Layer2MasteringSID,
Layer2ToolstampMasteringCode = this.Layer2ToolstampMasteringCode,
Layer3MasteringRing = this.Layer3MasteringRing,
Layer3MasteringSID = this.Layer3MasteringSID,
Layer3ToolstampMasteringCode = this.Layer3ToolstampMasteringCode,
RingZeroId = this.RingZeroId,
RingZeroDensity = this.RingZeroDensity,
RingWriteOffset = this.RingWriteOffset,
Barcode = this.Barcode,
EXEDateBuildDate = this.EXEDateBuildDate,
ErrorsCount = this.ErrorsCount,
Comments = this.Comments,
CommentsSpecialFields = commentsSpecialFields,
Contents = this.Contents,
ContentsSpecialFields = contentsSpecialFields,
};
}
}
/// <summary>
/// Version and editions section of New Disc form
/// </summary>
public class VersionAndEditionsSection : ICloneable
{
[JsonProperty(PropertyName = "d_version", NullValueHandling = NullValueHandling.Ignore)]
public string? Version { get; set; }
[JsonProperty(PropertyName = "d_version_datfile", NullValueHandling = NullValueHandling.Ignore)]
public string? VersionDatfile { get; set; }
[JsonProperty(PropertyName = "d_editions", NullValueHandling = NullValueHandling.Ignore)]
public string[]? CommonEditions { get; set; }
[JsonProperty(PropertyName = "d_editions_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherEditions { get; set; }
public object Clone()
{
return new VersionAndEditionsSection
{
Version = this.Version,
VersionDatfile = this.VersionDatfile,
CommonEditions = this.CommonEditions,
OtherEditions = this.OtherEditions,
};
}
}
/// <summary>
/// EDC section of New Disc form (PSX only)
/// </summary>
public class EDCSection : ICloneable
{
[JsonProperty(PropertyName = "d_edc", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? EDC { get; set; }
public object Clone()
{
return new EDCSection
{
EDC = this.EDC,
};
}
}
/// <summary>
/// Parent/Clone relationship section of New Disc form
/// </summary>
public class ParentCloneRelationshipSection : ICloneable
{
[JsonProperty(PropertyName = "d_parent_id", NullValueHandling = NullValueHandling.Ignore)]
public string? ParentID { get; set; }
[JsonProperty(PropertyName = "d_is_regional_parent", NullValueHandling = NullValueHandling.Ignore)]
public bool RegionalParent { get; set; }
public object Clone()
{
return new ParentCloneRelationshipSection
{
ParentID = this.ParentID,
RegionalParent = this.RegionalParent,
};
}
}
/// <summary>
/// Extras section of New Disc form
/// </summary>
public class ExtrasSection : ICloneable
{
[JsonProperty(PropertyName = "d_pvd", NullValueHandling = NullValueHandling.Ignore)]
public string? PVD { get; set; }
[JsonProperty(PropertyName = "d_d1_key", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscKey { get; set; }
[JsonProperty(PropertyName = "d_d2_key", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscID { get; set; }
[JsonProperty(PropertyName = "d_pic_data", NullValueHandling = NullValueHandling.Ignore)]
public string? PIC { get; set; }
[JsonProperty(PropertyName = "d_header", NullValueHandling = NullValueHandling.Ignore)]
public string? Header { get; set; }
[JsonProperty(PropertyName = "d_bca", NullValueHandling = NullValueHandling.Ignore)]
public string? BCA { get; set; }
[JsonProperty(PropertyName = "d_ssranges", NullValueHandling = NullValueHandling.Ignore)]
public string? SecuritySectorRanges { get; set; }
public object Clone()
{
return new ExtrasSection
{
PVD = this.PVD,
DiscKey = this.DiscKey,
DiscID = this.DiscID,
PIC = this.PIC,
Header = this.Header,
BCA = this.BCA,
SecuritySectorRanges = this.SecuritySectorRanges,
};
}
}
/// <summary>
/// Copy protection section of New Disc form
/// </summary>
public class CopyProtectionSection : ICloneable
{
[JsonProperty(PropertyName = "d_protection_a", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? AntiModchip { get; set; }
[JsonProperty(PropertyName = "d_protection_1", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? LibCrypt { get; set; }
[JsonProperty(PropertyName = "d_libcrypt", NullValueHandling = NullValueHandling.Ignore)]
public string? LibCryptData { get; set; }
[JsonProperty(PropertyName = "d_protection", NullValueHandling = NullValueHandling.Ignore)]
public string? Protection { get; set; }
[JsonIgnore]
public Dictionary<string, List<string>?>? FullProtections { get; set; }
[JsonProperty(PropertyName = "d_securom", NullValueHandling = NullValueHandling.Ignore)]
public string? SecuROMData { get; set; }
public object Clone()
{
Dictionary<string, List<string>?>? fullProtections = null;
if (this.FullProtections != null)
{
fullProtections = new Dictionary<string, List<string>?>();
foreach (var kvp in this.FullProtections)
{
fullProtections[kvp.Key] = kvp.Value;
}
}
return new CopyProtectionSection
{
AntiModchip = this.AntiModchip,
LibCrypt = this.LibCrypt,
LibCryptData = this.LibCryptData,
Protection = this.Protection,
FullProtections = fullProtections,
SecuROMData = this.SecuROMData,
};
}
}
/// <summary>
/// Dumpers and status section of New Disc form (Moderator only)
/// </summary>
public class DumpersAndStatusSection : ICloneable
{
[JsonProperty(PropertyName = "d_status", NullValueHandling = NullValueHandling.Ignore)]
public DumpStatus Status { get; set; }
[JsonProperty(PropertyName = "d_dumpers", NullValueHandling = NullValueHandling.Ignore)]
public string[]? Dumpers { get; set; }
[JsonProperty(PropertyName = "d_dumpers_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherDumpers { get; set; }
public object Clone()
{
return new DumpersAndStatusSection
{
Status = this.Status,
Dumpers = this.Dumpers?.Clone() as string[],
OtherDumpers = this.OtherDumpers,
};
}
}
/// <summary>
/// Tracks and write offsets section of New Disc form (CD/GD-based)
/// </summary>
public class TracksAndWriteOffsetsSection : ICloneable
{
[JsonProperty(PropertyName = "d_tracks", NullValueHandling = NullValueHandling.Ignore)]
public string? ClrMameProData { get; set; }
[JsonProperty(PropertyName = "d_cue", NullValueHandling = NullValueHandling.Ignore)]
public string? Cuesheet { get; set; }
[JsonProperty(PropertyName = "d_offset", NullValueHandling = NullValueHandling.Ignore)]
public int[]? CommonWriteOffsets { get; set; }
[JsonProperty(PropertyName = "d_offset_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherWriteOffsets { get; set; }
public object Clone()
{
return new TracksAndWriteOffsetsSection
{
ClrMameProData = this.ClrMameProData,
Cuesheet = this.Cuesheet,
CommonWriteOffsets = this.CommonWriteOffsets?.Clone() as int[],
OtherWriteOffsets = this.OtherWriteOffsets,
};
}
}
/// <summary>
/// Size &amp; checksums section of New Disc form (DVD/BD/UMD-based)
/// </summary>
public class SizeAndChecksumsSection : ICloneable
{
[JsonProperty(PropertyName = "d_layerbreak", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak { get; set; }
[JsonProperty(PropertyName = "d_layerbreak_2", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak2 { get; set; }
[JsonProperty(PropertyName = "d_layerbreak_3", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak3 { get; set; }
[JsonProperty(PropertyName = "d_pic_identifier", NullValueHandling = NullValueHandling.Ignore)]
public string? PICIdentifier { get; set; }
[JsonProperty(PropertyName = "d_size", NullValueHandling = NullValueHandling.Ignore)]
public long Size { get; set; }
[JsonProperty(PropertyName = "d_crc32", NullValueHandling = NullValueHandling.Ignore)]
public string? CRC32 { get; set; }
[JsonProperty(PropertyName = "d_md5", NullValueHandling = NullValueHandling.Ignore)]
public string? MD5 { get; set; }
[JsonProperty(PropertyName = "d_sha1", NullValueHandling = NullValueHandling.Ignore)]
public string? SHA1 { get; set; }
public object Clone()
{
return new SizeAndChecksumsSection
{
Layerbreak = this.Layerbreak,
Layerbreak2 = this.Layerbreak2,
Layerbreak3 = this.Layerbreak3,
PICIdentifier = this.PICIdentifier,
Size = this.Size,
CRC32 = this.CRC32,
MD5 = this.MD5,
SHA1 = this.SHA1,
};
}
}
/// <summary>
/// Dumping info section for moderation
/// </summary>
public class DumpingInfoSection : ICloneable
{
// Name not defined by Redump -- Only used with MPF
[JsonProperty(PropertyName = "d_frontend_version", DefaultValueHandling = DefaultValueHandling.Include)]
public string? FrontendVersion { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_program", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingProgram { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_date", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingDate { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_params", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingParameters { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_manufacturer", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Manufacturer { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_model", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Model { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_firmware", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Firmware { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_reported_disc_type", DefaultValueHandling = DefaultValueHandling.Include)]
public string? ReportedDiscType { get; set; }
// Name not defined by Redump -- Only used with Redumper
[JsonProperty(PropertyName = "d_errors_c2", NullValueHandling = NullValueHandling.Ignore)]
public string? C2ErrorsCount { get; set; }
public object Clone()
{
return new DumpingInfoSection
{
FrontendVersion = this.FrontendVersion,
DumpingProgram = this.DumpingProgram,
DumpingDate = this.DumpingDate,
DumpingParameters = this.DumpingParameters,
Manufacturer = this.Manufacturer,
Model = this.Model,
Firmware = this.Firmware,
ReportedDiscType = this.ReportedDiscType,
C2ErrorsCount = this.C2ErrorsCount,
};
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.Data.Sections;
namespace SabreTools.RedumpLib
{
@@ -38,6 +39,7 @@ namespace SabreTools.RedumpLib
SiteCode.SSVersion,
SiteCode.Filename,
SiteCode.TitleID,
SiteCode.Protection,
@@ -155,7 +157,7 @@ namespace SabreTools.RedumpLib
output.AppendLine();
// EDC section
FormatOutputData(output, info.EDC, info.CommonDiscInfo?.System);
FormatOutputData(output, info.EDC, info.CommonDiscInfo.System);
output.AppendLine();
// Extras section
@@ -163,11 +165,11 @@ namespace SabreTools.RedumpLib
output.AppendLine();
// Copy Protection section
FormatOutputData(output, info.CopyProtection, info.CommonDiscInfo?.System);
FormatOutputData(output, info.CopyProtection, info.CommonDiscInfo.System);
output.AppendLine();
// Tracks and Write Offsets section
if (!string.IsNullOrEmpty(info.TracksAndWriteOffsets?.ClrMameProData))
if (!string.IsNullOrEmpty(info.TracksAndWriteOffsets.ClrMameProData))
{
FormatOutputData(output, info.TracksAndWriteOffsets!);
output.AppendLine();
@@ -177,8 +179,8 @@ namespace SabreTools.RedumpLib
{
FormatOutputData(output,
info.SizeAndChecksums,
info.CommonDiscInfo?.Media.ToMediaType(),
info.CommonDiscInfo?.System,
info.CommonDiscInfo.Media.ToMediaType(),
info.CommonDiscInfo.System,
enableRedumpCompatibility);
output.AppendLine();
}
@@ -225,7 +227,7 @@ namespace SabreTools.RedumpLib
info.CommonDiscInfo.Comments = info.CommonDiscInfo.Comments.Trim();
// Wipe out the special fields dictionary
info.CommonDiscInfo.CommentsSpecialFields = null;
info.CommonDiscInfo.CommentsSpecialFields.Clear();
}
// Process the contents field
@@ -245,7 +247,7 @@ namespace SabreTools.RedumpLib
info.CommonDiscInfo.Contents = info.CommonDiscInfo.Contents.Trim();
// Wipe out the special fields dictionary
info.CommonDiscInfo.ContentsSpecialFields = null;
info.CommonDiscInfo.ContentsSpecialFields.Clear();
}
}
@@ -558,7 +560,7 @@ namespace SabreTools.RedumpLib
value = value.Replace("<TAB>", "\t");
value = value.Replace("<Tab>", "\t");
#endif
value = value.Replace(" ", "\t");
value = value.Replace(" ", "\t");
// Sanitize whitespace around tabs
value = Regex.Replace(value, @"\s*\t\s*", "\t", RegexOptions.Compiled);
@@ -687,13 +689,13 @@ namespace SabreTools.RedumpLib
return $"{mediaType.LongName()}-128";
else if (layerbreak2 != default && layerbreak2 != default(long))
return $"{mediaType.LongName()}-100";
else if (layerbreak != default && layerbreak != default(long) && picIdentifier == Models.PIC.Constants.DiscTypeIdentifierROMUltra)
else if (layerbreak != default && layerbreak != default(long) && picIdentifier == "BDU")
return $"{mediaType.LongName()}-66";
else if (layerbreak != default && layerbreak != default(long) && size > 53_687_063_712)
return $"{mediaType.LongName()}-66";
else if (layerbreak != default && layerbreak != default(long))
return $"{mediaType.LongName()}-50";
else if (picIdentifier == Models.PIC.Constants.DiscTypeIdentifierROMUltra)
else if (picIdentifier == "BDU")
return $"{mediaType.LongName()}-33";
else if (size > 26_843_531_856)
return $"{mediaType.LongName()}-33";

View File

@@ -8,7 +8,7 @@
<Nullable>enable</Nullable>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.7.1</Version>
<Version>1.8.0</Version>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>
@@ -33,8 +33,7 @@
<ItemGroup>
<PackageReference Include="MinAsyncBridge" Version="0.12.4" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))" />
<PackageReference Include="Net35.Actions" Version="1.4.0" Condition="$(TargetFramework.StartsWith(`net2`))" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="SabreTools.Models" Version="1.6.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>
</Project>
</Project>

View File

@@ -16,7 +16,7 @@ namespace SabreTools.RedumpLib
public static void NormalizeDiscType(SubmissionInfo info)
{
// If we have nothing valid, do nothing
if (info?.CommonDiscInfo?.Media == null || info?.SizeAndChecksums == null)
if (info.CommonDiscInfo.Media == null || info.SizeAndChecksums == default)
return;
switch (info.CommonDiscInfo.Media)
@@ -39,13 +39,13 @@ namespace SabreTools.RedumpLib
info.CommonDiscInfo.Media = DiscType.BD128;
else if (info.SizeAndChecksums.Layerbreak2 != default)
info.CommonDiscInfo.Media = DiscType.BD100;
else if (info.SizeAndChecksums.Layerbreak != default && info.SizeAndChecksums.PICIdentifier == Models.PIC.Constants.DiscTypeIdentifierROMUltra)
else if (info.SizeAndChecksums.Layerbreak != default && info.SizeAndChecksums.PICIdentifier == "BDU")
info.CommonDiscInfo.Media = DiscType.BD66;
else if (info.SizeAndChecksums.Layerbreak != default && info.SizeAndChecksums.Size > 50_050_629_632)
info.CommonDiscInfo.Media = DiscType.BD66;
else if (info.SizeAndChecksums.Layerbreak != default)
info.CommonDiscInfo.Media = DiscType.BD50;
else if (info.SizeAndChecksums.PICIdentifier == Models.PIC.Constants.DiscTypeIdentifierROMUltra)
else if (info.SizeAndChecksums.PICIdentifier == "BDU")
info.CommonDiscInfo.Media = DiscType.BD33;
else if (info.SizeAndChecksums.Size > 25_025_314_816)
info.CommonDiscInfo.Media = DiscType.BD33;
@@ -157,12 +157,11 @@ namespace SabreTools.RedumpLib
/// </summary>
/// <param name="rc">RedumpClient for making the connection</param>
/// <param name="info">Existing SubmissionInfo object to fill</param>
/// <param name="resultProgress">Optional result progress callback</param>
/// <returns>List of found values, if possible</returns>
public async static Task<List<int>?> ValidateUniversalHash(RedumpClient rc, SubmissionInfo info)
{
// If we don't have special fields
if (info.CommonDiscInfo?.CommentsSpecialFields == null)
if (info.CommonDiscInfo.CommentsSpecialFields == null)
return null;
// If we don't have a universal hash

View File

@@ -6,6 +6,11 @@ namespace SabreTools.RedumpLib.Web
{
internal class CookieWebClient : WebClient
{
/// <summary>
/// The timespan to wait before the request times out.
/// </summary>
public TimeSpan Timeout { get; set; }
// https://stackoverflow.com/questions/1777221/using-cookiecontainer-with-webclient-class
private readonly CookieContainer _container = new();
@@ -33,7 +38,7 @@ namespace SabreTools.RedumpLib.Web
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest webRequest)
{
webRequest.Timeout = 30 * 1000; // 30 seconds
webRequest.Timeout = (int)Timeout.TotalMilliseconds;
webRequest.CookieContainer = _container;
}

View File

@@ -31,15 +31,20 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Maximum retry count for any operation
/// </summary>
public int RetryCount { get; private set; } = 3;
public int RetryCount { get; }
/// <summary>
/// Maximum number of seconds for a retry
/// </summary>
public int TimeoutSeconds { get; }
/// <summary>
/// Internal client for interaction
/// </summary>
#if NETFRAMEWORK || NETSTANDARD2_0_OR_GREATER
private CookieWebClient _internalClient;
private readonly CookieWebClient _internalClient;
#else
private HttpClient _internalClient;
private readonly HttpClient _internalClient;
#endif
#endregion
@@ -47,25 +52,24 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Constructor
/// </summary>
public RedumpClient()
{
#if NETFRAMEWORK || NETSTANDARD2_0_OR_GREATER
_internalClient = new CookieWebClient();
#else
_internalClient = new HttpClient(new HttpClientHandler { UseCookies = true }) { Timeout = TimeSpan.FromSeconds(30) };
#endif
}
/// <summary>
/// Constructor
/// </summary>
public RedumpClient(int retryCount) : this()
public RedumpClient(int retryCount = 3, int timeoutSeconds = 30)
{
// Ensure there are a positive number of retries
if (retryCount <= 0)
retryCount = 3;
// Ensure a positive timespan
if (timeoutSeconds <= 0)
timeoutSeconds = 30;
RetryCount = retryCount;
TimeoutSeconds = timeoutSeconds;
#if NETFRAMEWORK || NETSTANDARD2_0_OR_GREATER
_internalClient = new CookieWebClient() { Timeout = TimeSpan.FromSeconds(TimeoutSeconds) };
#else
_internalClient = new HttpClient(new HttpClientHandler { UseCookies = true }) { Timeout = TimeSpan.FromSeconds(TimeoutSeconds) };
#endif
}
#region Credentials
@@ -362,10 +366,11 @@ namespace SabreTools.RedumpLib.Web
var value = Regex.Match(dumpsPage, @"/disc/(\d+)/sfv/").Groups[1].Value;
if (int.TryParse(value, out int id))
{
ids.Add(id);
bool downloaded = await DownloadSingleSiteID(id, outDir, false);
if (!downloaded && failOnSingle)
return ids;
ids.Add(id);
}
return ids;
@@ -382,10 +387,11 @@ namespace SabreTools.RedumpLib.Web
{
if (int.TryParse(match.Groups[1].Value, out int value))
{
ids.Add(value);
bool downloaded = await DownloadSingleSiteID(value, outDir, false);
if (!downloaded && failOnSingle)
return ids;
ids.Add(value);
}
}
catch (Exception ex)
@@ -861,7 +867,7 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Download a set of packs
/// </summary>
/// </summary>
/// <param name="url">Base URL to download using</param>
/// <param name="systems">Systems to download packs for</param>
/// <param name="title">Name of the pack that is downloading</param>