mirror of
https://github.com/SabreTools/MPF.git
synced 2026-02-05 21:29:24 +00:00
Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61f90a635f | ||
|
|
8cc0ff3829 | ||
|
|
cac6bcc4de | ||
|
|
7ac0089e81 | ||
|
|
48576b38be | ||
|
|
82dedf1ceb | ||
|
|
395cded5ef | ||
|
|
a48f9d1c83 | ||
|
|
3975003686 | ||
|
|
4beae71511 | ||
|
|
f0f41c86c5 | ||
|
|
b1b6eb2c9d | ||
|
|
29754b4c0e | ||
|
|
35cda84308 | ||
|
|
a877397fe6 | ||
|
|
2f0471d596 | ||
|
|
2037ded792 | ||
|
|
5f1a68a5f5 | ||
|
|
87746c8677 | ||
|
|
2665c29918 | ||
|
|
5637cf5201 | ||
|
|
eb1d000e4f | ||
|
|
8db467128d | ||
|
|
dc90e2609d | ||
|
|
e96bd21f1d | ||
|
|
693599b986 | ||
|
|
d482fe926c | ||
|
|
17b5432352 | ||
|
|
ca480f27ed | ||
|
|
4bad66e706 | ||
|
|
abe00fe132 | ||
|
|
ba73479837 | ||
|
|
f2a28dd36b | ||
|
|
928e30a5de | ||
|
|
007fc2f9b9 | ||
|
|
d2d23ebbdf | ||
|
|
e02ab769ec | ||
|
|
3df78def00 | ||
|
|
7eddfc5fed | ||
|
|
f6f154b6db | ||
|
|
47cd133437 | ||
|
|
74c9641a54 | ||
|
|
fc5929db2a | ||
|
|
f53b428075 | ||
|
|
46dc931b3f | ||
|
|
9608cfb700 | ||
|
|
3493238849 | ||
|
|
4c364f519e | ||
|
|
337a7a181c | ||
|
|
071e3a0024 | ||
|
|
ff0c742dee | ||
|
|
7aba0d1c9c | ||
|
|
ac6a77d9da | ||
|
|
6eb976c842 | ||
|
|
ba39a8b22f | ||
|
|
88a6fa71a9 | ||
|
|
584b8c0109 | ||
|
|
c6258b5520 | ||
|
|
d6dbbbe928 | ||
|
|
f22b3c4ac0 | ||
|
|
fae399f8bc | ||
|
|
d2ed2f81ae | ||
|
|
7dbcfce46c | ||
|
|
ebd0552a2a | ||
|
|
343973263c | ||
|
|
e5220a8224 | ||
|
|
146120c210 | ||
|
|
807e4655a6 | ||
|
|
e32ebec197 | ||
|
|
8d8886390d | ||
|
|
5a2aa9d325 | ||
|
|
37aa1645dd | ||
|
|
052d074e92 | ||
|
|
8c551dc990 | ||
|
|
b2fcc190fd | ||
|
|
2325844bd4 | ||
|
|
f63517bb52 | ||
|
|
99d26f177b | ||
|
|
d6b28de586 | ||
|
|
e8d1567d07 | ||
|
|
cd8b484ae3 | ||
|
|
65b9735941 | ||
|
|
22f7e2a0ed | ||
|
|
2c5dc7390a | ||
|
|
c5e01b9578 | ||
|
|
882243316c | ||
|
|
1b62ed0c03 | ||
|
|
edb8c08a39 | ||
|
|
ad93387aea |
2
.github/ISSUE_TEMPLATE/issue-report.md
vendored
2
.github/ISSUE_TEMPLATE/issue-report.md
vendored
@@ -25,7 +25,7 @@ What version are you using?
|
||||
**Build**
|
||||
What runtime version are you using?
|
||||
|
||||
- [ ] .NET 9.0 running on (Operating System)
|
||||
- [ ] .NET 10 running on (Operating System)
|
||||
|
||||
**Describe the issue**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
85
.github/workflows/build_and_test.yml
vendored
85
.github/workflows/build_and_test.yml
vendored
@@ -1,40 +1,59 @@
|
||||
name: Build and Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
push:
|
||||
branches: ["master"]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
6.0.x
|
||||
8.0.x
|
||||
9.0.x
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
|
||||
- name: Run publish script
|
||||
run: ./publish-nix.sh -dp
|
||||
steps:
|
||||
- name: Free Disk Space (Ubuntu)
|
||||
uses: jlumbroso/free-disk-space@v1.3.1
|
||||
with:
|
||||
dotnet: false
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
allowUpdates: True
|
||||
artifacts: "*.nupkg,*.snupkg,*.zip"
|
||||
body: 'Last built commit: ${{ github.sha }}'
|
||||
name: 'Rolling Release'
|
||||
prerelease: True
|
||||
replacesArtifacts: True
|
||||
tag: "rolling"
|
||||
updateOnlyUnreleased: True
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
9.0.x
|
||||
10.0.x
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
|
||||
- name: Run publish script
|
||||
run: ./publish-nix.sh -dp
|
||||
|
||||
- name: Update rolling tag
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git tag -f rolling
|
||||
git push origin :refs/tags/rolling || true
|
||||
git push origin rolling --force
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.20.0
|
||||
with:
|
||||
allowUpdates: True
|
||||
artifacts: "*.nupkg,*.snupkg,*.zip"
|
||||
body: "Last built commit: ${{ github.sha }}
|
||||
|
||||
## UI Builds
|
||||
|
||||
[Windows x64 UI Release](https://github.com/SabreTools/MPF/releases/download/rolling/MPF.UI_net10.0-windows_win-x64_release.zip)
|
||||
|
||||
[Windows x64 UI Debug](https://github.com/SabreTools/MPF/releases/download/rolling/MPF.UI_net10.0-windows_win-x64_debug.zip)"
|
||||
name: "Rolling Release"
|
||||
prerelease: True
|
||||
replacesArtifacts: True
|
||||
tag: "rolling"
|
||||
updateOnlyUnreleased: True
|
||||
|
||||
39
.github/workflows/check_pr.yml
vendored
39
.github/workflows/check_pr.yml
vendored
@@ -3,24 +3,29 @@ name: Build PR
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Free Disk Space (Ubuntu)
|
||||
uses: jlumbroso/free-disk-space@v1.3.1
|
||||
with:
|
||||
dotnet: false
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
6.0.x
|
||||
8.0.x
|
||||
9.0.x
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
9.0.x
|
||||
10.0.x
|
||||
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Test
|
||||
run: dotnet test
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
|
||||
- name: Test
|
||||
run: dotnet test
|
||||
|
||||
18
.vscode/launch.json
vendored
18
.vscode/launch.json
vendored
@@ -10,7 +10,7 @@
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/MPF.Check/bin/Debug/net9.0/MPF.Check.dll",
|
||||
"program": "${workspaceFolder}/MPF.Check/bin/Debug/net10.0/MPF.Check.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/MPF.Check",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
@@ -24,7 +24,7 @@
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/MPF.CLI/bin/Debug/net9.0/MPF.CLI.dll",
|
||||
"program": "${workspaceFolder}/MPF.CLI/bin/Debug/net10.0/MPF.CLI.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/MPF.CLI",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
@@ -32,6 +32,20 @@
|
||||
"stopAtEntry": false,
|
||||
"justMyCode": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Launch (UI)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/MPF.UI/bin/Debug/net10.0-windows/MPF.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/MPF.UI",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false,
|
||||
"justMyCode": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
"type": "coreclr",
|
||||
|
||||
@@ -1,3 +1,86 @@
|
||||
### 3.6.0 (2025-11-28)
|
||||
|
||||
- Add BCA to list of files to select in Check UI
|
||||
- Move Zstd compression helper to base processor
|
||||
- Add file merge method in CleanRip
|
||||
- Implement file merging in CleanRip
|
||||
- Support reparsing of MPF-processed outputs
|
||||
- Use WriteToFile extension for zip entries
|
||||
- Move output file implementations to separate namespace
|
||||
- Conditionally require state
|
||||
- Replace "We" comments
|
||||
- Parse XboxOne/SX Title IDs
|
||||
- Reduce chance of empty strings
|
||||
- Initial UI lang code
|
||||
- Move to enum-based model for UI language options
|
||||
- Slight cleanup to main window language handling
|
||||
- Clean up nullability
|
||||
- Clean up a bit of element work
|
||||
- Fill in some gaps
|
||||
- Add UI by default to launch
|
||||
- Continue UI translation work
|
||||
- Minor formatting cleanup
|
||||
- Ensure readers and writers dispose
|
||||
- Complete translation support
|
||||
- Add skeleton for 8 more languages
|
||||
- Add 8 more language menu items
|
||||
- Add basic translation for 8 more languages
|
||||
- Make Check flags toggle if config used
|
||||
- Add console print when Check loads from config
|
||||
- Add Ukrainian translation (superg)
|
||||
- Add list configuration commandline feature
|
||||
- Handle a provided log zip in Check operation
|
||||
- Allow files to be zipped but not deleted
|
||||
- Fix long translated strings
|
||||
- Allow placeholder files to be used in Check
|
||||
- Make .img not required for DIC outputs
|
||||
- Handle log zip path in information extraction
|
||||
- Redumper state file is not accessed
|
||||
- Fix tests broken by last commit
|
||||
- Regex outputs should not name based on pattern
|
||||
- Make log archive handling more user-apparent
|
||||
- Be selective on which systems to enable skeleton
|
||||
- Readme updates for accuracy
|
||||
- Separate out default program paths
|
||||
- Add per-OS executable names
|
||||
- Simplify first-run CLI experience
|
||||
- Change CLI first-run wording
|
||||
- Free disk space for runners
|
||||
- Possibly fix missing options string
|
||||
- Minor Spanish cleanup
|
||||
- Update RedumpLib to 1.8.0
|
||||
- Limit visibility of Compatible OS text box
|
||||
- Stop using long name for default system setting
|
||||
- Updated Polish translation
|
||||
- Fix rolling tag
|
||||
- Try to add UI links to rolling release
|
||||
- Slight tweak to automatic UI links
|
||||
- Add hidden language (NovaAurora)
|
||||
- Fix langs
|
||||
- Fix issues with path assembly
|
||||
- Clean up submission info use and log link text
|
||||
- Update Redumper to build 658
|
||||
- Pre-compress all skeletons for multi-track CDs
|
||||
- Add DVD-Video to list of copy protection scanning systems
|
||||
- Update Redumper to build 660
|
||||
- Use dated default output filenames
|
||||
- Update packages
|
||||
- Scan disc image if not multi-track
|
||||
- Scan multi-track images for protection
|
||||
- Move and rename new protection scan method
|
||||
- Path scan after image scan
|
||||
- Update Redumper to build 663
|
||||
- Name some type parameters
|
||||
- Ensure volume label is trimmed if used in filenames
|
||||
- Remove DPM identifier for StarForce Keyless
|
||||
- New Redumper Drive Pregap Start option
|
||||
- Clarify the unmounted device case
|
||||
- Add support for .NET 10
|
||||
- Update Redumper to build 665
|
||||
- Disable Zstd PKZIP outputs
|
||||
- Add commented fix for Zstd PKZIP
|
||||
- Reenable Zstd PKZIP outputs
|
||||
|
||||
### 3.5.0 (2025-10-10)
|
||||
|
||||
- Add failure if media type could not be determined
|
||||
|
||||
@@ -146,9 +146,9 @@ namespace MPF.CLI.Features
|
||||
}
|
||||
|
||||
// Ensure we have the values we need
|
||||
if (CustomParams == null && (DevicePath == null || FilePath == null))
|
||||
if (CustomParams == null && DevicePath == null)
|
||||
{
|
||||
Console.Error.WriteLine("Both a device path and file path need to be supplied, exiting...");
|
||||
Console.Error.WriteLine("Either custom parameters or a device path need to be provided, exiting...");
|
||||
return false;
|
||||
}
|
||||
if (Options.InternalProgram == InternalProgram.DiscImageCreator
|
||||
@@ -160,6 +160,12 @@ namespace MPF.CLI.Features
|
||||
}
|
||||
|
||||
// Normalize the file path
|
||||
if (DevicePath != null && FilePath == null)
|
||||
{
|
||||
FilePath = $"track_{DateTime.Now:yyyyMMdd-HHmm}.bin";
|
||||
if (Options.DefaultOutputPath != null)
|
||||
FilePath = Path.Combine(Options.DefaultOutputPath, FilePath);
|
||||
}
|
||||
if (FilePath != null)
|
||||
FilePath = FrontendTool.NormalizeOutputPaths(FilePath, getFullPath: true);
|
||||
|
||||
@@ -235,6 +241,7 @@ namespace MPF.CLI.Features
|
||||
Console.WriteLine("?, h, help Show this help text");
|
||||
Console.WriteLine("version Print the program version");
|
||||
Console.WriteLine("lc, listcodes List supported comment/content site codes");
|
||||
Console.WriteLine("lo, listconfig List current configuration values");
|
||||
Console.WriteLine("lm, listmedia List supported media types");
|
||||
Console.WriteLine("ls, listsystems List supported system types");
|
||||
Console.WriteLine("lp, listprograms List supported dumping program outputs");
|
||||
@@ -246,7 +253,7 @@ namespace MPF.CLI.Features
|
||||
Console.WriteLine("-t, --mediatype <mediatype> Set media type for dumping (Required for DIC)");
|
||||
Console.WriteLine("-d, --device <devicepath> Physical drive path (Required if no custom parameters set)");
|
||||
Console.WriteLine("-m, --mounted <dirpath> Mounted filesystem path for additional checks");
|
||||
Console.WriteLine("-f, --file \"<filepath>\" Output file path (Required if no custom parameters set)");
|
||||
Console.WriteLine("-f, --file \"<filepath>\" Output file path (Recommended, uses defaults otherwise)");
|
||||
Console.WriteLine("-s, --speed <speed> Override default dumping speed");
|
||||
Console.WriteLine("-c, --custom \"<params>\" Custom parameters to use");
|
||||
Console.WriteLine();
|
||||
@@ -258,7 +265,7 @@ namespace MPF.CLI.Features
|
||||
|
||||
Console.WriteLine("Custom dumping parameters, if used, will fully replace the default parameters.");
|
||||
Console.WriteLine("All dumping parameters need to be supplied if doing this.");
|
||||
Console.WriteLine("Otherwise, both a drive path and output file path are required.");
|
||||
Console.WriteLine("Otherwise, a drive path is required.");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine("Mounted filesystem path is only recommended on OSes that require block");
|
||||
|
||||
@@ -38,11 +38,11 @@ namespace MPF.CLI.Features
|
||||
|
||||
// Create return values
|
||||
MediaType = SabreTools.RedumpLib.Data.MediaType.NONE;
|
||||
FilePath = Path.Combine(Options.DefaultOutputPath ?? "ISO", "track.bin");
|
||||
FilePath = Path.Combine(Options.DefaultOutputPath ?? "ISO", $"track_{DateTime.Now:yyyyMMdd-HHmm}.bin");
|
||||
System = Options.DefaultSystem;
|
||||
|
||||
// Create state values
|
||||
string? result = string.Empty;
|
||||
string? result;
|
||||
|
||||
root:
|
||||
Console.Clear();
|
||||
@@ -115,9 +115,9 @@ namespace MPF.CLI.Features
|
||||
dumpingProgram:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Options:");
|
||||
Console.WriteLine($"{InternalProgram.Redumper.ToString().ToLowerInvariant().PadRight(15)} => {InternalProgram.Redumper.LongName()}");
|
||||
Console.WriteLine($"{InternalProgram.DiscImageCreator.ToString().ToLowerInvariant().PadRight(15)} => {InternalProgram.DiscImageCreator.LongName()}");
|
||||
Console.WriteLine($"{InternalProgram.Aaru.ToString().ToLowerInvariant().PadRight(15)} => {InternalProgram.Aaru.LongName()}");
|
||||
Console.WriteLine($"{InternalProgram.Redumper.ToString().ToLowerInvariant(),-15} => {InternalProgram.Redumper.LongName()}");
|
||||
Console.WriteLine($"{InternalProgram.DiscImageCreator.ToString().ToLowerInvariant(),-15} => {InternalProgram.DiscImageCreator.LongName()}");
|
||||
Console.WriteLine($"{InternalProgram.Aaru.ToString().ToLowerInvariant(),-15} => {InternalProgram.Aaru.LongName()}");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the dumping program and press Enter:");
|
||||
Console.Write("> ");
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||
@@ -12,7 +12,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.5.0</VersionPrefix>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Title>MPF CLI</Title>
|
||||
@@ -31,11 +31,11 @@
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`)) OR $(TargetFramework.StartsWith(`net10`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -43,8 +43,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.3.2]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.7.4]" />
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.0]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -4,7 +4,6 @@ using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using MPF.CLI.Features;
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Features;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.CommandLine;
|
||||
@@ -20,19 +19,12 @@ namespace MPF.CLI
|
||||
var options = OptionsLoader.LoadFromConfig();
|
||||
if (options.FirstRun)
|
||||
{
|
||||
// Application paths
|
||||
options.AaruPath = "FILL ME IN";
|
||||
options.DiscImageCreatorPath = "FILL ME IN";
|
||||
options.RedumperPath = "FILL ME IN";
|
||||
options.InternalProgram = InternalProgram.NONE;
|
||||
|
||||
// Reset first run
|
||||
options.FirstRun = false;
|
||||
OptionsLoader.SaveToConfig(options);
|
||||
|
||||
// Display non-error message
|
||||
Console.WriteLine("First-run detected! Please fill out config.json and run again.");
|
||||
BaseFeature.DisplayHelp();
|
||||
Console.WriteLine("First-run detected! Please verify the generated config.json and run again.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,6 +50,7 @@ namespace MPF.CLI
|
||||
case Help: BaseFeature.DisplayHelp(); return;
|
||||
case VersionFeature version: version.Execute(); return;
|
||||
case ListCodesFeature lc: lc.Execute(); return;
|
||||
case ListConfigFeature lc: lc.Execute(); return;
|
||||
case ListMediaTypesFeature lm: lm.Execute(); return;
|
||||
case ListProgramsFeature lp: lp.Execute(); return;
|
||||
case ListSystemsFeature ls: ls.Execute(); return;
|
||||
@@ -127,6 +120,7 @@ namespace MPF.CLI
|
||||
commandSet.Add(new Help());
|
||||
commandSet.Add(new VersionFeature());
|
||||
commandSet.Add(new ListCodesFeature());
|
||||
commandSet.Add(new ListConfigFeature());
|
||||
commandSet.Add(new ListMediaTypesFeature());
|
||||
commandSet.Add(new ListSystemsFeature());
|
||||
commandSet.Add(new ListProgramsFeature());
|
||||
|
||||
@@ -97,13 +97,6 @@ namespace MPF.Check.Features
|
||||
// Loop through all the rest of the args
|
||||
for (int i = 0; i < Inputs.Count; i++)
|
||||
{
|
||||
// Check for a file
|
||||
if (!File.Exists(Inputs[i].Trim('"')))
|
||||
{
|
||||
Console.Error.WriteLine($"{Inputs[i].Trim('"')} does not exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the full file path
|
||||
string filepath = Path.GetFullPath(Inputs[i].Trim('"'));
|
||||
|
||||
@@ -135,12 +128,13 @@ namespace MPF.Check.Features
|
||||
public static void DisplayHelp()
|
||||
{
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine("MPF.Check <system> [options] </path/to/output.cue/iso> ...");
|
||||
Console.WriteLine("MPF.Check <system> [options] </path/to/output.cue|iso|_logs.zip> ...");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Standalone Options:");
|
||||
Console.WriteLine("?, h, help Show this help text");
|
||||
Console.WriteLine("version Print the program version");
|
||||
Console.WriteLine("lc, listcodes List supported comment/content site codes");
|
||||
Console.WriteLine("lo, listconfig List current configuration values");
|
||||
Console.WriteLine("lm, listmedia List supported media types");
|
||||
Console.WriteLine("ls, listsystems List supported system types");
|
||||
Console.WriteLine("lp, listprograms List supported dumping program outputs");
|
||||
@@ -166,9 +160,14 @@ namespace MPF.Check.Features
|
||||
Console.WriteLine("-j, --json Enable submission JSON output");
|
||||
Console.WriteLine(" --include-artifacts Include artifacts in JSON (requires --json)");
|
||||
Console.WriteLine("-z, --zip Enable log file compression");
|
||||
Console.WriteLine(" --log-compression Set the log compression type (requires --zip)");
|
||||
Console.WriteLine(" --log-compression Set the log compression type (requires compression enabled)");
|
||||
Console.WriteLine("-d, --delete Enable unnecessary file deletion");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("WARNING: If using a configuration file alongside any of the above options");
|
||||
Console.WriteLine("then flag options will act as toggles instead of always enabling.");
|
||||
Console.WriteLine("For example, if log compression is enabled in your configuration file, then");
|
||||
Console.WriteLine("providing the --zip option would disable compression.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("WARNING: Check will overwrite both any existing submission information files as well");
|
||||
Console.WriteLine("as any log archives. Please make backups of those if you need to before running Check.");
|
||||
Console.WriteLine();
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace MPF.Check.Features
|
||||
hideDriveLetters = false;
|
||||
|
||||
// Create state values
|
||||
string? result = string.Empty;
|
||||
string? result;
|
||||
|
||||
root:
|
||||
Console.Clear();
|
||||
@@ -212,7 +212,7 @@ namespace MPF.Check.Features
|
||||
if (program == InternalProgram.NONE)
|
||||
continue;
|
||||
|
||||
Console.WriteLine($"{program.ToString().ToLowerInvariant().PadRight(15)} => {program.LongName()}");
|
||||
Console.WriteLine($"{program.ToString().ToLowerInvariant(),-15} => {program.LongName()}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
@@ -262,7 +262,7 @@ namespace MPF.Check.Features
|
||||
Console.WriteLine("Options:");
|
||||
foreach (var compressionType in (LogCompression[])Enum.GetValues(typeof(LogCompression)))
|
||||
{
|
||||
Console.WriteLine($"{compressionType.ToString().ToLowerInvariant().PadRight(15)} => {compressionType.LongName()}");
|
||||
Console.WriteLine($"{compressionType.ToString().ToLowerInvariant(),-15} => {compressionType.LongName()}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
@@ -48,7 +49,7 @@ namespace MPF.Check.Features
|
||||
internal readonly StringInput LoadSeedInput = new(_loadSeedName, "--load-seed", "Load a seed submission JSON for user information");
|
||||
|
||||
private const string _logCompressionName = "log-compression";
|
||||
internal readonly StringInput LogCompressionInput = new(_logCompressionName, "--log-compression", "Set the log compression type (requires --zip)");
|
||||
internal readonly StringInput LogCompressionInput = new(_logCompressionName, "--log-compression", "Set the log compression type (requires compression enabled)");
|
||||
|
||||
private const string _noPlaceholdersName = "no-placeholders";
|
||||
internal readonly FlagInput NoPlaceholdersInput = new(_noPlaceholdersName, "--no-placeholders", "Disable placeholder values in submission info");
|
||||
@@ -150,6 +151,10 @@ namespace MPF.Check.Features
|
||||
RedumpPassword = null,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Options will be loaded from found configuration file!");
|
||||
}
|
||||
|
||||
// The first argument is the system type
|
||||
System = args[0].Trim('"').ToRedumpSystem();
|
||||
@@ -167,19 +172,19 @@ namespace MPF.Check.Features
|
||||
|
||||
// Disable placeholder values in submission info
|
||||
else if (NoPlaceholdersInput.ProcessInput(args, ref index))
|
||||
Options.AddPlaceholders = false;
|
||||
Options.AddPlaceholders = !Options.AddPlaceholders;
|
||||
|
||||
// Create IRD from output files (PS3 only)
|
||||
else if (CreateIrdInput.ProcessInput(args, ref index))
|
||||
Options.CreateIRDAfterDumping = true;
|
||||
Options.CreateIRDAfterDumping = !Options.CreateIRDAfterDumping;
|
||||
|
||||
// Set the log compression type (requires --zip)
|
||||
// Set the log compression type (requires compression enabled)
|
||||
else if (LogCompressionInput.ProcessInput(args, ref index))
|
||||
Options.LogCompression = LogCompressionInput.Value.ToLogCompression();
|
||||
|
||||
// Retrieve Redump match information
|
||||
else if (NoRetrieveInput.ProcessInput(args, ref index))
|
||||
Options.RetrieveMatchInformation = false;
|
||||
Options.RetrieveMatchInformation = !Options.RetrieveMatchInformation;
|
||||
|
||||
// Redump login
|
||||
else if (args[index].StartsWith("-c=") || args[index].StartsWith("--credentials="))
|
||||
@@ -205,7 +210,7 @@ namespace MPF.Check.Features
|
||||
|
||||
// Pull all information (requires Redump login)
|
||||
else if (PullAllInput.ProcessInput(args, ref index))
|
||||
Options.PullAllInformation = true;
|
||||
Options.PullAllInformation = !Options.PullAllInformation;
|
||||
|
||||
// Use a device path for physical checks
|
||||
else if (PathInput.ProcessInput(args, ref index))
|
||||
@@ -229,23 +234,23 @@ namespace MPF.Check.Features
|
||||
|
||||
// Add filename suffix
|
||||
else if (SuffixInput.ProcessInput(args, ref index))
|
||||
Options.AddFilenameSuffix = true;
|
||||
Options.AddFilenameSuffix = !Options.AddFilenameSuffix;
|
||||
|
||||
// Output submission JSON
|
||||
else if (JsonInput.ProcessInput(args, ref index))
|
||||
Options.OutputSubmissionJSON = true;
|
||||
Options.OutputSubmissionJSON = !Options.OutputSubmissionJSON;
|
||||
|
||||
// Include JSON artifacts
|
||||
else if (IncludeArtifactsInput.ProcessInput(args, ref index))
|
||||
Options.IncludeArtifacts = true;
|
||||
Options.IncludeArtifacts = !Options.IncludeArtifacts;
|
||||
|
||||
// Compress log and extraneous files
|
||||
else if (ZipInput.ProcessInput(args, ref index))
|
||||
Options.CompressLogFiles = true;
|
||||
Options.CompressLogFiles = !Options.CompressLogFiles;
|
||||
|
||||
// Delete unnecessary files
|
||||
else if (DeleteInput.ProcessInput(args, ref index))
|
||||
Options.DeleteUnnecessaryFiles = true;
|
||||
Options.DeleteUnnecessaryFiles = !Options.DeleteUnnecessaryFiles;
|
||||
|
||||
// Default, add to inputs
|
||||
else
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||
@@ -12,7 +12,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.5.0</VersionPrefix>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Title>MPF Check</Title>
|
||||
@@ -31,11 +31,11 @@
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`)) OR $(TargetFramework.StartsWith(`net10`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -43,8 +43,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.3.2]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.7.4]" />
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.0]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -36,6 +36,7 @@ namespace MPF.Check
|
||||
case Help: BaseFeature.DisplayHelp(); return;
|
||||
case VersionFeature version: version.Execute(); return;
|
||||
case ListCodesFeature lc: lc.Execute(); return;
|
||||
case ListConfigFeature lc: lc.Execute(); return;
|
||||
case ListMediaTypesFeature lm: lm.Execute(); return;
|
||||
case ListProgramsFeature lp: lp.Execute(); return;
|
||||
case ListSystemsFeature ls: ls.Execute(); return;
|
||||
@@ -107,6 +108,7 @@ namespace MPF.Check
|
||||
commandSet.Add(new Help());
|
||||
commandSet.Add(new VersionFeature());
|
||||
commandSet.Add(new ListCodesFeature());
|
||||
commandSet.Add(new ListConfigFeature());
|
||||
commandSet.Add(new ListMediaTypesFeature());
|
||||
commandSet.Add(new ListSystemsFeature());
|
||||
commandSet.Add(new ListProgramsFeature());
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
#region Default Values
|
||||
|
||||
private static Dictionary<string, string?> AllOptions = new()
|
||||
private static readonly Dictionary<string, string?> AllOptions = new()
|
||||
{
|
||||
[SettingConstants.EnableDebug] = "true",
|
||||
[SettingConstants.EnableVerbose] = "true",
|
||||
@@ -514,4 +514,4 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,4 +461,4 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
#region Default Values
|
||||
|
||||
private static Dictionary<string, string?> AllOptions = new()
|
||||
private static readonly Dictionary<string, string?> AllOptions = new()
|
||||
{
|
||||
[SettingConstants.DVDRereadCount] = "1000",
|
||||
[SettingConstants.MultiSectorRead] = "true",
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", new string[] { "flag" }, 0, true, true)]
|
||||
public void FlagInputTest(string name, string[] parts, int index, bool success, bool expected)
|
||||
{
|
||||
FlagInput input = new FlagInput(name);
|
||||
var input = new FlagInput(name);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -55,7 +55,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=false" }, 0, true, false)]
|
||||
public void BooleanInputTest(string name, bool required, string[] parts, int index, bool success, bool? expected)
|
||||
{
|
||||
BooleanInput input = new BooleanInput(name, required);
|
||||
var input = new BooleanInput(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -90,7 +90,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=-1" }, 0, true, (sbyte)-1)]
|
||||
public void Int8InputTest(string name, bool required, string[] parts, int index, bool success, sbyte? expected)
|
||||
{
|
||||
Int8Input input = new Int8Input(name, required);
|
||||
var input = new Int8Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -123,7 +123,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (byte)1)]
|
||||
public void UInt8InputTest(string name, bool required, string[] parts, int index, bool success, byte? expected)
|
||||
{
|
||||
UInt8Input input = new UInt8Input(name, required);
|
||||
var input = new UInt8Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -158,7 +158,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=-1" }, 0, true, (short)-1)]
|
||||
public void Int16InputTest(string name, bool required, string[] parts, int index, bool success, short? expected)
|
||||
{
|
||||
Int16Input input = new Int16Input(name, required);
|
||||
var input = new Int16Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -191,7 +191,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (ushort)1)]
|
||||
public void UInt16InputTest(string name, bool required, string[] parts, int index, bool success, ushort? expected)
|
||||
{
|
||||
UInt16Input input = new UInt16Input(name, required);
|
||||
var input = new UInt16Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -226,7 +226,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=-1" }, 0, true, (int)-1)]
|
||||
public void Int32InputTest(string name, bool required, string[] parts, int index, bool success, int? expected)
|
||||
{
|
||||
Int32Input input = new Int32Input(name, required);
|
||||
var input = new Int32Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -259,7 +259,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (uint)1)]
|
||||
public void UInt32InputTest(string name, bool required, string[] parts, int index, bool success, uint? expected)
|
||||
{
|
||||
UInt32Input input = new UInt32Input(name, required);
|
||||
var input = new UInt32Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -294,7 +294,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=-1" }, 0, true, (long)-1)]
|
||||
public void Int64InputTest(string name, bool required, string[] parts, int index, bool success, long? expected)
|
||||
{
|
||||
Int64Input input = new Int64Input(name, required);
|
||||
var input = new Int64Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -327,7 +327,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (ulong)1)]
|
||||
public void UInt64InputTest(string name, bool required, string[] parts, int index, bool success, ulong? expected)
|
||||
{
|
||||
UInt64Input input = new UInt64Input(name, required);
|
||||
var input = new UInt64Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -355,7 +355,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=value" }, 0, true, "value")]
|
||||
public void StringInputTest(string name, bool required, string[] parts, int index, bool success, string? expected)
|
||||
{
|
||||
StringInput input = new StringInput(name, required);
|
||||
var input = new StringInput(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -407,4 +407,4 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -14,13 +14,13 @@
|
||||
</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="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.7.4]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.0]" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.24.0" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.25.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" />
|
||||
|
||||
@@ -27,10 +27,10 @@ namespace MPF.ExecutionContexts.Test
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Default Values
|
||||
|
||||
private static Dictionary<string, string?> AllOptions = new()
|
||||
private static readonly Dictionary<string, string?> AllOptions = new()
|
||||
{
|
||||
[SettingConstants.EnableVerbose] = "true",
|
||||
[SettingConstants.LeadinRetryCount] = "1000",
|
||||
|
||||
@@ -86,4 +86,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string WesternEuropeanMac = "macintosh";
|
||||
public const string WesternEuropeanRadix50 = "radix50";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,7 +538,11 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
if (string.IsNullOrEmpty(InputValue))
|
||||
return null;
|
||||
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (InputValue!.Contains(' '))
|
||||
#else
|
||||
if (InputValue!.Contains(" "))
|
||||
#endif
|
||||
parameters.Append($"\"{InputValue!.TrimEnd('\\')}\" ");
|
||||
else
|
||||
parameters.Append($"{InputValue!.TrimEnd('\\')} ");
|
||||
|
||||
@@ -170,4 +170,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,4 +166,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string XboxPartitioning = "Xbox partitioning";
|
||||
public const string XENIX = "XENIX";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,4 +24,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string WindowsNT83MixedCase = "nt";
|
||||
public const string OS2Extended = "os2";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string VMwareDiskImageSparse = "sparse"; // boolean, default false
|
||||
public const string VMwareDiskImageSplit = "split"; // boolean, default false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string StripPersonalData = "AaruStripPersonalData";
|
||||
public const bool StripPersonalDataDefault = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,9 +51,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -120,4 +120,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,4 +70,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
@@ -124,49 +122,77 @@ namespace MPF.ExecutionContexts.Data
|
||||
factor = 1;
|
||||
|
||||
// Characters
|
||||
if (value.EndsWith("c", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (value.EndsWith('c'))
|
||||
#else
|
||||
if (value.EndsWith("c", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 1;
|
||||
value = value.TrimEnd('c');
|
||||
}
|
||||
|
||||
// Words
|
||||
else if (value.EndsWith("w", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('w'))
|
||||
#else
|
||||
else if (value.EndsWith("w", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 2;
|
||||
value = value.TrimEnd('w');
|
||||
}
|
||||
|
||||
// Double Words
|
||||
else if (value.EndsWith("d", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('d'))
|
||||
#else
|
||||
else if (value.EndsWith("d", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 4;
|
||||
value = value.TrimEnd('d');
|
||||
}
|
||||
|
||||
// Quad Words
|
||||
else if (value.EndsWith("q", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('q'))
|
||||
#else
|
||||
else if (value.EndsWith("q", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 8;
|
||||
value = value.TrimEnd('q');
|
||||
}
|
||||
|
||||
// Kilobytes
|
||||
else if (value.EndsWith("k", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('k'))
|
||||
#else
|
||||
else if (value.EndsWith("k", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 1024;
|
||||
value = value.TrimEnd('k');
|
||||
}
|
||||
|
||||
// Megabytes
|
||||
else if (value.EndsWith("M", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('M'))
|
||||
#else
|
||||
else if (value.EndsWith("M", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 1024 * 1024;
|
||||
value = value.TrimEnd('M');
|
||||
}
|
||||
|
||||
// Gigabytes
|
||||
else if (value.EndsWith("G", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('G'))
|
||||
#else
|
||||
else if (value.EndsWith("G", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 1024 * 1024 * 1024;
|
||||
value = value.TrimEnd('G');
|
||||
@@ -189,7 +215,11 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (value[1] != 'x' && value[1] != 'X')
|
||||
return value;
|
||||
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
return value[2..];
|
||||
#else
|
||||
return value.Substring(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -258,4 +288,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,9 +74,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
int?[] nonNull = Array.FindAll(Value, i => i != null);
|
||||
@@ -158,4 +158,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,9 +64,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
if (Quotes)
|
||||
@@ -123,4 +123,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,4 +32,4 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
public const string XGD2Swap = "xgd2swap";
|
||||
public const string XGD3Swap = "xgd3swap";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,4 +97,4 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
@@ -441,7 +440,11 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
{
|
||||
if (DrivePath != null)
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (DrivePath.Contains(' '))
|
||||
#else
|
||||
if (DrivePath.Contains(" "))
|
||||
#endif
|
||||
parameters.Append($"\"{DrivePath}\" ");
|
||||
else
|
||||
parameters.Append($"{DrivePath} ");
|
||||
|
||||
@@ -47,4 +47,4 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
public const string VideoNowColor = "/vnc";
|
||||
public const string VideoNowXP = "/vnx";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,4 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
public const string UseCMIFlag = "DICUseCMIFlag";
|
||||
public const bool UseCMIFlagDefault = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
@@ -11,7 +11,7 @@
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.5.0</VersionPrefix>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
<WarningsNotAsErrors>NU5104</WarningsNotAsErrors>
|
||||
|
||||
<!-- Package Properties -->
|
||||
@@ -32,7 +32,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.7.4]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.0]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -29,4 +29,4 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string DebugFlip = "debug::flip";
|
||||
public const string DriveTest = "drive::test";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,4 +29,4 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
@@ -119,6 +120,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
//[FlagStrings.Firmware] = new StringInput(FlagStrings.Firmware) { Quotes = true },
|
||||
[FlagStrings.SkipSubcodeDesync] = new FlagInput(FlagStrings.SkipSubcodeDesync),
|
||||
[FlagStrings.Rings] = new FlagInput(FlagStrings.Rings),
|
||||
[FlagStrings.CdrErrorThreshold] = new Int32Input(FlagStrings.CdrErrorThreshold),
|
||||
|
||||
// Undocumented
|
||||
[FlagStrings.Debug] = new FlagInput(FlagStrings.Debug),
|
||||
@@ -217,6 +219,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
//FlagStrings.Firmware,
|
||||
FlagStrings.SkipSubcodeDesync,
|
||||
FlagStrings.Rings,
|
||||
FlagStrings.CdrErrorThreshold,
|
||||
|
||||
// Undocumented
|
||||
FlagStrings.Debug,
|
||||
@@ -313,22 +316,42 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
}
|
||||
if (GetBooleanSetting(options, SettingConstants.EnableSkeleton, SettingConstants.EnableSkeletonDefault))
|
||||
{
|
||||
// Enable skeleton for CD and DVD only, by default
|
||||
switch (MediaType)
|
||||
switch (RedumpSystem)
|
||||
{
|
||||
case SabreTools.RedumpLib.Data.MediaType.CDROM:
|
||||
case SabreTools.RedumpLib.Data.MediaType.DVD:
|
||||
this[FlagStrings.Skeleton] = true;
|
||||
(_inputs[FlagStrings.Skeleton] as FlagInput)?.SetValue(true);
|
||||
break;
|
||||
|
||||
// If the type is unknown, also enable
|
||||
case null:
|
||||
this[FlagStrings.Skeleton] = true;
|
||||
(_inputs[FlagStrings.Skeleton] as FlagInput)?.SetValue(true);
|
||||
// Systems known to have significant data outside the ISO9660 filesystem
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.MicrosoftXbox:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.MicrosoftXbox360:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.PlaymajiPolymega:
|
||||
// Skeletons from newer BD-based consoles unnecessary
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.MicrosoftXboxOne:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.MicrosoftXboxSeriesXS:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.SonyPlayStation3:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.SonyPlayStation4:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.SonyPlayStation5:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.NintendoWiiU:
|
||||
break;
|
||||
|
||||
default:
|
||||
// Enable skeleton for CD and DVD only, by default
|
||||
switch (MediaType)
|
||||
{
|
||||
case SabreTools.RedumpLib.Data.MediaType.CDROM:
|
||||
case SabreTools.RedumpLib.Data.MediaType.DVD:
|
||||
{
|
||||
this[FlagStrings.Skeleton] = true;
|
||||
(_inputs[FlagStrings.Skeleton] as FlagInput)?.SetValue(true);
|
||||
}
|
||||
break;
|
||||
|
||||
// If the type is unknown, also enable
|
||||
case null:
|
||||
this[FlagStrings.Skeleton] = true;
|
||||
(_inputs[FlagStrings.Skeleton] as FlagInput)?.SetValue(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -340,6 +363,13 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
(_inputs[FlagStrings.DriveReadMethod] as StringInput)?.SetValue(readMethod!);
|
||||
}
|
||||
|
||||
int drivePregapStart = GetInt32Setting(options, SettingConstants.DrivePregapStart, SettingConstants.DrivePregapStartDefault);
|
||||
if (drivePregapStart != SettingConstants.DrivePregapStartDefault)
|
||||
{
|
||||
this[FlagStrings.DrivePregapStart] = true;
|
||||
(_inputs[FlagStrings.DrivePregapStart] as Int32Input)?.SetValue(drivePregapStart);
|
||||
}
|
||||
|
||||
string? sectorOrder = GetStringSetting(options, SettingConstants.SectorOrder, SettingConstants.SectorOrderDefault);
|
||||
if (!string.IsNullOrEmpty(sectorOrder) && sectorOrder != SectorOrder.NONE.ToString())
|
||||
{
|
||||
@@ -447,7 +477,11 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
|
||||
// Default is either a flag or an invalid mode
|
||||
default:
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (part.StartsWith('-'))
|
||||
#else
|
||||
if (part.StartsWith("-"))
|
||||
#endif
|
||||
{
|
||||
isFlag = true;
|
||||
break;
|
||||
@@ -480,7 +514,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
|
||||
// If the image name was not set, set it with a default value
|
||||
if (string.IsNullOrEmpty((_inputs[FlagStrings.ImageName] as StringInput)?.Value))
|
||||
(_inputs[FlagStrings.ImageName] as StringInput)?.SetValue("track");
|
||||
(_inputs[FlagStrings.ImageName] as StringInput)?.SetValue($"track_{DateTime.Now:yyyyMMdd-HHmm}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string Firmware = "--firmware";
|
||||
public const string SkipSubcodeDesync = "--skip-subcode-desync";
|
||||
public const string Rings = "--rings";
|
||||
public const string CdrErrorThreshold = "--cdr-error-threshold";
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string LeadinRetryCount = "RedumperLeadinRetryCount";
|
||||
public const int LeadinRetryCountDefault = 4;
|
||||
|
||||
public const string DrivePregapStart = "RedumperDrivePregapStart";
|
||||
public const int DrivePregapStartDefault = 0;
|
||||
|
||||
public const string ReadMethod = "RedumperReadMethod";
|
||||
public static readonly string ReadMethodDefault = Redumper.ReadMethod.NONE.ToString();
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace MPF.Frontend.Test
|
||||
public static List<object?[]> GenerateDriveTypeMappingTestData()
|
||||
{
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
foreach (DriveType driveType in Enum.GetValues(typeof(DriveType)))
|
||||
foreach (DriveType driveType in Enum.GetValues<DriveType>())
|
||||
{
|
||||
if (Array.IndexOf(_mappableDriveTypes, driveType) > -1)
|
||||
testData.Add([driveType, false]);
|
||||
|
||||
@@ -14,6 +14,33 @@ namespace MPF.Frontend.Test
|
||||
{
|
||||
#region Long Name
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(InterfaceLanguage.AutoDetect, "Auto Detect")]
|
||||
[InlineData(InterfaceLanguage.English, "English")]
|
||||
[InlineData(InterfaceLanguage.French, "Français")]
|
||||
[InlineData(InterfaceLanguage.German, "Deutsch")]
|
||||
[InlineData(InterfaceLanguage.Italian, "Italiano")]
|
||||
[InlineData(InterfaceLanguage.Japanese, "日本語")]
|
||||
[InlineData(InterfaceLanguage.Korean, "한국어")]
|
||||
[InlineData(InterfaceLanguage.Polish, "Polski")]
|
||||
[InlineData(InterfaceLanguage.Russian, "Русский")]
|
||||
[InlineData(InterfaceLanguage.Spanish, "Español")]
|
||||
[InlineData(InterfaceLanguage.Swedish, "Svenska")]
|
||||
[InlineData(InterfaceLanguage.Ukrainian, "Українська")]
|
||||
[InlineData(InterfaceLanguage.L337, "L337")]
|
||||
public void LongName_InterfaceLanguage(InterfaceLanguage? lang, string? expected)
|
||||
{
|
||||
string? actual = lang.LongName();
|
||||
Assert.Equal(expected, actual);
|
||||
|
||||
if (lang != null)
|
||||
{
|
||||
actual = EnumExtensions.GetLongName(lang);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(InternalProgram.NONE, "Unknown")]
|
||||
@@ -115,6 +142,27 @@ namespace MPF.Frontend.Test
|
||||
|
||||
#region Short Name
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(InterfaceLanguage.AutoDetect, "auto")]
|
||||
[InlineData(InterfaceLanguage.English, "eng")]
|
||||
[InlineData(InterfaceLanguage.French, "fra")]
|
||||
[InlineData(InterfaceLanguage.German, "deu")]
|
||||
[InlineData(InterfaceLanguage.Italian, "ita")]
|
||||
[InlineData(InterfaceLanguage.Japanese, "jpn")]
|
||||
[InlineData(InterfaceLanguage.Korean, "kor")]
|
||||
[InlineData(InterfaceLanguage.Polish, "pol")]
|
||||
[InlineData(InterfaceLanguage.Russian, "rus")]
|
||||
[InlineData(InterfaceLanguage.Spanish, "spa")]
|
||||
[InlineData(InterfaceLanguage.Swedish, "swe")]
|
||||
[InlineData(InterfaceLanguage.Ukrainian, "ukr")]
|
||||
[InlineData(InterfaceLanguage.L337, "l37")]
|
||||
public void ShortName_InterfaceLanguage(InterfaceLanguage? lang, string? expected)
|
||||
{
|
||||
string? actual = lang.ShortName();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(InternalProgram.NONE, "Unknown")]
|
||||
@@ -135,6 +183,28 @@ namespace MPF.Frontend.Test
|
||||
|
||||
#region From String
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, InterfaceLanguage.AutoDetect)]
|
||||
[InlineData("", InterfaceLanguage.AutoDetect)]
|
||||
[InlineData("auto", InterfaceLanguage.AutoDetect)]
|
||||
[InlineData("eng", InterfaceLanguage.English)]
|
||||
[InlineData("fra", InterfaceLanguage.French)]
|
||||
[InlineData("deu", InterfaceLanguage.German)]
|
||||
[InlineData("ita", InterfaceLanguage.Italian)]
|
||||
[InlineData("jpn", InterfaceLanguage.Japanese)]
|
||||
[InlineData("kor", InterfaceLanguage.Korean)]
|
||||
[InlineData("pol", InterfaceLanguage.Polish)]
|
||||
[InlineData("rus", InterfaceLanguage.Russian)]
|
||||
[InlineData("spa", InterfaceLanguage.Spanish)]
|
||||
[InlineData("swe", InterfaceLanguage.Swedish)]
|
||||
[InlineData("ukr", InterfaceLanguage.Ukrainian)]
|
||||
[InlineData("l37", InterfaceLanguage.L337)]
|
||||
public void ToInterfaceLanguageTest(string? interfaceLanguage, InterfaceLanguage expected)
|
||||
{
|
||||
InterfaceLanguage actual = interfaceLanguage.ToInterfaceLanguage();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, InternalProgram.NONE)]
|
||||
[InlineData("", InternalProgram.NONE)]
|
||||
@@ -165,6 +235,7 @@ namespace MPF.Frontend.Test
|
||||
private static readonly RedumpSystem?[] _copyProtectionSystems =
|
||||
[
|
||||
RedumpSystem.AppleMacintosh,
|
||||
RedumpSystem.DVDVideo,
|
||||
RedumpSystem.EnhancedCD ,
|
||||
RedumpSystem.IBMPCcompatible,
|
||||
RedumpSystem.PalmOS,
|
||||
@@ -192,7 +263,7 @@ namespace MPF.Frontend.Test
|
||||
public static List<object?[]> GenerateSupportsAntiModchipScansData()
|
||||
{
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues<RedumpSystem>())
|
||||
{
|
||||
if (_antiModchipSystems.Contains(redumpSystem))
|
||||
testData.Add([redumpSystem, true]);
|
||||
@@ -206,7 +277,7 @@ namespace MPF.Frontend.Test
|
||||
public static List<object?[]> GenerateSupportsCopyProtectionScansData()
|
||||
{
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues<RedumpSystem>())
|
||||
{
|
||||
if (_copyProtectionSystems.Contains(redumpSystem))
|
||||
testData.Add([redumpSystem, true]);
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace MPF.Frontend.Test
|
||||
public void GetAllowedDriveSpeedForMediaTypeTest(MediaType? mediaType, int maxExpected)
|
||||
{
|
||||
var actual = InterfaceConstants.GetSpeedsForMediaType(mediaType);
|
||||
Assert.Equal(maxExpected, actual[actual.Count - 1]);
|
||||
Assert.Equal(maxExpected, actual[^1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -14,13 +14,13 @@
|
||||
</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="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.7.4]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.0]" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.24.0" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.25.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" />
|
||||
|
||||
@@ -44,4 +44,4 @@ namespace MPF.Frontend.Test
|
||||
Assert.Equal(expectedValue, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
[InlineData(MediaType.NintendoWiiUOpticalDisc, 16)]
|
||||
public void GetDefaultSpeedForMediaTypeTest(MediaType? mediaType, int expected)
|
||||
{
|
||||
Options options = new Options
|
||||
var options = new Options
|
||||
{
|
||||
PreferredDumpSpeedCD = 72,
|
||||
PreferredDumpSpeedDVD = 24,
|
||||
@@ -97,4 +97,4 @@ namespace MPF.Frontend.Test.Tools
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Data.Sections;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Frontend.Test.Tools
|
||||
@@ -10,7 +9,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
public class InfoToolTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsCompleteTest()
|
||||
public void ProcessSpecialFields_Complete()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
@@ -36,9 +35,9 @@ namespace MPF.Frontend.Test.Tools
|
||||
|
||||
// Validate the basics
|
||||
Assert.NotNull(info.CommonDiscInfo.Comments);
|
||||
Assert.Null(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.NotNull(info.CommonDiscInfo.Contents);
|
||||
Assert.Null(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
|
||||
// Split the values
|
||||
string[] splitComments = info.CommonDiscInfo.Comments.Split('\n');
|
||||
@@ -50,23 +49,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsNullObjectTest()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
{
|
||||
CommonDiscInfo = null,
|
||||
};
|
||||
|
||||
// Process the special fields
|
||||
Formatter.ProcessSpecialFields(info);
|
||||
|
||||
// Validate
|
||||
Assert.Null(info.CommonDiscInfo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsNullCommentsContentsTest()
|
||||
public void ProcessSpecialFields_NullStrings()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
@@ -92,9 +75,9 @@ namespace MPF.Frontend.Test.Tools
|
||||
|
||||
// Validate the basics
|
||||
Assert.NotNull(info.CommonDiscInfo.Comments);
|
||||
Assert.Null(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.NotNull(info.CommonDiscInfo.Contents);
|
||||
Assert.Null(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
|
||||
// Split the values
|
||||
string[] splitComments = info.CommonDiscInfo.Comments.Split('\n');
|
||||
@@ -106,7 +89,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsNullDictionariesTest()
|
||||
public void ProcessSpecialFields_EmptyDictionaries()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
@@ -114,10 +97,10 @@ namespace MPF.Frontend.Test.Tools
|
||||
CommonDiscInfo = new CommonDiscInfoSection()
|
||||
{
|
||||
Comments = "This is a comments line\n[T:ISBN] ISBN Value",
|
||||
CommentsSpecialFields = null,
|
||||
CommentsSpecialFields = [],
|
||||
|
||||
Contents = "This is a contents line\n[T:GF] Game Footage",
|
||||
ContentsSpecialFields = null,
|
||||
ContentsSpecialFields = [],
|
||||
}
|
||||
};
|
||||
|
||||
@@ -126,9 +109,9 @@ namespace MPF.Frontend.Test.Tools
|
||||
|
||||
// Validate the basics
|
||||
Assert.NotNull(info.CommonDiscInfo.Comments);
|
||||
Assert.Null(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.NotNull(info.CommonDiscInfo.Contents);
|
||||
Assert.Null(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
|
||||
// Split the values
|
||||
string[] splitComments = info.CommonDiscInfo.Comments.Split('\n');
|
||||
|
||||
@@ -661,7 +661,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
throw new ArgumentException("Invalid skip value", nameof(skip));
|
||||
|
||||
// The list is in order of preference
|
||||
protections = protections.Skip(skip).ToList();
|
||||
protections = [.. protections.Skip(skip)];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal(protections[0], sanitized);
|
||||
@@ -711,7 +711,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
throw new ArgumentException("Invalid skip value", nameof(skip));
|
||||
|
||||
// The list is in order of preference
|
||||
protections = protections.Skip(skip).ToList();
|
||||
protections = [.. protections.Skip(skip)];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal(expected, sanitized);
|
||||
@@ -770,12 +770,27 @@ namespace MPF.Frontend.Test.Tools
|
||||
throw new ArgumentException("Invalid skip value", nameof(skip));
|
||||
|
||||
// The list is in order of preference
|
||||
protections = protections.Skip(skip).ToList();
|
||||
protections = [.. protections.Skip(skip)];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal(protections[0], sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_StarForce_Keyless()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"StarForce Keyless",
|
||||
"StarForce Keyless - ",
|
||||
"StarForce Keyless - ESPY97LS8FHNYR52JDWL8D6FJ",
|
||||
"StarForce Keyless - UAYA-RPMVHJ-ZRY45G-ETUJ36-WL922B",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("StarForce Keyless", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_Sysiphus()
|
||||
{
|
||||
|
||||
@@ -6,18 +6,18 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
/// <summary>
|
||||
/// A generic combo box element
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Enum type representing the possible values</typeparam>
|
||||
public class Element<T> : IEquatable<Element<T>>, IElement where T : struct, Enum
|
||||
/// <typeparam name="TEnum">Enum type representing the possible values</typeparam>
|
||||
public class Element<TEnum> : IEquatable<Element<TEnum>>, IElement where TEnum : struct, Enum
|
||||
{
|
||||
private readonly T Data;
|
||||
private readonly TEnum Data;
|
||||
|
||||
public Element(T data) => Data = data;
|
||||
public Element(TEnum data) => Data = data;
|
||||
|
||||
/// <summary>
|
||||
/// Allow elements to be used as their internal enum type
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public static implicit operator T? (Element<T> item) => item?.Data;
|
||||
public static implicit operator TEnum?(Element<TEnum> item) => item?.Data;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string Name => EnumExtensions.GetLongName(Data);
|
||||
@@ -27,7 +27,7 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
/// <summary>
|
||||
/// Internal enum value
|
||||
/// </summary>
|
||||
public T Value => Data;
|
||||
public TEnum Value => Data;
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the item is selected or not
|
||||
@@ -39,20 +39,20 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
/// Generate all elements associated with the data enum type
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<Element<T>> GenerateElements()
|
||||
public static List<Element<TEnum>> GenerateElements()
|
||||
{
|
||||
var enumArr = (T[])Enum.GetValues(typeof(T));
|
||||
return [.. Array.ConvertAll(enumArr, e => new Element<T>(e))];
|
||||
var enumArr = (TEnum[])Enum.GetValues(typeof(TEnum));
|
||||
return [.. Array.ConvertAll(enumArr, e => new Element<TEnum>(e))];
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return Equals(obj as Element<T>);
|
||||
return Equals(obj as Element<TEnum>);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(Element<T>? other)
|
||||
public bool Equals(Element<TEnum>? other)
|
||||
{
|
||||
if (other == null)
|
||||
return false;
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
|
||||
var systemsValues = new List<RedumpSystemComboBoxItem>
|
||||
{
|
||||
new RedumpSystemComboBoxItem((RedumpSystem?)null),
|
||||
new((RedumpSystem?)null),
|
||||
};
|
||||
|
||||
foreach (var group in mapping)
|
||||
|
||||
@@ -86,7 +86,11 @@ namespace MPF.Frontend
|
||||
|
||||
// Sanitize a Windows-formatted long device path
|
||||
if (devicePath.StartsWith("\\\\.\\"))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
devicePath = devicePath["\\\\.\\".Length..];
|
||||
#else
|
||||
devicePath = devicePath.Substring("\\\\.\\".Length);
|
||||
#endif
|
||||
|
||||
// Create and validate the drive info object
|
||||
var driveInfo = new DriveInfo(devicePath);
|
||||
|
||||
@@ -81,11 +81,7 @@ namespace MPF.Frontend
|
||||
public int? Speed
|
||||
{
|
||||
get => _executionContext?.Speed;
|
||||
set
|
||||
{
|
||||
if (_executionContext != null)
|
||||
_executionContext.Speed = value;
|
||||
}
|
||||
set => _executionContext?.Speed = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Extensions.LongName(RedumpSystem?)/>
|
||||
@@ -292,7 +288,7 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
/// <param name="type">MediaType value to check</param>
|
||||
/// <returns>True if the media has variable dumping speeds, false otherwise</returns>
|
||||
public bool DoesSupportDriveSpeed(MediaType? mediaType)
|
||||
public static bool DoesSupportDriveSpeed(MediaType? mediaType)
|
||||
{
|
||||
return mediaType switch
|
||||
{
|
||||
@@ -486,6 +482,17 @@ namespace MPF.Frontend
|
||||
var outputDirectory = Path.GetDirectoryName(OutputPath);
|
||||
var outputFilename = Path.GetFileName(OutputPath);
|
||||
|
||||
// If a standard log zip was provided, replace the suffix with ".tmp" for easier processing
|
||||
if (outputFilename.EndsWith("_logs.zip", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
int zipSuffixIndex = outputFilename.LastIndexOf("_logs.zip", StringComparison.OrdinalIgnoreCase);
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
outputFilename = outputFilename[..zipSuffixIndex] + ".tmp";
|
||||
#else
|
||||
outputFilename = outputFilename.Substring(0, zipSuffixIndex) + ".tmp";
|
||||
#endif
|
||||
}
|
||||
|
||||
// Determine the media type from the processor
|
||||
MediaType? mediaType = _processor.DetermineMediaType(outputDirectory, outputFilename);
|
||||
if (mediaType == null)
|
||||
@@ -610,7 +617,7 @@ namespace MPF.Frontend
|
||||
if (_options.CreateIRDAfterDumping && _system == RedumpSystem.SonyPlayStation3 && mediaType == MediaType.BluRay)
|
||||
{
|
||||
resultProgress.Report(ResultEventArgs.Success("Creating IRD... please wait!"));
|
||||
bool deleteSuccess = await IRDTool.WriteIRD(OutputPath, submissionInfo?.Extras?.DiscKey, submissionInfo?.Extras?.DiscID, submissionInfo?.Extras?.PIC, submissionInfo?.SizeAndChecksums?.Layerbreak, submissionInfo?.SizeAndChecksums?.CRC32);
|
||||
bool deleteSuccess = await IRDTool.WriteIRD(OutputPath, submissionInfo?.Extras?.DiscKey, submissionInfo?.Extras?.DiscID, submissionInfo?.Extras?.PIC, submissionInfo?.SizeAndChecksums.Layerbreak, submissionInfo?.SizeAndChecksums.CRC32);
|
||||
if (deleteSuccess)
|
||||
resultProgress.Report(ResultEventArgs.Success("IRD created!"));
|
||||
else
|
||||
@@ -771,7 +778,7 @@ namespace MPF.Frontend
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -815,7 +822,11 @@ namespace MPF.Frontend
|
||||
{
|
||||
string scanPath = key;
|
||||
if (hideDriveLetters)
|
||||
scanPath = Path.DirectorySeparatorChar + key.Substring((Path.GetPathRoot(key) ?? String.Empty).Length);
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
scanPath = Path.DirectorySeparatorChar + key[(Path.GetPathRoot(key) ?? string.Empty).Length..];
|
||||
#else
|
||||
scanPath = Path.DirectorySeparatorChar + key.Substring((Path.GetPathRoot(key) ?? string.Empty).Length);
|
||||
#endif
|
||||
|
||||
List<string>? scanResult = info.CopyProtection.FullProtections[key];
|
||||
|
||||
@@ -827,7 +838,7 @@ namespace MPF.Frontend
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,41 @@ namespace MPF.Frontend
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the InterfaceLanguage enum values
|
||||
/// </summary>
|
||||
/// <param name="lang">InterfaceLanguage value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this InterfaceLanguage lang)
|
||||
=> ((InterfaceLanguage?)lang).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the InterfaceLanguage enum values
|
||||
/// </summary>
|
||||
/// <param name="lang">InterfaceLanguage value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this InterfaceLanguage? lang)
|
||||
{
|
||||
return lang switch
|
||||
{
|
||||
InterfaceLanguage.AutoDetect => "Auto Detect",
|
||||
InterfaceLanguage.English => "English",
|
||||
InterfaceLanguage.French => "Français",
|
||||
InterfaceLanguage.German => "Deutsch",
|
||||
InterfaceLanguage.Italian => "Italiano",
|
||||
InterfaceLanguage.Japanese => "日本語",
|
||||
InterfaceLanguage.Korean => "한국어",
|
||||
InterfaceLanguage.Polish => "Polski",
|
||||
InterfaceLanguage.Russian => "Русский",
|
||||
InterfaceLanguage.Spanish => "Español",
|
||||
InterfaceLanguage.Swedish => "Svenska",
|
||||
InterfaceLanguage.Ukrainian => "Українська",
|
||||
InterfaceLanguage.L337 => "L337",
|
||||
|
||||
_ => "Unknown",
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the InternalProgram enum values
|
||||
/// </summary>
|
||||
@@ -126,6 +161,14 @@ namespace MPF.Frontend
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperReadMethod enum values
|
||||
/// </summary>
|
||||
/// <param name="method">RedumperReadMethod value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this RedumperReadMethod method)
|
||||
=> ((RedumperReadMethod?)method).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperReadMethod enum values
|
||||
/// </summary>
|
||||
@@ -143,6 +186,14 @@ namespace MPF.Frontend
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperSectorOrder enum values
|
||||
/// </summary>
|
||||
/// <param name="order">RedumperSectorOrder value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this RedumperSectorOrder order)
|
||||
=> ((RedumperSectorOrder?)order).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperSectorOrder enum values
|
||||
/// </summary>
|
||||
@@ -162,6 +213,14 @@ namespace MPF.Frontend
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperDriveType enum values
|
||||
/// </summary>
|
||||
/// <param name="type">RedumperDriveType value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this RedumperDriveType type)
|
||||
=> ((RedumperDriveType?)type).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperDriveType enum values
|
||||
/// </summary>
|
||||
@@ -188,6 +247,41 @@ namespace MPF.Frontend
|
||||
|
||||
#region Convert to Short Name
|
||||
|
||||
/// <summary>
|
||||
/// Get the short string representation of the InterfaceLanguage enum values
|
||||
/// </summary>
|
||||
/// <param name="lang">InterfaceLanguage value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string ShortName(this InterfaceLanguage lang)
|
||||
=> ((InterfaceLanguage?)lang).ShortName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the short string representation of the InterfaceLanguage enum values
|
||||
/// </summary>
|
||||
/// <param name="lang">InterfaceLanguage value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string ShortName(this InterfaceLanguage? lang)
|
||||
{
|
||||
return lang switch
|
||||
{
|
||||
InterfaceLanguage.AutoDetect => "auto",
|
||||
InterfaceLanguage.English => "eng",
|
||||
InterfaceLanguage.French => "fra",
|
||||
InterfaceLanguage.German => "deu",
|
||||
InterfaceLanguage.Italian => "ita",
|
||||
InterfaceLanguage.Japanese => "jpn",
|
||||
InterfaceLanguage.Korean => "kor",
|
||||
InterfaceLanguage.Polish => "pol",
|
||||
InterfaceLanguage.Russian => "rus",
|
||||
InterfaceLanguage.Spanish => "spa",
|
||||
InterfaceLanguage.Swedish => "swe",
|
||||
InterfaceLanguage.Ukrainian => "ukr",
|
||||
InterfaceLanguage.L337 => "l37",
|
||||
|
||||
_ => "Unknown",
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the short string representation of the InternalProgram enum values
|
||||
/// </summary>
|
||||
@@ -223,6 +317,33 @@ namespace MPF.Frontend
|
||||
|
||||
#region Convert from String
|
||||
|
||||
/// <summary>
|
||||
/// Get the InterfaceLanguage enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="internalLanguage">String value to convert</param>
|
||||
/// <returns>InterfaceLanguage represented by the string, if possible</returns>
|
||||
public static InterfaceLanguage ToInterfaceLanguage(this string? internalLanguage)
|
||||
{
|
||||
return (internalLanguage?.ToLowerInvariant()) switch
|
||||
{
|
||||
"auto" or "autodetect" or "auto detect" => InterfaceLanguage.AutoDetect,
|
||||
"eng" or "english" => InterfaceLanguage.English,
|
||||
"fra" or "french" or "français" => InterfaceLanguage.French,
|
||||
"deu" or "german" or "deutsch" => InterfaceLanguage.German,
|
||||
"ita" or "italian" or "italiano" => InterfaceLanguage.Italian,
|
||||
"jpn" or "japanese" or "日本語" => InterfaceLanguage.Japanese,
|
||||
"kor" or "korean" or "한국어" => InterfaceLanguage.Korean,
|
||||
"pol" or "polish" or "polski" => InterfaceLanguage.Polish,
|
||||
"rus" or "russian" or "русский" => InterfaceLanguage.Russian,
|
||||
"spa" or "spanish" or "español" => InterfaceLanguage.Spanish,
|
||||
"swe" or "swedish" or "svenska" => InterfaceLanguage.Swedish,
|
||||
"ukr" or "ukranian" or "українська" => InterfaceLanguage.Ukrainian,
|
||||
"l37" or "l337" => InterfaceLanguage.L337,
|
||||
|
||||
_ => InterfaceLanguage.AutoDetect,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the InternalProgram enum value for a given string
|
||||
/// </summary>
|
||||
@@ -270,7 +391,7 @@ namespace MPF.Frontend
|
||||
/// Get the LogCompression enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="logCompression">String value to convert</param>
|
||||
/// <returns>LogCompression represented by teh string, if possible</returns>
|
||||
/// <returns>LogCompression represented by the string, if possible</returns>
|
||||
public static LogCompression ToLogCompression(this string? logCompression)
|
||||
{
|
||||
return (logCompression?.ToLowerInvariant()) switch
|
||||
@@ -345,31 +466,31 @@ namespace MPF.Frontend
|
||||
{
|
||||
"generic" => RedumperDriveType.GENERIC,
|
||||
"plextor" => RedumperDriveType.PLEXTOR,
|
||||
"lg_asus8a"
|
||||
or "lg-asus8a"
|
||||
or "lgasus8a"
|
||||
or "lg_asus_8a"
|
||||
or "lg-asus-8a" => RedumperDriveType.LG_ASU8A,
|
||||
"lg_asus8b"
|
||||
or "lg-asus8b"
|
||||
or "lgasus8b"
|
||||
or "lg_asus_8b"
|
||||
or "lg-asus-8b" => RedumperDriveType.LG_ASU8B,
|
||||
"lg_asus8c"
|
||||
or "lg-asus8c"
|
||||
or "lgasus8c"
|
||||
or "lg_asus_8c"
|
||||
or "lg-asus-8c" => RedumperDriveType.LG_ASU8C,
|
||||
"lg_asu8a"
|
||||
or "lg-asu8a"
|
||||
or "lgasu8a"
|
||||
or "lg_asu_8a"
|
||||
or "lg-asu-8a" => RedumperDriveType.LG_ASU8A,
|
||||
"lg_asu8b"
|
||||
or "lg-asu8b"
|
||||
or "lgasu8b"
|
||||
or "lg_asu_8b"
|
||||
or "lg-asu-8b" => RedumperDriveType.LG_ASU8B,
|
||||
"lg_asu8c"
|
||||
or "lg-asu8c"
|
||||
or "lgasu8c"
|
||||
or "lg_asu_8c"
|
||||
or "lg-asu-8c" => RedumperDriveType.LG_ASU8C,
|
||||
"lg_asus3"
|
||||
or "lg-asus3"
|
||||
or "lgasus3"
|
||||
or "lg_asus_3"
|
||||
or "lg-asus-3" => RedumperDriveType.LG_ASU3,
|
||||
"lg_asus2"
|
||||
or "lg-asus2"
|
||||
or "lgasus2"
|
||||
or "lg_asus_2"
|
||||
or "lg-asus-2" => RedumperDriveType.LG_ASU2,
|
||||
or "lg-asu3"
|
||||
or "lgasu3"
|
||||
or "lg_asu_3"
|
||||
or "lg-asu-3" => RedumperDriveType.LG_ASU3,
|
||||
"lg_asu2"
|
||||
or "lg-asu2"
|
||||
or "lgasu2"
|
||||
or "lg_asu_2"
|
||||
or "lg-asu-2" => RedumperDriveType.LG_ASU2,
|
||||
|
||||
_ => RedumperDriveType.NONE,
|
||||
};
|
||||
@@ -399,6 +520,7 @@ namespace MPF.Frontend
|
||||
return system switch
|
||||
{
|
||||
RedumpSystem.AppleMacintosh => true,
|
||||
RedumpSystem.DVDVideo => true,
|
||||
RedumpSystem.EnhancedCD => true,
|
||||
RedumpSystem.IBMPCcompatible => true,
|
||||
RedumpSystem.PalmOS => true,
|
||||
|
||||
@@ -1,5 +1,32 @@
|
||||
namespace MPF.Frontend
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface language
|
||||
/// </summary>
|
||||
public enum InterfaceLanguage
|
||||
{
|
||||
/// <summary>
|
||||
/// Default to auto-detecting language
|
||||
/// </summary>
|
||||
AutoDetect = 0,
|
||||
|
||||
// Selectable languages (in Manual Window dropdown)
|
||||
English,
|
||||
French,
|
||||
German,
|
||||
Italian,
|
||||
Japanese,
|
||||
Korean,
|
||||
Polish,
|
||||
Russian,
|
||||
Spanish,
|
||||
Swedish,
|
||||
Ukrainian,
|
||||
|
||||
// Hidden languages (not in Main Window dropdown)
|
||||
L337,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drive type for dumping
|
||||
/// </summary>
|
||||
@@ -40,4 +67,4 @@ namespace MPF.Frontend
|
||||
ERROR,
|
||||
SECRET,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
150
MPF.Frontend/Features/ListConfigFeature.cs
Normal file
150
MPF.Frontend/Features/ListConfigFeature.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class ListConfigFeature : SabreTools.CommandLine.Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "listconfig";
|
||||
|
||||
private static readonly string[] _flags = ["lo", "listconfig"];
|
||||
|
||||
private const string _description = "List current configuration values";
|
||||
|
||||
#endregion
|
||||
|
||||
public ListConfigFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
// Try to load the current config
|
||||
var options = OptionsLoader.LoadFromConfig();
|
||||
if (options.FirstRun)
|
||||
{
|
||||
Console.WriteLine("No valid configuration found!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Paths
|
||||
Console.WriteLine("Paths:");
|
||||
Console.WriteLine($" Aaru Path = {options.AaruPath}");
|
||||
Console.WriteLine($" DiscImageCreator Path = {options.DiscImageCreatorPath}");
|
||||
Console.WriteLine($" Redumper Path = {options.RedumperPath}");
|
||||
Console.WriteLine($" Default Program = {options.InternalProgram.LongName()}");
|
||||
Console.WriteLine();
|
||||
|
||||
// UI Defaults
|
||||
Console.WriteLine("UI Defaults:");
|
||||
Console.WriteLine($" Dark Mode = {options.EnableDarkMode}");
|
||||
Console.WriteLine($" Purp Mode = {options.EnablePurpMode}");
|
||||
Console.WriteLine($" Custom Background Color = {options.CustomBackgroundColor}");
|
||||
Console.WriteLine($" Custom Text Color = {options.CustomTextColor}");
|
||||
Console.WriteLine($" Check for Updates on Startup = {options.CheckForUpdatesOnStartup}");
|
||||
Console.WriteLine($" Copy Update URL to Clipboard = {options.CopyUpdateUrlToClipboard}");
|
||||
Console.WriteLine($" Fast Label Update = {options.FastUpdateLabel}");
|
||||
Console.WriteLine($" Default Interface Language = {options.DefaultInterfaceLanguage.LongName()}");
|
||||
Console.WriteLine($" Default Output Path = {options.DefaultOutputPath}");
|
||||
Console.WriteLine($" Default System = {options.DefaultSystem.LongName()}");
|
||||
Console.WriteLine($" Show Debug Menu Item = {options.ShowDebugViewMenuItem}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Dumping Speeds
|
||||
Console.WriteLine("Dumping Speeds:");
|
||||
Console.WriteLine($" Default CD Speed = {options.PreferredDumpSpeedCD}");
|
||||
Console.WriteLine($" Default DVD Speed = {options.PreferredDumpSpeedDVD}");
|
||||
Console.WriteLine($" Default HD-DVD Speed = {options.PreferredDumpSpeedHDDVD}");
|
||||
Console.WriteLine($" Default Blu-ray Speed = {options.PreferredDumpSpeedBD}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Aaru
|
||||
Console.WriteLine("Aaru-Specific Options:");
|
||||
Console.WriteLine($" Enable Debug = {options.AaruEnableDebug}");
|
||||
Console.WriteLine($" Enable Verbose = {options.AaruEnableVerbose}");
|
||||
Console.WriteLine($" Force Dumping = {options.AaruForceDumping}");
|
||||
Console.WriteLine($" Reread Count = {options.AaruRereadCount}");
|
||||
Console.WriteLine($" Strip Personal Data = {options.AaruStripPersonalData}");
|
||||
Console.WriteLine();
|
||||
|
||||
// DiscImageCreator
|
||||
Console.WriteLine("DiscImageCreator-Specific Options:");
|
||||
Console.WriteLine($" Multi-Sector Read Flag = {options.DICMultiSectorRead}");
|
||||
Console.WriteLine($" Multi-Sector Read Value = {options.DICMultiSectorReadValue}");
|
||||
Console.WriteLine($" Overly-Secure Flags = {options.DICParanoidMode}");
|
||||
Console.WriteLine($" Quiet Flag = {options.DICQuietMode}");
|
||||
Console.WriteLine($" CD Reread Count = {options.DICRereadCount}");
|
||||
Console.WriteLine($" DVD Reread Count = {options.DICDVDRereadCount}");
|
||||
Console.WriteLine($" Use CMI Flag = {options.DICUseCMIFlag}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Redumper
|
||||
Console.WriteLine("Redumper-Specific Options:");
|
||||
Console.WriteLine($" Enable Skeleton = {options.RedumperEnableSkeleton}");
|
||||
Console.WriteLine($" Enable Verbose = {options.RedumperEnableVerbose}");
|
||||
Console.WriteLine($" Lead-in Retry Count = {options.RedumperLeadinRetryCount}");
|
||||
Console.WriteLine($" Non-Redump Mode = {options.RedumperNonRedumpMode}");
|
||||
Console.WriteLine($" Drive Type = {options.RedumperDriveType.LongName()}");
|
||||
Console.WriteLine($" Read Method = {options.RedumperReadMethod.LongName()}");
|
||||
Console.WriteLine($" Sector Order = {options.RedumperSectorOrder.LongName()}");
|
||||
Console.WriteLine($" Reread Count = {options.RedumperRereadCount}");
|
||||
Console.WriteLine($" Refine Sector Mode = {options.RedumperRefineSectorMode}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Extra Dumping Options
|
||||
Console.WriteLine("Extra Dumping Options:");
|
||||
Console.WriteLine($" Scan for Protection = {options.ScanForProtection}");
|
||||
Console.WriteLine($" Add Placeholders = {options.AddPlaceholders}");
|
||||
Console.WriteLine($" Prompt for Media Information = {options.PromptForDiscInformation}");
|
||||
Console.WriteLine($" Pull All Information = {options.PullAllInformation}");
|
||||
Console.WriteLine($" Enable Tabs in Input Fields = {options.EnableTabsInInputFields}");
|
||||
Console.WriteLine($" Enable Redump Compatibility = {options.EnableRedumpCompatibility}");
|
||||
Console.WriteLine($" Show Disc Eject Reminder = {options.ShowDiscEjectReminder}");
|
||||
Console.WriteLine($" Ignore Fixed Drives = {options.IgnoreFixedDrives}");
|
||||
Console.WriteLine($" Add Filename Suffix = {options.AddFilenameSuffix}");
|
||||
Console.WriteLine($" Output Submission JSON = {options.OutputSubmissionJSON}");
|
||||
Console.WriteLine($" Include Artifacts = {options.IncludeArtifacts}");
|
||||
Console.WriteLine($" Compress Log Files = {options.CompressLogFiles}");
|
||||
Console.WriteLine($" Log Compression = {options.LogCompression.LongName()}");
|
||||
Console.WriteLine($" Delete Unnecessary Files = {options.DeleteUnnecessaryFiles}");
|
||||
Console.WriteLine($" Create IRD After Dumping = {options.CreateIRDAfterDumping}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Skip Options
|
||||
Console.WriteLine("Skip Options:");
|
||||
Console.WriteLine($" Skip System Detection = {options.SkipSystemDetection}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Protection Scanning Options
|
||||
Console.WriteLine("Protection Scanning Options:");
|
||||
Console.WriteLine($" Scan Archives for Protection = {options.ScanArchivesForProtection}");
|
||||
Console.WriteLine($" Include Debug Protection Information = {options.IncludeDebugProtectionInformation}");
|
||||
Console.WriteLine($" Hide Drive Letters = {options.HideDriveLetters}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Logging Options
|
||||
Console.WriteLine("Logging Options:");
|
||||
Console.WriteLine($" Verbose Logging = {options.VerboseLogging}");
|
||||
Console.WriteLine($" Open Log Window at Startup = {options.OpenLogWindowAtStartup}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Redump Login Information
|
||||
Console.WriteLine("Redump Login Information:");
|
||||
Console.WriteLine($" Retrieve Match Information = {options.RetrieveMatchInformation}");
|
||||
Console.WriteLine($" Redump Username = {options.RedumpUsername}");
|
||||
Console.WriteLine($" Redump Password = {(string.IsNullOrEmpty(options.RedumpPassword) ? "[UNSET]" : "[SET]")}");
|
||||
Console.WriteLine();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
@@ -10,7 +10,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.5.0</VersionPrefix>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
@@ -31,14 +31,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BinaryObjectScanner" Version="[3.4.5]" />
|
||||
<PackageReference Include="LibIRD" Version="[1.0.0]" />
|
||||
<PackageReference Include="BinaryObjectScanner" Version="[3.5.0]" />
|
||||
<PackageReference Include="LibIRD" Version="[1.0.1]" />
|
||||
<PackageReference Include="Microsoft.Management.Infrastructure" Version="3.0.0" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="Microsoft.Net.Http" Version="2.2.29" Condition="$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="MinThreadingBridge" Version="0.11.4" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.3.2]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.7.4]" />
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.0]" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -42,4 +42,4 @@ namespace MPF.Frontend
|
||||
IEnumerator IEnumerable.GetEnumerator() => _queue.GetEnumerator();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using AaruSettings = MPF.ExecutionContexts.Aaru.SettingConstants;
|
||||
using DICSettings = MPF.ExecutionContexts.DiscImageCreator.SettingConstants;
|
||||
@@ -12,6 +14,76 @@ namespace MPF.Frontend
|
||||
{
|
||||
public class Options
|
||||
{
|
||||
#region Default Paths
|
||||
|
||||
/// <summary>
|
||||
/// Default Aaru path
|
||||
/// </summary>
|
||||
private static string DefaultAaruPath
|
||||
{
|
||||
get
|
||||
{
|
||||
string executableName = Environment.OSVersion.Platform switch
|
||||
{
|
||||
PlatformID.Unix => "aaru",
|
||||
PlatformID.MacOSX => "aaru",
|
||||
_ => "aaru.exe"
|
||||
};
|
||||
|
||||
#if NET20 || NET35
|
||||
return Path.Combine("Programs", Path.Combine("Aaru", executableName));
|
||||
#else
|
||||
return Path.Combine("Programs", "Aaru", executableName);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default DiscImageCreator path
|
||||
/// </summary>
|
||||
private static string DefaultDiscImageCreatorPath
|
||||
{
|
||||
get
|
||||
{
|
||||
string executableName = Environment.OSVersion.Platform switch
|
||||
{
|
||||
PlatformID.Unix => "DiscImageCreator.out",
|
||||
PlatformID.MacOSX => "DiscImageCreator",
|
||||
_ => "DiscImageCreator.exe"
|
||||
};
|
||||
|
||||
#if NET20 || NET35
|
||||
return Path.Combine("Programs", Path.Combine("Creator", executableName));
|
||||
#else
|
||||
return Path.Combine("Programs", "Creator", executableName);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default Redumper path
|
||||
/// </summary>
|
||||
private static string DefaultRedumperPath
|
||||
{
|
||||
get
|
||||
{
|
||||
string executableName = Environment.OSVersion.Platform switch
|
||||
{
|
||||
PlatformID.Unix => "redumper",
|
||||
PlatformID.MacOSX => "redumper",
|
||||
_ => "redumper.exe"
|
||||
};
|
||||
|
||||
#if NET20 || NET35
|
||||
return Path.Combine("Programs", Path.Combine("Redumper", executableName));
|
||||
#else
|
||||
return Path.Combine("Programs", "Redumper", executableName);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// All settings in the form of a dictionary
|
||||
/// </summary>
|
||||
@@ -33,7 +105,7 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public string? AaruPath
|
||||
{
|
||||
get { return GetStringSetting(Settings, "AaruPath", "Programs\\Aaru\\Aaru.exe"); }
|
||||
get { return GetStringSetting(Settings, "AaruPath", DefaultAaruPath); }
|
||||
set { Settings["AaruPath"] = value; }
|
||||
}
|
||||
|
||||
@@ -42,7 +114,7 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public string? DiscImageCreatorPath
|
||||
{
|
||||
get { return GetStringSetting(Settings, "DiscImageCreatorPath", "Programs\\Creator\\DiscImageCreator.exe"); }
|
||||
get { return GetStringSetting(Settings, "DiscImageCreatorPath", DefaultDiscImageCreatorPath); }
|
||||
set { Settings["DiscImageCreatorPath"] = value; }
|
||||
}
|
||||
|
||||
@@ -51,7 +123,7 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public string? RedumperPath
|
||||
{
|
||||
get { return GetStringSetting(Settings, "RedumperPath", "Programs\\Redumper\\redumper.exe"); }
|
||||
get { return GetStringSetting(Settings, "RedumperPath", DefaultRedumperPath); }
|
||||
set { Settings["RedumperPath"] = value; }
|
||||
}
|
||||
|
||||
@@ -142,6 +214,22 @@ namespace MPF.Frontend
|
||||
set { Settings["FastUpdateLabel"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default interface language to launch MPF into
|
||||
/// </summary>
|
||||
public InterfaceLanguage DefaultInterfaceLanguage
|
||||
{
|
||||
get
|
||||
{
|
||||
var valueString = GetStringSetting(Settings, "DefaultInterfaceLanguage", InterfaceLanguage.AutoDetect.ShortName());
|
||||
return valueString.ToInterfaceLanguage();
|
||||
}
|
||||
set
|
||||
{
|
||||
Settings["DefaultInterfaceLanguage"] = value.ShortName();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default output path for dumps
|
||||
/// </summary>
|
||||
@@ -158,13 +246,13 @@ namespace MPF.Frontend
|
||||
{
|
||||
get
|
||||
{
|
||||
var valueString = GetStringSetting(Settings, "DefaultSystem", RedumpSystem.IBMPCcompatible.LongName());
|
||||
var valueString = GetStringSetting(Settings, "DefaultSystem", RedumpSystem.IBMPCcompatible.ToString());
|
||||
var valueEnum = (valueString ?? string.Empty).ToRedumpSystem();
|
||||
return valueEnum;
|
||||
}
|
||||
set
|
||||
{
|
||||
Settings["DefaultSystem"] = value.LongName();
|
||||
Settings["DefaultSystem"] = value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,6 +484,15 @@ namespace MPF.Frontend
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected default redumper drive pregap start sector
|
||||
/// </summary>
|
||||
public int RedumperDrivePregapStart
|
||||
{
|
||||
get { return GetInt32Setting(Settings, RedumperSettings.DrivePregapStart, RedumperSettings.DrivePregapStartDefault); }
|
||||
set { Settings[RedumperSettings.DrivePregapStart] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected default redumper read method
|
||||
/// </summary>
|
||||
|
||||
@@ -9,4 +9,4 @@ namespace MPF.Frontend
|
||||
/// <param name="info">Submission info that may be overwritten</param>
|
||||
/// <returns>True for successful updating, false or null otherwise</returns>
|
||||
public delegate bool? ProcessUserInfoDelegate(Options? options, ref SubmissionInfo? info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,4 +49,4 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public static implicit operator StringEventArgs(StringBuilder? sb) => new(sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ namespace MPF.Frontend.Tools
|
||||
if (string.IsNullOrEmpty(volumeLabel))
|
||||
return null;
|
||||
|
||||
// Trim the volume label
|
||||
volumeLabel = volumeLabel!.Trim();
|
||||
|
||||
// Audio CD
|
||||
if (volumeLabel!.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.AudioCD;
|
||||
@@ -151,8 +154,7 @@ namespace MPF.Frontend.Tools
|
||||
return title;
|
||||
|
||||
// If we have an invalid language, assume Language.English
|
||||
if (language == null)
|
||||
language = Language.English;
|
||||
language ??= Language.English;
|
||||
|
||||
// Get the title split into parts
|
||||
string[] splitTitle = Array.FindAll(title!.Split(' '), s => !string.IsNullOrEmpty(s));
|
||||
@@ -496,12 +498,20 @@ namespace MPF.Frontend.Tools
|
||||
else if (!itemInserted && segment.EndsWith(":"))
|
||||
{
|
||||
itemInserted = true;
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
newTitleBuilder.Append($" {segment[..^1]}, {firstItem}:");
|
||||
#else
|
||||
newTitleBuilder.Append($" {segment.Substring(0, segment.Length - 1)}, {firstItem}:");
|
||||
#endif
|
||||
}
|
||||
else if (!itemInserted && segment.EndsWith("-"))
|
||||
{
|
||||
itemInserted = true;
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
newTitleBuilder.Append($" {segment[..^1]}, {firstItem}-");
|
||||
#else
|
||||
newTitleBuilder.Append($" {segment.Substring(0, segment.Length - 1)}, {firstItem}-");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -666,4 +676,4 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -91,9 +91,9 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,10 +193,10 @@ namespace MPF.Frontend.Tools
|
||||
return new Options();
|
||||
|
||||
var serializer = JsonSerializer.Create();
|
||||
var stream = File.Open(ConfigurationPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
var reader = new StreamReader(stream);
|
||||
var stream = File.Open(ConfigurationPath, FileMode.Open, FileAccess.Read, FileShare.None);
|
||||
using var reader = new StreamReader(stream);
|
||||
var settings = serializer.Deserialize(reader, typeof(Dictionary<string, string?>)) as Dictionary<string, string?>;
|
||||
reader.Dispose();
|
||||
|
||||
return new Options(settings);
|
||||
}
|
||||
|
||||
@@ -225,13 +225,11 @@ namespace MPF.Frontend.Tools
|
||||
property.SetValue(options, val, null);
|
||||
}
|
||||
|
||||
// Handle a very strange edge case
|
||||
if (!File.Exists(ConfigurationPath))
|
||||
File.Create(ConfigurationPath).Dispose();
|
||||
|
||||
var serializer = JsonSerializer.Create();
|
||||
var sw = new StreamWriter(ConfigurationPath) { AutoFlush = true };
|
||||
var stream = File.Open(ConfigurationPath, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
using var sw = new StreamWriter(stream) { AutoFlush = true };
|
||||
var writer = new JsonTextWriter(sw) { Formatting = Formatting.Indented };
|
||||
|
||||
serializer.Serialize(writer, options.Settings, typeof(Dictionary<string, string>));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -57,7 +58,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -93,7 +94,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -149,7 +150,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -205,7 +206,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is, assume SYSTEM.CNF doesn't exist
|
||||
// Absorb the exception, assume SYSTEM.CNF doesn't exist
|
||||
}
|
||||
|
||||
// If the SYSTEM.CNF value can't be found, try PSX.EXE
|
||||
@@ -274,7 +275,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -306,7 +307,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -327,7 +328,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -364,7 +365,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -385,7 +386,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -430,7 +431,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -468,7 +469,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -506,7 +507,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -559,7 +560,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -582,7 +583,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -605,7 +606,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -657,7 +658,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -710,7 +711,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -726,11 +727,11 @@ namespace MPF.Frontend.Tools
|
||||
/// <returns>Filenames if possible, null on error</returns>
|
||||
public static string? GetXboxFilenames(Drive? drive)
|
||||
{
|
||||
// If there's no drive path, we can't get BEE flag
|
||||
// If there's no drive path, can't do anything
|
||||
if (string.IsNullOrEmpty(drive?.Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't get exe name
|
||||
// If the folder no longer exists, can't do anything
|
||||
if (!Directory.Exists(drive!.Name))
|
||||
return null;
|
||||
|
||||
@@ -747,7 +748,59 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Title ID(s) for Xbox One and Xbox Series X
|
||||
/// </summary>
|
||||
/// <param name="drive">Drive to extract information from</param>
|
||||
/// <returns>Title ID(s) if possible, null on error</returns>
|
||||
public static string? GetXboxTitleID(Drive? drive)
|
||||
{
|
||||
// If there's no drive path, can't do anything
|
||||
if (string.IsNullOrEmpty(drive?.Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, can't do anything
|
||||
if (!Directory.Exists(drive!.Name))
|
||||
return null;
|
||||
|
||||
// Get the catalog.js path
|
||||
#if NET20 || NET35
|
||||
string catalogjs = Path.Combine(drive.Name, Path.Combine("MSXC", Path.Combine("Metadata", "catalog.js")));
|
||||
#else
|
||||
string catalogjs = Path.Combine(drive.Name, "MSXC", "Metadata", "catalog.js");
|
||||
#endif
|
||||
// Check catalog.js exists
|
||||
if (!File.Exists(catalogjs))
|
||||
return null;
|
||||
|
||||
// Deserialize catalog.js and extract Title ID(s)
|
||||
try
|
||||
{
|
||||
var catalog = new SabreTools.Serialization.Readers.Catalog().Deserialize(catalogjs);
|
||||
if (catalog == null)
|
||||
return null;
|
||||
if (!string.IsNullOrEmpty(catalog.TitleID))
|
||||
return catalog.TitleID;
|
||||
if (catalog.Packages == null)
|
||||
return null;
|
||||
|
||||
List<string> titleIDs = [];
|
||||
foreach (var package in catalog.Packages)
|
||||
{
|
||||
if (package?.TitleID != null)
|
||||
titleIDs.Add(package.TitleID);
|
||||
}
|
||||
|
||||
return string.Join(", ", [.. titleIDs]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -815,4 +868,4 @@ namespace MPF.Frontend.Tools
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,72 @@ namespace MPF.Frontend.Tools
|
||||
#endregion
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Run comprehensive protection scans based on both the
|
||||
/// physical media as well as the image
|
||||
/// </summary>
|
||||
/// <param name="basePath">Base output image path</param>
|
||||
/// <param name="drive">Drive object representing the current drive</param>
|
||||
/// <param name="options">Options object that determines what to scan</param>
|
||||
/// <param name="progress">Optional progress callback</param>
|
||||
public async static Task<Dictionary<string, List<string>>> RunCombinedProtectionScans(string basePath,
|
||||
Drive? drive,
|
||||
Options options,
|
||||
IProgress<ProtectionProgress>? protectionProgress = null)
|
||||
{
|
||||
// Setup the output protections dictionary
|
||||
Dictionary<string, List<string>> protections = [];
|
||||
|
||||
// Scan the disc image, if possible
|
||||
if (File.Exists($"{basePath}.iso"))
|
||||
{
|
||||
var imageProtections = await RunProtectionScanOnImage($"{basePath}.iso", options, protectionProgress);
|
||||
MergeDictionaries(protections, imageProtections);
|
||||
}
|
||||
else if (File.Exists($"{basePath}.bin"))
|
||||
{
|
||||
var imageProtections = await RunProtectionScanOnImage($"{basePath}.bin", options, protectionProgress);
|
||||
MergeDictionaries(protections, imageProtections);
|
||||
}
|
||||
else if (File.Exists($"{basePath}.cue"))
|
||||
{
|
||||
string[] cueLines = File.ReadAllLines($"{basePath}.cue");
|
||||
foreach (string cueLine in cueLines)
|
||||
{
|
||||
// Skip all non-FILE lines
|
||||
if (!cueLine.StartsWith("FILE"))
|
||||
continue;
|
||||
|
||||
// Extract the information
|
||||
var match = Regex.Match(cueLine, @"FILE ""(.*?)"" BINARY");
|
||||
if (!match.Success || match.Groups.Count == 0)
|
||||
continue;
|
||||
|
||||
// Get the track name from the matches
|
||||
string trackName = match.Groups[1].Value;
|
||||
trackName = Path.GetFileNameWithoutExtension(trackName);
|
||||
string baseDir = Path.GetDirectoryName(basePath) ?? string.Empty;
|
||||
string trackPath = Path.Combine(baseDir, trackName);
|
||||
|
||||
// Scan the track for protections, if it exists
|
||||
if (File.Exists($"{trackPath}.bin"))
|
||||
{
|
||||
var trackProtections = await RunProtectionScanOnImage($"{trackPath}.bin", options, protectionProgress);
|
||||
MergeDictionaries(protections, trackProtections);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scan the mounted drive path
|
||||
if (drive?.Name != null)
|
||||
{
|
||||
var driveProtections = await RunProtectionScanOnPath(drive.Name, options, protectionProgress);
|
||||
MergeDictionaries(protections, driveProtections);
|
||||
}
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run protection scan on a given path
|
||||
/// </summary>
|
||||
@@ -101,17 +167,56 @@ namespace MPF.Frontend.Tools
|
||||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run protection scan on a disc image
|
||||
/// </summary>
|
||||
/// <param name="image">Image path to scan for protection</param>
|
||||
/// <param name="options">Options object that determines what to scan</param>
|
||||
/// <param name="progress">Optional progress callback</param>
|
||||
/// <returns>Set of all detected copy protections with an optional error string</returns>
|
||||
public static async Task<Dictionary<string, List<string>>> RunProtectionScanOnImage(string image,
|
||||
Options options,
|
||||
IProgress<ProtectionProgress>? progress = null)
|
||||
{
|
||||
#if NET40
|
||||
var found = await Task.Factory.StartNew(() =>
|
||||
#else
|
||||
var found = await Task.Run(() =>
|
||||
#endif
|
||||
{
|
||||
var scanner = new Scanner(
|
||||
scanArchives: false, // Disable extracting disc images for now
|
||||
scanContents: false, // Disabled for image scanning
|
||||
scanPaths: false, // Disabled for image scanning
|
||||
scanSubdirectories: false, // Disabled for image scanning
|
||||
options.IncludeDebugProtectionInformation,
|
||||
progress);
|
||||
|
||||
return scanner.GetProtections(image);
|
||||
});
|
||||
|
||||
// If nothing was returned, return
|
||||
if (found == null || found.Count == 0)
|
||||
return [];
|
||||
|
||||
// Return the filtered set of protections
|
||||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format found protections to a deduplicated, ordered string
|
||||
/// </summary>
|
||||
/// <param name="protections">Dictionary of file to list of protection mappings</param>
|
||||
/// <param name="drive">Drive object representing the current drive</param>
|
||||
/// <returns>Detected protections, if any</returns>
|
||||
public static string? FormatProtections(Dictionary<string, List<string>>? protections)
|
||||
public static string? FormatProtections(Dictionary<string, List<string>>? protections, Drive? drive)
|
||||
{
|
||||
// If the filtered list is empty in some way, return
|
||||
if (protections == null)
|
||||
return "(CHECK WITH PROTECTIONID)";
|
||||
else if (protections.Count == 0)
|
||||
return "[EXTERNAL SCAN NEEDED]";
|
||||
else if (protections.Count == 0 && drive?.Name == null)
|
||||
return "Mounted disc path missing [EXTERNAL SCAN NEEDED]";
|
||||
else if (protections.Count == 0 && drive?.Name != null)
|
||||
return "None found [OMIT FROM SUBMISSION]";
|
||||
|
||||
// Sanitize context-sensitive protections
|
||||
@@ -124,7 +229,7 @@ namespace MPF.Frontend.Tools
|
||||
{
|
||||
if (value.Count == 0)
|
||||
continue;
|
||||
|
||||
|
||||
foreach (var prot in value)
|
||||
{
|
||||
if (!protectionValues.Contains(prot))
|
||||
@@ -137,7 +242,7 @@ namespace MPF.Frontend.Tools
|
||||
.Distinct()
|
||||
.ToList();
|
||||
#endif
|
||||
|
||||
|
||||
// Sanitize and join protections for writing
|
||||
string protectionString = SanitizeFoundProtections(protectionValues);
|
||||
if (string.IsNullOrEmpty(protectionString))
|
||||
@@ -427,7 +532,7 @@ namespace MPF.Frontend.Tools
|
||||
.FindAll(p => p != "SafeDisc 2+");
|
||||
}
|
||||
|
||||
// Best case for SafeDisc 1.X: A full SafeDisc version is found that isn't part of a version range.
|
||||
// Best case for SafeDisc 1.X: A full SafeDisc version is found that isn't part of a version range.
|
||||
else if (foundProtections.Exists(p => Regex.IsMatch(p, @"SafeDisc 1\.[0-9]{2}\.[0-9]{3}$", RegexOptions.Compiled)
|
||||
&& !Regex.IsMatch(p, @"SafeDisc 1\.[0-9]{2}\.[0-9]{3}-[0-9]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled)))
|
||||
{
|
||||
@@ -536,6 +641,12 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
}
|
||||
|
||||
if (foundProtections.Exists(p => p.StartsWith("StarForce Keyless")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("StarForce Keyless"));
|
||||
foundProtections.Add("StarForce Keyless");
|
||||
}
|
||||
|
||||
// Sysiphus
|
||||
if (foundProtections.Exists(p => p == "Sysiphus")
|
||||
&& foundProtections.Exists(p => p.StartsWith("Sysiphus") && p.Length > "Sysiphus".Length))
|
||||
@@ -557,5 +668,31 @@ namespace MPF.Frontend.Tools
|
||||
foundProtections.Sort();
|
||||
return string.Join(", ", [.. foundProtections]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merge two dictionaries together based on keys
|
||||
/// </summary>
|
||||
/// <param name="original">Source dictionary to add to</param>
|
||||
/// <param name="add">Second dictionary to add from</param>
|
||||
/// TODO: Remove from here when IO is updated
|
||||
private static void MergeDictionaries(Dictionary<string, List<string>> original, Dictionary<string, List<string>> add)
|
||||
{
|
||||
// Ignore if there are no values to append
|
||||
if (add.Count == 0)
|
||||
return;
|
||||
|
||||
// Loop through and add from the new dictionary
|
||||
foreach (var kvp in add)
|
||||
{
|
||||
// Ignore empty values
|
||||
if (kvp.Value.Count == 0)
|
||||
continue;
|
||||
|
||||
if (!original.ContainsKey(kvp.Key))
|
||||
original[kvp.Key] = [];
|
||||
|
||||
original[kvp.Key].AddRange(kvp.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using BinaryObjectScanner;
|
||||
using MPF.Processors;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Data.Sections;
|
||||
using SabreTools.RedumpLib.Web;
|
||||
|
||||
namespace MPF.Frontend.Tools
|
||||
@@ -55,15 +56,30 @@ namespace MPF.Frontend.Tools
|
||||
var outputDirectory = Path.GetDirectoryName(outputPath);
|
||||
string outputFilename = Path.GetFileName(outputPath);
|
||||
|
||||
// If a standard log zip was provided, replace the suffix with ".tmp" for easier processing
|
||||
if (outputFilename.EndsWith("_logs.zip", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
int zipSuffixIndex = outputFilename.LastIndexOf("_logs.zip", StringComparison.OrdinalIgnoreCase);
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
outputFilename = outputFilename[..zipSuffixIndex] + ".tmp";
|
||||
#else
|
||||
outputFilename = outputFilename.Substring(0, zipSuffixIndex) + ".tmp";
|
||||
#endif
|
||||
}
|
||||
|
||||
// Check that all of the relevant files are there
|
||||
List<string> missingFiles = processor.FoundAllFiles(mediaType, outputDirectory, outputFilename);
|
||||
if (missingFiles.Count > 0)
|
||||
{
|
||||
resultProgress?.Report(ResultEventArgs.Failure($"There were files missing from the output:\n{string.Join("\n", [.. missingFiles])}"));
|
||||
resultProgress?.Report(ResultEventArgs.Failure($"This may indicate an issue with the hardware or media, including unsupported devices.\nPlease see dumping program documentation for more details."));
|
||||
resultProgress?.Report(ResultEventArgs.Failure($"There were files missing from the output:\n{string.Join("\n", [.. missingFiles])}\nThis may indicate an issue with the hardware or media, including unsupported devices.\nPlease see dumping program documentation for more details."));
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extract files from existing log archive, if it exists
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
processor.ExtractFromLogs(mediaType, outputDirectory, outputFilename);
|
||||
#endif
|
||||
|
||||
// Assemble a base path
|
||||
string basePath = Path.GetFileNameWithoutExtension(outputFilename);
|
||||
if (!string.IsNullOrEmpty(outputDirectory))
|
||||
@@ -77,21 +93,24 @@ namespace MPF.Frontend.Tools
|
||||
if (options.IncludeArtifacts)
|
||||
info.Artifacts = processor.GenerateArtifacts(mediaType, outputDirectory, outputFilename);
|
||||
|
||||
// Add a placeholder for the logs link
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.LogsLink] = "[Please provide a link to your logs here]";
|
||||
|
||||
// Get a list of matching IDs for each line in the DAT
|
||||
if (!string.IsNullOrEmpty(info.TracksAndWriteOffsets!.ClrMameProData))
|
||||
_ = await FillFromRedump(options, info, resultProgress);
|
||||
if (!string.IsNullOrEmpty(info.TracksAndWriteOffsets.ClrMameProData))
|
||||
{
|
||||
bool filledInfo = await FillFromRedump(options, info, resultProgress);
|
||||
|
||||
// Add a placeholder for the logs link if not a verification
|
||||
if (!filledInfo)
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.LogsLink] = "[Please provide a link to your logs here]";
|
||||
}
|
||||
|
||||
// If we have both ClrMamePro and Size and Checksums data, remove the ClrMamePro
|
||||
if (!string.IsNullOrEmpty(info.SizeAndChecksums?.CRC32))
|
||||
if (!string.IsNullOrEmpty(info.SizeAndChecksums.CRC32))
|
||||
info.TracksAndWriteOffsets.ClrMameProData = null;
|
||||
|
||||
// Add the volume label to comments, if possible or necessary
|
||||
string? volLabels = FormatVolumeLabels(drive?.VolumeLabel, processor.VolumeLabels);
|
||||
if (volLabels != null)
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.VolumeLabel] = volLabels;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.VolumeLabel] = volLabels;
|
||||
|
||||
// Extract info based generically on MediaType
|
||||
ProcessMediaType(info, mediaType, options.AddPlaceholders);
|
||||
@@ -100,7 +119,7 @@ namespace MPF.Frontend.Tools
|
||||
ProcessSystem(info, system, drive, options.AddPlaceholders, processor is DiscImageCreator, basePath);
|
||||
|
||||
// Run anti-modchip check, if necessary
|
||||
if (drive != null && system.SupportsAntiModchipScans() && info.CopyProtection!.AntiModchip == YesNo.NULL)
|
||||
if (drive != null && system.SupportsAntiModchipScans() && info.CopyProtection.AntiModchip == YesNo.NULL)
|
||||
{
|
||||
resultProgress?.Report(ResultEventArgs.Success("Checking for anti-modchip strings... this might take a while!"));
|
||||
info.CopyProtection.AntiModchip = await ProtectionTool.GetPlayStationAntiModchipDetected(drive?.Name) ? YesNo.Yes : YesNo.No;
|
||||
@@ -112,15 +131,21 @@ namespace MPF.Frontend.Tools
|
||||
{
|
||||
resultProgress?.Report(ResultEventArgs.Success("Running copy protection scan... this might take a while!"));
|
||||
|
||||
Dictionary<string, List<string>>? protections = null;
|
||||
try
|
||||
{
|
||||
if (options.ScanForProtection && drive?.Name != null)
|
||||
protections = await ProtectionTool.RunProtectionScanOnPath(drive.Name, options, protectionProgress);
|
||||
Dictionary<string, List<string>>? protections = null;
|
||||
if (options.ScanForProtection)
|
||||
{
|
||||
// Explicitly note missing/invalid device paths
|
||||
if (drive?.Name == null)
|
||||
resultProgress?.Report(ResultEventArgs.Success("No mounted device path found, protection outputs may be incomplete!"));
|
||||
|
||||
var protectionString = ProtectionTool.FormatProtections(protections);
|
||||
protections = await ProtectionTool.RunCombinedProtectionScans(basePath, drive, options, protectionProgress);
|
||||
}
|
||||
|
||||
info.CopyProtection!.Protection += protectionString;
|
||||
var protectionString = ProtectionTool.FormatProtections(protections, drive);
|
||||
|
||||
info.CopyProtection.Protection += protectionString;
|
||||
info.CopyProtection.FullProtections = ReformatProtectionDictionary(protections);
|
||||
resultProgress?.Report(ResultEventArgs.Success("Copy protection scan complete!"));
|
||||
}
|
||||
@@ -131,8 +156,8 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
|
||||
// Set fields that may have automatic filling otherwise
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Games;
|
||||
info.VersionAndEditions!.Version ??= options.AddPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Games;
|
||||
info.VersionAndEditions.Version ??= options.AddPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
|
||||
// Comments and contents have odd handling
|
||||
if (string.IsNullOrEmpty(info.CommonDiscInfo.Comments))
|
||||
@@ -161,7 +186,6 @@ namespace MPF.Frontend.Tools
|
||||
return false;
|
||||
|
||||
// Set the current dumper based on username
|
||||
info.DumpersAndStatus ??= new DumpersAndStatusSection();
|
||||
info.DumpersAndStatus.Dumpers = [options.RedumpUsername ?? "Anonymous User"];
|
||||
info.PartiallyMatchedIDs = [];
|
||||
|
||||
@@ -187,7 +211,7 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Loop through all of the hashdata to find matching IDs
|
||||
resultProgress?.Report(ResultEventArgs.Success("Finding disc matches on Redump..."));
|
||||
var splitData = info.TracksAndWriteOffsets?.ClrMameProData?.TrimEnd('\n')?.Split('\n');
|
||||
var splitData = info.TracksAndWriteOffsets.ClrMameProData?.TrimEnd('\n')?.Split('\n');
|
||||
int trackCount = splitData?.Length ?? 0;
|
||||
foreach (string hashData in splitData ?? [])
|
||||
{
|
||||
@@ -384,8 +408,6 @@ namespace MPF.Frontend.Tools
|
||||
},
|
||||
};
|
||||
|
||||
// Ensure that required sections exist
|
||||
info = Builder.EnsureAllSections(info);
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -575,7 +597,7 @@ namespace MPF.Frontend.Tools
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
case MediaType.GDROM:
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -588,9 +610,9 @@ namespace MPF.Frontend.Tools
|
||||
case MediaType.BluRay:
|
||||
|
||||
// If we have a single-layer disc
|
||||
if (info.SizeAndChecksums!.Layerbreak == default)
|
||||
if (info.SizeAndChecksums.Layerbreak == default)
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -598,9 +620,9 @@ namespace MPF.Frontend.Tools
|
||||
info.CommonDiscInfo.Layer0AdditionalMould = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
}
|
||||
// If we have a dual-layer disc
|
||||
else if (info.SizeAndChecksums!.Layerbreak2 == default)
|
||||
else if (info.SizeAndChecksums.Layerbreak2 == default)
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -612,9 +634,9 @@ namespace MPF.Frontend.Tools
|
||||
info.CommonDiscInfo.Layer1MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
}
|
||||
// If we have a triple-layer disc
|
||||
else if (info.SizeAndChecksums!.Layerbreak3 == default)
|
||||
else if (info.SizeAndChecksums.Layerbreak3 == default)
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -632,7 +654,7 @@ namespace MPF.Frontend.Tools
|
||||
// If we have a quad-layer disc
|
||||
else
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -655,22 +677,22 @@ namespace MPF.Frontend.Tools
|
||||
break;
|
||||
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer1MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0AdditionalMould = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.Extras!.BCA ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.Extras.BCA ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
case MediaType.NintendoWiiUOpticalDisc:
|
||||
|
||||
// If we have a single-layer disc
|
||||
if (info.SizeAndChecksums!.Layerbreak == default)
|
||||
if (info.SizeAndChecksums.Layerbreak == default)
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -680,7 +702,7 @@ namespace MPF.Frontend.Tools
|
||||
// If we have a dual-layer disc
|
||||
else
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -692,14 +714,14 @@ namespace MPF.Frontend.Tools
|
||||
info.CommonDiscInfo.Layer1MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
}
|
||||
|
||||
info.Extras!.DiscKey = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.Extras.DiscKey = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.Extras.BCA ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
|
||||
break;
|
||||
|
||||
case MediaType.UMD:
|
||||
// Both single- and dual-layer discs have two "layers" for the ring
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -708,10 +730,10 @@ namespace MPF.Frontend.Tools
|
||||
info.CommonDiscInfo.Layer1MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer1ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
|
||||
info.SizeAndChecksums!.CRC32 ??= (addPlaceholders ? RequiredValue + " [Not automatically generated for UMD]" : string.Empty);
|
||||
info.SizeAndChecksums.CRC32 ??= (addPlaceholders ? RequiredValue + " [Not automatically generated for UMD]" : string.Empty);
|
||||
info.SizeAndChecksums.MD5 ??= (addPlaceholders ? RequiredValue + " [Not automatically generated for UMD]" : string.Empty);
|
||||
info.SizeAndChecksums.SHA1 ??= (addPlaceholders ? RequiredValue + " [Not automatically generated for UMD]" : string.Empty);
|
||||
info.TracksAndWriteOffsets!.ClrMameProData = null;
|
||||
info.TracksAndWriteOffsets.ClrMameProData = null;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -727,85 +749,85 @@ namespace MPF.Frontend.Tools
|
||||
switch (system)
|
||||
{
|
||||
case RedumpSystem.AcornArchimedes:
|
||||
info.CommonDiscInfo!.Region ??= Region.UnitedKingdom;
|
||||
info.CommonDiscInfo.Region ??= Region.UnitedKingdom;
|
||||
break;
|
||||
|
||||
case RedumpSystem.AudioCD:
|
||||
case RedumpSystem.DVDAudio:
|
||||
case RedumpSystem.EnhancedCD:
|
||||
case RedumpSystem.SuperAudioCD:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Audio;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Audio;
|
||||
break;
|
||||
|
||||
case RedumpSystem.BandaiPlaydiaQuickInteractiveSystem:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= info.CommonDiscInfo.Region ?? Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.BDVideo:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Video;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Video;
|
||||
bool bee = PhysicalTool.GetBusEncryptionEnabled(drive);
|
||||
if (bee && string.IsNullOrEmpty(info.CopyProtection!.Protection))
|
||||
if (bee && string.IsNullOrEmpty(info.CopyProtection.Protection))
|
||||
info.CopyProtection.Protection = "Bus encryption enabled flag set";
|
||||
else if (bee)
|
||||
info.CopyProtection!.Protection += "\nBus encryption enabled flag set";
|
||||
info.CopyProtection.Protection += "\nBus encryption enabled flag set";
|
||||
else
|
||||
info.CopyProtection!.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CopyProtection.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
|
||||
break;
|
||||
|
||||
case RedumpSystem.DVDVideo:
|
||||
case RedumpSystem.HDDVDVideo:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Video;
|
||||
info.CopyProtection!.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Video;
|
||||
info.CopyProtection.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.CommodoreAmigaCD:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.CommodoreAmigaCD32:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= Region.Europe;
|
||||
break;
|
||||
|
||||
case RedumpSystem.CommodoreAmigaCDTV:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= Region.Europe;
|
||||
break;
|
||||
|
||||
case RedumpSystem.FujitsuFMTownsseries:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.FujitsuFMTownsMarty:
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.HasbroVideoNow:
|
||||
case RedumpSystem.HasbroVideoNowColor:
|
||||
case RedumpSystem.HasbroVideoNowJr:
|
||||
case RedumpSystem.VideoCD:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Video;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Video;
|
||||
break;
|
||||
|
||||
case RedumpSystem.HasbroVideoNowXP:
|
||||
case RedumpSystem.PhotoCD:
|
||||
case RedumpSystem.SonyElectronicBook:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Multimedia;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Multimedia;
|
||||
break;
|
||||
|
||||
case RedumpSystem.IncredibleTechnologiesEagle:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamieAmusement:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiFireBeat:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiPython2:
|
||||
@@ -813,89 +835,91 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// TODO: Remove this hack when DIC supports build date output
|
||||
if (isDiscImageCreator)
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", kp2Exe);
|
||||
info.CommonDiscInfo.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", kp2Exe);
|
||||
|
||||
SetCommentFieldIfNotExists(info, SiteCode.InternalSerialName, drive, PhysicalTool.GetPlayStationSerial);
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, kp2Exe, fixTwoDigitYear: true);
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, kp2Exe, fixTwoDigitYear: true);
|
||||
|
||||
if (CommentFieldExists(info, SiteCode.InternalSerialName, out kp2Exe))
|
||||
info.CommonDiscInfo!.Region = ProcessingTool.GetPlayStationRegion(kp2Exe);
|
||||
info.CommonDiscInfo.Region = ProcessingTool.GetPlayStationRegion(kp2Exe);
|
||||
|
||||
SetVersionIfNotExists(info, drive, PhysicalTool.GetPlayStation2Version);
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiSystemGV:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiSystem573:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiTwinkle:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.MattelHyperScan:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.MicrosoftXboxOne:
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.Filename] = PhysicalTool.GetXboxFilenames(drive) ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.Filename] = PhysicalTool.GetXboxFilenames(drive) ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.TitleID] = PhysicalTool.GetXboxTitleID(drive) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.MicrosoftXboxSeriesXS:
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.Filename] = PhysicalTool.GetXboxFilenames(drive) ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.Filename] = PhysicalTool.GetXboxFilenames(drive) ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.TitleID] = PhysicalTool.GetXboxTitleID(drive) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.NamcoSegaNintendoTriforce:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.NavisoftNaviken21:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.NECPC88series:
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.NECPC98series:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.NECPCFXPCFXGA:
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaChihiro:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaDreamcast:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaNaomi:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaNaomi2:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaTitanVideo:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SharpX68000:
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SNKNeoGeoCD:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation:
|
||||
@@ -903,26 +927,26 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// TODO: Remove this hack when DIC supports build date output
|
||||
if (isDiscImageCreator)
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", ps1Exe, psx: true);
|
||||
info.CommonDiscInfo.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", ps1Exe, psx: true);
|
||||
|
||||
SetCommentFieldIfNotExists(info, SiteCode.InternalSerialName, drive, PhysicalTool.GetPlayStationSerial);
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, ps1Exe, fixTwoDigitYear: true);
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, ps1Exe, fixTwoDigitYear: true);
|
||||
|
||||
if (CommentFieldExists(info, SiteCode.InternalSerialName, out ps1Exe))
|
||||
info.CommonDiscInfo!.Region = ProcessingTool.GetPlayStationRegion(ps1Exe);
|
||||
info.CommonDiscInfo.Region = ProcessingTool.GetPlayStationRegion(ps1Exe);
|
||||
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation2:
|
||||
info.CommonDiscInfo!.LanguageSelection ??= [];
|
||||
info.CommonDiscInfo.LanguageSelection ??= [];
|
||||
string? ps2Exe = PhysicalTool.GetPlayStationExecutableName(drive);
|
||||
|
||||
// TODO: Remove this hack when DIC supports build date output
|
||||
if (isDiscImageCreator)
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", ps2Exe);
|
||||
info.CommonDiscInfo.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", ps2Exe);
|
||||
|
||||
SetCommentFieldIfNotExists(info, SiteCode.InternalSerialName, drive, PhysicalTool.GetPlayStationSerial);
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, ps2Exe, fixTwoDigitYear: true);
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, ps2Exe, fixTwoDigitYear: true);
|
||||
|
||||
if (CommentFieldExists(info, SiteCode.InternalSerialName, out ps2Exe))
|
||||
info.CommonDiscInfo.Region = ProcessingTool.GetPlayStationRegion(ps2Exe);
|
||||
@@ -931,7 +955,7 @@ namespace MPF.Frontend.Tools
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation3:
|
||||
info.Extras!.DiscKey ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.Extras.DiscKey ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.Extras.DiscID ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
|
||||
SetCommentFieldIfNotExists(info, SiteCode.InternalSerialName, drive, PhysicalTool.GetPlayStation3Serial);
|
||||
@@ -952,12 +976,12 @@ namespace MPF.Frontend.Tools
|
||||
break;
|
||||
|
||||
case RedumpSystem.TomyKissSite:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Video;
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Video;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem:
|
||||
info.CopyProtection!.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CopyProtection.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -982,7 +1006,7 @@ namespace MPF.Frontend.Tools
|
||||
private static bool CommentFieldExists(SubmissionInfo info, SiteCode key, out string? value)
|
||||
{
|
||||
// Ensure the comments fields exist
|
||||
if (info.CommonDiscInfo!.CommentsSpecialFields == null)
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null)
|
||||
info.CommonDiscInfo.CommentsSpecialFields = [];
|
||||
|
||||
// Check if the field exists
|
||||
@@ -1007,7 +1031,7 @@ namespace MPF.Frontend.Tools
|
||||
// Set the value
|
||||
string? value = valueFunc(drive);
|
||||
if (value != null)
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![key] = value;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1016,7 +1040,7 @@ namespace MPF.Frontend.Tools
|
||||
private static bool ContentFieldExists(SubmissionInfo info, SiteCode key, out string? value)
|
||||
{
|
||||
// Ensure the contents fields exist
|
||||
if (info.CommonDiscInfo!.ContentsSpecialFields == null)
|
||||
if (info.CommonDiscInfo.ContentsSpecialFields == null)
|
||||
info.CommonDiscInfo.ContentsSpecialFields = [];
|
||||
|
||||
// Check if the field exists
|
||||
@@ -1041,7 +1065,7 @@ namespace MPF.Frontend.Tools
|
||||
// Set the value
|
||||
string? value = valueFunc(drive);
|
||||
if (value != null)
|
||||
info.CommonDiscInfo!.ContentsSpecialFields![key] = value;
|
||||
info.CommonDiscInfo.ContentsSpecialFields![key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1050,7 +1074,7 @@ namespace MPF.Frontend.Tools
|
||||
private static void SetVersionIfNotExists(SubmissionInfo info, Drive? drive, Func<Drive?, string?> valueFunc)
|
||||
{
|
||||
// If the version already exists, skip
|
||||
if (!string.IsNullOrEmpty(info.VersionAndEditions!.Version))
|
||||
if (!string.IsNullOrEmpty(info.VersionAndEditions.Version))
|
||||
return;
|
||||
|
||||
// Set the version
|
||||
|
||||
@@ -544,7 +544,7 @@ namespace MPF.Frontend.ViewModels
|
||||
/// </summary>
|
||||
private bool ShouldEnableCreateIRDButton()
|
||||
{
|
||||
if(string.IsNullOrEmpty(InputPath) || !File.Exists(InputPath))
|
||||
if (string.IsNullOrEmpty(InputPath) || !File.Exists(InputPath))
|
||||
{
|
||||
CreateIRDStatus = "Please provide an ISO";
|
||||
return false;
|
||||
|
||||
@@ -9,6 +9,7 @@ using MPF.Frontend.Tools;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Data.Sections;
|
||||
|
||||
namespace MPF.Frontend.ViewModels
|
||||
{
|
||||
@@ -543,11 +544,11 @@ namespace MPF.Frontend.ViewModels
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
#region Strings
|
||||
|
||||
private const string DiscNotDetectedValue = "Disc Not Detected";
|
||||
private const string StartDumpingValue = "Start Dumping";
|
||||
private const string StopDumpingValue = "Stop Dumping";
|
||||
private string StartDumpingValue = "Start Dumping";
|
||||
private string StopDumpingValue = "Stop Dumping";
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -813,25 +814,6 @@ namespace MPF.Frontend.ViewModels
|
||||
message = "An exception occurred while checking for versions, please try again later. See the log window for more details.";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build the about text
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string CreateAboutText()
|
||||
{
|
||||
string aboutText = $"Media Preservation Frontend (MPF)"
|
||||
+ $"{Environment.NewLine}"
|
||||
+ $"{Environment.NewLine}A community preservation frontend developed in C#."
|
||||
+ $"{Environment.NewLine}Supports Redumper, Aaru, and DiscImageCreator."
|
||||
+ $"{Environment.NewLine}Originally created to help the Redump project."
|
||||
+ $"{Environment.NewLine}"
|
||||
+ $"{Environment.NewLine}Thanks to everyone who has supported this project!"
|
||||
+ $"{Environment.NewLine}"
|
||||
+ $"{Environment.NewLine}Version {FrontendTool.GetCurrentVersion()}";
|
||||
SecretLogLn(aboutText);
|
||||
return aboutText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build a dummy SubmissionInfo
|
||||
/// </summary>
|
||||
@@ -1377,7 +1359,7 @@ namespace MPF.Frontend.ViewModels
|
||||
StartStopButtonEnabled = result && ShouldEnableDumpingButton();
|
||||
|
||||
// If we're in a type that doesn't support drive speeds
|
||||
DriveSpeedComboBoxEnabled = _environment.DoesSupportDriveSpeed(CurrentMediaType);
|
||||
DriveSpeedComboBoxEnabled = DumpEnvironment.DoesSupportDriveSpeed(CurrentMediaType);
|
||||
|
||||
// If input params are enabled, generate the full parameters from the environment
|
||||
if (ParametersCheckBoxEnabled)
|
||||
@@ -1410,9 +1392,9 @@ namespace MPF.Frontend.ViewModels
|
||||
string programShort = program == "DiscImageCreator" ? "DIC" : program;
|
||||
if (string.IsNullOrEmpty(programShort))
|
||||
programShort = "Unknown Program";
|
||||
string label = GetFormattedVolumeLabel(_currentDrive) ?? "track";
|
||||
string label = GetFormattedVolumeLabel(_currentDrive) ?? $"track_{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
if (string.IsNullOrEmpty(label))
|
||||
label = "track";
|
||||
label = $"track_{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
string date = DateTime.Today.ToString("yyyyMMdd");
|
||||
if (string.IsNullOrEmpty(date))
|
||||
date = "UNKNOWN";
|
||||
@@ -1447,7 +1429,7 @@ namespace MPF.Frontend.ViewModels
|
||||
// Get path pieces that are used in all branches
|
||||
string defaultOutputPath = Options.DefaultOutputPath ?? "ISO";
|
||||
string extension = _environment?.GetDefaultExtension(CurrentMediaType) ?? ".bin";
|
||||
string label = GetFormattedVolumeLabel(CurrentDrive) ?? CurrentSystem.LongName() ?? "track";
|
||||
string label = GetFormattedVolumeLabel(CurrentDrive) ?? CurrentSystem.LongName() ?? $"track_{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
string defaultFilename = $"{label}{extension}";
|
||||
|
||||
// If no path exists, set one using default values
|
||||
@@ -1526,7 +1508,7 @@ namespace MPF.Frontend.ViewModels
|
||||
return null;
|
||||
}
|
||||
|
||||
// We're going to assume for floppies, HDDs, and removable drives
|
||||
// Floppies, HDDs, and removable drives are assumed
|
||||
if (drive.InternalDriveType != InternalDriveType.Optical)
|
||||
return RedumpSystem.IBMPCcompatible;
|
||||
|
||||
@@ -1636,7 +1618,7 @@ namespace MPF.Frontend.ViewModels
|
||||
if (!File.Exists(catalogjs))
|
||||
return RedumpSystem.MicrosoftXboxOne;
|
||||
|
||||
SabreTools.Data.Models.Xbox.Catalog? catalog = new SabreTools.Serialization.Readers.Catalog().Deserialize(catalogjs);
|
||||
var catalog = new SabreTools.Serialization.Readers.Catalog().Deserialize(catalogjs);
|
||||
if (catalog != null && catalog.Version != null && catalog.Packages != null)
|
||||
{
|
||||
if (!double.TryParse(catalog.Version, out double version))
|
||||
@@ -1880,6 +1862,14 @@ namespace MPF.Frontend.ViewModels
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs the About text
|
||||
/// </summary>
|
||||
public void LogAboutText(string message)
|
||||
{
|
||||
SecretLogLn(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the current custom parameters back into UI values
|
||||
/// </summary>
|
||||
@@ -1969,7 +1959,7 @@ namespace MPF.Frontend.ViewModels
|
||||
try
|
||||
{
|
||||
var protections = await ProtectionTool.RunProtectionScanOnPath(CurrentDrive.Name, Options, progress);
|
||||
var output = ProtectionTool.FormatProtections(protections);
|
||||
var output = ProtectionTool.FormatProtections(protections, CurrentDrive);
|
||||
|
||||
LogLn($"Detected the following protections in {CurrentDrive.Name}:\r\n\r\n{output}");
|
||||
return output;
|
||||
@@ -2007,7 +1997,7 @@ namespace MPF.Frontend.ViewModels
|
||||
/// <summary>
|
||||
/// Media label as read by Windows, formatted to avoid odd outputs
|
||||
/// If no volume label present, use PSX or PS2 serial if valid
|
||||
/// Otherwise, use "track" as volume label
|
||||
/// Otherwise, use "track" with current datetime as volume label
|
||||
/// </summary>
|
||||
private static string? GetFormattedVolumeLabel(Drive? drive)
|
||||
{
|
||||
@@ -2020,13 +2010,13 @@ namespace MPF.Frontend.ViewModels
|
||||
return DiscNotDetectedValue;
|
||||
|
||||
// Use internal serials where appropriate
|
||||
string? volumeLabel = string.IsNullOrEmpty(drive.VolumeLabel) ? null : drive.VolumeLabel;
|
||||
string? volumeLabel = string.IsNullOrEmpty(drive.VolumeLabel) ? null : drive.VolumeLabel!.Trim();
|
||||
switch (GetRedumpSystem(drive))
|
||||
{
|
||||
case RedumpSystem.SonyPlayStation:
|
||||
case RedumpSystem.SonyPlayStation2:
|
||||
string? ps12Serial = PhysicalTool.GetPlayStationSerial(drive);
|
||||
volumeLabel ??= ps12Serial ?? "track";
|
||||
volumeLabel ??= ps12Serial ?? $"track_{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation3:
|
||||
@@ -2034,7 +2024,7 @@ namespace MPF.Frontend.ViewModels
|
||||
if (volumeLabel == "PS3VOLUME")
|
||||
volumeLabel = ps3Serial ?? volumeLabel;
|
||||
else
|
||||
volumeLabel ??= ps3Serial ?? "track";
|
||||
volumeLabel ??= ps3Serial ?? $"track_{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation4:
|
||||
@@ -2042,7 +2032,7 @@ namespace MPF.Frontend.ViewModels
|
||||
if (volumeLabel == "PS4VOLUME")
|
||||
volumeLabel = ps4Serial ?? volumeLabel;
|
||||
else
|
||||
volumeLabel ??= ps4Serial ?? "track";
|
||||
volumeLabel ??= ps4Serial ?? $"track_{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation5:
|
||||
@@ -2050,11 +2040,11 @@ namespace MPF.Frontend.ViewModels
|
||||
if (volumeLabel == "PS5VOLUME")
|
||||
volumeLabel = ps5Serial ?? volumeLabel;
|
||||
else
|
||||
volumeLabel ??= ps5Serial ?? "track";
|
||||
volumeLabel ??= ps5Serial ?? $"track_{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
break;
|
||||
|
||||
default:
|
||||
volumeLabel ??= "track";
|
||||
volumeLabel ??= $"track_{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2457,6 +2447,31 @@ namespace MPF.Frontend.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translates strings in MainModelView
|
||||
/// </summary>
|
||||
/// <param name="translationStrings">Dictionary of keys and their translated string</param>
|
||||
public void TranslateStrings(Dictionary<string, string>? translationStrings)
|
||||
{
|
||||
if (translationStrings != null)
|
||||
{
|
||||
// Cache current start dumping string
|
||||
var oldStartDumpingValue = StartDumpingValue;
|
||||
|
||||
// Get translated strings
|
||||
if (translationStrings.TryGetValue("StartDumpingButtonString", out string? startDumpingButtonString))
|
||||
StartDumpingValue = startDumpingButtonString ?? StartDumpingValue;
|
||||
if (translationStrings.TryGetValue("StopDumpingButtonString", out string? stopDumpingValue))
|
||||
StopDumpingValue = stopDumpingValue ?? StopDumpingValue;
|
||||
|
||||
// Set button text
|
||||
if (StartStopButtonText as string == oldStartDumpingValue)
|
||||
StartStopButtonText = StartDumpingValue;
|
||||
else
|
||||
StartStopButtonText = StopDumpingValue;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Progress Reporting
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using MPF.Frontend.ComboBoxItems;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Data.Sections;
|
||||
|
||||
namespace MPF.Frontend.ViewModels
|
||||
{
|
||||
@@ -39,8 +40,8 @@ namespace MPF.Frontend.ViewModels
|
||||
/// <summary>
|
||||
/// List of Redump-supported Regions
|
||||
/// </summary>
|
||||
private static readonly List<Region> RedumpRegions = new()
|
||||
{
|
||||
private static readonly List<Region> RedumpRegions =
|
||||
[
|
||||
Region.Argentina,
|
||||
Region.Asia,
|
||||
Region.AsiaEurope,
|
||||
@@ -120,7 +121,7 @@ namespace MPF.Frontend.ViewModels
|
||||
Region.USAJapan,
|
||||
Region.USAKorea,
|
||||
Region.World,
|
||||
};
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// List of available languages
|
||||
@@ -131,8 +132,8 @@ namespace MPF.Frontend.ViewModels
|
||||
/// <summary>
|
||||
/// List of Redump-supported Languages
|
||||
/// </summary>
|
||||
private static readonly List<Language> RedumpLanguages = new()
|
||||
{
|
||||
private static readonly List<Language> RedumpLanguages =
|
||||
[
|
||||
Language.Afrikaans,
|
||||
Language.Albanian,
|
||||
Language.Arabic,
|
||||
@@ -181,7 +182,7 @@ namespace MPF.Frontend.ViewModels
|
||||
Language.Turkish,
|
||||
Language.Ukrainian,
|
||||
Language.Vietnamese,
|
||||
};
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// List of available languages
|
||||
|
||||
@@ -51,25 +51,30 @@ namespace MPF.Frontend.ViewModels
|
||||
/// </summary>
|
||||
public static List<Element<InternalProgram>> InternalPrograms => PopulateInternalPrograms();
|
||||
|
||||
/// <summary>
|
||||
/// List of available interface languages
|
||||
/// </summary>
|
||||
public static List<Element<InterfaceLanguage>> InterfaceLanguages => Element<InterfaceLanguage>.GenerateElements();
|
||||
|
||||
/// <summary>
|
||||
/// List of available log compression methods
|
||||
/// </summary>
|
||||
public static List<Element<LogCompression>> LogCompressions => PopulateLogCompressions();
|
||||
public static List<Element<LogCompression>> LogCompressions => Element<LogCompression>.GenerateElements();
|
||||
|
||||
/// <summary>
|
||||
/// Current list of supported Redumper read methods
|
||||
/// </summary>
|
||||
public static List<Element<RedumperReadMethod>> RedumperReadMethods => PopulateRedumperReadMethods();
|
||||
public static List<Element<RedumperReadMethod>> RedumperReadMethods => Element<RedumperReadMethod>.GenerateElements();
|
||||
|
||||
/// <summary>
|
||||
/// Current list of supported Redumper sector orders
|
||||
/// </summary>
|
||||
public static List<Element<RedumperSectorOrder>> RedumperSectorOrders => PopulateRedumperSectorOrders();
|
||||
public static List<Element<RedumperSectorOrder>> RedumperSectorOrders => Element<RedumperSectorOrder>.GenerateElements();
|
||||
|
||||
/// <summary>
|
||||
/// Current list of supported Redumper drive types
|
||||
/// </summary>
|
||||
public static List<Element<RedumperDriveType>> RedumperDriveTypes => PopulateRedumperDriveTypes();
|
||||
public static List<Element<RedumperDriveType>> RedumperDriveTypes => Element<RedumperDriveType>.GenerateElements();
|
||||
|
||||
/// <summary>
|
||||
/// Current list of supported system profiles
|
||||
@@ -105,43 +110,6 @@ namespace MPF.Frontend.ViewModels
|
||||
return internalPrograms.ConvertAll(ip => new Element<InternalProgram>(ip));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of supported log compression methods
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static List<Element<LogCompression>> PopulateLogCompressions()
|
||||
{
|
||||
var logCompressions = new List<LogCompression> { LogCompression.DeflateDefault, LogCompression.DeflateMaximum, LogCompression.Zstd19 };
|
||||
return logCompressions.ConvertAll(lc => new Element<LogCompression>(lc));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of supported redumper drive read methods
|
||||
/// </summary>
|
||||
private static List<Element<RedumperReadMethod>> PopulateRedumperReadMethods()
|
||||
{
|
||||
var readMethods = new List<RedumperReadMethod> { RedumperReadMethod.NONE, RedumperReadMethod.D8, RedumperReadMethod.BE };
|
||||
return readMethods.ConvertAll(rm => new Element<RedumperReadMethod>(rm));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of supported redumper drive sector orders
|
||||
/// </summary>
|
||||
private static List<Element<RedumperSectorOrder>> PopulateRedumperSectorOrders()
|
||||
{
|
||||
var sectorOrders = new List<RedumperSectorOrder> { RedumperSectorOrder.NONE, RedumperSectorOrder.DATA_C2_SUB, RedumperSectorOrder.DATA_SUB_C2, RedumperSectorOrder.DATA_SUB, RedumperSectorOrder.DATA_C2 };
|
||||
return sectorOrders.ConvertAll(so => new Element<RedumperSectorOrder>(so));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of supported redumper drive types
|
||||
/// </summary>
|
||||
private static List<Element<RedumperDriveType>> PopulateRedumperDriveTypes()
|
||||
{
|
||||
var driveTypes = new List<RedumperDriveType> { RedumperDriveType.NONE, RedumperDriveType.GENERIC, RedumperDriveType.PLEXTOR, RedumperDriveType.LG_ASU8A, RedumperDriveType.LG_ASU8B, RedumperDriveType.LG_ASU8C, RedumperDriveType.LG_ASU3, RedumperDriveType.LG_ASU2 };
|
||||
return driveTypes.ConvertAll(dt => new Element<RedumperDriveType>(dt));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI Commands
|
||||
|
||||
@@ -246,6 +246,30 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetPreservedFilePaths
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Invalid_Empty()
|
||||
{
|
||||
string? outputDirectory = null;
|
||||
string outputFilename = string.Empty;
|
||||
var processor = new Aaru(RedumpSystem.IBMPCcompatible);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.CDROM, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Valid_Empty()
|
||||
{
|
||||
string? outputDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "Aaru", "CDROM");
|
||||
string outputFilename = "test.aaruf";
|
||||
var processor = new Aaru(RedumpSystem.IBMPCcompatible);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.CDROM, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GenerateCuesheet
|
||||
|
||||
[Fact]
|
||||
@@ -260,7 +284,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GenerateCuesheet_Empty_Null()
|
||||
{
|
||||
CICMMetadataType? cicmSidecar = new CICMMetadataType();
|
||||
CICMMetadataType? cicmSidecar = new();
|
||||
string basePath = "test";
|
||||
string? actual = Aaru.GenerateCuesheet(cicmSidecar, basePath);
|
||||
Assert.Null(actual);
|
||||
@@ -269,7 +293,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GenerateCuesheet_Valid_Filled()
|
||||
{
|
||||
TrackType trackType = new TrackType
|
||||
TrackType trackType = new()
|
||||
{
|
||||
BytesPerSector = 2352,
|
||||
Flags = new TrackFlagsType { Quadraphonic = true },
|
||||
@@ -279,7 +303,7 @@ namespace MPF.Processors.Test
|
||||
TrackType1 = TrackTypeTrackType.mode1,
|
||||
};
|
||||
|
||||
OpticalDiscType opticalDiscType = new OpticalDiscType
|
||||
OpticalDiscType opticalDiscType = new()
|
||||
{
|
||||
DiscType = "CD-ROM",
|
||||
MediaCatalogueNumber = "mcn",
|
||||
@@ -287,7 +311,7 @@ namespace MPF.Processors.Test
|
||||
Tracks = [1],
|
||||
};
|
||||
|
||||
CICMMetadataType? cicmSidecar = new CICMMetadataType
|
||||
CICMMetadataType? cicmSidecar = new()
|
||||
{
|
||||
OpticalDisc = [opticalDiscType],
|
||||
Performer = ["performer"],
|
||||
@@ -317,7 +341,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GenerateDatafile_Empty_Null()
|
||||
{
|
||||
CICMMetadataType? cicmSidecar = new CICMMetadataType();
|
||||
CICMMetadataType? cicmSidecar = new();
|
||||
string basePath = "test";
|
||||
var actual = Aaru.GenerateDatafile(cicmSidecar, basePath);
|
||||
Assert.Null(actual);
|
||||
@@ -326,7 +350,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GenerateDatafile_Valid_Filled()
|
||||
{
|
||||
TrackType trackType = new TrackType
|
||||
TrackType trackType = new()
|
||||
{
|
||||
Checksums =
|
||||
[
|
||||
@@ -338,7 +362,7 @@ namespace MPF.Processors.Test
|
||||
Size = 12345,
|
||||
};
|
||||
|
||||
OpticalDiscType opticalDiscType = new OpticalDiscType
|
||||
OpticalDiscType opticalDiscType = new()
|
||||
{
|
||||
DiscType = "CD-ROM",
|
||||
MediaCatalogueNumber = "mcn",
|
||||
@@ -346,7 +370,7 @@ namespace MPF.Processors.Test
|
||||
Tracks = [1],
|
||||
};
|
||||
|
||||
CICMMetadataType? cicmSidecar = new CICMMetadataType
|
||||
CICMMetadataType? cicmSidecar = new()
|
||||
{
|
||||
OpticalDisc = [opticalDiscType],
|
||||
};
|
||||
@@ -373,7 +397,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GeneratePVD_Empty_Null()
|
||||
{
|
||||
CICMMetadataType? cicmSidecar = new CICMMetadataType();
|
||||
CICMMetadataType? cicmSidecar = new();
|
||||
var actual = Aaru.GeneratePVD(cicmSidecar);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
@@ -381,7 +405,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GeneratePVD_Valid_Filled()
|
||||
{
|
||||
FileSystemType fileSystemType = new FileSystemType
|
||||
FileSystemType fileSystemType = new()
|
||||
{
|
||||
CreationDate = DateTime.UtcNow,
|
||||
CreationDateSpecified = true,
|
||||
@@ -393,22 +417,22 @@ namespace MPF.Processors.Test
|
||||
EffectiveDateSpecified = true,
|
||||
};
|
||||
|
||||
PartitionType partitionType = new PartitionType
|
||||
PartitionType partitionType = new()
|
||||
{
|
||||
FileSystems = [fileSystemType],
|
||||
};
|
||||
|
||||
TrackType trackType = new TrackType
|
||||
TrackType trackType = new()
|
||||
{
|
||||
FileSystemInformation = [partitionType],
|
||||
};
|
||||
|
||||
OpticalDiscType opticalDiscType = new OpticalDiscType
|
||||
OpticalDiscType opticalDiscType = new()
|
||||
{
|
||||
Track = [trackType],
|
||||
};
|
||||
|
||||
CICMMetadataType? cicmSidecar = new CICMMetadataType
|
||||
CICMMetadataType? cicmSidecar = new()
|
||||
{
|
||||
OpticalDisc = [opticalDiscType],
|
||||
};
|
||||
@@ -565,4 +589,4 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,4 +310,4 @@ FILE ""track (Track 2).bin"" BINARY
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,6 +290,30 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetPreservedFilePaths
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Invalid_Empty()
|
||||
{
|
||||
string? outputDirectory = null;
|
||||
string outputFilename = string.Empty;
|
||||
var processor = new CleanRip(RedumpSystem.NintendoGameCube);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.DVD, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Valid_Empty()
|
||||
{
|
||||
string? outputDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "CleanRip", "DVD");
|
||||
string outputFilename = "test.iso";
|
||||
var processor = new CleanRip(RedumpSystem.NintendoGameCube);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.DVD, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GenerateCleanripDatafile
|
||||
|
||||
[Fact]
|
||||
@@ -422,4 +446,4 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ namespace MPF.Processors.Test
|
||||
string outputFilename = string.Empty;
|
||||
var processor = new DiscImageCreator(RedumpSystem.IBMPCcompatible);
|
||||
var actual = processor.FoundAllFiles(MediaType.CDROM, outputDirectory, outputFilename);
|
||||
Assert.Equal(15, actual.Count);
|
||||
Assert.Equal(14, actual.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -324,9 +324,33 @@ namespace MPF.Processors.Test
|
||||
string outputFilename = "test.cue";
|
||||
var processor = new DiscImageCreator(RedumpSystem.IBMPCcompatible);
|
||||
var actual = processor.GetZippableFilePaths(MediaType.CDROM, outputDirectory, outputFilename);
|
||||
Assert.Equal(23, actual.Count);
|
||||
Assert.Equal(24, actual.Count);
|
||||
}
|
||||
|
||||
#region GetPreservedFilePaths
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Invalid_Empty()
|
||||
{
|
||||
string? outputDirectory = null;
|
||||
string outputFilename = string.Empty;
|
||||
var processor = new DiscImageCreator(RedumpSystem.IBMPCcompatible);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.CDROM, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Valid_Filled()
|
||||
{
|
||||
string? outputDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "DiscImageCreator", "CDROM");
|
||||
string outputFilename = "test.cue";
|
||||
var processor = new DiscImageCreator(RedumpSystem.IBMPCcompatible);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.CDROM, outputDirectory, outputFilename);
|
||||
Assert.Single(actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetCommandFilePathAndVersion
|
||||
@@ -402,7 +426,7 @@ namespace MPF.Processors.Test
|
||||
public void GetDiscType_Empty_Null()
|
||||
{
|
||||
string disc = string.Empty;
|
||||
bool actual = DiscImageCreator.GetDiscType(disc, out string? discTypeOrBookType);
|
||||
bool actual = DiscImageCreator.GetDiscType(disc, out _);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
@@ -410,7 +434,7 @@ namespace MPF.Processors.Test
|
||||
public void GetDiscType_Invalid_Null()
|
||||
{
|
||||
string disc = "INVALID";
|
||||
bool actual = DiscImageCreator.GetDiscType(disc, out string? discTypeOrBookType);
|
||||
bool actual = DiscImageCreator.GetDiscType(disc, out _);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
@@ -1165,7 +1189,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GetXGDAuxHashInfo_Invalid_Null()
|
||||
{
|
||||
Datafile? suppl = new Datafile();
|
||||
Datafile? suppl = new();
|
||||
bool actual = DiscImageCreator.GetXGDAuxHashInfo(suppl,
|
||||
out string? dmihash,
|
||||
out string? pfihash,
|
||||
@@ -1180,7 +1204,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GetXGDAuxHashInfo_Valid_Filled()
|
||||
{
|
||||
Datafile? suppl = new Datafile
|
||||
Datafile? suppl = new()
|
||||
{
|
||||
Game =
|
||||
[
|
||||
@@ -1271,4 +1295,4 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -24,13 +24,13 @@
|
||||
</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="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.7.4]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.0]" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.24.0" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.25.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" />
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using MPF.Processors.OutputFiles;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Processors.Test
|
||||
@@ -15,6 +16,7 @@ namespace MPF.Processors.Test
|
||||
[InlineData(OutputFileFlags.Binary, false)]
|
||||
[InlineData(OutputFileFlags.Deleteable, false)]
|
||||
[InlineData(OutputFileFlags.Zippable, false)]
|
||||
[InlineData(OutputFileFlags.Preserve, false)]
|
||||
public void IsRequiredTest(OutputFileFlags flags, bool expected)
|
||||
{
|
||||
var of = new OutputFile("file", flags, "key");
|
||||
@@ -33,6 +35,7 @@ namespace MPF.Processors.Test
|
||||
[InlineData(OutputFileFlags.Binary, true)]
|
||||
[InlineData(OutputFileFlags.Deleteable, false)]
|
||||
[InlineData(OutputFileFlags.Zippable, false)]
|
||||
[InlineData(OutputFileFlags.Preserve, false)]
|
||||
public void IsArtifactTest(OutputFileFlags flags, bool expected)
|
||||
{
|
||||
var of = new OutputFile("file", flags, "key");
|
||||
@@ -51,6 +54,7 @@ namespace MPF.Processors.Test
|
||||
[InlineData(OutputFileFlags.Binary, true)]
|
||||
[InlineData(OutputFileFlags.Deleteable, false)]
|
||||
[InlineData(OutputFileFlags.Zippable, false)]
|
||||
[InlineData(OutputFileFlags.Preserve, false)]
|
||||
public void IsBinaryArtifactTest(OutputFileFlags flags, bool expected)
|
||||
{
|
||||
var of = new OutputFile("file", flags, "key");
|
||||
@@ -69,6 +73,7 @@ namespace MPF.Processors.Test
|
||||
[InlineData(OutputFileFlags.Binary, false)]
|
||||
[InlineData(OutputFileFlags.Deleteable, true)]
|
||||
[InlineData(OutputFileFlags.Zippable, false)]
|
||||
[InlineData(OutputFileFlags.Preserve, false)]
|
||||
public void IsDeleteableTest(OutputFileFlags flags, bool expected)
|
||||
{
|
||||
var of = new OutputFile("file", flags, "key");
|
||||
@@ -87,6 +92,7 @@ namespace MPF.Processors.Test
|
||||
[InlineData(OutputFileFlags.Binary, false)]
|
||||
[InlineData(OutputFileFlags.Deleteable, false)]
|
||||
[InlineData(OutputFileFlags.Zippable, true)]
|
||||
[InlineData(OutputFileFlags.Preserve, true)]
|
||||
public void IsZippableTest(OutputFileFlags flags, bool expected)
|
||||
{
|
||||
var of = new OutputFile("file", flags, "key");
|
||||
@@ -98,6 +104,25 @@ namespace MPF.Processors.Test
|
||||
Assert.Equal(expected, rof.IsZippable);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(OutputFileFlags.None, false)]
|
||||
[InlineData(OutputFileFlags.Required, false)]
|
||||
[InlineData(OutputFileFlags.Artifact, false)]
|
||||
[InlineData(OutputFileFlags.Binary, false)]
|
||||
[InlineData(OutputFileFlags.Deleteable, false)]
|
||||
[InlineData(OutputFileFlags.Zippable, false)]
|
||||
[InlineData(OutputFileFlags.Preserve, true)]
|
||||
public void IsPreservedTest(OutputFileFlags flags, bool expected)
|
||||
{
|
||||
var of = new OutputFile("file", flags, "key");
|
||||
var cof = new CustomOutputFile("file", flags, "key", File.Exists);
|
||||
var rof = new RegexOutputFile("file", flags, "key");
|
||||
|
||||
Assert.Equal(expected, of.IsPreserved);
|
||||
Assert.Equal(expected, cof.IsPreserved);
|
||||
Assert.Equal(expected, rof.IsPreserved);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Exists
|
||||
@@ -210,4 +235,4 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,5 +207,29 @@ namespace MPF.Processors.Test
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetPreservedFilePaths
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Invalid_Empty()
|
||||
{
|
||||
string? outputDirectory = null;
|
||||
string outputFilename = string.Empty;
|
||||
var processor = new PS3CFW(RedumpSystem.SonyPlayStation3);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.BluRay, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Valid_Empty()
|
||||
{
|
||||
string? outputDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "PS3CFW", "BluRay");
|
||||
string outputFilename = "test.iso";
|
||||
var processor = new PS3CFW(RedumpSystem.SonyPlayStation3);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.BluRay, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GenerateDatfile_Invalid_Null()
|
||||
{
|
||||
Datafile? datafile = new Datafile();
|
||||
Datafile? datafile = new();
|
||||
string? actual = ProcessingTool.GenerateDatfile(datafile);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace MPF.Processors.Test
|
||||
public void GenerateDatfile_Valid_Filled()
|
||||
{
|
||||
string? expected = "<rom name=\"test\" size=\"12345\" crc=\"00000000\" md5=\"d41d8cd98f00b204e9800998ecf8427e\" sha1=\"da39a3ee5e6b4b0d3255bfef95601890afd80709\" />";
|
||||
Rom rom = new Rom
|
||||
Rom rom = new()
|
||||
{
|
||||
Name = "test",
|
||||
Size = "12345",
|
||||
@@ -41,8 +41,8 @@ namespace MPF.Processors.Test
|
||||
MD5 = "d41d8cd98f00b204e9800998ecf8427e",
|
||||
SHA1 = "da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
||||
};
|
||||
Game game = new Game { Rom = [rom] };
|
||||
Datafile? datafile = new Datafile { Game = [game] };
|
||||
Game game = new() { Rom = [rom] };
|
||||
Datafile? datafile = new() { Game = [game] };
|
||||
|
||||
string? actual = ProcessingTool.GenerateDatfile(datafile);
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -181,7 +181,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GetISOHashValues_Datafile_Empty_Null()
|
||||
{
|
||||
Datafile? datafile = new Datafile();
|
||||
Datafile? datafile = new();
|
||||
bool actual = ProcessingTool.GetISOHashValues(datafile,
|
||||
out long size,
|
||||
out string? crc32,
|
||||
@@ -203,7 +203,7 @@ namespace MPF.Processors.Test
|
||||
string? expectedMd5 = "d41d8cd98f00b204e9800998ecf8427e";
|
||||
string? expectedSha1 = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
|
||||
|
||||
Rom rom = new Rom
|
||||
Rom rom = new()
|
||||
{
|
||||
Name = "test",
|
||||
Size = "12345",
|
||||
@@ -211,8 +211,8 @@ namespace MPF.Processors.Test
|
||||
MD5 = "d41d8cd98f00b204e9800998ecf8427e",
|
||||
SHA1 = "da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
||||
};
|
||||
Game game = new Game { Rom = [rom] };
|
||||
Datafile? datafile = new Datafile { Game = [game] };
|
||||
Game game = new() { Rom = [rom] };
|
||||
Datafile? datafile = new() { Game = [game] };
|
||||
|
||||
bool actual = ProcessingTool.GetISOHashValues(datafile,
|
||||
out long size,
|
||||
@@ -322,7 +322,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GetLayerbreaks_Empty_Null()
|
||||
{
|
||||
DiscInformation? di = new DiscInformation();
|
||||
DiscInformation? di = new();
|
||||
bool actual = ProcessingTool.GetLayerbreaks(di,
|
||||
out long? layerbreak1,
|
||||
out long? layerbreak2,
|
||||
@@ -341,35 +341,35 @@ namespace MPF.Processors.Test
|
||||
long? expectedLayerbreak2 = 134744076;
|
||||
long? expectedLayerbreak3 = 202116114;
|
||||
|
||||
DiscInformationUnit layer0 = new DiscInformationUnit
|
||||
DiscInformationUnit layer0 = new()
|
||||
{
|
||||
Body = new DiscInformationUnitBody
|
||||
{
|
||||
FormatDependentContents = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08],
|
||||
}
|
||||
};
|
||||
DiscInformationUnit layer1 = new DiscInformationUnit
|
||||
DiscInformationUnit layer1 = new()
|
||||
{
|
||||
Body = new DiscInformationUnitBody
|
||||
{
|
||||
FormatDependentContents = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08],
|
||||
}
|
||||
};
|
||||
DiscInformationUnit layer2 = new DiscInformationUnit
|
||||
DiscInformationUnit layer2 = new()
|
||||
{
|
||||
Body = new DiscInformationUnitBody
|
||||
{
|
||||
FormatDependentContents = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08],
|
||||
}
|
||||
};
|
||||
DiscInformationUnit layer3 = new DiscInformationUnit
|
||||
DiscInformationUnit layer3 = new()
|
||||
{
|
||||
Body = new DiscInformationUnitBody
|
||||
{
|
||||
FormatDependentContents = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08],
|
||||
}
|
||||
};
|
||||
DiscInformation? di = new DiscInformation
|
||||
DiscInformation? di = new()
|
||||
{
|
||||
Units = [layer0, layer1, layer2, layer3],
|
||||
};
|
||||
@@ -400,7 +400,7 @@ namespace MPF.Processors.Test
|
||||
[Fact]
|
||||
public void GetPICIdentifier_Empty_Null()
|
||||
{
|
||||
DiscInformation? di = new DiscInformation();
|
||||
DiscInformation? di = new();
|
||||
string? actual = ProcessingTool.GetPICIdentifier(di);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
@@ -409,14 +409,14 @@ namespace MPF.Processors.Test
|
||||
public void GetPICIdentifier_Valid_Filled()
|
||||
{
|
||||
string? expected = "UHD";
|
||||
DiscInformationUnit layer0 = new DiscInformationUnit
|
||||
DiscInformationUnit layer0 = new()
|
||||
{
|
||||
Body = new DiscInformationUnitBody
|
||||
{
|
||||
DiscTypeIdentifier = "UHD",
|
||||
}
|
||||
};
|
||||
DiscInformation? di = new DiscInformation
|
||||
DiscInformation? di = new()
|
||||
{
|
||||
Units = [layer0],
|
||||
};
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace MPF.Processors.Test
|
||||
string outputFilename = string.Empty;
|
||||
var processor = new Redumper(RedumpSystem.IBMPCcompatible);
|
||||
var actual = processor.FoundAllFiles(MediaType.CDROM, outputDirectory, outputFilename);
|
||||
Assert.Equal(7, actual.Count);
|
||||
Assert.Equal(5, actual.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -277,7 +277,31 @@ namespace MPF.Processors.Test
|
||||
string outputFilename = "test.cue";
|
||||
var processor = new Redumper(RedumpSystem.IBMPCcompatible);
|
||||
var actual = processor.GetZippableFilePaths(MediaType.CDROM, outputDirectory, outputFilename);
|
||||
Assert.Equal(10, actual.Count);
|
||||
Assert.Equal(11, actual.Count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetPreservedFilePaths
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Invalid_Empty()
|
||||
{
|
||||
string? outputDirectory = null;
|
||||
string outputFilename = string.Empty;
|
||||
var processor = new Redumper(RedumpSystem.IBMPCcompatible);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.CDROM, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Valid_Filled()
|
||||
{
|
||||
string? outputDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "Redumper", "CDROM");
|
||||
string outputFilename = "test.cue";
|
||||
var processor = new Redumper(RedumpSystem.IBMPCcompatible);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.CDROM, outputDirectory, outputFilename);
|
||||
Assert.Single(actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -1450,4 +1474,4 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,6 +209,30 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetPreservedFilePaths
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Invalid_Empty()
|
||||
{
|
||||
string? outputDirectory = null;
|
||||
string outputFilename = string.Empty;
|
||||
var processor = new UmdImageCreator(RedumpSystem.SonyPlayStationPortable);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.UMD, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Valid_Empty()
|
||||
{
|
||||
string? outputDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "UmdImageCreator", "UMD");
|
||||
string outputFilename = "test.iso";
|
||||
var processor = new UmdImageCreator(RedumpSystem.SonyPlayStationPortable);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.UMD, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetPVD
|
||||
|
||||
[Fact]
|
||||
@@ -353,4 +377,4 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,6 +209,30 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetPreservedFilePaths
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Invalid_Empty()
|
||||
{
|
||||
string? outputDirectory = null;
|
||||
string outputFilename = string.Empty;
|
||||
var processor = new XboxBackupCreator(RedumpSystem.MicrosoftXbox);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.DVD, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetPreservedFilePaths_Valid_Empty()
|
||||
{
|
||||
string? outputDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "XboxBackupCreator", "DVD");
|
||||
string outputFilename = "test.iso";
|
||||
var processor = new XboxBackupCreator(RedumpSystem.MicrosoftXbox);
|
||||
var actual = processor.GetPreservedFilePaths(MediaType.DVD, outputDirectory, outputFilename);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetLogName
|
||||
|
||||
[Fact]
|
||||
@@ -460,4 +484,4 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
#if NET35_OR_GREATER || NETCOREAPP
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using MPF.Processors.OutputFiles;
|
||||
using SabreTools.Data.Models.CueSheets;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Schemas;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Common;
|
||||
#endif
|
||||
|
||||
#pragma warning disable CS0618 // Ignore "Type or member is obsolete"
|
||||
#pragma warning disable IDE0059 // Unnecessary assignment of a value
|
||||
@@ -38,6 +46,24 @@ namespace MPF.Processors
|
||||
if (!string.IsNullOrEmpty(outputDirectory))
|
||||
basePath = Path.Combine(outputDirectory, basePath);
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
// Extract sidecar from archive, if it is zipped
|
||||
string sidecarPath = $"{basePath}.cicm.xml";
|
||||
if (!File.Exists(sidecarPath) && File.Exists($"{basePath}_logs.zip"))
|
||||
{
|
||||
ZipArchive? logArchive = null;
|
||||
try
|
||||
{
|
||||
logArchive = ZipArchive.Open($"{basePath}_logs.zip");
|
||||
string sidecarName = $"{Path.GetFileNameWithoutExtension(outputFilename)}.cicm.xml";
|
||||
var sidecarEntry = logArchive.Entries.FirstOrDefault(e => e.Key == sidecarName && !e.IsDirectory);
|
||||
sidecarEntry?.WriteToFile(sidecarPath, new ExtractionOptions { ExtractFullPath = false, Overwrite = true });
|
||||
}
|
||||
catch { }
|
||||
logArchive?.Dispose();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Deserialize the sidecar, if possible
|
||||
var sidecar = GenerateSidecar($"{basePath}.cicm.xml");
|
||||
|
||||
@@ -55,11 +81,8 @@ namespace MPF.Processors
|
||||
// TODO: Fill in submission info specifics for Aaru
|
||||
var outputDirectory = Path.GetDirectoryName(basePath);
|
||||
|
||||
// Ensure that required sections exist
|
||||
info = Builder.EnsureAllSections(info);
|
||||
|
||||
// TODO: Determine if there's an Aaru version anywhere
|
||||
info.DumpingInfo!.DumpingDate = ProcessingTool.GetFileModifiedDate($"{basePath}.cicm.xml")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
info.DumpingInfo.DumpingDate = ProcessingTool.GetFileModifiedDate($"{basePath}.cicm.xml")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
// Deserialize the sidecar, if possible
|
||||
var sidecar = GenerateSidecar($"{basePath}.cicm.xml");
|
||||
@@ -92,11 +115,11 @@ namespace MPF.Processors
|
||||
|
||||
// Get the Datafile information
|
||||
var datafile = GenerateDatafile(sidecar, basePath);
|
||||
info.TracksAndWriteOffsets!.ClrMameProData = ProcessingTool.GenerateDatfile(datafile);
|
||||
info.TracksAndWriteOffsets.ClrMameProData = ProcessingTool.GenerateDatfile(datafile);
|
||||
|
||||
// Get the error count
|
||||
long errorCount = GetErrorCount($"{basePath}.resume.xml");
|
||||
info.CommonDiscInfo!.ErrorsCount = (errorCount == -1 ? "Error retrieving error count" : errorCount.ToString());
|
||||
info.CommonDiscInfo.ErrorsCount = (errorCount == -1 ? "Error retrieving error count" : errorCount.ToString());
|
||||
|
||||
// Get the write offset, if it exists
|
||||
string? writeOffset = GetWriteOffset(sidecar);
|
||||
@@ -118,7 +141,7 @@ namespace MPF.Processors
|
||||
// Get the individual hash data, as per internal
|
||||
if (ProcessingTool.GetISOHashValues(datafile, out long size, out var crc32, out var md5, out var sha1))
|
||||
{
|
||||
info.SizeAndChecksums!.Size = size;
|
||||
info.SizeAndChecksums.Size = size;
|
||||
info.SizeAndChecksums.CRC32 = crc32;
|
||||
info.SizeAndChecksums.MD5 = md5;
|
||||
info.SizeAndChecksums.SHA1 = sha1;
|
||||
@@ -130,7 +153,7 @@ namespace MPF.Processors
|
||||
if (mediaType == MediaType.DVD)
|
||||
layerbreak = GetLayerbreak(sidecar) ?? string.Empty;
|
||||
else if (mediaType == MediaType.BluRay)
|
||||
layerbreak = info.SizeAndChecksums!.Size > 25_025_314_816 ? "25025314816" : null;
|
||||
layerbreak = info.SizeAndChecksums.Size > 25_025_314_816 ? "25025314816" : null;
|
||||
|
||||
// If we have a single-layer disc
|
||||
if (string.IsNullOrEmpty(layerbreak))
|
||||
@@ -140,7 +163,7 @@ namespace MPF.Processors
|
||||
// If we have a dual-layer disc
|
||||
else
|
||||
{
|
||||
info.SizeAndChecksums!.Layerbreak = long.Parse(layerbreak);
|
||||
info.SizeAndChecksums.Layerbreak = long.Parse(layerbreak);
|
||||
}
|
||||
|
||||
// TODO: Investigate XGD disc outputs
|
||||
@@ -160,23 +183,23 @@ namespace MPF.Processors
|
||||
|
||||
case RedumpSystem.DVDAudio:
|
||||
case RedumpSystem.DVDVideo:
|
||||
info.CopyProtection!.Protection = GetDVDProtection(sidecar) ?? string.Empty;
|
||||
info.CopyProtection.Protection = GetDVDProtection(sidecar) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.MicrosoftXbox:
|
||||
if (GetXgdAuxInfo(sidecar, out var xgd1DMIHash, out var xgd1PFIHash, out var xgd1SSHash, out var ss, out var xgd1SSVer))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = xgd1DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd1DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd1PFIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd1SSHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd1SSVer ?? string.Empty;
|
||||
info.Extras!.SecuritySectorRanges = ss ?? string.Empty;
|
||||
info.Extras.SecuritySectorRanges = ss ?? string.Empty;
|
||||
}
|
||||
|
||||
if (GetXboxDMIInfo(sidecar, out var serial, out var version, out Region? region))
|
||||
{
|
||||
info.CommonDiscInfo!.Serial = serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.Serial = serial ?? string.Empty;
|
||||
info.VersionAndEditions.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.Region = region;
|
||||
}
|
||||
|
||||
@@ -185,17 +208,17 @@ namespace MPF.Processors
|
||||
case RedumpSystem.MicrosoftXbox360:
|
||||
if (GetXgdAuxInfo(sidecar, out var xgd23DMIHash, out var xgd23PFIHash, out var xgd23SSHash, out var ss360, out var xgd23SSVer))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = xgd23DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd23DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd23PFIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd23SSHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd23SSVer ?? string.Empty;
|
||||
info.Extras!.SecuritySectorRanges = ss360 ?? string.Empty;
|
||||
info.Extras.SecuritySectorRanges = ss360 ?? string.Empty;
|
||||
}
|
||||
|
||||
if (GetXbox360DMIInfo(sidecar, out var serial360, out var version360, out Region? region360))
|
||||
{
|
||||
info.CommonDiscInfo!.Serial = serial360 ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = version360 ?? string.Empty;
|
||||
info.CommonDiscInfo.Serial = serial360 ?? string.Empty;
|
||||
info.VersionAndEditions.Version = version360 ?? string.Empty;
|
||||
info.CommonDiscInfo.Region = region360;
|
||||
}
|
||||
break;
|
||||
@@ -384,8 +407,8 @@ namespace MPF.Processors
|
||||
else
|
||||
{
|
||||
// Default if index data missing from sidecar
|
||||
cueTrack.Indices = new CueIndex[]
|
||||
{
|
||||
cueTrack.Indices =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Index = 1,
|
||||
@@ -393,7 +416,7 @@ namespace MPF.Processors
|
||||
Seconds = 0,
|
||||
Frames = 0,
|
||||
},
|
||||
};
|
||||
];
|
||||
}
|
||||
|
||||
// Add the track to the file
|
||||
@@ -1147,7 +1170,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return long.MaxValue;
|
||||
}
|
||||
}
|
||||
@@ -1290,7 +1313,7 @@ namespace MPF.Processors
|
||||
{
|
||||
foreach (ChecksumType checksum in dmi.Checksums)
|
||||
{
|
||||
// We only care about the CRC32
|
||||
// Only CRC is collected
|
||||
if (checksum.type == ChecksumTypeType.crc32)
|
||||
{
|
||||
dmihash = checksum.Value;
|
||||
@@ -1308,7 +1331,7 @@ namespace MPF.Processors
|
||||
{
|
||||
foreach (ChecksumType checksum in pfi.Checksums)
|
||||
{
|
||||
// We only care about the CRC32
|
||||
// Only CRC is collected
|
||||
if (checksum.type == ChecksumTypeType.crc32)
|
||||
{
|
||||
pfihash = checksum.Value;
|
||||
@@ -1328,7 +1351,7 @@ namespace MPF.Processors
|
||||
{
|
||||
foreach (ChecksumType checksum in security.Checksums)
|
||||
{
|
||||
// We only care about the CRC32
|
||||
// Only CRC is collected
|
||||
if (checksum.type == ChecksumTypeType.crc32)
|
||||
{
|
||||
// TODO: Validate correctness for all 3 fields
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using MPF.Processors.OutputFiles;
|
||||
using SabreTools.Hashing;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
@@ -9,7 +10,9 @@ using SabreTools.RedumpLib.Data;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
using SharpCompress.Compressors.ZStandard;
|
||||
using SharpCompress.Writers.Zip;
|
||||
#endif
|
||||
|
||||
@@ -59,7 +62,7 @@ namespace MPF.Processors
|
||||
/// <param name="redumpCompat">Determines if outputs are processed according to Redump specifications</param>
|
||||
public abstract void GenerateSubmissionInfo(SubmissionInfo submissionInfo, MediaType? mediaType, string basePath, bool redumpCompat);
|
||||
|
||||
// <summary>
|
||||
/// <summary>
|
||||
/// Generate a list of all output files generated
|
||||
/// </summary>
|
||||
/// <param name="mediaType">Media type for controlling expected file sets</param>
|
||||
@@ -105,6 +108,7 @@ namespace MPF.Processors
|
||||
|
||||
// Get the lists of zippable files
|
||||
var zippableFiles = GetZippableFilePaths(mediaType, outputDirectory, outputFilename);
|
||||
var preservedFiles = GetPreservedFilePaths(mediaType, outputDirectory, outputFilename);
|
||||
var generatedFiles = GetGeneratedFilePaths(outputDirectory, filenameSuffix);
|
||||
|
||||
// Don't create an archive if there are no paths
|
||||
@@ -137,7 +141,7 @@ namespace MPF.Processors
|
||||
zf.SaveTo(archiveName, new ZipWriterOptions(CompressionType.Deflate, CompressionLevel.BestCompression) { UseZip64 = true });
|
||||
break;
|
||||
case LogCompression.Zstd19:
|
||||
zf.SaveTo(archiveName, new ZipWriterOptions(CompressionType.ZStandard, (CompressionLevel)19) { UseZip64 = true });
|
||||
zf.SaveTo(archiveName, new ZipWriterOptions(CompressionType.ZStandard, (CompressionLevel)19) { UseZip64 = true, CompressionBufferSize = 0x20000 });
|
||||
break;
|
||||
case LogCompression.DeflateDefault:
|
||||
default:
|
||||
@@ -152,6 +156,10 @@ namespace MPF.Processors
|
||||
// Delete all successful files
|
||||
foreach (string file in successful)
|
||||
{
|
||||
// Ignore files that are preserved
|
||||
if (preservedFiles.Contains(file))
|
||||
continue;
|
||||
|
||||
try { File.Delete(file); } catch { }
|
||||
}
|
||||
|
||||
@@ -289,6 +297,52 @@ namespace MPF.Processors
|
||||
return missingFiles;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts found files from a found archive if it exists
|
||||
/// </summary>
|
||||
/// <param name="mediaType">Media type for controlling expected file sets</param>
|
||||
/// <param name="outputDirectory">Output folder to use as the base path</param>
|
||||
/// <param name="outputFilename">Output filename to use as the base path</param>
|
||||
/// <remarks>Assumes filename has an extension</remarks>
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
public void ExtractFromLogs(MediaType? mediaType, string? outputDirectory, string outputFilename)
|
||||
{
|
||||
// Get the list of output files
|
||||
var outputFiles = GetOutputFiles(mediaType, outputDirectory, outputFilename);
|
||||
if (outputFiles.Count == 0)
|
||||
return;
|
||||
|
||||
// Assemble a base path
|
||||
string basePath = Path.GetFileNameWithoutExtension(outputFilename);
|
||||
if (!string.IsNullOrEmpty(outputDirectory))
|
||||
basePath = Path.Combine(outputDirectory, basePath);
|
||||
|
||||
// Check for the log archive
|
||||
if (!File.Exists($"{basePath}_logs.zip"))
|
||||
return;
|
||||
|
||||
// Extract all found output files from the archive
|
||||
ZipArchive? logArchive = null;
|
||||
try
|
||||
{
|
||||
logArchive = ZipArchive.Open($"{basePath}_logs.zip");
|
||||
foreach (var outputFile in outputFiles)
|
||||
{
|
||||
outputFile.Extract(logArchive, outputDirectory ?? string.Empty);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Absorb the exception
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
logArchive?.Dispose();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that no potential output files have been created
|
||||
/// </summary>
|
||||
@@ -426,7 +480,11 @@ namespace MPF.Processors
|
||||
// Get the entry name from the file
|
||||
string entryName = file;
|
||||
if (!string.IsNullOrEmpty(outputDirectory))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
entryName = entryName[outputDirectory.Length..];
|
||||
#else
|
||||
entryName = entryName.Substring(outputDirectory!.Length);
|
||||
#endif
|
||||
|
||||
// Ensure the entry is formatted correctly
|
||||
entryName = entryName.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
@@ -559,10 +617,91 @@ namespace MPF.Processors
|
||||
return zippablePaths;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a list of all preserved file paths
|
||||
/// </summary>
|
||||
/// <param name="mediaType">Media type for controlling expected file sets</param>
|
||||
/// <param name="outputDirectory">Output folder to use as the base path</param>
|
||||
/// <param name="outputFilename">Output filename to use as the base path</param>
|
||||
/// <returns>List of all preserved file paths, empty otherwise</returns>
|
||||
/// <remarks>Assumes filename has an extension</remarks>
|
||||
internal List<string> GetPreservedFilePaths(MediaType? mediaType, string? outputDirectory, string outputFilename)
|
||||
{
|
||||
// Get the list of output files
|
||||
var outputFiles = GetOutputFiles(mediaType, outputDirectory, outputFilename);
|
||||
if (outputFiles.Count == 0)
|
||||
return [];
|
||||
|
||||
// Filter down to zippable files
|
||||
var preserved = outputFiles.FindAll(of => of.IsPreserved);
|
||||
|
||||
// Get all paths that exist
|
||||
var preservedPaths = new List<string>();
|
||||
foreach (var file in preserved)
|
||||
{
|
||||
var paths = file.GetPaths(outputDirectory ?? string.Empty);
|
||||
paths = paths.FindAll(File.Exists);
|
||||
preservedPaths.AddRange(paths);
|
||||
}
|
||||
|
||||
return preservedPaths;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Shared Methods
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to compress a file to Zstandard, removing the original on success
|
||||
/// </summary>
|
||||
/// <param name="file">Full path to an existing file</param>
|
||||
/// <returns>True if the compression was a success, false otherwise</returns>
|
||||
internal static bool CompressZstandard(string file)
|
||||
{
|
||||
#if NET20 || NET35 || NET40 || NET452
|
||||
// Compression is not available for this framework version
|
||||
return false;
|
||||
#else
|
||||
// Ensure the file exists
|
||||
if (!File.Exists(file))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
// Prepare the input and output streams
|
||||
using var ifs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
using var ofs = File.Open($"{file}.zst", FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
using var zst = new ZStandardStream(ofs, CompressionMode.Compress, compressionLevel: 19, leaveOpen: true);
|
||||
|
||||
// Compress and write in blocks
|
||||
int read = 0;
|
||||
do
|
||||
{
|
||||
byte[] buffer = new byte[3 * 1024 * 1024];
|
||||
|
||||
read = ifs.Read(buffer, 0, buffer.Length);
|
||||
if (read == 0)
|
||||
break;
|
||||
|
||||
zst.Write(buffer, 0, read);
|
||||
zst.Flush();
|
||||
} while (read > 0);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Try to delete the incomplete
|
||||
try { File.Delete($"{file}.zst"); } catch { }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to delete the file
|
||||
try { File.Delete(file); } catch { }
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a CMP XML datfile string based on a single input file
|
||||
/// </summary>
|
||||
@@ -623,14 +762,18 @@ namespace MPF.Processors
|
||||
return null;
|
||||
|
||||
if (trimLength > -1 && trimLength < hex.Length)
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
hex = hex[..trimLength];
|
||||
#else
|
||||
hex = hex.Substring(0, trimLength);
|
||||
#endif
|
||||
|
||||
// TODO: Check for non-zero values in discarded PIC
|
||||
return SplitString(hex, 32);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was right now
|
||||
// Absorb the exception right now
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -672,7 +815,8 @@ namespace MPF.Processors
|
||||
else
|
||||
pvdCharArray[i] = '.';
|
||||
}
|
||||
string pvdASCII = new string(pvdCharArray, 0, 96);
|
||||
|
||||
string pvdASCII = new(pvdCharArray, 0, 96);
|
||||
pvd = string.Empty;
|
||||
for (int i = 0; i < 96; i += 16)
|
||||
{
|
||||
@@ -684,13 +828,13 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a Cuesheet consists of only Audio tracks, false otherwise
|
||||
/// Returns true if a Cuesheet consists of only Audio tracks, false otherwise
|
||||
/// </summary>
|
||||
internal static bool IsAudio(string? cue)
|
||||
{
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using MPF.Processors.OutputFiles;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.Hashing;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Processors
|
||||
@@ -32,20 +32,20 @@ namespace MPF.Processors
|
||||
/// <inheritdoc/>
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, MediaType? mediaType, string basePath, bool redumpCompat)
|
||||
{
|
||||
// Ensure that required sections exist
|
||||
info = Builder.EnsureAllSections(info);
|
||||
|
||||
// TODO: Determine if there's a CleanRip version anywhere
|
||||
info.DumpingInfo!.DumpingDate = ProcessingTool.GetFileModifiedDate($"{basePath}-dumpinfo.txt")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
info.DumpingInfo.DumpingDate = ProcessingTool.GetFileModifiedDate($"{basePath}-dumpinfo.txt")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
// Try to merge parts together, if needed
|
||||
_ = MergeFileParts(basePath);
|
||||
|
||||
// Get the Datafile information
|
||||
var datafile = GenerateCleanripDatafile($"{basePath}.iso", $"{basePath}-dumpinfo.txt");
|
||||
info.TracksAndWriteOffsets!.ClrMameProData = ProcessingTool.GenerateDatfile(datafile);
|
||||
info.TracksAndWriteOffsets.ClrMameProData = ProcessingTool.GenerateDatfile(datafile);
|
||||
|
||||
// Get the individual hash data, as per internal
|
||||
if (ProcessingTool.GetISOHashValues(datafile, out long size, out var crc32, out var md5, out var sha1))
|
||||
{
|
||||
info.SizeAndChecksums!.Size = size;
|
||||
info.SizeAndChecksums.Size = size;
|
||||
info.SizeAndChecksums.CRC32 = crc32;
|
||||
info.SizeAndChecksums.MD5 = md5;
|
||||
info.SizeAndChecksums.SHA1 = sha1;
|
||||
@@ -56,16 +56,16 @@ namespace MPF.Processors
|
||||
}
|
||||
|
||||
// Get BCA information, if available
|
||||
info.Extras!.BCA = GetBCA(basePath + $"{basePath}.bca");
|
||||
info.Extras.BCA = GetBCA($"{basePath}.bca");
|
||||
|
||||
// Get internal information
|
||||
if (GetGameCubeWiiInformation(basePath + $"{basePath}-dumpinfo.txt", out Region? region, out var version, out var internalName, out var serial))
|
||||
if (GetGameCubeWiiInformation($"{basePath}-dumpinfo.txt", out Region? region, out var version, out var internalName, out var serial))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalName] = internalName ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalName] = internalName ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
if (!redumpCompat)
|
||||
{
|
||||
info.VersionAndEditions!.Version = version ?? info.VersionAndEditions.Version;
|
||||
info.VersionAndEditions.Version = version ?? info.VersionAndEditions.Version;
|
||||
info.CommonDiscInfo.Region = region ?? info.CommonDiscInfo.Region;
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,68 @@ namespace MPF.Processors
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Extra Methods
|
||||
|
||||
/// <summary>
|
||||
/// Merge all file parts based on a base path
|
||||
/// </summary>
|
||||
/// <param name="basePath">Base path to use for building</param>
|
||||
/// <returns>Filename of the merged parts on success, null otherwise</returns>
|
||||
/// <remarks>This assumes that all file parts are named like $"{basePath}.part{i}.iso"</remarks>
|
||||
internal static string? MergeFileParts(string basePath)
|
||||
{
|
||||
// If the expected output already exists
|
||||
if (File.Exists($"{basePath}.iso"))
|
||||
return $"{basePath}.iso";
|
||||
|
||||
// If the first part does not exist
|
||||
if (!File.Exists($"{basePath}.part0.iso"))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
// Try to build the new output file
|
||||
string combined = $"{basePath}.iso";
|
||||
using var ofs = File.Open(combined, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
// Get the next file part
|
||||
string part = $"{basePath}.part{i++}.iso";
|
||||
if (!File.Exists(part))
|
||||
break;
|
||||
|
||||
// Copy the file part to the output
|
||||
using var ifs = File.Open(part, FileMode.Open, FileAccess.Read, FileShare.None);
|
||||
|
||||
// Write in blocks
|
||||
int read = 0;
|
||||
do
|
||||
{
|
||||
byte[] buffer = new byte[3 * 1024 * 1024];
|
||||
|
||||
read = ifs.Read(buffer, 0, buffer.Length);
|
||||
if (read == 0)
|
||||
break;
|
||||
|
||||
ofs.Write(buffer, 0, read);
|
||||
ofs.Flush();
|
||||
} while (read > 0);
|
||||
|
||||
} while (true);
|
||||
|
||||
return combined;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Absorb the exception right now
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Information Extraction Methods
|
||||
|
||||
/// <summary>
|
||||
@@ -129,11 +191,23 @@ namespace MPF.Processors
|
||||
if (string.IsNullOrEmpty(line))
|
||||
continue;
|
||||
else if (line!.StartsWith("CRC32"))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
crc = line[7..].ToLowerInvariant();
|
||||
#else
|
||||
crc = line.Substring(7).ToLowerInvariant();
|
||||
#endif
|
||||
else if (line.StartsWith("MD5"))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
md5 = line[5..];
|
||||
#else
|
||||
md5 = line.Substring(5);
|
||||
#endif
|
||||
else if (line.StartsWith("SHA-1"))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
sha1 = line[7..];
|
||||
#else
|
||||
sha1 = line.Substring(7);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +233,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -199,7 +273,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was right now
|
||||
// Absorb the exception right now
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -240,15 +314,27 @@ namespace MPF.Processors
|
||||
}
|
||||
else if (line!.StartsWith("Version"))
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
version = line["Version: ".Length..];
|
||||
#else
|
||||
version = line.Substring("Version: ".Length);
|
||||
#endif
|
||||
}
|
||||
else if (line.StartsWith("Internal Name"))
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
name = line["Internal Name: ".Length..];
|
||||
#else
|
||||
name = line.Substring("Internal Name: ".Length);
|
||||
#endif
|
||||
}
|
||||
else if (line.StartsWith("Filename"))
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
serial = line["Filename: ".Length..];
|
||||
#else
|
||||
serial = line.Substring("Filename: ".Length);
|
||||
#endif
|
||||
if (serial.EndsWith("-disc2"))
|
||||
serial = serial.Replace("-disc2", string.Empty);
|
||||
|
||||
@@ -314,7 +400,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,14 @@ using System.IO;
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Text.RegularExpressions;
|
||||
using MPF.Processors.OutputFiles;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Common;
|
||||
#endif
|
||||
|
||||
/*
|
||||
If there are no external programs, such as error checking, etc., DIC outputs
|
||||
@@ -79,6 +84,24 @@ namespace MPF.Processors
|
||||
if (!string.IsNullOrEmpty(outputDirectory))
|
||||
basePath = Path.Combine(outputDirectory, basePath);
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
// Extract _disc.txt from archive, if it is zipped
|
||||
string discPath = $"{basePath}_disc.txt";
|
||||
if (!File.Exists(discPath) && File.Exists($"{basePath}_logs.zip"))
|
||||
{
|
||||
ZipArchive? logArchive = null;
|
||||
try
|
||||
{
|
||||
logArchive = ZipArchive.Open($"{basePath}_logs.zip");
|
||||
string discName = $"{Path.GetFileNameWithoutExtension(outputFilename)}_disc.txt";
|
||||
var discEntry = logArchive.Entries.FirstOrDefault(e => e.Key == discName && !e.IsDirectory);
|
||||
discEntry?.WriteToFile(discPath, new ExtractionOptions { ExtractFullPath = false, Overwrite = true });
|
||||
}
|
||||
catch { }
|
||||
logArchive?.Dispose();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get the comma-separated list of values
|
||||
if (GetDiscType($"{basePath}_disc.txt", out var discType) && discType != null)
|
||||
{
|
||||
@@ -149,12 +172,9 @@ namespace MPF.Processors
|
||||
/// <inheritdoc/>
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, MediaType? mediaType, string basePath, bool redumpCompat)
|
||||
{
|
||||
// Ensure that required sections exist
|
||||
info = Builder.EnsureAllSections(info);
|
||||
|
||||
// Get the dumping program and version
|
||||
var dicVersion = GetCommandFilePathAndVersion(basePath, out var dicCmd);
|
||||
info.DumpingInfo!.DumpingProgram ??= string.Empty;
|
||||
info.DumpingInfo.DumpingProgram ??= string.Empty;
|
||||
info.DumpingInfo.DumpingProgram += $" {dicVersion ?? "Unknown Version"}";
|
||||
info.DumpingInfo.DumpingParameters = GetParameters(dicCmd) ?? "Unknown Parameters";
|
||||
info.DumpingInfo.DumpingDate = ProcessingTool.GetFileModifiedDate(dicCmd)?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
@@ -172,21 +192,21 @@ namespace MPF.Processors
|
||||
info.DumpingInfo.ReportedDiscType = discTypeOrBookType;
|
||||
|
||||
// Get the PVD, if it exists
|
||||
info.Extras!.PVD = GetPVD($"{basePath}_mainInfo.txt") ?? "Disc has no PVD";
|
||||
info.Extras.PVD = GetPVD($"{basePath}_mainInfo.txt") ?? "Disc has no PVD";
|
||||
|
||||
// Get the Datafile information
|
||||
var datafile = ProcessingTool.GetDatafile($"{basePath}.dat");
|
||||
info.TracksAndWriteOffsets!.ClrMameProData = ProcessingTool.GenerateDatfile(datafile);
|
||||
info.TracksAndWriteOffsets.ClrMameProData = ProcessingTool.GenerateDatfile(datafile);
|
||||
|
||||
// Get the write offset, if it exists
|
||||
string? writeOffset = GetWriteOffset($"{basePath}_disc.txt");
|
||||
info.CommonDiscInfo!.RingWriteOffset = writeOffset;
|
||||
info.CommonDiscInfo.RingWriteOffset = writeOffset;
|
||||
info.TracksAndWriteOffsets.OtherWriteOffsets = writeOffset;
|
||||
|
||||
// Attempt to get multisession data
|
||||
string? multiSessionInfo = GetMultisessionInformation($"{basePath}_disc.txt");
|
||||
if (!string.IsNullOrEmpty(multiSessionInfo))
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.Multisession] = multiSessionInfo!;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.Multisession] = multiSessionInfo!;
|
||||
|
||||
// Fill in the volume labels
|
||||
if (GetVolumeLabels($"{basePath}_volDesc.txt", out var volLabels))
|
||||
@@ -202,7 +222,7 @@ namespace MPF.Processors
|
||||
// Audio-only discs will fail if there are any C2 errors, so they would never get here
|
||||
if (IsAudio(info.TracksAndWriteOffsets.Cuesheet))
|
||||
{
|
||||
info.CommonDiscInfo!.ErrorsCount = "0";
|
||||
info.CommonDiscInfo.ErrorsCount = "0";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -212,7 +232,7 @@ namespace MPF.Processors
|
||||
else if (File.Exists($"{basePath}.img_EccEdc.txt"))
|
||||
errorCount = GetErrorCount($"{basePath}.img_EccEdc.txt");
|
||||
|
||||
info.CommonDiscInfo!.ErrorsCount = (errorCount == -1 ? "Error retrieving error count" : errorCount.ToString());
|
||||
info.CommonDiscInfo.ErrorsCount = (errorCount == -1 ? "Error retrieving error count" : errorCount.ToString());
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -224,7 +244,7 @@ namespace MPF.Processors
|
||||
// Get the individual hash data, as per internal
|
||||
if (ProcessingTool.GetISOHashValues(datafile, out long size, out var crc32, out var md5, out var sha1))
|
||||
{
|
||||
info.SizeAndChecksums!.Size = size;
|
||||
info.SizeAndChecksums.Size = size;
|
||||
info.SizeAndChecksums.CRC32 = crc32;
|
||||
info.SizeAndChecksums.MD5 = md5;
|
||||
info.SizeAndChecksums.SHA1 = sha1;
|
||||
@@ -234,12 +254,12 @@ namespace MPF.Processors
|
||||
if (mediaType == MediaType.DVD)
|
||||
{
|
||||
string layerbreak = GetLayerbreak($"{basePath}_disc.txt", System.IsXGD()) ?? string.Empty;
|
||||
info.SizeAndChecksums!.Layerbreak = !string.IsNullOrEmpty(layerbreak) ? long.Parse(layerbreak) : default;
|
||||
info.SizeAndChecksums.Layerbreak = !string.IsNullOrEmpty(layerbreak) ? long.Parse(layerbreak) : default;
|
||||
}
|
||||
else if (mediaType == MediaType.BluRay)
|
||||
{
|
||||
var di = ProcessingTool.GetDiscInformation($"{basePath}_PIC.bin");
|
||||
info.SizeAndChecksums!.PICIdentifier = ProcessingTool.GetPICIdentifier(di);
|
||||
info.SizeAndChecksums.PICIdentifier = ProcessingTool.GetPICIdentifier(di);
|
||||
if (ProcessingTool.GetLayerbreaks(di, out long? layerbreak1, out long? layerbreak2, out long? layerbreak3))
|
||||
{
|
||||
if (layerbreak1 != null && layerbreak1 * 2048 < info.SizeAndChecksums.Size)
|
||||
@@ -264,16 +284,16 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SonyPlayStation3:
|
||||
case RedumpSystem.SonyPlayStation4:
|
||||
case RedumpSystem.SonyPlayStation5:
|
||||
if (info.SizeAndChecksums!.Layerbreak3 != default)
|
||||
if (info.SizeAndChecksums.Layerbreak3 != default)
|
||||
trimLength = 520;
|
||||
else if (info.SizeAndChecksums!.Layerbreak2 != default)
|
||||
else if (info.SizeAndChecksums.Layerbreak2 != default)
|
||||
trimLength = 392;
|
||||
else
|
||||
trimLength = 264;
|
||||
break;
|
||||
}
|
||||
|
||||
info.Extras!.PIC = GetPIC($"{basePath}_PIC.bin", trimLength) ?? string.Empty;
|
||||
info.Extras.PIC = GetPIC($"{basePath}_PIC.bin", trimLength) ?? string.Empty;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -287,17 +307,17 @@ namespace MPF.Processors
|
||||
case RedumpSystem.IBMPCcompatible:
|
||||
case RedumpSystem.RainbowDisc:
|
||||
case RedumpSystem.SonyElectronicBook:
|
||||
info.CopyProtection!.SecuROMData = GetSecuROMData($"{basePath}_subIntention.txt", out SecuROMScheme secuROMScheme) ?? string.Empty;
|
||||
info.CopyProtection.SecuROMData = GetSecuROMData($"{basePath}_subIntention.txt", out SecuROMScheme secuROMScheme) ?? string.Empty;
|
||||
if (secuROMScheme == SecuROMScheme.Unknown)
|
||||
info.CommonDiscInfo!.Comments = $"Warning: Incorrect SecuROM sector count{Environment.NewLine}";
|
||||
info.CommonDiscInfo.Comments = $"Warning: Incorrect SecuROM sector count{Environment.NewLine}";
|
||||
|
||||
// Needed for some odd copy protections
|
||||
info.CopyProtection!.Protection = GetDVDProtection($"{basePath}_CSSKey.txt", $"{basePath}_disc.txt", false) ?? string.Empty;
|
||||
info.CopyProtection.Protection = GetDVDProtection($"{basePath}_CSSKey.txt", $"{basePath}_disc.txt", false) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.DVDAudio:
|
||||
case RedumpSystem.DVDVideo:
|
||||
info.CopyProtection!.Protection = GetDVDProtection($"{basePath}_CSSKey.txt", $"{basePath}_disc.txt", true) ?? string.Empty;
|
||||
info.CopyProtection.Protection = GetDVDProtection($"{basePath}_CSSKey.txt", $"{basePath}_disc.txt", true) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.MicrosoftXbox:
|
||||
@@ -305,11 +325,11 @@ namespace MPF.Processors
|
||||
var xmid = SabreTools.Serialization.Wrappers.XMID.Create(xmidString);
|
||||
if (xmid != null)
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.XMID] = xmidString?.TrimEnd('\0') ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.XMID] = xmidString?.TrimEnd('\0') ?? string.Empty;
|
||||
info.CommonDiscInfo.Serial = xmid.Serial ?? string.Empty;
|
||||
if (!redumpCompat)
|
||||
{
|
||||
info.VersionAndEditions!.Version = xmid.Version ?? string.Empty;
|
||||
info.VersionAndEditions.Version = xmid.Version ?? string.Empty;
|
||||
info.CommonDiscInfo.Region = ProcessingTool.GetXGDRegion(xmid.Model.RegionIdentifier);
|
||||
}
|
||||
}
|
||||
@@ -320,28 +340,28 @@ namespace MPF.Processors
|
||||
var suppl = ProcessingTool.GetDatafile($"{basePath}_suppl.dat");
|
||||
if (GetXGDAuxHashInfo(suppl, out var xgd1DMIHash, out var xgd1PFIHash, out var xgd1SSHash))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = xgd1DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd1DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd1PFIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd1SSHash ?? string.Empty;
|
||||
}
|
||||
|
||||
if (GetXGDAuxInfo($"{basePath}_disc.txt", out _, out _, out _, out var xgd1SS, out _))
|
||||
{
|
||||
// We no longer care about SS Version from DIC
|
||||
//info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.SSVersion] = xgd1SSVer ?? string.Empty;
|
||||
info.Extras!.SecuritySectorRanges = xgd1SS ?? string.Empty;
|
||||
// SS Version from DIC is ignored now
|
||||
//info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd1SSVer ?? string.Empty;
|
||||
info.Extras.SecuritySectorRanges = xgd1SS ?? string.Empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetXGDAuxInfo($"{basePath}_disc.txt", out var xgd1DMIHash, out var xgd1PFIHash, out var xgd1SSHash, out var xgd1SS, out _))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = xgd1DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd1DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd1PFIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd1SSHash ?? string.Empty;
|
||||
// We no longer care about SS Version from DIC
|
||||
// SS Version from DIC is ignored now
|
||||
//info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd1SSVer ?? string.Empty;
|
||||
info.Extras!.SecuritySectorRanges = xgd1SS ?? string.Empty;
|
||||
info.Extras.SecuritySectorRanges = xgd1SS ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,10 +372,10 @@ namespace MPF.Processors
|
||||
var xemid = SabreTools.Serialization.Wrappers.XeMID.Create(xemidString);
|
||||
if (xemid != null)
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.XeMID] = xemidString?.TrimEnd('\0') ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.XeMID] = xemidString?.TrimEnd('\0') ?? string.Empty;
|
||||
info.CommonDiscInfo.Serial = xemid.Serial ?? string.Empty;
|
||||
if (!redumpCompat)
|
||||
info.VersionAndEditions!.Version = xemid.Version ?? string.Empty;
|
||||
info.VersionAndEditions.Version = xemid.Version ?? string.Empty;
|
||||
|
||||
info.CommonDiscInfo.Region = ProcessingTool.GetXGDRegion(xemid.Model.RegionIdentifier);
|
||||
}
|
||||
@@ -366,28 +386,28 @@ namespace MPF.Processors
|
||||
var suppl = ProcessingTool.GetDatafile($"{basePath}_suppl.dat");
|
||||
if (GetXGDAuxHashInfo(suppl, out var xgd23DMIHash, out var xgd23PFIHash, out var xgd23SSHash))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = xgd23DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd23DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd23PFIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd23SSHash ?? string.Empty;
|
||||
}
|
||||
|
||||
if (GetXGDAuxInfo($"{basePath}_disc.txt", out _, out _, out _, out var xgd23SS, out _))
|
||||
{
|
||||
// We no longer care about SS Version from DIC
|
||||
//info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.SSVersion] = xgd23SSVer ?? string.Empty;
|
||||
info.Extras!.SecuritySectorRanges = xgd23SS ?? string.Empty;
|
||||
// SS Version from DIC is ignored now
|
||||
//info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd23SSVer ?? string.Empty;
|
||||
info.Extras.SecuritySectorRanges = xgd23SS ?? string.Empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetXGDAuxInfo($"{basePath}_disc.txt", out var xgd23DMIHash, out var xgd23PFIHash, out var xgd23SSHash, out var xgd23SS, out _))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = xgd23DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd23DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd23PFIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd23SSHash ?? string.Empty;
|
||||
// We no longer care about SS Version from DIC
|
||||
// SS Version from DIC is ignored now
|
||||
//info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd23SSVer ?? string.Empty;
|
||||
info.Extras!.SecuritySectorRanges = xgd23SS ?? string.Empty;
|
||||
info.Extras.SecuritySectorRanges = xgd23SS ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +416,7 @@ namespace MPF.Processors
|
||||
case RedumpSystem.NamcoSegaNintendoTriforce:
|
||||
if (mediaType == MediaType.CDROM)
|
||||
{
|
||||
info.Extras!.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
|
||||
// Take only the first 16 lines for GD-ROM
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
@@ -408,8 +428,8 @@ namespace MPF.Processors
|
||||
out var date))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.VersionAndEditions.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = date ?? string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -417,7 +437,7 @@ namespace MPF.Processors
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaMegaCDSegaCD:
|
||||
info.Extras!.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
|
||||
// Take only the last 16 lines for Sega CD
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
@@ -426,7 +446,7 @@ namespace MPF.Processors
|
||||
if (GetSegaCDBuildInfo(info.Extras.Header, out var scdSerial, out var fixedDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = scdSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = scdSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = fixedDate ?? string.Empty;
|
||||
}
|
||||
|
||||
@@ -435,7 +455,7 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SegaChihiro:
|
||||
if (mediaType == MediaType.CDROM)
|
||||
{
|
||||
info.Extras!.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
|
||||
// Take only the first 16 lines for GD-ROM
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
@@ -447,8 +467,8 @@ namespace MPF.Processors
|
||||
out var date))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.VersionAndEditions.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = date ?? string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -458,7 +478,7 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SegaDreamcast:
|
||||
if (mediaType == MediaType.CDROM)
|
||||
{
|
||||
info.Extras!.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
|
||||
// Take only the first 16 lines for GD-ROM
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
@@ -470,8 +490,8 @@ namespace MPF.Processors
|
||||
out var date))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.VersionAndEditions.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = date ?? string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -481,7 +501,7 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SegaNaomi:
|
||||
if (mediaType == MediaType.CDROM)
|
||||
{
|
||||
info.Extras!.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
|
||||
// Take only the first 16 lines for GD-ROM
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
@@ -493,8 +513,8 @@ namespace MPF.Processors
|
||||
out var date))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.VersionAndEditions.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = date ?? string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -504,7 +524,7 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SegaNaomi2:
|
||||
if (mediaType == MediaType.CDROM)
|
||||
{
|
||||
info.Extras!.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
|
||||
// Take only the first 16 lines for GD-ROM
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
@@ -516,8 +536,8 @@ namespace MPF.Processors
|
||||
out var date))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.VersionAndEditions.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = date ?? string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -525,7 +545,7 @@ namespace MPF.Processors
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaSaturn:
|
||||
info.Extras!.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
|
||||
|
||||
// Take only the first 16 lines for Saturn
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
@@ -534,8 +554,8 @@ namespace MPF.Processors
|
||||
if (GetSaturnBuildInfo(info.Extras.Header, out var saturnSerial, out var saturnVersion, out var buildDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = saturnSerial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = saturnVersion ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = saturnSerial ?? string.Empty;
|
||||
info.VersionAndEditions.Version = saturnVersion ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = buildDate ?? string.Empty;
|
||||
}
|
||||
|
||||
@@ -548,8 +568,8 @@ namespace MPF.Processors
|
||||
else if (File.Exists($"{basePath}.img_EccEdc.txt"))
|
||||
psEdcStatus = GetPlayStationEDCStatus($"{basePath}.img_EccEdc.txt");
|
||||
|
||||
info.EDC!.EDC = psEdcStatus.ToYesNo();
|
||||
info.CopyProtection!.AntiModchip = GetPlayStationAntiModchipDetected($"{basePath}_disc.txt").ToYesNo();
|
||||
info.EDC.EDC = psEdcStatus.ToYesNo();
|
||||
info.CopyProtection.AntiModchip = GetPlayStationAntiModchipDetected($"{basePath}_disc.txt").ToYesNo();
|
||||
GetLibCryptDetected(basePath, out YesNo libCryptDetected, out string? libCryptData);
|
||||
info.CopyProtection.LibCrypt = libCryptDetected;
|
||||
info.CopyProtection.LibCryptData = libCryptData;
|
||||
@@ -558,10 +578,10 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SonyPlayStation3:
|
||||
if (GetPlayStation3Info($"{basePath}_disc.txt", out string? ps3Serial, out string? ps3Version, out string? ps3FirmwareVersion))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = ps3Serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = ps3Version ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = ps3Serial ?? string.Empty;
|
||||
info.VersionAndEditions.Version = ps3Version ?? string.Empty;
|
||||
if (ps3FirmwareVersion != null)
|
||||
info.CommonDiscInfo!.ContentsSpecialFields![SiteCode.Patches] = $"PS3 Firmware {ps3FirmwareVersion}";
|
||||
info.CommonDiscInfo.ContentsSpecialFields![SiteCode.Patches] = $"PS3 Firmware {ps3FirmwareVersion}";
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -585,11 +605,11 @@ namespace MPF.Processors
|
||||
| OutputFileFlags.Binary
|
||||
| OutputFileFlags.Zippable,
|
||||
"ccd"),
|
||||
new($"{outputFilename}.cue", OutputFileFlags.Required),
|
||||
new($"{outputFilename}.cue", OutputFileFlags.Required
|
||||
| OutputFileFlags.Preserve),
|
||||
new($"{outputFilename}.dat", OutputFileFlags.Required
|
||||
| OutputFileFlags.Zippable),
|
||||
new($"{outputFilename}.img", OutputFileFlags.Required
|
||||
| OutputFileFlags.Deleteable),
|
||||
new($"{outputFilename}.img", OutputFileFlags.Deleteable),
|
||||
new([$"{outputFilename}.img_EdcEcc.txt", $"{outputFilename}.img_EccEdc.txt"], OutputFileFlags.Artifact
|
||||
| OutputFileFlags.Zippable,
|
||||
"img_edcecc"),
|
||||
@@ -910,7 +930,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -947,17 +967,31 @@ namespace MPF.Processors
|
||||
// The exe date is listed in a single line, File Identifier: ABCD_123.45;1
|
||||
if (line.Length >= "File Identifier: ".Length + 11 &&
|
||||
line.StartsWith("File Identifier:") &&
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
line["File Identifier: ".Length..] == exeName)
|
||||
#else
|
||||
line.Substring("File Identifier: ".Length) == exeName)
|
||||
#endif
|
||||
{
|
||||
// Account for Y2K date problem
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (exeDate != null && exeDate[..2] == "19")
|
||||
#else
|
||||
if (exeDate != null && exeDate.Substring(0, 2) == "19")
|
||||
#endif
|
||||
{
|
||||
string decade = exeDate!.Substring(2, 1);
|
||||
|
||||
// Does only PSX need to account for 1920s-60s?
|
||||
if (decade == "0" || decade == "1" ||
|
||||
psx && (decade == "2" || decade == "3" || decade == "4" || decade == "5" || decade == "6"))
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
exeDate = $"20{exeDate[2..]}";
|
||||
#else
|
||||
exeDate = $"20{exeDate.Substring(2)}";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Currently stored date is the EXE date, return it
|
||||
@@ -979,7 +1013,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1021,25 +1055,41 @@ namespace MPF.Processors
|
||||
if (line.StartsWith("DiscType:"))
|
||||
{
|
||||
// DiscType: <discType>
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string identifier = line["DiscType: ".Length..];
|
||||
#else
|
||||
string identifier = line.Substring("DiscType: ".Length);
|
||||
#endif
|
||||
discTypeOrBookTypeSet.Add(identifier);
|
||||
}
|
||||
else if (line.StartsWith("DiscTypeIdentifier:"))
|
||||
{
|
||||
// DiscTypeIdentifier: <discType>
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string identifier = line["DiscTypeIdentifier: ".Length..];
|
||||
#else
|
||||
string identifier = line.Substring("DiscTypeIdentifier: ".Length);
|
||||
#endif
|
||||
discTypeOrBookTypeSet.Add(identifier);
|
||||
}
|
||||
else if (line.StartsWith("DiscTypeSpecific:"))
|
||||
{
|
||||
// DiscTypeSpecific: <discType>
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string identifier = line["DiscTypeSpecific: ".Length..];
|
||||
#else
|
||||
string identifier = line.Substring("DiscTypeSpecific: ".Length);
|
||||
#endif
|
||||
discTypeOrBookTypeSet.Add(identifier);
|
||||
}
|
||||
else if (line.StartsWith("BookType:"))
|
||||
{
|
||||
// BookType: <discType>
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string identifier = line["BookType: ".Length..];
|
||||
#else
|
||||
string identifier = line.Substring("BookType: ".Length);
|
||||
#endif
|
||||
discTypeOrBookTypeSet.Add(identifier);
|
||||
}
|
||||
|
||||
@@ -1054,7 +1104,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
discTypeOrBookType = null;
|
||||
return false;
|
||||
}
|
||||
@@ -1098,9 +1148,17 @@ namespace MPF.Processors
|
||||
break;
|
||||
|
||||
if (line.StartsWith("CopyrightProtectionType"))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
copyrightProtectionSystemType = line["CopyrightProtectionType: ".Length..];
|
||||
#else
|
||||
copyrightProtectionSystemType = line.Substring("CopyrightProtectionType: ".Length);
|
||||
#endif
|
||||
else if (line.StartsWith("RegionManagementInformation"))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
region = line["RegionManagementInformation: ".Length..];
|
||||
#else
|
||||
region = line.Substring("RegionManagementInformation: ".Length);
|
||||
#endif
|
||||
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
@@ -1123,7 +1181,11 @@ namespace MPF.Processors
|
||||
|
||||
if (line.StartsWith("DecryptedDiscKey"))
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
decryptedDiscKey = line["DecryptedDiscKey[020]: ".Length..];
|
||||
#else
|
||||
decryptedDiscKey = line.Substring("DecryptedDiscKey[020]: ".Length);
|
||||
#endif
|
||||
}
|
||||
else if (line.StartsWith("LBA:"))
|
||||
{
|
||||
@@ -1136,7 +1198,11 @@ namespace MPF.Processors
|
||||
var match = Regex.Match(line, @"^LBA:\s*[0-9]+, Filename: (.*?), No TitleKey$", RegexOptions.Compiled);
|
||||
string matchedFilename = match.Groups[1].Value;
|
||||
if (matchedFilename.EndsWith(";1"))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
matchedFilename = matchedFilename[..^2];
|
||||
#else
|
||||
matchedFilename = matchedFilename.Substring(0, matchedFilename.Length - 2);
|
||||
#endif
|
||||
|
||||
vobKeys += $"{matchedFilename} Title Key: No Title Key\n";
|
||||
}
|
||||
@@ -1145,7 +1211,11 @@ namespace MPF.Processors
|
||||
var match = Regex.Match(line, @"^LBA:\s*[0-9]+, Filename: (.*?), EncryptedTitleKey: .*?, DecryptedTitleKey: (.*?)$", RegexOptions.Compiled);
|
||||
string matchedFilename = match.Groups[1].Value;
|
||||
if (matchedFilename.EndsWith(";1"))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
matchedFilename = matchedFilename[..^2];
|
||||
#else
|
||||
matchedFilename = matchedFilename.Substring(0, matchedFilename.Length - 2);
|
||||
#endif
|
||||
|
||||
vobKeys += $"{matchedFilename} Title Key: {match.Groups[2].Value}\n";
|
||||
}
|
||||
@@ -1217,13 +1287,21 @@ namespace MPF.Processors
|
||||
else if (line.StartsWith("Total errors"))
|
||||
{
|
||||
totalErrors ??= 0;
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (long.TryParse(line["Total errors: ".Length..].Trim(), out long te))
|
||||
#else
|
||||
if (long.TryParse(line.Substring("Total errors: ".Length).Trim(), out long te))
|
||||
#endif
|
||||
totalErrors += te;
|
||||
}
|
||||
else if (line.StartsWith("Total warnings"))
|
||||
{
|
||||
totalErrors ??= 0;
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (long.TryParse(line["Total warnings: ".Length..].Trim(), out long tw))
|
||||
#else
|
||||
if (long.TryParse(line.Substring("Total warnings: ".Length).Trim(), out long tw))
|
||||
#endif
|
||||
totalErrors += tw;
|
||||
}
|
||||
}
|
||||
@@ -1233,7 +1311,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1255,17 +1333,25 @@ namespace MPF.Processors
|
||||
try
|
||||
{
|
||||
string[] header = segaHeader!.Split('\n');
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string versionLine = header[4][58..];
|
||||
string dateLine = header[5][58..];
|
||||
serial = versionLine[..10].TrimEnd();
|
||||
version = versionLine.Substring(10, 6).TrimStart('V', 'v');
|
||||
date = dateLine[..8];
|
||||
#else
|
||||
string versionLine = header[4].Substring(58);
|
||||
string dateLine = header[5].Substring(58);
|
||||
serial = versionLine.Substring(0, 10).TrimEnd();
|
||||
version = versionLine.Substring(10, 6).TrimStart('V', 'v');
|
||||
date = dateLine.Substring(0, 8);
|
||||
#endif
|
||||
date = $"{date[0]}{date[1]}{date[2]}{date[3]}-{date[4]}{date[5]}-{date[6]}{date[7]}";
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1299,17 +1385,29 @@ namespace MPF.Processors
|
||||
if (string.IsNullOrEmpty(manufacturer) && line.StartsWith("VendorId"))
|
||||
{
|
||||
// VendorId: <manufacturer>
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
manufacturer = line["VendorId: ".Length..];
|
||||
#else
|
||||
manufacturer = line.Substring("VendorId: ".Length);
|
||||
#endif
|
||||
}
|
||||
else if (string.IsNullOrEmpty(model) && line.StartsWith("ProductId"))
|
||||
{
|
||||
// ProductId: <model>
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
model = line["ProductId: ".Length..];
|
||||
#else
|
||||
model = line.Substring("ProductId: ".Length);
|
||||
#endif
|
||||
}
|
||||
else if (string.IsNullOrEmpty(firmware) && line.StartsWith("ProductRevisionLevel"))
|
||||
{
|
||||
// ProductRevisionLevel: <firmware>
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
firmware = line["ProductRevisionLevel: ".Length..];
|
||||
#else
|
||||
firmware = line.Substring("ProductRevisionLevel: ".Length);
|
||||
#endif
|
||||
}
|
||||
|
||||
line = sr.ReadLine();
|
||||
@@ -1319,7 +1417,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1377,7 +1475,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1389,7 +1487,7 @@ namespace MPF.Processors
|
||||
/// <returns>Status of the LibCrypt data, if possible</returns>
|
||||
private static void GetLibCryptDetected(string basePath, out YesNo detected, out string? data)
|
||||
{
|
||||
string subPath = basePath + ".sub";
|
||||
string subPath = $"{basePath}.sub";
|
||||
if (!File.Exists(subPath))
|
||||
{
|
||||
detected = YesNo.NULL;
|
||||
@@ -1405,9 +1503,9 @@ namespace MPF.Processors
|
||||
}
|
||||
|
||||
// Guard against false positives
|
||||
if (File.Exists(basePath + "_subIntention.txt"))
|
||||
if (File.Exists($"{basePath}_subIntention.txt"))
|
||||
{
|
||||
string libCryptData = ProcessingTool.GetFullFile(basePath + "_subIntention.txt") ?? "";
|
||||
string libCryptData = ProcessingTool.GetFullFile($"{basePath}_subIntention.txt") ?? "";
|
||||
if (string.IsNullOrEmpty(libCryptData))
|
||||
{
|
||||
detected = YesNo.No;
|
||||
@@ -1507,7 +1605,11 @@ namespace MPF.Processors
|
||||
// TODO: Are there any examples of 3+ session discs?
|
||||
|
||||
// Read the first session lead-out
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
var firstSessionLeadOutLengthString = line?["Lead-out length of 1st session: ".Length..];
|
||||
#else
|
||||
var firstSessionLeadOutLengthString = line?.Substring("Lead-out length of 1st session: ".Length);
|
||||
#endif
|
||||
line = sr.ReadLine()?.Trim();
|
||||
if (line == null)
|
||||
return null;
|
||||
@@ -1516,12 +1618,20 @@ namespace MPF.Processors
|
||||
string? secondSessionLeadInLengthString = null;
|
||||
if (line?.StartsWith("Lead-in length") == true)
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
secondSessionLeadInLengthString = line?["Lead-in length of 2nd session: ".Length..];
|
||||
#else
|
||||
secondSessionLeadInLengthString = line?.Substring("Lead-in length of 2nd session: ".Length);
|
||||
#endif
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
|
||||
// Read the second session pregap
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
var secondSessionPregapLengthString = line?["Pregap length of 1st track of 2nd session: ".Length..];
|
||||
#else
|
||||
var secondSessionPregapLengthString = line?.Substring("Pregap length of 1st track of 2nd session: ".Length);
|
||||
#endif
|
||||
|
||||
// Calculate the session gap total
|
||||
if (!int.TryParse(firstSessionLeadOutLengthString, out int firstSessionLeadOutLength))
|
||||
@@ -1558,7 +1668,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1596,7 +1706,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1647,7 +1757,11 @@ namespace MPF.Processors
|
||||
// Firmware Version
|
||||
if (line.StartsWith("version") && section == "UPDATE")
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
firmwareVersion = line["version: ".Length..];
|
||||
#else
|
||||
firmwareVersion = line.Substring("version: ".Length);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Internal Serial
|
||||
@@ -1655,9 +1769,17 @@ namespace MPF.Processors
|
||||
{
|
||||
// Always use the SFB if it exists
|
||||
if (section == "SFB")
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
serial = line["TITLE_ID: ".Length..];
|
||||
#else
|
||||
serial = line.Substring("TITLE_ID: ".Length);
|
||||
#endif
|
||||
else if (section == "SFO" && string.IsNullOrEmpty(version))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
serial = line["TITLE_ID: ".Length..].Insert(4, "-");
|
||||
#else
|
||||
serial = line.Substring("TITLE_ID: ".Length).Insert(4, "-");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Version
|
||||
@@ -1665,9 +1787,17 @@ namespace MPF.Processors
|
||||
{
|
||||
// Always use the SFB if it exists
|
||||
if (section == "SFB")
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
version = line["VERSION: ".Length..];
|
||||
#else
|
||||
version = line.Substring("VERSION: ".Length);
|
||||
#endif
|
||||
else if (section == "SFO" && string.IsNullOrEmpty(version))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
version = line["VERSION: ".Length..];
|
||||
#else
|
||||
version = line.Substring("VERSION: ".Length);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set the section, if needed
|
||||
@@ -1692,7 +1822,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1749,7 +1879,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1805,7 +1935,7 @@ namespace MPF.Processors
|
||||
if (line == null)
|
||||
return null;
|
||||
|
||||
// We assume the first non-LBA0/4 sector listed is the proper one
|
||||
// Assume the first non-LBA0/4 sector listed is the proper one
|
||||
// Fast forward to the PVD
|
||||
while ((line = sr.ReadLine())?.StartsWith("0310") == false) ;
|
||||
|
||||
@@ -1818,7 +1948,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1840,17 +1970,25 @@ namespace MPF.Processors
|
||||
try
|
||||
{
|
||||
string[] header = segaHeader!.Split('\n');
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string serialVersionLine = header[2][58..];
|
||||
string dateLine = header[3][58..];
|
||||
serial = serialVersionLine[..10].Trim();
|
||||
version = serialVersionLine.Substring(10, 6).TrimStart('V', 'v');
|
||||
date = dateLine[..8];
|
||||
#else
|
||||
string serialVersionLine = header[2].Substring(58);
|
||||
string dateLine = header[3].Substring(58);
|
||||
serial = serialVersionLine.Substring(0, 10).Trim();
|
||||
version = serialVersionLine.Substring(10, 6).TrimStart('V', 'v');
|
||||
date = dateLine.Substring(0, 8);
|
||||
#endif
|
||||
date = $"{date[0]}{date[1]}{date[2]}{date[3]}-{date[4]}{date[5]}-{date[6]}{date[7]}";
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1901,7 +2039,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
secuROMScheme = SecuROMScheme.None;
|
||||
return null;
|
||||
}
|
||||
@@ -1925,16 +2063,27 @@ namespace MPF.Processors
|
||||
try
|
||||
{
|
||||
string[] header = segaHeader!.Split('\n');
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string serialVersionLine = header[8][58..];
|
||||
string dateLine = header[1][58..];
|
||||
serial = serialVersionLine.Substring(3, 8).TrimEnd('-', ' ');
|
||||
date = dateLine[8..].Trim();
|
||||
#else
|
||||
string serialVersionLine = header[8].Substring(58);
|
||||
string dateLine = header[1].Substring(58);
|
||||
serial = serialVersionLine.Substring(3, 8).TrimEnd('-', ' ');
|
||||
date = dateLine.Substring(8).Trim();
|
||||
#endif
|
||||
|
||||
// Properly format the date string, if possible
|
||||
string[] dateSplit = date.Split('.');
|
||||
|
||||
if (dateSplit.Length == 1)
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
dateSplit = [date[..4], date[4..]];
|
||||
#else
|
||||
dateSplit = [date.Substring(0, 4), date.Substring(4)];
|
||||
#endif
|
||||
|
||||
string month = dateSplit[1];
|
||||
dateSplit[1] = month switch
|
||||
@@ -1960,7 +2109,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2028,7 +2177,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -2062,7 +2211,11 @@ namespace MPF.Processors
|
||||
// ISO9660 and extensions section
|
||||
if (line.StartsWith("Volume Descriptor Type: "))
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
_ = int.TryParse(line["Volume Descriptor Type: ".Length..], out int volTypeInt);
|
||||
#else
|
||||
int.TryParse(line.Substring("Volume Descriptor Type: ".Length), out int volTypeInt);
|
||||
#endif
|
||||
volType = volTypeInt switch
|
||||
{
|
||||
// 0 => "Boot Record" // Should not not contain a Volume Identifier
|
||||
@@ -2081,11 +2234,19 @@ namespace MPF.Processors
|
||||
// Identifier
|
||||
else if (line.StartsWith("Volume Identifier: "))
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
label = line["Volume Identifier: ".Length..];
|
||||
#else
|
||||
label = line.Substring("Volume Identifier: ".Length);
|
||||
#endif
|
||||
|
||||
// Remove leading non-printable character (unsure why DIC outputs this)
|
||||
if (Convert.ToUInt32(label[0]) == 0x7F || Convert.ToUInt32(label[0]) < 0x20)
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
label = label[1..];
|
||||
#else
|
||||
label = label.Substring(1);
|
||||
#endif
|
||||
|
||||
// Skip if label is blank, and skip Joliet (DIC Joliet parsing is broken?)
|
||||
if (label == null || label.Length <= 0 || volType == "Joliet")
|
||||
@@ -2112,7 +2273,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
volLabels = [];
|
||||
return false;
|
||||
}
|
||||
@@ -2152,7 +2313,11 @@ namespace MPF.Processors
|
||||
|
||||
// Now that we're at the offsets, attempt to get the sample offset
|
||||
var offsetLine = sr.ReadLine()?.Split(' ');
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string offset = offsetLine != null ? offsetLine[^1] : string.Empty;
|
||||
#else
|
||||
string offset = offsetLine != null ? offsetLine[offsetLine.Length - 1] : string.Empty;
|
||||
#endif
|
||||
offsets.Add(offset);
|
||||
}
|
||||
|
||||
@@ -2169,10 +2334,9 @@ namespace MPF.Processors
|
||||
|
||||
offsets = temp;
|
||||
#else
|
||||
offsets = offsets
|
||||
offsets = [.. offsets
|
||||
.FindAll(s => !string.IsNullOrEmpty(s))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
.Distinct()];
|
||||
#endif
|
||||
|
||||
// Now that we're at the offsets, attempt to get the sample offset
|
||||
@@ -2180,7 +2344,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -2304,7 +2468,7 @@ namespace MPF.Processors
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace MPF.Processors
|
||||
{
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Indicates the type of compression used for logs
|
||||
/// </summary>
|
||||
public enum LogCompression
|
||||
@@ -14,7 +14,7 @@ namespace MPF.Processors
|
||||
/// PKZIP using DEFLATE level 9
|
||||
/// </summary>
|
||||
DeflateMaximum,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// PKZIP using Zstd level 19
|
||||
/// </summary>
|
||||
@@ -53,4 +53,4 @@ namespace MPF.Processors
|
||||
/// </summary>
|
||||
V4Plus,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MPF.Processors.OutputFiles;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.Hashing;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Processors
|
||||
@@ -27,24 +27,21 @@ namespace MPF.Processors
|
||||
/// <inheritdoc/>
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, MediaType? mediaType, string basePath, bool redumpCompat)
|
||||
{
|
||||
// Ensure that required sections exist
|
||||
info = Builder.EnsureAllSections(info);
|
||||
|
||||
// Get the dumping program and version
|
||||
info.DumpingInfo!.DumpingProgram = "UNKNOWN PROGRAM";
|
||||
info.DumpingInfo.DumpingProgram = "UNKNOWN PROGRAM";
|
||||
info.DumpingInfo.DumpingDate = GetDumpingDate(basePath);
|
||||
|
||||
// Get the Datafile information
|
||||
var datafile = GetDatafile(basePath);
|
||||
if (datafile != null)
|
||||
info.TracksAndWriteOffsets!.ClrMameProData = ProcessingTool.GenerateDatfile(datafile);
|
||||
info.TracksAndWriteOffsets.ClrMameProData = ProcessingTool.GenerateDatfile(datafile);
|
||||
|
||||
// Extract info based generically on MediaType
|
||||
switch (mediaType)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
case MediaType.GDROM:
|
||||
info.TracksAndWriteOffsets!.Cuesheet = ProcessingTool.GetFullFile($"{basePath}.cue") ?? string.Empty;
|
||||
info.TracksAndWriteOffsets.Cuesheet = ProcessingTool.GetFullFile($"{basePath}.cue") ?? string.Empty;
|
||||
break;
|
||||
|
||||
case MediaType.DVD:
|
||||
@@ -57,7 +54,7 @@ namespace MPF.Processors
|
||||
var firstRom = datafile?.Game?[0]?.Rom?[0];
|
||||
if (firstRom != null)
|
||||
{
|
||||
info.SizeAndChecksums!.Size = long.Parse(firstRom.Size ?? "0");
|
||||
info.SizeAndChecksums.Size = long.Parse(firstRom.Size ?? "0");
|
||||
info.SizeAndChecksums.CRC32 = firstRom.CRC;
|
||||
info.SizeAndChecksums.MD5 = firstRom.MD5;
|
||||
info.SizeAndChecksums.SHA1 = firstRom.SHA1;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
@@ -12,8 +12,7 @@
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.5.0</VersionPrefix>
|
||||
<WarningsNotAsErrors>NU5104</WarningsNotAsErrors>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
@@ -33,12 +32,12 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GrindCore.SharpCompress" Version="0.40.4-alpha" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="[1.5.1]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.7.6]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.7.4]" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.0.2]" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.9" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="GrindCore.SharpCompress" Version="0.41.1" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="[1.6.0]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.9.0]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.0]" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.2.1]" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="10.0.0" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user