mirror of
https://github.com/SabreTools/MPF.git
synced 2026-02-05 05:37:36 +00:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79716ea0b5 | ||
|
|
43477a133f | ||
|
|
8889beef1d | ||
|
|
ac4be751b3 | ||
|
|
69f855fc93 | ||
|
|
cf01095623 | ||
|
|
3236223e3f | ||
|
|
36450cd22b | ||
|
|
6a9b6748d2 | ||
|
|
3bf83378a2 | ||
|
|
bc938fd58c | ||
|
|
f50a110acd | ||
|
|
fcda2a6e3b | ||
|
|
d33526b27e | ||
|
|
0b0427e9c1 | ||
|
|
c34b92bad8 | ||
|
|
89145df0fa | ||
|
|
ee7cde6360 | ||
|
|
8e9edf43ac | ||
|
|
51115430cb | ||
|
|
7cf108828e | ||
|
|
020390af65 | ||
|
|
e04ceb953c | ||
|
|
363b018cb7 | ||
|
|
cf025522ef | ||
|
|
0fb8bf5c29 | ||
|
|
e280745eee | ||
|
|
fb306750e6 | ||
|
|
da5a514482 | ||
|
|
fc288e1c46 | ||
|
|
102acb9ebf | ||
|
|
b76b2a69f5 | ||
|
|
254ad6cfd0 | ||
|
|
f432f438ab | ||
|
|
e890243830 | ||
|
|
6493b462f1 | ||
|
|
54c0716ea9 | ||
|
|
7fbb5133d7 | ||
|
|
993a0fd7d3 | ||
|
|
47878fee1f | ||
|
|
4cb8a31505 | ||
|
|
0685972842 | ||
|
|
5b1cc3c715 | ||
|
|
572f0d5095 | ||
|
|
23bafad3db | ||
|
|
c7b77e4bd7 | ||
|
|
755eee4441 | ||
|
|
fca2c53d6c | ||
|
|
8f6f5f6ef0 | ||
|
|
2e9970ee6a | ||
|
|
4fa1273111 |
@@ -1,3 +1,57 @@
|
||||
### 3.4.1 (2025-09-29)
|
||||
|
||||
- Experiment with only showing media type box for DIC
|
||||
- Default media type box to hidden to avoid visual issues
|
||||
- Limit media type visibility further
|
||||
- Set media type visibility when options changed
|
||||
- Change label with media type visibility
|
||||
- Update media type visibility on system change
|
||||
- Return full result from dump checks
|
||||
- Fix logic from around Macrovision security driver filtering
|
||||
- Remove SkipMediaTypeDetection option, cleanup options window
|
||||
- Minor tweaks to frontend code
|
||||
- Default to CD speed range
|
||||
- Skip trying to set speeds if no drives
|
||||
- Fix tests
|
||||
- Make media type a named parameter for CLI
|
||||
- Reduction in media type use for dumping
|
||||
- Update BinaryObjectScanner to 3.4.3
|
||||
|
||||
### 3.4.0 (2025-09-25)
|
||||
|
||||
- Remove media type from Check Dump UI
|
||||
- Always trust the output files for processing
|
||||
- UI consistency when parameters are editable
|
||||
- Let the processor always deal with unsupported
|
||||
- Put a try/catch around GenerateArtifacts
|
||||
- Reduce preprocessing in DumpEnvironment
|
||||
- Update RedumpLib to 1.6.9
|
||||
- Treat all UMD as DL visually
|
||||
- Add CopyUpdateUrlToClipboard option
|
||||
- Fix inconsistency with newlines
|
||||
- Update Aaru to build 5.4.1
|
||||
- Fix for C2 error doubling issue (fuzz6001)
|
||||
- Update RedumpLib and LibIRD
|
||||
- Update LibIRD
|
||||
- Update redumper to build 653
|
||||
- Minor cleanup
|
||||
- Update test Nuget packages
|
||||
- Update RedumpLib to 1.7.1
|
||||
- Support multisession cache files
|
||||
- Update DIC to 20250901 (Windows/Linux only)
|
||||
- Fix UIC processing logic
|
||||
- Update RedumpLib, detect Playmaji Polymega system
|
||||
- Update redumper to b655
|
||||
- Support new versioning format in redumper (fuzz6001)
|
||||
- Add RedumperRefineSectorMode setting
|
||||
- Update BinaryObjectScanner to 3.4.0
|
||||
- Add context-sensitive protections helper method
|
||||
- Further flesh out framework
|
||||
- Add filters to handle Release Control output (Bestest)
|
||||
- Cleanup last commits, add tests
|
||||
- Update BinaryObjectScanner to 3.4.2
|
||||
- Update RedumpLib to 1.7.4
|
||||
|
||||
### 3.3.3 (2025-07-18)
|
||||
|
||||
- Handle layers for PS3CFW
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.3.3</VersionPrefix>
|
||||
<VersionPrefix>3.4.1</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Title>MPF CLI</Title>
|
||||
@@ -43,7 +43,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.8" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.7.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -44,20 +44,19 @@ namespace MPF.CLI
|
||||
|
||||
// Setup common outputs
|
||||
CommandOptions opts;
|
||||
MediaType mediaType;
|
||||
RedumpSystem? knownSystem;
|
||||
|
||||
// Use interactive mode
|
||||
if (args.Length > 0 && (args[0] == "-i" || args[0] == "--interactive"))
|
||||
{
|
||||
opts = InteractiveMode(options, out mediaType, out knownSystem);
|
||||
opts = InteractiveMode(options, out knownSystem);
|
||||
}
|
||||
|
||||
// Use normal commandline parameters
|
||||
else
|
||||
{
|
||||
// Try processing the common arguments
|
||||
bool success = OptionsLoader.ProcessCommonArguments(args, out mediaType, out knownSystem, out var error);
|
||||
bool success = OptionsLoader.ProcessCommonArguments(args, out knownSystem, out var error);
|
||||
if (!success)
|
||||
{
|
||||
DisplayHelp(error);
|
||||
@@ -123,13 +122,20 @@ namespace MPF.CLI
|
||||
DisplayHelp("Both a device path and file path need to be supplied, exiting...");
|
||||
return;
|
||||
}
|
||||
if (options.InternalProgram == InternalProgram.DiscImageCreator
|
||||
&& opts.CustomParams == null
|
||||
&& (opts.MediaType == null || opts.MediaType == MediaType.NONE))
|
||||
{
|
||||
DisplayHelp("Media type is required for DiscImageCreator, exiting...");
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize the file path
|
||||
if (opts.FilePath != null)
|
||||
opts.FilePath = FrontendTool.NormalizeOutputPaths(opts.FilePath, getFullPath: true);
|
||||
if (opts.FilePath != null)
|
||||
opts.FilePath = FrontendTool.NormalizeOutputPaths(opts.FilePath, getFullPath: true);
|
||||
|
||||
// Get the speed from the options
|
||||
int speed = opts.DriveSpeed ?? FrontendTool.GetDefaultSpeedForMediaType(mediaType, options);
|
||||
int speed = opts.DriveSpeed ?? FrontendTool.GetDefaultSpeedForMediaType(opts.MediaType, options);
|
||||
|
||||
// Populate an environment
|
||||
var drive = Drive.Create(null, opts.DevicePath ?? string.Empty);
|
||||
@@ -138,22 +144,22 @@ namespace MPF.CLI
|
||||
drive,
|
||||
knownSystem,
|
||||
options.InternalProgram);
|
||||
env.SetExecutionContext(mediaType, null);
|
||||
env.SetExecutionContext(opts.MediaType, null);
|
||||
env.SetProcessor();
|
||||
|
||||
// Process the parameters
|
||||
string? paramStr = opts.CustomParams ?? env.GetFullParameters(mediaType, speed);
|
||||
string? paramStr = opts.CustomParams ?? env.GetFullParameters(opts.MediaType, speed);
|
||||
if (string.IsNullOrEmpty(paramStr))
|
||||
{
|
||||
DisplayHelp("No valid environment could be created, exiting...");
|
||||
return;
|
||||
}
|
||||
|
||||
env.SetExecutionContext(mediaType, paramStr);
|
||||
env.SetExecutionContext(opts.MediaType, paramStr);
|
||||
|
||||
// Invoke the dumping program
|
||||
Console.WriteLine($"Invoking {options.InternalProgram} using '{paramStr}'");
|
||||
var dumpResult = env.Run(mediaType).GetAwaiter().GetResult();
|
||||
var dumpResult = env.Run(opts.MediaType).GetAwaiter().GetResult();
|
||||
Console.WriteLine(dumpResult.Message);
|
||||
if (!dumpResult)
|
||||
return;
|
||||
@@ -174,12 +180,12 @@ namespace MPF.CLI
|
||||
drive,
|
||||
knownSystem,
|
||||
internalProgram: null);
|
||||
env.SetExecutionContext(mediaType, null);
|
||||
env.SetExecutionContext(opts.MediaType, null);
|
||||
env.SetProcessor();
|
||||
}
|
||||
|
||||
// Finally, attempt to do the output dance
|
||||
var verifyResult = env.VerifyAndSaveDumpOutput(mediaType: mediaType)
|
||||
var verifyResult = env.VerifyAndSaveDumpOutput()
|
||||
.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
Console.WriteLine(verifyResult.Message);
|
||||
}
|
||||
@@ -194,7 +200,7 @@ namespace MPF.CLI
|
||||
Console.WriteLine(error);
|
||||
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine("MPF.CLI <mediatype> <system> [options]");
|
||||
Console.WriteLine("MPF.CLI <system> [options]");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Standalone Options:");
|
||||
Console.WriteLine("-h, -?, --help Show this help text");
|
||||
@@ -208,6 +214,7 @@ namespace MPF.CLI
|
||||
|
||||
Console.WriteLine("CLI Options:");
|
||||
Console.WriteLine("-u, --use <program> Override configured dumping program name");
|
||||
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)");
|
||||
@@ -233,14 +240,14 @@ namespace MPF.CLI
|
||||
/// <summary>
|
||||
/// Enable interactive mode for entering information
|
||||
/// </summary>
|
||||
private static CommandOptions InteractiveMode(Options options, out MediaType mediaType, out RedumpSystem? system)
|
||||
private static CommandOptions InteractiveMode(Options options, out RedumpSystem? system)
|
||||
{
|
||||
// Create return values
|
||||
var opts = new CommandOptions
|
||||
{
|
||||
MediaType = MediaType.NONE,
|
||||
FilePath = Path.Combine(options.DefaultOutputPath ?? "ISO", "track.bin"),
|
||||
};
|
||||
mediaType = MediaType.NONE;
|
||||
system = options.DefaultSystem;
|
||||
|
||||
// Create state values
|
||||
@@ -251,9 +258,9 @@ namespace MPF.CLI
|
||||
Console.WriteLine("MPF.CLI Interactive Mode - Main Menu");
|
||||
Console.WriteLine("-------------------------");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"1) Set media type (Currently '{mediaType}')");
|
||||
Console.WriteLine($"2) Set system (Currently '{system}')");
|
||||
Console.WriteLine($"3) Set dumping program (Currently '{options.InternalProgram}')");
|
||||
Console.WriteLine($"1) Set system (Currently '{system}')");
|
||||
Console.WriteLine($"2) Set dumping program (Currently '{options.InternalProgram}')");
|
||||
Console.WriteLine($"3) Set media type (Currently '{opts.MediaType}')");
|
||||
Console.WriteLine($"4) Set device path (Currently '{opts.DevicePath}')");
|
||||
Console.WriteLine($"5) Set mounted path (Currently '{opts.MountedPath}')");
|
||||
Console.WriteLine($"6) Set file path (Currently '{opts.FilePath}')");
|
||||
@@ -268,11 +275,11 @@ namespace MPF.CLI
|
||||
switch (result)
|
||||
{
|
||||
case "1":
|
||||
goto mediaType;
|
||||
case "2":
|
||||
goto system;
|
||||
case "3":
|
||||
case "2":
|
||||
goto dumpingProgram;
|
||||
case "3":
|
||||
goto mediaType;
|
||||
case "4":
|
||||
goto devicePath;
|
||||
case "5":
|
||||
@@ -304,14 +311,6 @@ namespace MPF.CLI
|
||||
goto root;
|
||||
}
|
||||
|
||||
mediaType:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the media type and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
mediaType = OptionsLoader.ToMediaType(result);
|
||||
goto root;
|
||||
|
||||
system:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the system and press Enter:");
|
||||
@@ -328,6 +327,14 @@ namespace MPF.CLI
|
||||
options.InternalProgram = result.ToInternalProgram();
|
||||
goto root;
|
||||
|
||||
mediaType:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the media type and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
opts.MediaType = OptionsLoader.ToMediaType(result);
|
||||
goto root;
|
||||
|
||||
devicePath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the device path and press Enter:");
|
||||
@@ -412,6 +419,17 @@ namespace MPF.CLI
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Use a device path
|
||||
else if (args[startIndex].StartsWith("-t=") || args[startIndex].StartsWith("--mediatype="))
|
||||
{
|
||||
opts.MediaType = OptionsLoader.ToMediaType(args[startIndex].Split('=')[1].Trim('"'));
|
||||
}
|
||||
else if (args[startIndex] == "-t" || args[startIndex] == "--mediatype")
|
||||
{
|
||||
opts.MediaType = OptionsLoader.ToMediaType(args[startIndex + 1].Trim('"'));
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Use a device path
|
||||
else if (args[startIndex].StartsWith("-d=") || args[startIndex].StartsWith("--device="))
|
||||
{
|
||||
@@ -488,6 +506,12 @@ namespace MPF.CLI
|
||||
/// </summary>
|
||||
private class CommandOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Media type to dump
|
||||
/// </summary>
|
||||
/// <remarks>Required for DIC and if custom parameters not set</remarks>
|
||||
public MediaType? MediaType { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Path to the device to dump
|
||||
/// </summary>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.3.3</VersionPrefix>
|
||||
<VersionPrefix>3.4.1</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Title>MPF Check</Title>
|
||||
@@ -43,7 +43,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.8" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.7.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -40,15 +40,15 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, null, "filename.bin", null, null)]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.DVD, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.SegaDreamcast, MediaType.GDROM, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.SegaDreamcast, MediaType.GDROM, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.HDDVDVideo, MediaType.HDDVD, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.BDVideo, MediaType.BluRay, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoGameCube, MediaType.NintendoGameCubeGameDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoWii, MediaType.NintendoWiiOpticalDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoWiiU, MediaType.NintendoWiiUOpticalDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.FloppyDisk, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoGameCube, MediaType.NintendoGameCubeGameDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoWii, MediaType.NintendoWiiOpticalDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoWiiU, MediaType.NintendoWiiUOpticalDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.FloppyDisk, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
public void DefaultValueTest(RedumpSystem? system,
|
||||
MediaType? type,
|
||||
string? drivePath,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -14,13 +14,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.13.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.8" />
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.14.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.7.4" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.21.0" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.24.0" />
|
||||
<PackageReference Include="xunit.assert" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.core" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.9.3" />
|
||||
@@ -29,7 +29,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, null, "filename.bin", null, "")]
|
||||
[InlineData(null, null, null, "filename.bin", null, "disc --verbose --retries=1000 --image-name=\"filename\" --drive-type=GENERIC --drive-read-method=BE --drive-sector-order=DATA_C2_SUB --plextor-leadin-retries=1000")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.CDROM, "/dev/sr0", "path/filename.bin", 2, "disc --verbose --skeleton --drive=/dev/sr0 --speed=2 --retries=1000 --image-path=\"path\" --image-name=\"filename\" --drive-type=GENERIC --drive-read-method=BE --drive-sector-order=DATA_C2_SUB --plextor-leadin-retries=1000")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.DVD, "/dev/sr0", "path/filename.bin", 2, "disc --verbose --drive=/dev/sr0 --speed=2 --retries=1000 --image-path=\"path\" --image-name=\"filename\" --drive-type=GENERIC --drive-read-method=BE --drive-sector-order=DATA_C2_SUB --plextor-leadin-retries=1000")]
|
||||
[InlineData(RedumpSystem.NintendoGameCube, MediaType.NintendoGameCubeGameDisc, "/dev/sr0", "path/filename.bin", 2, "disc --verbose --drive=/dev/sr0 --speed=2 --retries=1000 --image-path=\"path\" --image-name=\"filename\" --drive-type=GENERIC --drive-read-method=BE --drive-sector-order=DATA_C2_SUB --plextor-leadin-retries=1000")]
|
||||
|
||||
@@ -638,11 +638,6 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
(_inputs[FlagStrings.SpeedLong] as Int8Input)?.SetValue((sbyte)driveSpeed);
|
||||
}
|
||||
|
||||
// First check to see if the combination of system and MediaType is valid
|
||||
var validTypes = RedumpSystem.MediaTypes();
|
||||
if (!validTypes.Contains(MediaType))
|
||||
return;
|
||||
|
||||
// Set retry count
|
||||
int rereadCount = GetInt32Setting(options, SettingConstants.RereadCount, SettingConstants.RereadCountDefault);
|
||||
if (rereadCount > 0)
|
||||
@@ -673,57 +668,13 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
(_inputs[FlagStrings.PrivateLong] as BooleanInput)?.SetValue(true);
|
||||
}
|
||||
|
||||
// TODO: Look at dump-media formats and the like and see what options there are there to fill in defaults
|
||||
// Now sort based on disc type
|
||||
switch (MediaType)
|
||||
{
|
||||
case SabreTools.RedumpLib.Data.MediaType.CDROM:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.DVD:
|
||||
this[FlagStrings.StoreEncryptedLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.StoreEncryptedLong] as BooleanInput)?.SetValue(true);
|
||||
this[FlagStrings.TitleKeysLong] = false; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TitleKeysLong] as BooleanInput)?.SetValue(false);
|
||||
this[FlagStrings.TrimLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TrimLong] as BooleanInput)?.SetValue(true);
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.GDROM:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.HDDVD:
|
||||
this[FlagStrings.StoreEncryptedLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.StoreEncryptedLong] as BooleanInput)?.SetValue(true);
|
||||
this[FlagStrings.TitleKeysLong] = false; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TitleKeysLong] as BooleanInput)?.SetValue(false);
|
||||
this[FlagStrings.TrimLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TrimLong] as BooleanInput)?.SetValue(true);
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.BluRay:
|
||||
this[FlagStrings.StoreEncryptedLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.StoreEncryptedLong] as BooleanInput)?.SetValue(true);
|
||||
this[FlagStrings.TitleKeysLong] = false; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TitleKeysLong] as BooleanInput)?.SetValue(false);
|
||||
this[FlagStrings.TrimLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TrimLong] as BooleanInput)?.SetValue(true);
|
||||
break;
|
||||
|
||||
// Special Formats
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoGameCubeGameDisc:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoWiiOpticalDisc:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoWiiUOpticalDisc:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
|
||||
// Non-optical
|
||||
case SabreTools.RedumpLib.Data.MediaType.FloppyDisk:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
}
|
||||
// Set generic, sane defaults to cover all bases
|
||||
this[FlagStrings.StoreEncryptedLong] = true;
|
||||
(_inputs[FlagStrings.StoreEncryptedLong] as BooleanInput)?.SetValue(true);
|
||||
this[FlagStrings.TitleKeysLong] = false;
|
||||
(_inputs[FlagStrings.TitleKeysLong] as BooleanInput)?.SetValue(false);
|
||||
this[FlagStrings.TrimLong] = true;
|
||||
(_inputs[FlagStrings.TrimLong] as BooleanInput)?.SetValue(true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.3.3</VersionPrefix>
|
||||
<VersionPrefix>3.4.1</VersionPrefix>
|
||||
<WarningsNotAsErrors>NU5104</WarningsNotAsErrors>
|
||||
|
||||
<!-- Package Properties -->
|
||||
@@ -32,7 +32,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.8" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.7.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -21,6 +21,8 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string Info = "info";
|
||||
public const string Skeleton = "skeleton";
|
||||
public const string FlashMT1339 = "flash::mt1339";
|
||||
public const string FlashSD616 = "flash::sd616";
|
||||
public const string FlashPlextor = "flash::plextor";
|
||||
public const string Subchannel = "subchannel";
|
||||
public const string Debug = "debug";
|
||||
public const string FixMSF = "fixmsf";
|
||||
|
||||
@@ -49,11 +49,6 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
|
||||
#region Flag Values
|
||||
|
||||
/// <summary>
|
||||
/// Mode being run
|
||||
/// </summary>
|
||||
public string? ModeValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set of all command flags
|
||||
/// </summary>
|
||||
@@ -241,9 +236,9 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
var parameters = new StringBuilder();
|
||||
|
||||
// Command Mode
|
||||
ModeValue ??= CommandStrings.NONE;
|
||||
if (ModeValue != CommandStrings.NONE)
|
||||
parameters.Append($"{ModeValue} ");
|
||||
BaseCommand ??= CommandStrings.NONE;
|
||||
if (BaseCommand != CommandStrings.NONE)
|
||||
parameters.Append($"{BaseCommand} ");
|
||||
|
||||
// Loop though and append all existing
|
||||
foreach (var kvp in _inputs)
|
||||
@@ -270,8 +265,8 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public override bool IsDumpingCommand()
|
||||
{
|
||||
// `dump` command does not provide hashes so will error out after dump if run via MPF
|
||||
return ModeValue == CommandStrings.NONE
|
||||
|| ModeValue == CommandStrings.Disc;
|
||||
return BaseCommand == CommandStrings.NONE
|
||||
|| BaseCommand == CommandStrings.Disc;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -291,25 +286,13 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
int? driveSpeed,
|
||||
Dictionary<string, string?> options)
|
||||
{
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
switch (MediaType)
|
||||
{
|
||||
case SabreTools.RedumpLib.Data.MediaType.CDROM:
|
||||
case SabreTools.RedumpLib.Data.MediaType.DVD:
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoGameCubeGameDisc:
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoWiiOpticalDisc:
|
||||
case SabreTools.RedumpLib.Data.MediaType.HDDVD:
|
||||
case SabreTools.RedumpLib.Data.MediaType.BluRay:
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoWiiUOpticalDisc:
|
||||
ModeValue = CommandStrings.Disc;
|
||||
break;
|
||||
default:
|
||||
BaseCommand = null;
|
||||
return;
|
||||
}
|
||||
BaseCommand = CommandStrings.Disc;
|
||||
|
||||
this[FlagStrings.Drive] = true;
|
||||
(_inputs[FlagStrings.Drive] as StringInput)?.SetValue(drivePath ?? string.Empty);
|
||||
if (drivePath != null)
|
||||
{
|
||||
this[FlagStrings.Drive] = true;
|
||||
(_inputs[FlagStrings.Drive] as StringInput)?.SetValue(drivePath);
|
||||
}
|
||||
|
||||
if (driveSpeed != null && driveSpeed > 0)
|
||||
{
|
||||
@@ -350,7 +333,6 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
}
|
||||
|
||||
string? readMethod = GetStringSetting(options, SettingConstants.ReadMethod, SettingConstants.ReadMethodDefault);
|
||||
|
||||
if (!string.IsNullOrEmpty(readMethod) && readMethod != ReadMethod.NONE.ToString())
|
||||
{
|
||||
this[FlagStrings.DriveReadMethod] = true;
|
||||
@@ -390,7 +372,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
}
|
||||
|
||||
int retries = GetInt32Setting(options, SettingConstants.RereadCount, SettingConstants.RereadCountDefault);
|
||||
if(retries > 0)
|
||||
if (retries > 0)
|
||||
{
|
||||
this[FlagStrings.Retries] = true;
|
||||
(_inputs[FlagStrings.Retries] as Int32Input)?.SetValue(retries);
|
||||
@@ -402,13 +384,17 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
this[FlagStrings.PlextorLeadinRetries] = true;
|
||||
(_inputs[FlagStrings.PlextorLeadinRetries] as Int32Input)?.SetValue(leadinRetries);
|
||||
}
|
||||
|
||||
if (GetBooleanSetting(options, SettingConstants.RefineSectorMode, SettingConstants.RefineSectorModeDefault))
|
||||
{
|
||||
this[FlagStrings.RefineSectorMode] = true;
|
||||
(_inputs[FlagStrings.RefineSectorMode] as FlagInput)?.SetValue(true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool ValidateAndSetParameters(string? parameters)
|
||||
{
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
|
||||
// The string has to be valid by itself first
|
||||
if (string.IsNullOrEmpty(parameters))
|
||||
return false;
|
||||
@@ -417,7 +403,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
string[] parts = SplitParameterString(parameters!);
|
||||
|
||||
// Setup the modes
|
||||
ModeValue = null;
|
||||
BaseCommand = null;
|
||||
|
||||
// All modes should be cached separately
|
||||
int index = 0;
|
||||
@@ -444,16 +430,18 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
case CommandStrings.Info:
|
||||
case CommandStrings.Skeleton:
|
||||
case CommandStrings.FlashMT1339:
|
||||
case CommandStrings.FlashSD616:
|
||||
case CommandStrings.FlashPlextor:
|
||||
case CommandStrings.Subchannel:
|
||||
case CommandStrings.Debug:
|
||||
case CommandStrings.FixMSF:
|
||||
case CommandStrings.DebugFlip:
|
||||
case CommandStrings.DriveTest:
|
||||
// Only allow one mode per command
|
||||
if (ModeValue != null)
|
||||
if (BaseCommand != null)
|
||||
continue;
|
||||
|
||||
ModeValue = part;
|
||||
BaseCommand = part;
|
||||
break;
|
||||
|
||||
// Default is either a flag or an invalid mode
|
||||
|
||||
@@ -17,6 +17,9 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string ReadMethod = "RedumperReadMethod";
|
||||
public static readonly string ReadMethodDefault = Redumper.ReadMethod.NONE.ToString();
|
||||
|
||||
public const string RefineSectorMode = "RedumperRefineSectorMode";
|
||||
public const bool RefineSectorModeDefault = false;
|
||||
|
||||
public const string RereadCount = "RedumperRereadCount";
|
||||
public const int RereadCountDefault = 20;
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace MPF.Frontend.Test
|
||||
[InlineData(MediaType.HDDVD, 24)]
|
||||
[InlineData(MediaType.BluRay, 16)]
|
||||
[InlineData(MediaType.NintendoWiiUOpticalDisc, 16)]
|
||||
[InlineData(MediaType.LaserDisc, 1)]
|
||||
[InlineData(null, 1)]
|
||||
[InlineData(MediaType.LaserDisc, 72)]
|
||||
[InlineData(null, 72)]
|
||||
public void GetAllowedDriveSpeedForMediaTypeTest(MediaType? mediaType, int maxExpected)
|
||||
{
|
||||
var actual = InterfaceConstants.GetSpeedsForMediaType(mediaType);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -14,13 +14,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.13.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.8" />
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.14.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.7.4" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.21.0" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.24.0" />
|
||||
<PackageReference Include="xunit.assert" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.core" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.9.3" />
|
||||
@@ -29,7 +29,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -8,12 +8,114 @@ namespace MPF.Frontend.Test.Tools
|
||||
{
|
||||
public class ProtectionToolTests
|
||||
{
|
||||
#region SanitizeContextSensitiveProtections
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_Empty_NoException()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_NoMatch_NoChange()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_Match_NoSub_NoChange()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
protections["File2"] = ["SecuROM Release Control - ANYTHING", "Protection 2"];
|
||||
protections["File3"] = ["Protection 1", "SecuROM Release Control -"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
Assert.Contains("File2", keys);
|
||||
Assert.Contains("File3", keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_Match_Sub_Change()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
protections["File2"] = ["SecuROM Release Control - ANYTHING"];
|
||||
protections["File2/FileA"] = ["ANYTHING GitHub ANYTHING"];
|
||||
protections["File2/FileB"] = ["SecuROM 7"];
|
||||
protections["File2/FileC"] = ["SecuROM 8"];
|
||||
protections["File2/FileD"] = ["SecuROM Content Activation"];
|
||||
protections["File2/FileE"] = ["SecuROM Data File Activation"];
|
||||
protections["File2/FileF"] = ["Unlock"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
Assert.Contains("File2", keys);
|
||||
Assert.Contains("File2/FileA", keys);
|
||||
Assert.DoesNotContain("File2/FileB", keys);
|
||||
Assert.DoesNotContain("File2/FileC", keys);
|
||||
Assert.DoesNotContain("File2/FileD", keys);
|
||||
Assert.DoesNotContain("File2/FileE", keys);
|
||||
Assert.DoesNotContain("File2/FileF", keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_MultiMatch_Sub_Change()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
protections["File2"] = ["SecuROM Release Control - ANYTHING"];
|
||||
protections["File2/FileA"] = ["ANYTHING GitHub ANYTHING"];
|
||||
protections["File2/FileB"] = ["SecuROM 7"];
|
||||
protections["File2/FileC"] = ["SecuROM 8"];
|
||||
protections["File3"] = ["SecuROM Release Control - ANYTHING"];
|
||||
protections["File3/FileD"] = ["SecuROM Content Activation"];
|
||||
protections["File3/FileE"] = ["SecuROM Data File Activation"];
|
||||
protections["File3/FileF"] = ["Unlock"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
Assert.Contains("File2", keys);
|
||||
Assert.Contains("File2/FileA", keys);
|
||||
Assert.DoesNotContain("File2/FileB", keys);
|
||||
Assert.DoesNotContain("File2/FileC", keys);
|
||||
Assert.Contains("File3", keys);
|
||||
Assert.DoesNotContain("File3/FileD", keys);
|
||||
Assert.DoesNotContain("File3/FileE", keys);
|
||||
Assert.DoesNotContain("File3/FileF", keys);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SanitizeFoundProtections
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_Exception()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Anything Else Protection",
|
||||
"[Access issue when opening file",
|
||||
"[Exception opening file",
|
||||
];
|
||||
|
||||
@@ -581,9 +683,9 @@ namespace MPF.Frontend.Test.Tools
|
||||
[Theory]
|
||||
[InlineData(0, "Macrovision Protected Application [SafeDisc 0.00.000], SafeDisc 0.00.000, SafeDisc Lite")]
|
||||
[InlineData(1, "Macrovision Protected Application [SafeDisc 0.00.000 / SRV Tool APP], SafeDisc 0.00.000, SafeDisc Lite")]
|
||||
[InlineData(2, "Macrovision Security Driver, Macrovision Security Driver [SafeDisc 1.11.111], SafeDisc 0.00.000, SafeDisc 0.00.000-1.11.111, SafeDisc Lite")]
|
||||
[InlineData(3, "Macrovision Security Driver, Macrovision Security Driver [SafeDisc 1.11.111], SafeDisc 0.00.000, SafeDisc Lite")]
|
||||
[InlineData(4, "Macrovision Security Driver, Macrovision Security Driver [SafeDisc 1.11.111], SafeDisc Lite")]
|
||||
[InlineData(2, "SafeDisc 0.00.000, SafeDisc 0.00.000-1.11.111, SafeDisc 3+ (DVD), SafeDisc Lite")]
|
||||
[InlineData(3, "SafeDisc 0.00.000, SafeDisc 3+ (DVD), SafeDisc Lite")]
|
||||
[InlineData(4, "SafeDisc 3+ (DVD), SafeDisc Lite")]
|
||||
[InlineData(5, "Macrovision Security Driver, SafeDisc Lite")]
|
||||
[InlineData(6, "Macrovision Protection File, SafeDisc 2+, SafeDisc 3+ (DVD), SafeDisc Lite")]
|
||||
[InlineData(7, "SafeDisc 3+ (DVD)")]
|
||||
@@ -592,11 +694,11 @@ namespace MPF.Frontend.Test.Tools
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Macrovision Protected Application [SafeDisc 0.00.000]",
|
||||
"Macrovision Protected Application [SafeDisc 0.00.000]",
|
||||
"Macrovision Protected Application [SafeDisc 0.00.000 / SRV Tool APP]",
|
||||
"SafeDisc 0.00.000-1.11.111",
|
||||
"SafeDisc 0.00.000",
|
||||
"Macrovision Security Driver [SafeDisc 1.11.111]",
|
||||
"Macrovision Security Driver 1.11.111 / SafeDisc 1.11.111",
|
||||
"Macrovision Security Driver",
|
||||
"SafeDisc Lite",
|
||||
"SafeDisc 3+ (DVD)",
|
||||
@@ -615,6 +717,38 @@ namespace MPF.Frontend.Test.Tools
|
||||
Assert.Equal(expected, sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectsion_SafeDisc_MacrovisionSecurityDriver()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Macrovision Protection File [Likely indicates either SafeDisc 1.45.011+ (CD) or CDS-300]",
|
||||
"Macrovision Security Driver 4.00.060 / SafeDisc 4.00.000-4.70.000",
|
||||
"SafeDisc 4.00.000-4.00.003",
|
||||
"SafeDisc 4.00.002, Macrovision Protected Application"
|
||||
];
|
||||
|
||||
string expected = "SafeDisc 4.00.002";
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal(expected, sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_SecuROM()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"SecuROM Release Control",
|
||||
"SecuROM Release Control - ANYTHING",
|
||||
"SecuROM Release Control - ANYTHING ELSE",
|
||||
"SecuROM Release Control - EVEN MORE",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("SecuROM Release Control", sanitized);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(1)]
|
||||
@@ -669,5 +803,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,14 +449,12 @@ namespace MPF.Frontend
|
||||
/// <summary>
|
||||
/// Verify that the current environment has a complete dump and create submission info is possible
|
||||
/// </summary>
|
||||
/// <param name="mediaType">Media type for controlling expected file sets, if available</param>
|
||||
/// <param name="resultProgress">Optional result progress callback</param>
|
||||
/// <param name="protectionProgress">Optional protection progress callback</param>
|
||||
/// <param name="processUserInfo">Optional user prompt to deal with submission information</param>
|
||||
/// <param name="seedInfo">A seed SubmissionInfo object that contains user data</param>
|
||||
/// <returns>Result instance with the outcome</returns>
|
||||
public async Task<ResultEventArgs> VerifyAndSaveDumpOutput(
|
||||
MediaType? mediaType = null,
|
||||
IProgress<ResultEventArgs>? resultProgress = null,
|
||||
IProgress<ProtectionProgress>? protectionProgress = null,
|
||||
ProcessUserInfoDelegate? processUserInfo = null,
|
||||
@@ -485,16 +483,8 @@ namespace MPF.Frontend
|
||||
var outputDirectory = Path.GetDirectoryName(OutputPath);
|
||||
var outputFilename = Path.GetFileName(OutputPath);
|
||||
|
||||
// Determine the media type from the processor, if not provided
|
||||
mediaType ??= _processor.DetermineMediaType(outputDirectory, outputFilename);
|
||||
|
||||
// Check to make sure that the output had all the correct files
|
||||
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])}"));
|
||||
return ResultEventArgs.Failure("Error! Please check output directory as dump may be incomplete!");
|
||||
}
|
||||
// Determine the media type from the processor
|
||||
MediaType? mediaType = _processor.DetermineMediaType(outputDirectory, outputFilename);
|
||||
|
||||
// Extract the information from the output files
|
||||
resultProgress.Report(ResultEventArgs.Success("Extracting output information from output files..."));
|
||||
@@ -507,7 +497,15 @@ namespace MPF.Frontend
|
||||
_processor,
|
||||
resultProgress,
|
||||
protectionProgress);
|
||||
resultProgress.Report(ResultEventArgs.Success("Extracting information complete!"));
|
||||
if (submissionInfo == null)
|
||||
{
|
||||
resultProgress.Report(ResultEventArgs.Failure("There was an issue extracting information!"));
|
||||
return ResultEventArgs.Failure();
|
||||
}
|
||||
else
|
||||
{
|
||||
resultProgress.Report(ResultEventArgs.Success("Extracting information complete!"));
|
||||
}
|
||||
|
||||
// Inject seed submission info data, if necessary
|
||||
if (seedInfo != null)
|
||||
|
||||
@@ -33,11 +33,6 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public static List<int> BD => _speedValues.FindAll(s => s <= 16);
|
||||
|
||||
/// <summary>
|
||||
/// Set of accepted speeds for all other media
|
||||
/// </summary>
|
||||
public static List<int> Unknown => [1];
|
||||
|
||||
/// <summary>
|
||||
/// Get list of all drive speeds for a given MediaType
|
||||
/// </summary>
|
||||
@@ -55,7 +50,9 @@ namespace MPF.Frontend
|
||||
MediaType.HDDVD => HDDVD,
|
||||
MediaType.BluRay
|
||||
or MediaType.NintendoWiiUOpticalDisc => BD,
|
||||
_ => Unknown,
|
||||
|
||||
// Default to CD speed range
|
||||
_ => CD,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.3.3</VersionPrefix>
|
||||
<VersionPrefix>3.4.1</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
@@ -31,12 +31,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BinaryObjectScanner" Version="3.3.4" />
|
||||
<PackageReference Include="LibIRD" Version="0.9.3" />
|
||||
<PackageReference Include="BinaryObjectScanner" Version="3.4.2" />
|
||||
<PackageReference Include="LibIRD" Version="1.0.0" />
|
||||
<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="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.8" />
|
||||
<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.RedumpLib" Version="1.7.4" />
|
||||
<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>
|
||||
|
||||
|
||||
@@ -123,6 +123,15 @@ namespace MPF.Frontend
|
||||
set { Settings["CheckForUpdatesOnStartup"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to copy the update URL to the clipboard if one is found
|
||||
/// </summary>
|
||||
public bool CopyUpdateUrlToClipboard
|
||||
{
|
||||
get { return GetBooleanSetting(Settings, "CopyUpdateUrlToClipboard", true); }
|
||||
set { Settings["CopyUpdateUrlToClipboard"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fast update label - Skips disc checks and updates path only
|
||||
/// </summary>
|
||||
@@ -427,6 +436,15 @@ namespace MPF.Frontend
|
||||
set { Settings[RedumperSettings.RereadCount] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable the refine sector mode flag by default
|
||||
/// </summary>
|
||||
public bool RedumperRefineSectorMode
|
||||
{
|
||||
get { return GetBooleanSetting(Settings, RedumperSettings.RefineSectorMode, RedumperSettings.RefineSectorModeDefault); }
|
||||
set { Settings[RedumperSettings.RefineSectorMode] = value.ToString(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extra Dumping Options
|
||||
@@ -561,15 +579,6 @@ namespace MPF.Frontend
|
||||
|
||||
#region Skip Options
|
||||
|
||||
/// <summary>
|
||||
/// Skip detecting media type on disc scan
|
||||
/// </summary>
|
||||
public bool SkipMediaTypeDetection
|
||||
{
|
||||
get { return GetBooleanSetting(Settings, "SkipMediaTypeDetection", false); }
|
||||
set { Settings["SkipMediaTypeDetection"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Skip detecting known system on disc scan
|
||||
/// </summary>
|
||||
|
||||
108
MPF.Frontend/Progress.cs
Normal file
108
MPF.Frontend/Progress.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
#if NET20 || NET35 || NET40
|
||||
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace MPF.Frontend
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an IProgress{T} that invokes callbacks for each reported progress value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Specifies the type of the progress report value.</typeparam>
|
||||
/// <remarks>
|
||||
/// Any handler provided to the constructor or event handlers registered with
|
||||
/// the <see cref="ProgressChanged"/> event are invoked through a
|
||||
/// <see cref="SynchronizationContext"/> instance captured
|
||||
/// when the instance is constructed. If there is no current SynchronizationContext
|
||||
/// at the time of construction, the callbacks will be invoked on the ThreadPool.
|
||||
/// </remarks>
|
||||
/// <see href="https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Progress.cs"/>
|
||||
internal class Progress<T> : IProgress<T> where T : EventArgs
|
||||
{
|
||||
/// <summary>The synchronization context captured upon construction. This will never be null.</summary>
|
||||
private readonly SynchronizationContext? _synchronizationContext;
|
||||
/// <summary>The handler specified to the constructor. This may be null.</summary>
|
||||
private readonly Action<T>? _handler;
|
||||
/// <summary>A cached delegate used to post invocation to the synchronization context.</summary>
|
||||
private readonly SendOrPostCallback _invokeHandlers;
|
||||
|
||||
/// <summary>Initializes the <see cref="Progress{T}"/>.</summary>
|
||||
public Progress()
|
||||
{
|
||||
// Capture the current synchronization context.
|
||||
// If there is no current context, we use a default instance targeting the ThreadPool.
|
||||
_synchronizationContext = SynchronizationContext.Current ?? ProgressStatics.DefaultContext;
|
||||
Debug.Assert(_synchronizationContext != null);
|
||||
_invokeHandlers = new SendOrPostCallback(InvokeHandlers);
|
||||
}
|
||||
|
||||
/// <summary>Initializes the <see cref="Progress{T}"/> with the specified callback.</summary>
|
||||
/// <param name="handler">
|
||||
/// A handler to invoke for each reported progress value. This handler will be invoked
|
||||
/// in addition to any delegates registered with the <see cref="ProgressChanged"/> event.
|
||||
/// Depending on the <see cref="SynchronizationContext"/> instance captured by
|
||||
/// the <see cref="Progress{T}"/> at construction, it's possible that this handler instance
|
||||
/// could be invoked concurrently with itself.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="handler"/> is null (<see langword="Nothing" /> in Visual Basic).</exception>
|
||||
public Progress(Action<T> handler) : this()
|
||||
{
|
||||
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
|
||||
}
|
||||
|
||||
/// <summary>Raised for each reported progress value.</summary>
|
||||
/// <remarks>
|
||||
/// Handlers registered with this event will be invoked on the
|
||||
/// <see cref="SynchronizationContext"/> captured when the instance was constructed.
|
||||
/// </remarks>
|
||||
public event EventHandler<T>? ProgressChanged;
|
||||
|
||||
/// <summary>Reports a progress change.</summary>
|
||||
/// <param name="value">The value of the updated progress.</param>
|
||||
protected virtual void OnReport(T value)
|
||||
{
|
||||
// If there's no handler, don't bother going through the sync context.
|
||||
// Inside the callback, we'll need to check again, in case
|
||||
// an event handler is removed between now and then.
|
||||
Action<T>? handler = _handler;
|
||||
EventHandler<T>? changedEvent = ProgressChanged;
|
||||
if (handler != null || changedEvent != null)
|
||||
{
|
||||
// Post the processing to the sync context.
|
||||
// (If T is a value type, it will get boxed here.)
|
||||
_synchronizationContext?.Post(_invokeHandlers, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Reports a progress change.</summary>
|
||||
/// <param name="value">The value of the updated progress.</param>
|
||||
void IProgress<T>.Report(T value) { OnReport(value); }
|
||||
|
||||
/// <summary>Invokes the action and event callbacks.</summary>
|
||||
/// <param name="state">The progress value.</param>
|
||||
private void InvokeHandlers(object? state)
|
||||
{
|
||||
T value = (T)state!;
|
||||
|
||||
Action<T>? handler = _handler;
|
||||
EventHandler<T>? changedEvent = ProgressChanged;
|
||||
|
||||
handler?.Invoke(value);
|
||||
changedEvent?.Invoke(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Holds static values for <see cref="Progress{T}"/>.</summary>
|
||||
/// <remarks>This avoids one static instance per type T.</remarks>
|
||||
internal static class ProgressStatics
|
||||
{
|
||||
/// <summary>A default synchronization context that targets the ThreadPool.</summary>
|
||||
internal static readonly SynchronizationContext DefaultContext = new();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -119,42 +119,6 @@ namespace MPF.Frontend.Tools
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process common arguments for all functionality
|
||||
/// </summary>
|
||||
/// <returns>True if all arguments pass, false otherwise</returns>
|
||||
public static bool ProcessCommonArguments(string[] args, out MediaType mediaType, out RedumpSystem? system, out string? message)
|
||||
{
|
||||
// All other use requires at least 3 arguments
|
||||
if (args.Length < 3)
|
||||
{
|
||||
mediaType = MediaType.NONE;
|
||||
system = null;
|
||||
message = "Invalid number of arguments";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the MediaType
|
||||
mediaType = ToMediaType(args[0].Trim('"'));
|
||||
if (mediaType == MediaType.NONE)
|
||||
{
|
||||
system = null;
|
||||
message = $"{args[0]} is not a recognized media type";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the RedumpSystem
|
||||
system = Extensions.ToRedumpSystem(args[1].Trim('"'));
|
||||
if (system == null)
|
||||
{
|
||||
message = $"{args[1]} is not a recognized system";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the MediaType enum value for a given string
|
||||
/// </summary>
|
||||
|
||||
@@ -545,11 +545,11 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Read the app.pkg header
|
||||
using var fileStream = new FileStream(appPkgPath, FileMode.Open, FileAccess.Read);
|
||||
var appPkgHeaderDeserializer = new SabreTools.Serialization.Deserializers.AppPkgHeader();
|
||||
var appPkgHeaderDeserializer = new SabreTools.Serialization.Readers.AppPkgHeader();
|
||||
var appPkgHeader = appPkgHeaderDeserializer.Deserialize(fileStream);
|
||||
|
||||
if (appPkgHeader != null)
|
||||
pkgInfo += $"{appPkgHeader.ContentID}" + Environment.NewLine;
|
||||
pkgInfo += $"{appPkgHeader.ContentID}{Environment.NewLine}";
|
||||
}
|
||||
|
||||
if (pkgInfo == "")
|
||||
@@ -696,11 +696,11 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Read the app_sc.pkg header
|
||||
using var fileStream = new FileStream(appPkgPath, FileMode.Open, FileAccess.Read);
|
||||
var appPkgHeaderDeserializer = new SabreTools.Serialization.Deserializers.AppPkgHeader();
|
||||
var appPkgHeaderDeserializer = new SabreTools.Serialization.Readers.AppPkgHeader();
|
||||
var appPkgHeader = appPkgHeaderDeserializer.Deserialize(fileStream);
|
||||
|
||||
if (appPkgHeader != null)
|
||||
pkgInfo += $"{appPkgHeader.ContentID}" + Environment.NewLine;
|
||||
pkgInfo += $"{appPkgHeader.ContentID}{Environment.NewLine}";
|
||||
}
|
||||
|
||||
if (pkgInfo == "")
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace MPF.Frontend.Tools
|
||||
/// <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<ProtectionDictionary> RunProtectionScanOnPath(string path,
|
||||
public static async Task<Dictionary<string, List<string>>> RunProtectionScanOnPath(string path,
|
||||
Options options,
|
||||
IProgress<ProtectionProgress>? progress = null)
|
||||
{
|
||||
@@ -97,9 +97,6 @@ namespace MPF.Frontend.Tools
|
||||
if (found == null || found.Count == 0)
|
||||
return [];
|
||||
|
||||
// Filter out any empty protections
|
||||
found.ClearEmptyKeys();
|
||||
|
||||
// Return the filtered set of protections
|
||||
return found;
|
||||
}
|
||||
@@ -109,7 +106,7 @@ namespace MPF.Frontend.Tools
|
||||
/// </summary>
|
||||
/// <param name="protections">Dictionary of file to list of protection mappings</param>
|
||||
/// <returns>Detected protections, if any</returns>
|
||||
public static string? FormatProtections(ProtectionDictionary? protections)
|
||||
public static string? FormatProtections(Dictionary<string, List<string>>? protections)
|
||||
{
|
||||
// If the filtered list is empty in some way, return
|
||||
if (protections == null)
|
||||
@@ -117,6 +114,9 @@ namespace MPF.Frontend.Tools
|
||||
else if (protections.Count == 0)
|
||||
return "None found [OMIT FROM SUBMISSION]";
|
||||
|
||||
// Sanitize context-sensitive protections
|
||||
protections = SanitizeContextSensitiveProtections(protections);
|
||||
|
||||
// Get a list of distinct found protections
|
||||
#if NET20
|
||||
var protectionValues = new List<string>();
|
||||
@@ -137,7 +137,7 @@ namespace MPF.Frontend.Tools
|
||||
.Distinct()
|
||||
.ToList();
|
||||
#endif
|
||||
|
||||
|
||||
// Sanitize and join protections for writing
|
||||
string protectionString = SanitizeFoundProtections(protectionValues);
|
||||
if (string.IsNullOrEmpty(protectionString))
|
||||
@@ -184,6 +184,66 @@ namespace MPF.Frontend.Tools
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sanitize unnecessary protections where context matters
|
||||
/// </summary>
|
||||
/// <param name="protections">Dictionary of file to list of protection mappings</param>
|
||||
/// <returns>Dictionary with all necessary items filtered out</returns>
|
||||
public static Dictionary<string, List<string>> SanitizeContextSensitiveProtections(Dictionary<string, List<string>> protections)
|
||||
{
|
||||
// Setup the output dictionary
|
||||
Dictionary<string, List<string>> filtered = [];
|
||||
|
||||
// Setup a list for keys that need additional processing
|
||||
List<string> foundKeys = [];
|
||||
|
||||
// Loop through the keys and add relevant ones
|
||||
string[] paths = [.. protections.Keys];
|
||||
foreach (var path in paths)
|
||||
{
|
||||
if (!protections.TryGetValue(path, out var values) || values == null || values.Count == 0)
|
||||
continue;
|
||||
|
||||
// Always copy the values if they're valid
|
||||
filtered[path] = values;
|
||||
|
||||
if (values.Exists(s => s.StartsWith("SecuROM Release Control -")))
|
||||
foundKeys.Add(path);
|
||||
}
|
||||
|
||||
// If there are no keys found
|
||||
if (foundKeys.Count == 0)
|
||||
return filtered;
|
||||
|
||||
// Process the keys as necessary
|
||||
foreach (var key in foundKeys)
|
||||
{
|
||||
// Get all matching paths
|
||||
var matchingPaths = Array.FindAll(paths, s => s != key && s.StartsWith(key));
|
||||
if (matchingPaths.Length == 0)
|
||||
continue;
|
||||
|
||||
// Loop through the matching paths
|
||||
foreach (var path in matchingPaths)
|
||||
{
|
||||
if (!filtered.TryGetValue(path, out var values) || values == null || values.Count == 0)
|
||||
continue;
|
||||
|
||||
if (values.Exists(s => !s.Contains("GitHub") &&
|
||||
(s.Contains("SecuROM 7")
|
||||
|| s.Contains("SecuROM 8")
|
||||
|| s.Contains("SecuROM Content Activation")
|
||||
|| s.Contains("SecuROM Data File Activation")
|
||||
|| s.Contains("Unlock"))))
|
||||
{
|
||||
filtered.Remove(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sanitize unnecessary protection duplication from output
|
||||
/// </summary>
|
||||
@@ -200,7 +260,12 @@ namespace MPF.Frontend.Tools
|
||||
// EXCEPTIONS
|
||||
if (foundProtections.Exists(p => p.StartsWith("[Exception opening file")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("[Exception opening file"));
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("[Exception opening file") && !p.StartsWith("[Access issue when opening file"));
|
||||
foundProtections.Add("Exception occurred while scanning [RESCAN NEEDED]");
|
||||
}
|
||||
if (foundProtections.Exists(p => p.StartsWith("[Access issue when opening file")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("[Exception opening file") && !p.StartsWith("[Access issue when opening file"));
|
||||
foundProtections.Add("Exception occurred while scanning [RESCAN NEEDED]");
|
||||
}
|
||||
|
||||
@@ -310,9 +375,8 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Best case scenario for SafeDisc 2+: A full SafeDisc version is found in a line starting with "Macrovision Protected Application".
|
||||
// All other SafeDisc detections can be safely scrubbed.
|
||||
// TODO: Scrub "Macrovision Protected Application, " from before the SafeDisc version.
|
||||
if (foundProtections.Exists(p => Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled)
|
||||
&& p.StartsWith("Macrovision Protected Application")
|
||||
&& p.Contains("Macrovision Protected Application")
|
||||
&& !p.Contains("SRV Tool APP")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("Macrovision Protection File"))
|
||||
@@ -326,11 +390,14 @@ namespace MPF.Frontend.Tools
|
||||
.FindAll(p => p != "SafeDisc 1/Lite")
|
||||
.FindAll(p => p != "SafeDisc 2+")
|
||||
.FindAll(p => p != "SafeDisc 3+ (DVD)");
|
||||
foundProtections = foundProtections.ConvertAll(p => p
|
||||
.Replace("Macrovision Protected Application, ", string.Empty)
|
||||
.Replace(", Macrovision Protected Application", string.Empty));
|
||||
}
|
||||
|
||||
// Next best case for SafeDisc 2+: A full SafeDisc version is found from the "SafeDisc SRV Tool APP".
|
||||
else if (foundProtections.Exists(p => Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled)
|
||||
&& p.StartsWith("Macrovision Protected Application")
|
||||
&& p.Contains("Macrovision Protected Application")
|
||||
&& p.Contains("SRV Tool APP")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("Macrovision Protection File"))
|
||||
@@ -374,7 +441,6 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
|
||||
// Next best case for SafeDisc 1: A SafeDisc version range is found from "SECDRV.SYS".
|
||||
// TODO: Scrub "Macrovision Security Driver {Version}" from before the SafeDisc version.
|
||||
else if (foundProtections.Exists(p => p.StartsWith("Macrovision Security Driver")
|
||||
&& Regex.IsMatch(p, @"SafeDisc 1\.[0-9]{2}\.[0-9]{3}-[1-2]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled)
|
||||
|| Regex.IsMatch(p, @"SafeDisc 1\.[0-9]{2}\.[0-9]{3}$")))
|
||||
@@ -386,10 +452,12 @@ namespace MPF.Frontend.Tools
|
||||
.FindAll(p => p != "SafeDisc")
|
||||
.FindAll(p => p != "SafeDisc 1")
|
||||
.FindAll(p => p != "SafeDisc 1/Lite");
|
||||
foundProtections = foundProtections.ConvertAll(p => p.StartsWith("Macrovision Security Driver") && p.Split('/').Length > 1
|
||||
? p.Split('/')[1].TrimStart()
|
||||
: p);
|
||||
}
|
||||
|
||||
// Next best case for SafeDisc 2+: A SafeDisc version range is found from "SECDRV.SYS".
|
||||
// TODO: Scrub "Macrovision Security Driver {Version}" from before the SafeDisc version.
|
||||
else if (foundProtections.Exists(p => p.StartsWith("Macrovision Security Driver")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("Macrovision Protection File"))
|
||||
@@ -401,6 +469,9 @@ namespace MPF.Frontend.Tools
|
||||
.FindAll(p => p != "SafeDisc 1/Lite")
|
||||
.FindAll(p => p != "SafeDisc 2+")
|
||||
.FindAll(p => p != "SafeDisc 3+ (DVD)");
|
||||
foundProtections = foundProtections.ConvertAll(p => p.StartsWith("Macrovision Security Driver") && p.Split('/').Length > 1
|
||||
? p.Split('/')[1].TrimStart()
|
||||
: p);
|
||||
}
|
||||
|
||||
// Only SafeDisc Lite is found.
|
||||
@@ -429,7 +500,11 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
|
||||
// SecuROM
|
||||
// TODO: Figure this one out
|
||||
if (foundProtections.Exists(p => p.StartsWith("SecuROM Release Control")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("SecuROM Release Control"));
|
||||
foundProtections.Add("SecuROM Release Control");
|
||||
}
|
||||
|
||||
// SolidShield
|
||||
// TODO: Figure this one out
|
||||
|
||||
@@ -51,10 +51,6 @@ namespace MPF.Frontend.Tools
|
||||
IProgress<ResultEventArgs>? resultProgress = null,
|
||||
IProgress<ProtectionProgress>? protectionProgress = null)
|
||||
{
|
||||
// Ensure the current disc combination should exist
|
||||
if (!system.MediaTypes().Contains(mediaType))
|
||||
return null;
|
||||
|
||||
// Split the output path for easier use
|
||||
var outputDirectory = Path.GetDirectoryName(outputPath);
|
||||
string outputFilename = Path.GetFileName(outputPath);
|
||||
@@ -77,9 +73,9 @@ namespace MPF.Frontend.Tools
|
||||
SubmissionInfo info = CreateDefaultSubmissionInfo(processor, system, mediaType, options.AddPlaceholders);
|
||||
|
||||
// Get specific tool output handling
|
||||
processor?.GenerateSubmissionInfo(info, mediaType, basePath, options.EnableRedumpCompatibility);
|
||||
processor.GenerateSubmissionInfo(info, mediaType, basePath, options.EnableRedumpCompatibility);
|
||||
if (options.IncludeArtifacts)
|
||||
info.Artifacts = processor?.GenerateArtifacts(mediaType, outputDirectory, outputFilename);
|
||||
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]";
|
||||
@@ -93,7 +89,7 @@ namespace MPF.Frontend.Tools
|
||||
info.TracksAndWriteOffsets.ClrMameProData = null;
|
||||
|
||||
// Add the volume label to comments, if possible or necessary
|
||||
string? volLabels = FormatVolumeLabels(drive?.VolumeLabel, processor?.VolumeLabels);
|
||||
string? volLabels = FormatVolumeLabels(drive?.VolumeLabel, processor.VolumeLabels);
|
||||
if (volLabels != null)
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.VolumeLabel] = volLabels;
|
||||
|
||||
@@ -116,7 +112,7 @@ namespace MPF.Frontend.Tools
|
||||
{
|
||||
resultProgress?.Report(ResultEventArgs.Success("Running copy protection scan... this might take a while!"));
|
||||
|
||||
ProtectionDictionary? protections = null;
|
||||
Dictionary<string, List<string>>? protections = null;
|
||||
try
|
||||
{
|
||||
if (options.ScanForProtection && drive?.Name != null)
|
||||
@@ -1002,7 +998,7 @@ namespace MPF.Frontend.Tools
|
||||
/// <summary>
|
||||
/// Set a comment field if it doesn't already have a value
|
||||
/// </summary>
|
||||
private static void SetCommentFieldIfNotExists(SubmissionInfo info, SiteCode key, Drive? drive, Func<Drive?, string?> valueFunc)
|
||||
private static void SetCommentFieldIfNotExists(SubmissionInfo info, SiteCode key, Drive? drive, System.Func<Drive?, string?> valueFunc)
|
||||
{
|
||||
// If the field has a valid value, skip
|
||||
if (CommentFieldExists(info, key, out _))
|
||||
@@ -1066,7 +1062,7 @@ namespace MPF.Frontend.Tools
|
||||
/// </summary>
|
||||
/// <param name="oldDict">ProtectionDictionary to format</param>
|
||||
/// <returns>Reformatted dictionary on success, empty on error</returns>
|
||||
private static Dictionary<string, List<string>?> ReformatProtectionDictionary(ProtectionDictionary? oldDict)
|
||||
private static Dictionary<string, List<string>?> ReformatProtectionDictionary(Dictionary<string, List<string>>? oldDict)
|
||||
{
|
||||
// Null or empty protections return empty
|
||||
if (oldDict == null || oldDict.Count == 0)
|
||||
|
||||
@@ -66,34 +66,6 @@ namespace MPF.Frontend.ViewModels
|
||||
}
|
||||
private bool _systemTypeComboBoxEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected media type value
|
||||
/// </summary>
|
||||
public MediaType? CurrentMediaType
|
||||
{
|
||||
get => _currentMediaType;
|
||||
set
|
||||
{
|
||||
_currentMediaType = value;
|
||||
TriggerPropertyChanged(nameof(CurrentMediaType));
|
||||
}
|
||||
}
|
||||
private MediaType? _currentMediaType;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the status of the media type combo box
|
||||
/// </summary>
|
||||
public bool MediaTypeComboBoxEnabled
|
||||
{
|
||||
get => _mediaTypeComboBoxEnabled;
|
||||
set
|
||||
{
|
||||
_mediaTypeComboBoxEnabled = value;
|
||||
TriggerPropertyChanged(nameof(MediaTypeComboBoxEnabled));
|
||||
}
|
||||
}
|
||||
private bool _mediaTypeComboBoxEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Currently provided input path
|
||||
/// </summary>
|
||||
@@ -229,20 +201,6 @@ namespace MPF.Frontend.ViewModels
|
||||
|
||||
#region List Properties
|
||||
|
||||
/// <summary>
|
||||
/// Current list of supported media types
|
||||
/// </summary>
|
||||
public List<Element<MediaType>>? MediaTypes
|
||||
{
|
||||
get => _mediaTypes;
|
||||
set
|
||||
{
|
||||
_mediaTypes = value;
|
||||
TriggerPropertyChanged(nameof(MediaTypes));
|
||||
}
|
||||
}
|
||||
private List<Element<MediaType>>? _mediaTypes;
|
||||
|
||||
/// <summary>
|
||||
/// Current list of supported system profiles
|
||||
/// </summary>
|
||||
@@ -287,16 +245,13 @@ namespace MPF.Frontend.ViewModels
|
||||
SystemTypeComboBoxEnabled = true;
|
||||
InputPathTextBoxEnabled = true;
|
||||
InputPathBrowseButtonEnabled = true;
|
||||
MediaTypeComboBoxEnabled = true;
|
||||
DumpingProgramComboBoxEnabled = true;
|
||||
CheckDumpButtonEnabled = false;
|
||||
CancelButtonEnabled = true;
|
||||
|
||||
MediaTypes = [];
|
||||
Systems = RedumpSystemComboBoxItem.GenerateElements();
|
||||
InternalPrograms = [];
|
||||
|
||||
PopulateMediaType();
|
||||
PopulateInternalPrograms();
|
||||
EnableEventHandlers();
|
||||
}
|
||||
@@ -327,15 +282,6 @@ namespace MPF.Frontend.ViewModels
|
||||
/// Change the currently selected system
|
||||
/// </summary>
|
||||
public void ChangeSystem()
|
||||
{
|
||||
PopulateMediaType();
|
||||
CheckDumpButtonEnabled = ShouldEnableCheckDumpButton();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change the currently selected media type
|
||||
/// </summary>
|
||||
public void ChangeMediaType()
|
||||
{
|
||||
CheckDumpButtonEnabled = ShouldEnableCheckDumpButton();
|
||||
}
|
||||
@@ -369,7 +315,6 @@ namespace MPF.Frontend.ViewModels
|
||||
InputPathTextBoxEnabled = true;
|
||||
InputPathBrowseButtonEnabled = true;
|
||||
DumpingProgramComboBoxEnabled = true;
|
||||
PopulateMediaType();
|
||||
CheckDumpButtonEnabled = ShouldEnableCheckDumpButton();
|
||||
CancelButtonEnabled = true;
|
||||
}
|
||||
@@ -382,7 +327,6 @@ namespace MPF.Frontend.ViewModels
|
||||
SystemTypeComboBoxEnabled = false;
|
||||
InputPathTextBoxEnabled = false;
|
||||
InputPathBrowseButtonEnabled = false;
|
||||
MediaTypeComboBoxEnabled = false;
|
||||
DumpingProgramComboBoxEnabled = false;
|
||||
CheckDumpButtonEnabled = false;
|
||||
CancelButtonEnabled = false;
|
||||
@@ -392,35 +336,6 @@ namespace MPF.Frontend.ViewModels
|
||||
|
||||
#region Population
|
||||
|
||||
/// <summary>
|
||||
/// Populate media type according to system type
|
||||
/// </summary>
|
||||
private void PopulateMediaType()
|
||||
{
|
||||
// Disable other UI updates
|
||||
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
|
||||
DisableEventHandlers();
|
||||
|
||||
if (CurrentSystem != null)
|
||||
{
|
||||
var mediaTypeValues = CurrentSystem.MediaTypes();
|
||||
int index = mediaTypeValues.FindIndex(m => m == CurrentMediaType);
|
||||
|
||||
MediaTypes = mediaTypeValues.ConvertAll(m => new Element<MediaType>(m ?? MediaType.NONE));
|
||||
MediaTypeComboBoxEnabled = MediaTypes.Count > 1;
|
||||
CurrentMediaType = (index > -1 ? MediaTypes[index] : MediaTypes[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
MediaTypeComboBoxEnabled = false;
|
||||
MediaTypes = null;
|
||||
CurrentMediaType = null;
|
||||
}
|
||||
|
||||
// Reenable event handlers, if necessary
|
||||
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate media type according to system type
|
||||
/// </summary>
|
||||
@@ -451,7 +366,7 @@ namespace MPF.Frontend.ViewModels
|
||||
|
||||
private bool ShouldEnableCheckDumpButton()
|
||||
{
|
||||
return CurrentSystem != null && CurrentMediaType != null && !string.IsNullOrEmpty(InputPath);
|
||||
return CurrentSystem != null && !string.IsNullOrEmpty(InputPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -478,13 +393,13 @@ namespace MPF.Frontend.ViewModels
|
||||
/// Performs MPF.Check functionality
|
||||
/// </summary>
|
||||
/// <returns>An error message if failed, otherwise string.Empty/null</returns>
|
||||
public async Task<string?> CheckDump(ProcessUserInfoDelegate processUserInfo)
|
||||
public async Task<ResultEventArgs> CheckDump(ProcessUserInfoDelegate processUserInfo)
|
||||
{
|
||||
if (string.IsNullOrEmpty(InputPath))
|
||||
return "Invalid Input path";
|
||||
return ResultEventArgs.Failure("Invalid Input path");
|
||||
|
||||
if (!File.Exists(InputPath!.Trim('"')))
|
||||
return "Input Path is not a valid file";
|
||||
return ResultEventArgs.Failure("Input Path is not a valid file");
|
||||
|
||||
// Disable UI while Check is running
|
||||
DisableUIElements();
|
||||
@@ -507,7 +422,6 @@ namespace MPF.Frontend.ViewModels
|
||||
|
||||
// Finally, attempt to do the output dance
|
||||
var result = await env.VerifyAndSaveDumpOutput(
|
||||
mediaType: CurrentMediaType,
|
||||
resultProgress: resultProgress,
|
||||
protectionProgress: protectionProgress,
|
||||
processUserInfo: processUserInfo);
|
||||
@@ -517,7 +431,7 @@ namespace MPF.Frontend.ViewModels
|
||||
if (cachedCanExecuteSelectionChanged)
|
||||
EnableEventHandlers();
|
||||
|
||||
return result.Message;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -674,7 +674,7 @@ namespace MPF.Frontend.ViewModels
|
||||
|
||||
// Set the selected index
|
||||
CurrentDrive = (index != -1 ? Drives[index] : Drives[0]);
|
||||
Status = "Valid drive found! Choose your Media Type";
|
||||
Status = "Valid drive found!";
|
||||
CopyProtectScanButtonEnabled = true;
|
||||
|
||||
// Get the current system type
|
||||
@@ -1213,14 +1213,8 @@ namespace MPF.Frontend.ViewModels
|
||||
if (defaultMediaType == MediaType.NONE)
|
||||
defaultMediaType = MediaType.CDROM;
|
||||
|
||||
// If we're skipping detection, set the default value
|
||||
if (Options.SkipMediaTypeDetection)
|
||||
{
|
||||
VerboseLogLn($"Media type detection disabled, defaulting to {defaultMediaType.LongName()}.");
|
||||
CurrentMediaType = defaultMediaType;
|
||||
}
|
||||
// If the drive is marked active, try to read from it
|
||||
else if (CurrentDrive.MarkedActive)
|
||||
if (CurrentDrive.MarkedActive)
|
||||
{
|
||||
VerboseLog($"Trying to detect media type for drive {CurrentDrive.Name} [{CurrentDrive.DriveFormat}] using size and filesystem.. ");
|
||||
MediaType? detectedMediaType = CurrentDrive.GetMediaType(CurrentSystem);
|
||||
@@ -1238,8 +1232,7 @@ namespace MPF.Frontend.ViewModels
|
||||
CurrentMediaType = detectedMediaType;
|
||||
}
|
||||
}
|
||||
|
||||
// All other cases, just use the default
|
||||
// Otherwise just use the default
|
||||
else
|
||||
{
|
||||
VerboseLogLn($"Drive marked as empty, defaulting to {defaultMediaType.LongName()}.");
|
||||
@@ -1366,6 +1359,10 @@ namespace MPF.Frontend.ViewModels
|
||||
/// </summary>
|
||||
public void EnsureMediaInformation()
|
||||
{
|
||||
// If the drive list is empty, ignore updates
|
||||
if (Drives.Count == 0)
|
||||
return;
|
||||
|
||||
// Get the current environment information
|
||||
_environment = DetermineEnvironment();
|
||||
|
||||
@@ -1639,7 +1636,7 @@ namespace MPF.Frontend.ViewModels
|
||||
if (!File.Exists(catalogjs))
|
||||
return RedumpSystem.MicrosoftXboxOne;
|
||||
|
||||
SabreTools.Models.Xbox.Catalog? catalog = SabreTools.Serialization.Deserializers.Catalog.DeserializeFile(catalogjs);
|
||||
SabreTools.Data.Models.Xbox.Catalog? 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))
|
||||
@@ -1665,6 +1662,12 @@ namespace MPF.Frontend.ViewModels
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Playmaji Polymega
|
||||
if (File.Exists(Path.Combine(drive.Name, "Get Polymega App.url")))
|
||||
{
|
||||
return RedumpSystem.PlaymajiPolymega;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Sega Saturn / Sega Dreamcast / Sega Mega-CD / Sega-CD
|
||||
@@ -2100,6 +2103,10 @@ namespace MPF.Frontend.ViewModels
|
||||
/// </summary>
|
||||
public void SetSupportedDriveSpeed()
|
||||
{
|
||||
// Skip trying to set speeds if no drives
|
||||
if (Drives.Count == 0)
|
||||
return;
|
||||
|
||||
// Set the drive speed list that's appropriate
|
||||
DriveSpeeds = InterfaceConstants.GetSpeedsForMediaType(CurrentMediaType);
|
||||
VerboseLogLn($"Supported media speeds: {string.Join(", ", [.. DriveSpeeds.ConvertAll(ds => ds.ToString())])}");
|
||||
@@ -2113,8 +2120,7 @@ namespace MPF.Frontend.ViewModels
|
||||
/// </summary>
|
||||
private bool ShouldEnableDumpingButton()
|
||||
{
|
||||
return Drives != null
|
||||
&& Drives.Count > 0
|
||||
return Drives.Count > 0
|
||||
&& CurrentSystem != null
|
||||
&& CurrentMediaType != null
|
||||
&& ProgramSupportsMedia();
|
||||
@@ -2190,23 +2196,6 @@ namespace MPF.Frontend.ViewModels
|
||||
// Force an internal drive refresh in case the user entered things manually
|
||||
_environment.RefreshDrive();
|
||||
|
||||
// If still in custom parameter mode, check that users meant to continue or not
|
||||
if (ParametersCheckBoxEnabled == false && _displayUserMessage != null)
|
||||
{
|
||||
bool? result = _displayUserMessage("Custom Changes", "It looks like you have custom parameters that have not been saved. Would you like to dump with these custom parameters?", 2, true);
|
||||
if (result == true)
|
||||
{
|
||||
ParametersCheckBoxEnabled = true;
|
||||
ProcessCustomParameters();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Re-allow quick exiting
|
||||
AskBeforeQuit = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Run pre-dumping validation checks
|
||||
@@ -2256,7 +2245,6 @@ namespace MPF.Frontend.ViewModels
|
||||
if (result)
|
||||
{
|
||||
result = await _environment.VerifyAndSaveDumpOutput(
|
||||
mediaType: CurrentMediaType,
|
||||
resultProgress: resultProgress,
|
||||
protectionProgress: protectionProgress,
|
||||
processUserInfo: _processUserInfo);
|
||||
@@ -2304,6 +2292,7 @@ namespace MPF.Frontend.ViewModels
|
||||
MediaScanButtonEnabled = false;
|
||||
UpdateVolumeLabelEnabled = false;
|
||||
CopyProtectScanButtonEnabled = false;
|
||||
StartStopButtonEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2324,6 +2313,7 @@ namespace MPF.Frontend.ViewModels
|
||||
MediaScanButtonEnabled = true;
|
||||
UpdateVolumeLabelEnabled = true;
|
||||
CopyProtectScanButtonEnabled = true;
|
||||
StartStopButtonEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Processors.Test
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -24,13 +24,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.13.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.8" />
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.14.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.7.4" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.21.0" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.24.0" />
|
||||
<PackageReference Include="xunit.assert" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.core" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.9.3" />
|
||||
@@ -39,7 +39,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Models.PIC;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.Data.Models.PIC;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
@@ -471,12 +471,9 @@ namespace MPF.Processors.Test
|
||||
[Theory]
|
||||
[InlineData(null, null)]
|
||||
[InlineData("", null)]
|
||||
[InlineData("GAME", DiscCategory.Games)]
|
||||
[InlineData("game", DiscCategory.Games)]
|
||||
[InlineData("VIDEO", DiscCategory.Video)]
|
||||
[InlineData("video", DiscCategory.Video)]
|
||||
[InlineData("AUDIO", DiscCategory.Audio)]
|
||||
[InlineData("audio", DiscCategory.Audio)]
|
||||
[InlineData("(GAME)", DiscCategory.Games)]
|
||||
[InlineData("(VIDEO)", DiscCategory.Video)]
|
||||
[InlineData("(AUDIO)", DiscCategory.Audio)]
|
||||
[InlineData("INVALID", null)]
|
||||
public void GetUMDCategoryTest(string? category, DiscCategory? expected)
|
||||
{
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace MPF.Processors.Test
|
||||
var processor = new Redumper(RedumpSystem.IBMPCcompatible);
|
||||
|
||||
var actual = processor.GetOutputFiles(MediaType.CDROM, outputDirectory, outputFilename);
|
||||
Assert.Equal(16, actual.Count);
|
||||
Assert.Equal(17, actual.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -114,7 +114,7 @@ namespace MPF.Processors.Test
|
||||
var processor = new Redumper(RedumpSystem.IBMPCcompatible);
|
||||
|
||||
var actual = processor.GetOutputFiles(MediaType.DVD, outputDirectory, outputFilename);
|
||||
Assert.Equal(17, actual.Count);
|
||||
Assert.Equal(15, actual.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,21 @@
|
||||
<< GetUMDAuxInfo >>
|
||||
TITLE title
|
||||
DISC_ID serial
|
||||
DISC_VERSION version
|
||||
pspUmdTypes GAME
|
||||
L0 length 12345
|
||||
FileSize: 12345
|
||||
disc0:/PSP_GAME/PARAM.SFO
|
||||
magic: PSF
|
||||
version: 1.01
|
||||
BOOTABLE: 1
|
||||
CATEGORY: UG
|
||||
DISC_ID: ABCD12345
|
||||
DISC_NUMBER: 1
|
||||
DISC_TOTAL: 1
|
||||
DISC_VERSION: 1.01
|
||||
PARENTAL_LEVEL: 1
|
||||
PSP_SYSTEM_VER: 1.00
|
||||
REGION: 32768
|
||||
TITLE: title
|
||||
|
||||
pspUmdTypes: 0x10 (GAME)
|
||||
L0 length: 442560 (0x6c0c0)
|
||||
L1 length: 276096 (0x43680)
|
||||
---------------------------
|
||||
Total: 718656 (0xaf740)
|
||||
FileSize: 1471807488 (0x57ba0000)
|
||||
|
||||
@@ -291,10 +291,10 @@ namespace MPF.Processors.Test
|
||||
{
|
||||
string? expectedTitle = "title";
|
||||
DiscCategory? expectedCategory = DiscCategory.Games;
|
||||
string? expectedSerial = "seri-al";
|
||||
string? expectedVersion = "version";
|
||||
string? expectedLayer = "12345";
|
||||
long expectedSize = 12345;
|
||||
string? expectedSerial = "ABCD-12345";
|
||||
string? expectedVersion = "1.01";
|
||||
string? expectedLayer = "442560";
|
||||
long expectedSize = 1471807488;
|
||||
|
||||
string disc = Path.Combine(Environment.CurrentDirectory, "TestData", "UmdImageCreator", "UMD", "test_disc.txt");
|
||||
bool actual = UmdImageCreator.GetUMDAuxInfo(disc,
|
||||
|
||||
@@ -5,8 +5,8 @@ using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using SabreTools.Models.CueSheets;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Data.Models.CueSheets;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Schemas;
|
||||
@@ -409,7 +409,7 @@ namespace MPF.Processors
|
||||
cueSheet.Files = [.. cueFiles];
|
||||
if (cueSheet != null && cueSheet != default)
|
||||
{
|
||||
var ms = SabreTools.Serialization.Serializers.CueSheet.SerializeStream(cueSheet);
|
||||
var ms = new SabreTools.Serialization.Writers.CueSheet().SerializeStream(cueSheet);
|
||||
if (ms == null)
|
||||
return null;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.IO.Compression;
|
||||
#endif
|
||||
using System.Text;
|
||||
using SabreTools.Hashing;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Processors
|
||||
@@ -312,42 +312,50 @@ namespace MPF.Processors
|
||||
if (outputFiles.Count == 0)
|
||||
return [];
|
||||
|
||||
// Create the artifacts dictionary
|
||||
var artifacts = new Dictionary<string, string>();
|
||||
|
||||
// Only try to create artifacts for files that exist
|
||||
foreach (var outputFile in outputFiles)
|
||||
try
|
||||
{
|
||||
// Skip non-artifact files
|
||||
if (!outputFile.IsArtifact || outputFile.ArtifactKey == null)
|
||||
continue;
|
||||
// Create the artifacts dictionary
|
||||
var artifacts = new Dictionary<string, string>();
|
||||
|
||||
// Skip non-existent files
|
||||
if (!outputFile.Exists(outputDirectory ?? string.Empty))
|
||||
continue;
|
||||
|
||||
// Skip non-existent files
|
||||
foreach (var filePath in outputFile.GetPaths(outputDirectory ?? string.Empty))
|
||||
// Only try to create artifacts for files that exist
|
||||
foreach (var outputFile in outputFiles)
|
||||
{
|
||||
// Get binary artifacts as a byte array
|
||||
if (outputFile.IsBinaryArtifact)
|
||||
{
|
||||
byte[] data = File.ReadAllBytes(filePath);
|
||||
string str = Convert.ToBase64String(data);
|
||||
artifacts[outputFile.ArtifactKey] = str;
|
||||
}
|
||||
else
|
||||
{
|
||||
string? data = ProcessingTool.GetFullFile(filePath);
|
||||
string str = ProcessingTool.GetBase64(data) ?? string.Empty;
|
||||
artifacts[outputFile.ArtifactKey] = str;
|
||||
}
|
||||
// Skip non-artifact files
|
||||
if (!outputFile.IsArtifact || outputFile.ArtifactKey == null)
|
||||
continue;
|
||||
|
||||
break;
|
||||
// Skip non-existent files
|
||||
if (!outputFile.Exists(outputDirectory ?? string.Empty))
|
||||
continue;
|
||||
|
||||
// Skip non-existent files
|
||||
foreach (var filePath in outputFile.GetPaths(outputDirectory ?? string.Empty))
|
||||
{
|
||||
// Get binary artifacts as a byte array
|
||||
if (outputFile.IsBinaryArtifact)
|
||||
{
|
||||
byte[] data = File.ReadAllBytes(filePath);
|
||||
string str = Convert.ToBase64String(data);
|
||||
artifacts[outputFile.ArtifactKey] = str;
|
||||
}
|
||||
else
|
||||
{
|
||||
string? data = ProcessingTool.GetFullFile(filePath);
|
||||
string str = ProcessingTool.GetBase64(data) ?? string.Empty;
|
||||
artifacts[outputFile.ArtifactKey] = str;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return artifacts;
|
||||
return artifacts;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Any issues shouldn't stop processing
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
#if NET452_OR_GREATER || NETCOREAPP
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.Hashing;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Text.RegularExpressions;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
@@ -289,7 +289,7 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SonyElectronicBook:
|
||||
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;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.Hashing;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.3.3</VersionPrefix>
|
||||
<VersionPrefix>3.4.1</VersionPrefix>
|
||||
<WarningsNotAsErrors>NU5104</WarningsNotAsErrors>
|
||||
|
||||
<!-- Package Properties -->
|
||||
@@ -33,13 +33,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.Hashing" Version="1.4.2" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.5.8" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.8" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.8.6" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="1.5.0" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.7.5" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.7.4" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="2.0.0" />
|
||||
<PackageReference Include="System.IO.Compression" Version="4.3.0" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`))" />
|
||||
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.4" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.9" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
|
||||
@@ -10,9 +10,8 @@ using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using SabreTools.Hashing;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Models.PIC;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.Data.Models.PIC;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Processors
|
||||
@@ -133,7 +132,7 @@ namespace MPF.Processors
|
||||
{
|
||||
try
|
||||
{
|
||||
return SabreTools.Serialization.Deserializers.PIC.DeserializeFile(pic);
|
||||
return new SabreTools.Serialization.Readers.PIC().Deserialize(pic);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -375,9 +374,9 @@ namespace MPF.Processors
|
||||
{
|
||||
return category?.ToLowerInvariant() switch
|
||||
{
|
||||
"game" => DiscCategory.Games,
|
||||
"video" => DiscCategory.Video,
|
||||
"audio" => DiscCategory.Audio,
|
||||
"(game)" => DiscCategory.Games,
|
||||
"(video)" => DiscCategory.Video,
|
||||
"(audio)" => DiscCategory.Audio,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
@@ -1074,7 +1073,7 @@ namespace MPF.Processors
|
||||
// Only continue to check SSv2 for XGD3
|
||||
if (xgdType != 3)
|
||||
return true;
|
||||
|
||||
|
||||
// Determine if XGD3 SS.bin is SSv1 (Original Kreon) or SSv2 (0800 / Repaired Kreon)
|
||||
#if NET20
|
||||
var checkArr = new byte[72];
|
||||
@@ -1126,8 +1125,8 @@ namespace MPF.Processors
|
||||
else if (xgdType == 3)
|
||||
ccrt_offset = 0x20;
|
||||
|
||||
int[] entry_offsets = {0, 9, 18, 27, 36, 45, 54, 63};
|
||||
int[] entry_lengths = {8, 8, 8, 8, 4, 4, 4, 4};
|
||||
int[] entry_offsets = { 0, 9, 18, 27, 36, 45, 54, 63 };
|
||||
int[] entry_lengths = { 8, 8, 8, 8, 4, 4, 4, 4 };
|
||||
for (int i = 0; i < entry_offsets.Length; i++)
|
||||
{
|
||||
bool emptyResponse = true;
|
||||
@@ -1289,7 +1288,7 @@ namespace MPF.Processors
|
||||
// Determine XGD type
|
||||
if (!GetXGDType(ss, out int xgdType))
|
||||
return false;
|
||||
|
||||
|
||||
// Determine if XGD3 SS.bin is SSv1 (Original Kreon) or SSv2 (0800 / Repaired Kreon)
|
||||
#if NET20
|
||||
var checkArr = new byte[72];
|
||||
@@ -1300,7 +1299,7 @@ namespace MPF.Processors
|
||||
#endif
|
||||
|
||||
// Do not produce an SS hash for bad SS (SSv1 XGD3 / Unrepaired Kreon SS)
|
||||
if(xgdType == 3 && !ssv2)
|
||||
if (xgdType == 3 && !ssv2)
|
||||
return false;
|
||||
|
||||
switch (xgdType)
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace MPF.Processors
|
||||
{
|
||||
// Ensure that required sections exist
|
||||
info = Builder.EnsureAllSections(info);
|
||||
info.CommonDiscInfo!.Comments = string.Empty;
|
||||
|
||||
// Get the dumping program and version
|
||||
info.DumpingInfo!.DumpingProgram ??= string.Empty;
|
||||
@@ -72,13 +73,16 @@ namespace MPF.Processors
|
||||
|
||||
// Get the PVD, if it exists
|
||||
info.Extras!.PVD = GetPVD($"{basePath}.log") ?? "Disc has no PVD";
|
||||
string? sfsvd = GetSFSVD($"{basePath}.log");
|
||||
if (!string.IsNullOrEmpty(sfsvd))
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.HighSierraVolumeDescriptor] = sfsvd!;
|
||||
|
||||
// Get the Datafile information
|
||||
info.TracksAndWriteOffsets!.ClrMameProData = GetDatfile($"{basePath}.log");
|
||||
|
||||
// Get the write offset, if it exists
|
||||
string? writeOffset = GetWriteOffset($"{basePath}.log");
|
||||
info.CommonDiscInfo!.RingWriteOffset = writeOffset;
|
||||
info.CommonDiscInfo.RingWriteOffset = writeOffset;
|
||||
info.TracksAndWriteOffsets.OtherWriteOffsets = writeOffset;
|
||||
|
||||
// Attempt to get multisession data
|
||||
@@ -146,7 +150,7 @@ namespace MPF.Processors
|
||||
|
||||
// Attempt to get the error count
|
||||
long scsiErrors = GetSCSIErrorCount($"{basePath}.log");
|
||||
info.CommonDiscInfo!.ErrorsCount = (scsiErrors == -1 ? "Error retrieving error count" : scsiErrors.ToString());
|
||||
info.CommonDiscInfo.ErrorsCount = (scsiErrors == -1 ? "Error retrieving error count" : scsiErrors.ToString());
|
||||
|
||||
// Bluray-specific options
|
||||
if (mediaType == MediaType.BluRay || mediaType == MediaType.NintendoWiiUOpticalDisc)
|
||||
@@ -192,7 +196,7 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SonyElectronicBook:
|
||||
info.CopyProtection!.SecuROMData = GetSecuROMData($"{basePath}.log", 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}.log", false) ?? string.Empty;
|
||||
@@ -206,7 +210,7 @@ namespace MPF.Processors
|
||||
case RedumpSystem.KonamiPython2:
|
||||
if (GetPlayStationInfo($"{basePath}.log", out string? kp2EXEDate, out string? kp2Serial, out string? kp2Version))
|
||||
{
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = kp2EXEDate;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = kp2EXEDate;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = kp2Serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = kp2Version ?? string.Empty;
|
||||
}
|
||||
@@ -226,7 +230,7 @@ namespace MPF.Processors
|
||||
string xmidString = ProcessingTool.GetXMID($"{basePath}.dmi").Trim('\0');
|
||||
if (!string.IsNullOrEmpty(xmidString))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.XMID] = xmidString;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.XMID] = xmidString;
|
||||
var xmid = SabreTools.Serialization.Wrappers.XMID.Create(xmidString);
|
||||
info.CommonDiscInfo.Serial = xmid?.Serial ?? string.Empty;
|
||||
if (!redumpCompat)
|
||||
@@ -239,7 +243,7 @@ namespace MPF.Processors
|
||||
string xemidString = ProcessingTool.GetXeMID($"{basePath}.dmi").Trim('\0');
|
||||
if (!string.IsNullOrEmpty(xemidString))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.XeMID] = xemidString;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.XeMID] = xemidString;
|
||||
var xemid = SabreTools.Serialization.Wrappers.XeMID.Create(xemidString);
|
||||
info.CommonDiscInfo.Serial = xemid?.Serial ?? string.Empty;
|
||||
if (!redumpCompat)
|
||||
@@ -251,15 +255,15 @@ namespace MPF.Processors
|
||||
|
||||
string? dmiCrc = HashTool.GetFileHash($"{basePath}.dmi", HashType.CRC32);
|
||||
if (dmiCrc != null)
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = dmiCrc.ToUpperInvariant();
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.DMIHash] = dmiCrc.ToUpperInvariant();
|
||||
string? pfiCrc = HashTool.GetFileHash($"{basePath}.pfi", HashType.CRC32);
|
||||
if (pfiCrc != null)
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.PFIHash] = pfiCrc.ToUpperInvariant();
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.PFIHash] = pfiCrc.ToUpperInvariant();
|
||||
if (ProcessingTool.IsValidSS($"{basePath}.ss") && !ProcessingTool.IsValidPartialSS($"{basePath}.ss"))
|
||||
{
|
||||
string? ssCrc = HashTool.GetFileHash($"{basePath}.ss", HashType.CRC32);
|
||||
if (ssCrc != null)
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.SSHash] = ssCrc.ToUpperInvariant();
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.SSHash] = ssCrc.ToUpperInvariant();
|
||||
}
|
||||
|
||||
string? ssRanges = ProcessingTool.GetSSRanges($"{basePath}.ss");
|
||||
@@ -276,7 +280,7 @@ namespace MPF.Processors
|
||||
out string? serial,
|
||||
out _,
|
||||
out string? version) ?? string.Empty;
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = buildDate ?? string.Empty;
|
||||
// TODO: Support region setting from parsed value
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
@@ -285,7 +289,7 @@ namespace MPF.Processors
|
||||
|
||||
case RedumpSystem.SegaMegaCDSegaCD:
|
||||
info.Extras!.Header = GetSegaCDHeader($"{basePath}.log", out var scdBuildDate, out var scdSerial, out _) ?? string.Empty;
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = scdSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = scdSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = scdBuildDate ?? string.Empty;
|
||||
// TODO: Support region setting from parsed value
|
||||
break;
|
||||
@@ -298,7 +302,7 @@ namespace MPF.Processors
|
||||
out string? serial,
|
||||
out _,
|
||||
out string? version) ?? string.Empty;
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = buildDate ?? string.Empty;
|
||||
// TODO: Support region setting from parsed value
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
@@ -313,7 +317,7 @@ namespace MPF.Processors
|
||||
out string? serial,
|
||||
out _,
|
||||
out string? version) ?? string.Empty;
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = buildDate ?? string.Empty;
|
||||
// TODO: Support region setting from parsed value
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
@@ -328,7 +332,7 @@ namespace MPF.Processors
|
||||
out string? serial,
|
||||
out _,
|
||||
out string? version) ?? string.Empty;
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = buildDate ?? string.Empty;
|
||||
// TODO: Support region setting from parsed value
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
@@ -343,7 +347,7 @@ namespace MPF.Processors
|
||||
out string? serial,
|
||||
out _,
|
||||
out string? version) ?? string.Empty;
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = serial ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = buildDate ?? string.Empty;
|
||||
// TODO: Support region setting from parsed value
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
@@ -356,7 +360,7 @@ namespace MPF.Processors
|
||||
out string? saturnSerial,
|
||||
out _,
|
||||
out string? saturnVersion) ?? string.Empty;
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = saturnSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = saturnSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = saturnBuildDate ?? string.Empty;
|
||||
// TODO: Support region setting from parsed value
|
||||
info.VersionAndEditions!.Version = saturnVersion ?? string.Empty;
|
||||
@@ -365,7 +369,7 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SonyPlayStation:
|
||||
if (GetPlayStationInfo($"{basePath}.log", out string? psxEXEDate, out string? psxSerial, out var _))
|
||||
{
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = psxEXEDate;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = psxEXEDate;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = psxSerial ?? string.Empty;
|
||||
}
|
||||
|
||||
@@ -378,21 +382,21 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SonyPlayStation2:
|
||||
if (GetPlayStationInfo($"{basePath}.log", out string? ps2EXEDate, out string? ps2Serial, out var ps2Version))
|
||||
{
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = ps2EXEDate;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = ps2EXEDate;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = ps2Serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = ps2Version ?? string.Empty;
|
||||
}
|
||||
|
||||
string? ps2Protection = GetPlayStation2Protection($"{basePath}.log");
|
||||
if (ps2Protection != null)
|
||||
info.CommonDiscInfo!.Comments = $"<b>Protection</b>: {ps2Protection}" + Environment.NewLine;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.Protection] = ps2Protection;
|
||||
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation3:
|
||||
if (GetPlayStationInfo($"{basePath}.log", out var _, out string? ps3Serial, out var ps3Version))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = ps3Serial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = ps3Serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = ps3Version ?? string.Empty;
|
||||
}
|
||||
|
||||
@@ -401,7 +405,7 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SonyPlayStation4:
|
||||
if (GetPlayStationInfo($"{basePath}.log", out var _, out string? ps4Serial, out var ps4Version))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = ps4Serial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = ps4Serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = ps4Version ?? string.Empty;
|
||||
}
|
||||
|
||||
@@ -410,7 +414,7 @@ namespace MPF.Processors
|
||||
case RedumpSystem.SonyPlayStation5:
|
||||
if (GetPlayStationInfo($"{basePath}.log", out var _, out string? ps5Serial, out var ps5Version))
|
||||
{
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = ps5Serial ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalSerialName] = ps5Serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = ps5Version ?? string.Empty;
|
||||
}
|
||||
|
||||
@@ -441,9 +445,12 @@ namespace MPF.Processors
|
||||
new($"{outputFilename}.atip", OutputFileFlags.Binary
|
||||
| OutputFileFlags.Zippable,
|
||||
"atip"),
|
||||
new($"{outputFilename}.cache", OutputFileFlags.Binary
|
||||
new([$"{outputFilename}.cache", $"{outputFilename}.1.cache"], OutputFileFlags.Binary
|
||||
| OutputFileFlags.Zippable,
|
||||
"cache"),
|
||||
new($"{outputFilename}.2.cache", OutputFileFlags.Binary
|
||||
| OutputFileFlags.Zippable,
|
||||
"cache_2"),
|
||||
new($"{outputFilename}.cdtext", OutputFileFlags.Binary
|
||||
| OutputFileFlags.Zippable,
|
||||
"cdtext"),
|
||||
@@ -527,13 +534,6 @@ namespace MPF.Processors
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
return [
|
||||
// .asus is obsolete: newer redumper produces .cache instead
|
||||
new($"{outputFilename}.asus", OutputFileFlags.Binary
|
||||
| OutputFileFlags.Zippable,
|
||||
"asus"),
|
||||
new($"{outputFilename}.cache", OutputFileFlags.Binary
|
||||
| OutputFileFlags.Zippable,
|
||||
"cache"),
|
||||
new($"{outputFilename}.dmi", OutputFileFlags.Binary
|
||||
| OutputFileFlags.Zippable,
|
||||
"dmi"),
|
||||
@@ -573,6 +573,7 @@ namespace MPF.Processors
|
||||
new($"{outputFilename}.ss", OutputFileFlags.Binary
|
||||
| OutputFileFlags.Zippable,
|
||||
"ss"),
|
||||
// ssv1 and ssv2 extensions are obsolete
|
||||
new($"{outputFilename}.ssv1", OutputFileFlags.Binary
|
||||
| OutputFileFlags.Zippable,
|
||||
"ssv1"),
|
||||
@@ -1204,7 +1205,7 @@ namespace MPF.Processors
|
||||
}
|
||||
|
||||
// Reset C2 errors when a media errors section is found
|
||||
else if (line.StartsWith("media errors:"))
|
||||
else if (line.StartsWith("media errors:") || line.StartsWith("initial dump media errors:"))
|
||||
{
|
||||
c2Errors = 0;
|
||||
}
|
||||
@@ -1800,6 +1801,44 @@ namespace MPF.Processors
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the SFSVD from the input file, if possible
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Newline-delimited SFSVD if possible, null on error</returns>
|
||||
internal static string? GetSFSVD(string log)
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (string.IsNullOrEmpty(log))
|
||||
return null;
|
||||
if (!File.Exists(log))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
// Fast forward to the SFSVD line
|
||||
using var sr = File.OpenText(log);
|
||||
while (!sr.EndOfStream && sr.ReadLine()?.TrimStart()?.StartsWith("SFSVD:") == false) ;
|
||||
if (sr.EndOfStream)
|
||||
return null;
|
||||
|
||||
// Now that we're at the relevant entries, read each line in and concatenate
|
||||
string? sfsvdString = string.Empty, line = sr.ReadLine();
|
||||
while (line?.StartsWith("03") == true)
|
||||
{
|
||||
sfsvdString += line + "\n";
|
||||
line = sr.ReadLine();
|
||||
}
|
||||
|
||||
return sfsvdString.TrimEnd('\n');
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the non-zero data start from the input file, if possible
|
||||
/// </summary>
|
||||
@@ -2254,6 +2293,7 @@ namespace MPF.Processors
|
||||
// redumper v2022.10.28 [Oct 28 2022, 05:41:43] (print usage: --help,-h)
|
||||
// redumper v2022.12.22 build_87 [Dec 22 2022, 01:56:26]
|
||||
// redumper v2025.03.29 build_481
|
||||
// redumper (build: b652)
|
||||
|
||||
try
|
||||
{
|
||||
@@ -2267,10 +2307,7 @@ namespace MPF.Processors
|
||||
nextLine = sr.ReadLine()?.Trim() ?? string.Empty;
|
||||
|
||||
// Generate regex
|
||||
// Permissive
|
||||
var regex = new Regex(@"^redumper (v.+)", RegexOptions.Compiled);
|
||||
// Strict
|
||||
//var regex = new Regex(@"^redumper (v\d{4}\.\d{2}\.\d{2}(| build_\d+)) \[.+\]", RegexOptions.Compiled);
|
||||
var regex = new Regex(@"^redumper (.+)", RegexOptions.Compiled);
|
||||
|
||||
// Extract the version string
|
||||
var match = regex.Match(nextLine);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.Hashing;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
@@ -184,13 +184,13 @@ namespace MPF.Processors
|
||||
break;
|
||||
|
||||
if (line.StartsWith("TITLE") && title == null)
|
||||
title = line.Split(' ')[1];
|
||||
title = line.Substring("TITLE: ".Length);
|
||||
else if (line.StartsWith("DISC_ID") && version == null)
|
||||
serial = line.Split(' ')[1];
|
||||
else if (line.StartsWith("DISC_VERSION") && version == null)
|
||||
version = line.Split(' ')[1];
|
||||
else if (line.StartsWith("pspUmdTypes"))
|
||||
category = ProcessingTool.GetUMDCategory(line.Split(' ')[1]);
|
||||
category = ProcessingTool.GetUMDCategory(line.Split(' ')[2]);
|
||||
else if (line.StartsWith("L0 length"))
|
||||
layer = line.Split(' ')[2];
|
||||
else if (line.StartsWith("FileSize:"))
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SabreTools.Data.Models.Logiqx;
|
||||
using SabreTools.Hashing;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<UseWPF>true</UseWPF>
|
||||
<VersionPrefix>3.3.3</VersionPrefix>
|
||||
<VersionPrefix>3.4.1</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<AssemblyName>MPF</AssemblyName>
|
||||
@@ -70,7 +70,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.8" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.7.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
<Button x:Name="InputPathBrowseButton" Grid.Row="0" Grid.Column="1" Height="22" Width="50" HorizontalAlignment="Right" Content="Browse"
|
||||
IsEnabled="{Binding InputPathBrowseButtonEnabled}" Style="{DynamicResource CustomButtonStyle}"/>
|
||||
|
||||
<Label x:Name="SystemMediaTypeLabel" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Content="System/Media Type" />
|
||||
<Label x:Name="SystemTypeLabel" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Content="System Type" />
|
||||
<ComboBox x:Name="SystemTypeComboBox" Grid.Row="1" Grid.Column="1" Height="22" Width="250" HorizontalAlignment="Left"
|
||||
ItemsSource="{Binding Systems}" SelectedItem="{Binding Path=CurrentSystem, Converter={StaticResource ElementConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
IsEnabled="{Binding SystemTypeComboBoxEnabled}" Style="{DynamicResource CustomComboBoxStyle}">
|
||||
@@ -99,9 +99,6 @@
|
||||
</Style>
|
||||
</ComboBox.ItemContainerStyle>
|
||||
</ComboBox>
|
||||
<ComboBox x:Name="MediaTypeComboBox" Grid.Row="1" Grid.Column="1" Height="22" Width="140" HorizontalAlignment="Right"
|
||||
ItemsSource="{Binding MediaTypes}" SelectedItem="{Binding Path=CurrentMediaType, Converter={StaticResource ElementConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
IsEnabled="{Binding MediaTypeComboBoxEnabled}" Style="{DynamicResource CustomComboBoxStyle}" />
|
||||
|
||||
<Label x:Name="DumpingProgramLabel" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Content="Dumping Program"/>
|
||||
<ComboBox x:Name="DumpingProgramComboBox" Grid.Row="2" Grid.Column="1" Height="22" Width="250" HorizontalAlignment="Left"
|
||||
|
||||
@@ -29,7 +29,6 @@ namespace MPF.UI.Windows
|
||||
private ComboBox? DumpingProgramComboBox => ItemHelper.FindChild<ComboBox>(this, "DumpingProgramComboBox");
|
||||
private Button? InputPathBrowseButton => ItemHelper.FindChild<Button>(this, "InputPathBrowseButton");
|
||||
private TextBox? InputPathTextBox => ItemHelper.FindChild<TextBox>(this, "InputPathTextBox");
|
||||
private ComboBox? MediaTypeComboBox => ItemHelper.FindChild<ComboBox>(this, "MediaTypeComboBox");
|
||||
private ComboBox? SystemTypeComboBox => ItemHelper.FindChild<ComboBox>(this, "SystemTypeComboBox");
|
||||
|
||||
#endregion
|
||||
@@ -89,7 +88,6 @@ namespace MPF.UI.Windows
|
||||
|
||||
// User Area SelectionChanged
|
||||
SystemTypeComboBox!.SelectionChanged += SystemTypeComboBoxSelectionChanged;
|
||||
MediaTypeComboBox!.SelectionChanged += MediaTypeComboBoxSelectionChanged;
|
||||
DumpingProgramComboBox!.SelectionChanged += DumpingProgramComboBoxSelectionChanged;
|
||||
|
||||
// User Area TextChanged
|
||||
@@ -160,8 +158,8 @@ namespace MPF.UI.Windows
|
||||
/// </summary>
|
||||
private async void OnCheckDumpClick(object sender, EventArgs e)
|
||||
{
|
||||
string? errorMessage = await CheckDumpViewModel.CheckDump(ShowMediaInformationWindow);
|
||||
if (string.IsNullOrEmpty(errorMessage))
|
||||
var result = await CheckDumpViewModel.CheckDump(ShowMediaInformationWindow);
|
||||
if (result)
|
||||
{
|
||||
bool? checkAgain = DisplayUserMessage("Check Complete", "The dump has been processed successfully! Would you like to check another dump?", 2, false);
|
||||
if (checkAgain == false)
|
||||
@@ -171,7 +169,8 @@ namespace MPF.UI.Windows
|
||||
}
|
||||
else
|
||||
{
|
||||
DisplayUserMessage("Check Failed", errorMessage!, 1, false);
|
||||
string? message = result.Message ?? "Please check all files exist and try again!";
|
||||
DisplayUserMessage("Check Failed", message, 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,15 +210,6 @@ namespace MPF.UI.Windows
|
||||
CheckDumpViewModel.ChangeInputPath();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MediaTypeComboBox SelectionChanged event
|
||||
/// </summary>
|
||||
public void MediaTypeComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (CheckDumpViewModel.CanExecuteSelectionChanged)
|
||||
CheckDumpViewModel.ChangeMediaType();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for SystemTypeComboBox SelectionChanged event
|
||||
/// </summary>
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label x:Name="SystemMediaTypeLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Content="System/Media Type" />
|
||||
<Label x:Name="SystemMediaTypeLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Content="System" />
|
||||
<ComboBox x:Name="SystemTypeComboBox" Grid.Row="0" Grid.Column="1" Height="22" Width="250" HorizontalAlignment="Left"
|
||||
ItemsSource="{Binding Systems}" SelectedItem="{Binding Path=CurrentSystem, Converter={StaticResource ElementConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
IsEnabled="{Binding SystemTypeComboBoxEnabled}" Style="{DynamicResource CustomComboBoxStyle}">
|
||||
@@ -150,7 +150,8 @@
|
||||
</ComboBox>
|
||||
<ComboBox x:Name="MediaTypeComboBox" Grid.Row="0" Grid.Column="1" Height="22" Width="140" HorizontalAlignment="Right"
|
||||
ItemsSource="{Binding MediaTypes}" SelectedItem="{Binding Path=CurrentMediaType, Converter={StaticResource ElementConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
IsEnabled="{Binding MediaTypeComboBoxEnabled}" Style="{DynamicResource CustomComboBoxStyle}" />
|
||||
IsEnabled="{Binding MediaTypeComboBoxEnabled}" Style="{DynamicResource CustomComboBoxStyle}"
|
||||
Visibility="Hidden" />
|
||||
|
||||
<Label x:Name="OutputPathLabel" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Content="Output Path"/>
|
||||
<TextBox x:Name="OutputPathTextBox" Grid.Row="1" Grid.Column="1" Height="22" Width="345" HorizontalAlignment="Left" VerticalContentAlignment="Center"
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace MPF.UI.Windows
|
||||
private ComboBox? MediaTypeComboBox => ItemHelper.FindChild<ComboBox>(this, "MediaTypeComboBox");
|
||||
private Button? OutputPathBrowseButton => ItemHelper.FindChild<Button>(this, "OutputPathBrowseButton");
|
||||
private TextBox? OutputPathTextBox => ItemHelper.FindChild<TextBox>(this, "OutputPathTextBox");
|
||||
private Label? SystemMediaTypeLabel => ItemHelper.FindChild<Label>(this, "SystemMediaTypeLabel");
|
||||
private ComboBox? SystemTypeComboBox => ItemHelper.FindChild<ComboBox>(this, "SystemTypeComboBox");
|
||||
|
||||
#endregion
|
||||
@@ -113,6 +114,9 @@ namespace MPF.UI.Windows
|
||||
// Set the UI color scheme according to the options
|
||||
ApplyTheme();
|
||||
|
||||
// Hide or show the media type box based on program
|
||||
SetMediaTypeVisibility();
|
||||
|
||||
// Check for updates, if necessary
|
||||
if (MainViewModel.Options.CheckForUpdatesOnStartup)
|
||||
CheckForUpdates(showIfSame: false);
|
||||
@@ -205,8 +209,14 @@ namespace MPF.UI.Windows
|
||||
MainViewModel.CheckForUpdates(out bool different, out string message, out var url);
|
||||
|
||||
// If we have a new version, put it in the clipboard
|
||||
if (different && !string.IsNullOrEmpty(url))
|
||||
Clipboard.SetText(url);
|
||||
if (MainViewModel.Options.CopyUpdateUrlToClipboard && different && !string.IsNullOrEmpty(url))
|
||||
{
|
||||
try
|
||||
{
|
||||
Clipboard.SetText(url);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
if (showIfSame || different)
|
||||
CustomMessageBox.Show(this, message, "Version Update Check", MessageBoxButton.OK, different ? MessageBoxImage.Exclamation : MessageBoxImage.Information);
|
||||
@@ -337,6 +347,37 @@ namespace MPF.UI.Windows
|
||||
optionsWindow.Show();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set media type combo box visibility based on current program
|
||||
/// </summary>
|
||||
public void SetMediaTypeVisibility()
|
||||
{
|
||||
// Only DiscImageCreator uses the media type box
|
||||
if (MainViewModel.CurrentProgram != InternalProgram.DiscImageCreator)
|
||||
{
|
||||
SystemMediaTypeLabel!.Content = "System";
|
||||
MediaTypeComboBox!.Visibility = Visibility.Hidden;
|
||||
return;
|
||||
}
|
||||
|
||||
// If there are no media types defined
|
||||
if (MainViewModel.MediaTypes == null)
|
||||
{
|
||||
SystemMediaTypeLabel!.Content = "System";
|
||||
MediaTypeComboBox!.Visibility = Visibility.Hidden;
|
||||
return;
|
||||
}
|
||||
|
||||
// Only systems with more than one media type should show the box
|
||||
bool visible = MainViewModel.MediaTypes.Count > 1;
|
||||
SystemMediaTypeLabel!.Content = visible
|
||||
? "System/Media Type"
|
||||
: "System";
|
||||
MediaTypeComboBox!.Visibility = visible
|
||||
? Visibility.Visible
|
||||
: Visibility.Hidden;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the UI color scheme according to the options
|
||||
/// </summary>
|
||||
@@ -431,6 +472,9 @@ namespace MPF.UI.Windows
|
||||
|
||||
// Set the UI color scheme according to the options
|
||||
ApplyTheme();
|
||||
|
||||
// Hide or show the media type box based on program
|
||||
SetMediaTypeVisibility();
|
||||
}
|
||||
|
||||
#region Menu Bar
|
||||
@@ -524,7 +568,10 @@ namespace MPF.UI.Windows
|
||||
public void DumpingProgramComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (MainViewModel.CanExecuteSelectionChanged)
|
||||
{
|
||||
MainViewModel.ChangeDumpingProgram();
|
||||
SetMediaTypeVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -581,7 +628,10 @@ namespace MPF.UI.Windows
|
||||
public void SystemTypeComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (MainViewModel.CanExecuteSelectionChanged)
|
||||
{
|
||||
MainViewModel.ChangeSystem();
|
||||
SetMediaTypeVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -240,6 +240,8 @@
|
||||
Text="{Binding Path=SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[(redump:SiteCode)FoxInteractiveID], Mode=TwoWay}"/>
|
||||
<controls:UserInput x:Name="GTInteractiveIDTextBox" Label="GT Interactive ID"
|
||||
Text="{Binding Path=SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[(redump:SiteCode)GTInteractiveID], Mode=TwoWay}"/>
|
||||
<controls:UserInput x:Name="InterplayIDTextBox" Label="Interplay ID"
|
||||
Text="{Binding Path=SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[(redump:SiteCode)InterplayID], Mode=TwoWay}"/>
|
||||
<controls:UserInput x:Name="JASRACIDTextBox" Label="JASRAC ID"
|
||||
Text="{Binding Path=SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[(redump:SiteCode)JASRACID], Mode=TwoWay}"/>
|
||||
<controls:UserInput x:Name="KingRecordsIDTextBox" Label="King Records ID"
|
||||
|
||||
@@ -332,8 +332,6 @@ namespace MPF.UI.Windows
|
||||
case DiscType.NintendoWiiOpticalDiscSL:
|
||||
case DiscType.NintendoWiiOpticalDiscDL:
|
||||
case DiscType.NintendoWiiUOpticalDiscSL:
|
||||
case DiscType.UMDSL:
|
||||
case DiscType.UMDDL:
|
||||
// Quad-layer discs
|
||||
if (submissionInfo?.SizeAndChecksums?.Layerbreak3 != default(long))
|
||||
{
|
||||
@@ -428,6 +426,23 @@ namespace MPF.UI.Windows
|
||||
|
||||
break;
|
||||
|
||||
case DiscType.UMDSL:
|
||||
case DiscType.UMDDL:
|
||||
L0Info!.Header = reverseOrder ? "Layer 0 (Outer)" : "Layer 0 (Inner)";
|
||||
L0MasteringRing!.Label = "Mastering Ring";
|
||||
L0MasteringSID!.Label = "Mastering SID";
|
||||
L0Toolstamp!.Label = "Toolstamp/Mastering Code";
|
||||
L0MouldSID!.Label = "Data Side Mould SID";
|
||||
L0AdditionalMould!.Label = "Data Side Additional Mould";
|
||||
|
||||
L1Info!.Header = reverseOrder ? "Layer 1 (Inner)" : "Layer 1 (Outer)";
|
||||
L1MasteringRing!.Label = "Mastering Ring";
|
||||
L1MasteringSID!.Label = "Mastering SID";
|
||||
L1Toolstamp!.Label = "Toolstamp/Mastering Code";
|
||||
L1MouldSID!.Label = "Label Side Mould SID";
|
||||
L1AdditionalMould!.Label = "Label Side Additional Mould";
|
||||
break;
|
||||
|
||||
// All other media we assume to have no rings
|
||||
default:
|
||||
L0Info!.Visibility = Visibility.Collapsed;
|
||||
|
||||
@@ -82,6 +82,11 @@
|
||||
ToolTip="Check for updates when the application starts" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Copy Update URL to Clipboard"
|
||||
IsChecked="{Binding Options.CopyUpdateUrlToClipboard}"
|
||||
ToolTip="If an update is found, try to copy the update URL to the clipboard" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Fast Update Label"
|
||||
IsChecked="{Binding Options.FastUpdateLabel}"
|
||||
ToolTip="Bypasses disc checks to quickly update the output path. Use with caution!" Margin="0,4"
|
||||
@@ -90,22 +95,16 @@
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Detection">
|
||||
<UniformGrid Columns="2" Rows="3">
|
||||
<CheckBox x:Name="SkipMediaTypeDetectionCheckBox" VerticalAlignment="Center" Content="Skip Type Detect"
|
||||
IsChecked="{Binding Options.SkipMediaTypeDetection}"
|
||||
ToolTip="Disable trying to guess media type inserted (may improve performance at startup)" Margin="0,4"
|
||||
/>
|
||||
|
||||
<UniformGrid Columns="2" Rows="2">
|
||||
<CheckBox VerticalAlignment="Center" Content="Skip System Detect"
|
||||
IsChecked="{Binding Options.SkipSystemDetection}"
|
||||
ToolTip="Disable trying to guess system (may improve performance at startup)" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="No Fixed Drives"
|
||||
IsChecked="{Binding Options.IgnoreFixedDrives}"
|
||||
ToolTip="Ignore hard drives and other fixed drives" Margin="0,4"
|
||||
IsChecked="{Binding Options.IgnoreFixedDrives}"
|
||||
ToolTip="Ignore hard drives and other fixed drives" Margin="0,4"
|
||||
/>
|
||||
<Label/> <!-- Empty label for padding -->
|
||||
|
||||
<Label VerticalAlignment="Center" Content="Default System:" HorizontalAlignment="Right" />
|
||||
<ComboBox x:Name="DefaultSystemComboBox" Height="22" Width="200" HorizontalAlignment="Left"
|
||||
@@ -403,12 +402,16 @@
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Redumper">
|
||||
<UniformGrid Columns="2" Rows="7">
|
||||
<UniformGrid Columns="2" Rows="8">
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Verbose Output"
|
||||
IsChecked="{Binding Options.RedumperEnableVerbose}"
|
||||
ToolTip="Enable verbose output in logs" Margin="0,4"
|
||||
/>
|
||||
<Label/> <!-- Empty label for padding -->
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Refine Sector Mode Flag"
|
||||
IsChecked="{Binding Options.RedumperRefineSectorMode}"
|
||||
ToolTip="Enable the refine sector mode flag by default" Margin="0,4"
|
||||
/>
|
||||
|
||||
<Label Content="Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center" Width="200" HorizontalAlignment="Left"
|
||||
@@ -472,7 +475,8 @@
|
||||
IsEnabled="{Binding Options.RetrieveMatchInformation}" />
|
||||
|
||||
<Label VerticalAlignment="Center" HorizontalAlignment="Right" Content="Password" />
|
||||
<PasswordBox x:Name="RedumpPasswordBox" Height="22" HorizontalAlignment="Stretch" PasswordChar="*" />
|
||||
<PasswordBox x:Name="RedumpPasswordBox" Height="22" HorizontalAlignment="Stretch" PasswordChar="*"
|
||||
IsEnabled="{Binding Options.RetrieveMatchInformation}"/>
|
||||
|
||||
<Button x:Name="RedumpLoginTestButton" Height="22" Width="80" Content="Test Login"
|
||||
Style="{DynamicResource CustomButtonStyle}"
|
||||
|
||||
@@ -81,31 +81,31 @@ function download_programs() {
|
||||
declare -A DL_MAP
|
||||
|
||||
# Aaru
|
||||
DL_MAP["Aaru_linux-arm64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_linux_arm64.tar.gz"
|
||||
DL_MAP["Aaru_linux-x64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_linux_amd64.tar.gz"
|
||||
DL_MAP["Aaru_osx-arm64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_macos.zip"
|
||||
DL_MAP["Aaru_osx-x64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_macos.zip"
|
||||
DL_MAP["Aaru_win-arm64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_windows_aarch64.zip"
|
||||
DL_MAP["Aaru_win-x86"]="https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_windows_x86.zip"
|
||||
DL_MAP["Aaru_win-x64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_windows_x64.zip"
|
||||
DL_MAP["Aaru_linux-arm64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_linux_arm64.tar.gz"
|
||||
DL_MAP["Aaru_linux-x64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_linux_amd64.tar.gz"
|
||||
DL_MAP["Aaru_osx-arm64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_macos-aarch64.zip"
|
||||
DL_MAP["Aaru_osx-x64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_macos.zip"
|
||||
DL_MAP["Aaru_win-arm64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_windows_aarch64.zip"
|
||||
DL_MAP["Aaru_win-x86"]="https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_windows_x64.zip"
|
||||
DL_MAP["Aaru_win-x64"]="https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_windows_x64.zip"
|
||||
|
||||
# DiscImageCreator
|
||||
DL_MAP["Creator_linux-arm64"]=""
|
||||
DL_MAP["Creator_linux-x64"]="https://github.com/user-attachments/files/20000183/DiscImageCreator_20250501.tar.gz"
|
||||
DL_MAP["Creator_linux-x64"]="https://github.com/user-attachments/files/22080484/DiscImageCreator_20250901.tar.gz"
|
||||
DL_MAP["Creator_osx-arm64"]="https://github.com/user-attachments/files/20000184/DiscImageCreator_20250501.zip"
|
||||
DL_MAP["Creator_osx-x64"]="https://github.com/user-attachments/files/20000184/DiscImageCreator_20250501.zip"
|
||||
DL_MAP["Creator_win-arm64"]=""
|
||||
DL_MAP["Creator_win-x86"]="https://github.com/user-attachments/files/20000181/DiscImageCreator_20250501.zip"
|
||||
DL_MAP["Creator_win-x64"]="https://github.com/user-attachments/files/20000181/DiscImageCreator_20250501.zip"
|
||||
DL_MAP["Creator_win-x86"]="https://github.com/user-attachments/files/22080480/DiscImageCreator_20250901.zip"
|
||||
DL_MAP["Creator_win-x64"]="https://github.com/user-attachments/files/22080480/DiscImageCreator_20250901.zip"
|
||||
|
||||
# Redumper
|
||||
DL_MAP["Redumper_linux-arm64"]=""
|
||||
DL_MAP["Redumper_linux-x64"]="https://github.com/superg/redumper/releases/download/build_631/redumper-2025.07.14_build631-Linux64.zip"
|
||||
DL_MAP["Redumper_osx-arm64"]="https://github.com/superg/redumper/releases/download/build_631/redumper-2025.07.14_build631-Darwin64.zip"
|
||||
DL_MAP["Redumper_osx-x64"]="https://github.com/superg/redumper/releases/download/build_631/redumper-2025.07.14_build631-Darwin64.zip"
|
||||
DL_MAP["Redumper_win-arm64"]=""
|
||||
DL_MAP["Redumper_win-x86"]="https://github.com/superg/redumper/releases/download/build_631/redumper-2025.07.14_build631-Windows32.zip"
|
||||
DL_MAP["Redumper_win-x64"]="https://github.com/superg/redumper/releases/download/build_631/redumper-2025.07.14_build631-Windows64.zip"
|
||||
DL_MAP["Redumper_linux-arm64"]="https://github.com/superg/redumper/releases/download/b655/redumper-b655-linux-arm64.zip"
|
||||
DL_MAP["Redumper_linux-x64"]="https://github.com/superg/redumper/releases/download/b655/redumper-b655-linux-x64.zip"
|
||||
DL_MAP["Redumper_osx-arm64"]="https://github.com/superg/redumper/releases/download/b655/redumper-b655-macos-arm64.zip"
|
||||
DL_MAP["Redumper_osx-x64"]=""
|
||||
DL_MAP["Redumper_win-arm64"]="https://github.com/superg/redumper/releases/download/b655/redumper-b655-windows-arm64.zip"
|
||||
DL_MAP["Redumper_win-x86"]="https://github.com/superg/redumper/releases/download/b655/redumper-b655-windows-x86.zip"
|
||||
DL_MAP["Redumper_win-x64"]="https://github.com/superg/redumper/releases/download/b655/redumper-b655-windows-x64.zip"
|
||||
|
||||
# Download and extract files
|
||||
echo "===== Downloading Required Programs ====="
|
||||
|
||||
@@ -70,31 +70,31 @@ function Download-Programs {
|
||||
$DL_PREFIXES = ("Aaru", "Creator", "Redumper")
|
||||
$DL_MAP = @{
|
||||
# Aaru
|
||||
"Aaru_linux-arm64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_linux_arm64.tar.gz"
|
||||
"Aaru_linux-x64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_linux_amd64.tar.gz"
|
||||
"Aaru_osx-arm64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_macos.zip"
|
||||
"Aaru_osx-x64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_macos.zip"
|
||||
"Aaru_win-arm64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_windows_aarch64.zip"
|
||||
"Aaru_win-x86" = "https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_windows_x86.zip"
|
||||
"Aaru_win-x64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_windows_x64.zip"
|
||||
"Aaru_linux-arm64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_linux_arm64.tar.gz"
|
||||
"Aaru_linux-x64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_linux_amd64.tar.gz"
|
||||
"Aaru_osx-arm64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_macos-aarch64.zip"
|
||||
"Aaru_osx-x64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_macos.zip"
|
||||
"Aaru_win-arm64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_windows_aarch64.zip"
|
||||
"Aaru_win-x86" = "https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_windows_x64.zip"
|
||||
"Aaru_win-x64" = "https://github.com/aaru-dps/Aaru/releases/download/v5.4.1/aaru-5.4.1_windows_x64.zip"
|
||||
|
||||
# DiscImageCreator
|
||||
"Creator_linux-arm64" = ""
|
||||
"Creator_linux-x64" = "https://github.com/user-attachments/files/20000183/DiscImageCreator_20250501.tar.gz"
|
||||
"Creator_linux-x64" = "https://github.com/user-attachments/files/22080484/DiscImageCreator_20250901.tar.gz"
|
||||
"Creator_osx-arm64" = "https://github.com/user-attachments/files/20000184/DiscImageCreator_20250501.zip"
|
||||
"Creator_osx-x64" = "https://github.com/user-attachments/files/20000184/DiscImageCreator_20250501.zip"
|
||||
"Creator_win-arm64" = ""
|
||||
"Creator_win-x86" = "https://github.com/user-attachments/files/20000181/DiscImageCreator_20250501.zip"
|
||||
"Creator_win-x64" = "https://github.com/user-attachments/files/20000181/DiscImageCreator_20250501.zip"
|
||||
"Creator_win-x86" = "https://github.com/user-attachments/files/22080480/DiscImageCreator_20250901.zip"
|
||||
"Creator_win-x64" = "https://github.com/user-attachments/files/22080480/DiscImageCreator_20250901.zip"
|
||||
|
||||
# Redumper
|
||||
"Redumper_linux-arm64" = ""
|
||||
"Redumper_linux-x64" = "https://github.com/superg/redumper/releases/download/build_631/redumper-2025.07.14_build631-Linux64.zip"
|
||||
"Redumper_osx-arm64" = "https://github.com/superg/redumper/releases/download/build_631/redumper-2025.07.14_build631-Darwin64.zip"
|
||||
"Redumper_osx-x64" = "https://github.com/superg/redumper/releases/download/build_631/redumper-2025.07.14_build631-Darwin64.zip"
|
||||
"Redumper_win-arm64" = ""
|
||||
"Redumper_win-x86" = "https://github.com/superg/redumper/releases/download/build_631/redumper-2025.07.14_build631-Windows32.zip"
|
||||
"Redumper_win-x64" = "https://github.com/superg/redumper/releases/download/build_631/redumper-2025.07.14_build631-Windows64.zip"
|
||||
"Redumper_linux-arm64" = "https://github.com/superg/redumper/releases/download/b655/redumper-b655-linux-arm64.zip"
|
||||
"Redumper_linux-x64" = "https://github.com/superg/redumper/releases/download/b655/redumper-b655-linux-x64.zip"
|
||||
"Redumper_osx-arm64" = "https://github.com/superg/redumper/releases/download/b655/redumper-b655-macos-arm64.zip"
|
||||
"Redumper_osx-x64" = ""
|
||||
"Redumper_win-arm64" = "https://github.com/superg/redumper/releases/download/b655/redumper-b655-windows-arm64.zip"
|
||||
"Redumper_win-x86" = "https://github.com/superg/redumper/releases/download/b655/redumper-b655-windows-x86.zip"
|
||||
"Redumper_win-x64" = "https://github.com/superg/redumper/releases/download/b655/redumper-b655-windows-x64.zip"
|
||||
}
|
||||
|
||||
# Download and extract files
|
||||
|
||||
Reference in New Issue
Block a user