mirror of
https://github.com/SabreTools/MPF.git
synced 2026-02-04 21:30:11 +00:00
Compare commits
116 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
229db5dda2 | ||
|
|
4f2a8d354a | ||
|
|
b886471d72 | ||
|
|
2bab266ae2 | ||
|
|
6c5fd9bac8 | ||
|
|
08e93d7f13 | ||
|
|
7a510e084b | ||
|
|
da46d20ffc | ||
|
|
234c0bfbab | ||
|
|
82d60dbf4a | ||
|
|
6dffb80609 | ||
|
|
267c0e3184 | ||
|
|
033ccbbe67 | ||
|
|
c31b3f5894 | ||
|
|
9b1a303fea | ||
|
|
80a0f6da35 | ||
|
|
0c30eb7a60 | ||
|
|
7a8125bb71 | ||
|
|
c4beffd845 | ||
|
|
f97c112a53 | ||
|
|
5ef43ab6be | ||
|
|
2c399f99bf | ||
|
|
42e9eb0b96 | ||
|
|
e67d65f908 | ||
|
|
4ec8954b14 | ||
|
|
1a6abb039c | ||
|
|
bb5d1e5ac8 | ||
|
|
03c4c475eb | ||
|
|
04d7817d28 | ||
|
|
7cd100bc53 | ||
|
|
019924232a | ||
|
|
b5fc9f0275 | ||
|
|
44509b72ed | ||
|
|
d532a63dbd | ||
|
|
227785b079 | ||
|
|
0e364be998 | ||
|
|
7ae1f64ee3 | ||
|
|
92463a103d | ||
|
|
101cdb7b34 | ||
|
|
e924299f85 | ||
|
|
b983f7eb4a | ||
|
|
33b4be8b24 | ||
|
|
71a4edc8ba | ||
|
|
ceb305eb54 | ||
|
|
0b0d13dcf3 | ||
|
|
9f02368622 | ||
|
|
152010ee14 | ||
|
|
c6d5f0aea5 | ||
|
|
8c2ad64bb8 | ||
|
|
fa54d694b6 | ||
|
|
dc35b08624 | ||
|
|
4429515ba2 | ||
|
|
fdbc7b34e5 | ||
|
|
a1ab442cf0 | ||
|
|
9ed5c297f6 | ||
|
|
4ce9b214b0 | ||
|
|
7dcdadda75 | ||
|
|
f87a4d9fe2 | ||
|
|
e4e5d173f0 | ||
|
|
115b242d59 | ||
|
|
706bf8a431 | ||
|
|
87ecf1aa99 | ||
|
|
b5cf274333 | ||
|
|
4f4b6879b6 | ||
|
|
3b19463913 | ||
|
|
37386cd182 | ||
|
|
e04bdad16c | ||
|
|
e37f12705d | ||
|
|
5c8dc2c23a | ||
|
|
e9121f3b03 | ||
|
|
d68175db4e | ||
|
|
9d8181b0e2 | ||
|
|
6d657f268a | ||
|
|
3b3c5f823d | ||
|
|
09fc313492 | ||
|
|
316d0f6e54 | ||
|
|
a0033238bd | ||
|
|
5b1c6a7f46 | ||
|
|
8c0dff6552 | ||
|
|
43b230c84a | ||
|
|
f1b657011d | ||
|
|
e4d8ac8e1c | ||
|
|
08f44173dd | ||
|
|
54765c71fd | ||
|
|
01f8b49214 | ||
|
|
e8b0b3efaa | ||
|
|
f637938858 | ||
|
|
ae326c1d2f | ||
|
|
a4a1e6bf0a | ||
|
|
ecee44966e | ||
|
|
83437977ba | ||
|
|
8fcac1d425 | ||
|
|
705b5f1049 | ||
|
|
367d0c104b | ||
|
|
5d4bed2d9e | ||
|
|
63756192d8 | ||
|
|
b68ec78184 | ||
|
|
c55d5183fb | ||
|
|
f82e925944 | ||
|
|
c19f9ea173 | ||
|
|
76b2dd79ab | ||
|
|
c96ff23ad1 | ||
|
|
cd68b55b93 | ||
|
|
cad14d96f7 | ||
|
|
daaf9f1932 | ||
|
|
cb7502b450 | ||
|
|
ece142bbf1 | ||
|
|
611fee4605 | ||
|
|
791e2d0272 | ||
|
|
81742a4676 | ||
|
|
1ff3f2210c | ||
|
|
be9e4b91d5 | ||
|
|
854dcc5f95 | ||
|
|
29b71db33a | ||
|
|
2ee64b222a | ||
|
|
afda54f97b |
1
.github/ISSUE_TEMPLATE/feature-request.md
vendored
1
.github/ISSUE_TEMPLATE/feature-request.md
vendored
@@ -10,7 +10,6 @@ assignees: mnadareski
|
||||
**Before You Submit**
|
||||
- Remember to try the [latest WIP build](https://ci.appveyor.com/project/mnadareski/mpf/build/artifacts) to see if the feature already exists.
|
||||
- Is it copy protection related? If so, report the issue [here](https://github.com/mnadareski/BurnOutSharp/issues) instead.
|
||||
- .NET 6.0 has known limitations, so make sure that what you're asking for isn't already in another build.
|
||||
- Check [previous issues](https://github.com/SabreTools/MPF/issues) to see if any of those are related to what you're about to ask for.
|
||||
|
||||
If none of those apply, then continue...
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/informational.md
vendored
1
.github/ISSUE_TEMPLATE/informational.md
vendored
@@ -10,7 +10,6 @@ assignees: mnadareski
|
||||
**Before You Submit**
|
||||
- Remember to try the [latest WIP build](https://ci.appveyor.com/project/mnadareski/mpf/build/artifacts) to see if the feature already exists.
|
||||
- Is it copy protection related? If so, report the issue [here](https://github.com/mnadareski/BurnOutSharp/issues) instead.
|
||||
- .NET 6.0 has known limitations, so make sure that what you're giving information on isn't already in another build.
|
||||
- Check [previous issues](https://github.com/SabreTools/MPF/issues) to see if any of those are related to what you're about to ask for.
|
||||
|
||||
If none of those apply, then continue...
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/issue-report.md
vendored
2
.github/ISSUE_TEMPLATE/issue-report.md
vendored
@@ -10,7 +10,6 @@ assignees: mnadareski
|
||||
**Before You Submit**
|
||||
- Remember to try the [latest WIP build](https://ci.appveyor.com/project/mnadareski/mpf/build/artifacts) to see if the issue has already been addressed.
|
||||
- Is it copy protection related? If so, report the issue [here](https://github.com/mnadareski/BurnOutSharp/issues) instead.
|
||||
- .NET 6.0 has known issues, please try using another build to reproduce the error
|
||||
- Check multiple discs to help narrow down the issue
|
||||
- Check the Options to see if changing any of those affects your issue.
|
||||
|
||||
@@ -27,6 +26,7 @@ What runtime version are you using?
|
||||
|
||||
- [ ] .NET Framework 4.8 running on (Operating System)
|
||||
- [ ] .NET 6.0 running on (Operating System)
|
||||
- [ ] .NET 7.0 running on (Operating System)
|
||||
|
||||
**Describe the issue**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
111
CHANGELIST.md
111
CHANGELIST.md
@@ -1,3 +1,114 @@
|
||||
### 2.7.5 (2023-11-06)
|
||||
|
||||
- Remove psxt001z Pkg Ref in MPF.Test (Deterous)
|
||||
- Update Redumper to build 247
|
||||
- Focus main window after child window closes (Deterous)
|
||||
- Try to get PS3 data from SFB
|
||||
- Fix PS3 version finding
|
||||
- Pull PS3 Firmware Version (Deterous)
|
||||
- Fix default layerbreak output
|
||||
- Enable browsing for Redumper path (Deterous)
|
||||
- Update to MMI 3.0.0 (Deterous)
|
||||
|
||||
### 2.7.4 (2023-10-31)
|
||||
|
||||
- Move Hash enum and simplify
|
||||
- Add other non-cryptographic hashes
|
||||
- Avoid unncessary allocation in hashing
|
||||
- Make Hasher more consistent
|
||||
- Move all hashing to Hasher
|
||||
- Separate out static hashing
|
||||
- Remove unncessary summary
|
||||
- Version-gate new switch statement
|
||||
- Ignore empty protection results
|
||||
- Remove and Sort Usings
|
||||
- Update Redumper to build 244
|
||||
- Enable Bluray dumping with Redumper
|
||||
- Add Bluray layerbreak support for Redumper
|
||||
- Remove now-obsolete notes
|
||||
- Compile most regex statements
|
||||
- Handle a couple of messages
|
||||
- Remove .manufacturer for Bluray
|
||||
- Fix typo that disables DIC during media check (Deterous)
|
||||
- Fix build
|
||||
- Remove duplicate check
|
||||
- Add PIC output for Redumper
|
||||
- Update Redumper to build 246
|
||||
- Enable HD-DVD for Redumper in UI
|
||||
- Attempt to fix window owner issue
|
||||
|
||||
### 2.7.3 (2023-10-26)
|
||||
|
||||
- Split InfoTool into 2 classes
|
||||
- Add path variants for PlayStation info
|
||||
- Convert Drive to use paths internally
|
||||
- Create skeleton for first-run
|
||||
- Show options window on first run
|
||||
- Fix drive letter issue in UI
|
||||
- Add first-run Options title, fix saving bug
|
||||
- Fix multiple handler invocation
|
||||
- Create method for applying theme
|
||||
- Fix drive letter check
|
||||
- Simply theme application
|
||||
- Add framework for deleteable files
|
||||
- Add deleteable file lists for Redumper and DIC
|
||||
- Add optional file deletion
|
||||
- Rearrange OptionsWindow to be easier to navigate
|
||||
- Fix up DumpEnvironment a bit
|
||||
- Add filename suffix setting (nw)
|
||||
- Wire through filename suffix
|
||||
- Expose suffix setting
|
||||
- Set UDF CD threshold at 800MB (Deterous)
|
||||
- Update package versions
|
||||
- Attempt to parse out PS5 params.json
|
||||
- Fix CRC32 hashing
|
||||
- Update XUnit packages
|
||||
- Update to BurnOutSharp 2.9.0
|
||||
- Update to MMI 3.0.0-preview.4
|
||||
- Fix two small nullability issues
|
||||
- Use Array.Empty in hasher
|
||||
- Always use relative path internally (Deterous)
|
||||
|
||||
### 2.7.2 (2023-10-17)
|
||||
|
||||
- Fix options loading for Check
|
||||
- Cleanup and gated code
|
||||
- Gate some switch expressions
|
||||
- Suppress some unnecessary messages
|
||||
- Disable dumping button when Redumper selected with unsupported media type (Deterous)
|
||||
- Improve check for which program supports which media (Deterous)
|
||||
- Remove code for getting Universal Hash from DIC logs (Deterous)
|
||||
- Fix Redumper retry count not showing
|
||||
- Enable parameters checkbox by default
|
||||
- Update Redumper to build 230
|
||||
- Fix GetPVD in dic (fuzz6001)
|
||||
- Get SecuROM data from Redumper
|
||||
- Clean up issue templates
|
||||
- Support Redumper 231 outputs
|
||||
|
||||
### 2.7.1 (2023-10-11)
|
||||
|
||||
- Add pull-all flag for Check
|
||||
- Fix errant version detection issue
|
||||
- Allow user-supplied information in Check
|
||||
- Add BE read flag for Redumper
|
||||
- Add generic drive flag for Redumper
|
||||
- Handle numeric disc titles as issue numbers
|
||||
- Unify handling of enable/disable events
|
||||
- Enable nullability in Check
|
||||
- Remove all but .NET 6 for AppVeyor packaging
|
||||
- Place message boxes at center of main window (Deterous)
|
||||
- Enable nullability in MPF
|
||||
- Enable nullability in MPF.UI.Core
|
||||
- Enable nullability in MPF.Test
|
||||
- Handle some suggested changes
|
||||
- Var-ify many instances
|
||||
- Version-gate some newer syntax
|
||||
- Fix Check always showing Help text
|
||||
- Version-gate some more newer syntax
|
||||
- Enable path browse button by default
|
||||
- Remove unnecessary namespacing
|
||||
|
||||
### 2.7.0 (2023-10-11)
|
||||
|
||||
- Attempt to replace NRT
|
||||
|
||||
@@ -8,7 +8,11 @@
|
||||
<Description>Validator for various dumping programs</Description>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2023</Copyright>
|
||||
<VersionPrefix>2.7.0</VersionPrefix>
|
||||
<VersionPrefix>2.7.5</VersionPrefix>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -20,7 +24,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.8.0" GeneratePathProperty="true">
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.9.0" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.1.1" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp;
|
||||
using BinaryObjectScanner;
|
||||
using MPF.Core;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Utilities;
|
||||
@@ -14,14 +14,16 @@ namespace MPF.Check
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// Try processing the standalone arguments
|
||||
if (!OptionsLoader.ProcessStandaloneArguments(args))
|
||||
bool? standaloneProcessed = OptionsLoader.ProcessStandaloneArguments(args);
|
||||
if (standaloneProcessed != false)
|
||||
{
|
||||
DisplayHelp();
|
||||
if (standaloneProcessed == null)
|
||||
DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Try processing the common arguments
|
||||
(bool success, MediaType mediaType, RedumpSystem? knownSystem, string error) = OptionsLoader.ProcessCommonArguments(args);
|
||||
(bool success, MediaType mediaType, RedumpSystem? knownSystem, var error) = OptionsLoader.ProcessCommonArguments(args);
|
||||
if (!success)
|
||||
{
|
||||
DisplayHelp(error);
|
||||
@@ -29,7 +31,7 @@ namespace MPF.Check
|
||||
}
|
||||
|
||||
// Loop through and process options
|
||||
(Core.Data.Options options, string path, int startIndex) = OptionsLoader.LoadFromArguments(args, startIndex: 2);
|
||||
(var options, var seedInfo, var path, int startIndex) = OptionsLoader.LoadFromArguments(args, startIndex: 2);
|
||||
if (options.InternalProgram == InternalProgram.NONE)
|
||||
{
|
||||
DisplayHelp("A program name needs to be provided");
|
||||
@@ -46,7 +48,7 @@ namespace MPF.Check
|
||||
#if NET48
|
||||
(bool? _, string message) = RedumpWebClient.ValidateCredentials(options?.RedumpUsername, options?.RedumpPassword);
|
||||
#else
|
||||
(bool? _, string message) = RedumpHttpClient.ValidateCredentials(options?.RedumpUsername, options?.RedumpPassword).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
(bool? _, string? message) = RedumpHttpClient.ValidateCredentials(options.RedumpUsername ?? string.Empty, options.RedumpPassword ?? string.Empty).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
#endif
|
||||
if (!string.IsNullOrWhiteSpace(message))
|
||||
Console.WriteLine(message);
|
||||
@@ -65,7 +67,11 @@ namespace MPF.Check
|
||||
string filepath = Path.GetFullPath(args[i].Trim('"'));
|
||||
|
||||
// Now populate an environment
|
||||
#if NET48
|
||||
Drive drive = null;
|
||||
#else
|
||||
Drive? drive = null;
|
||||
#endif
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
drive = Drive.Create(null, path);
|
||||
|
||||
@@ -81,7 +87,11 @@ namespace MPF.Check
|
||||
/// Display help for MPF.Check
|
||||
/// </summary>
|
||||
/// <param name="error">Error string to prefix the help text with</param>
|
||||
#if NET48
|
||||
private static void DisplayHelp(string error = null)
|
||||
#else
|
||||
private static void DisplayHelp(string? error = null)
|
||||
#endif
|
||||
{
|
||||
if (error != null)
|
||||
Console.WriteLine(error);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using BurnOutSharp;
|
||||
using BinaryObjectScanner;
|
||||
using MPF.Core.Data;
|
||||
|
||||
namespace MPF.Core
|
||||
@@ -9,7 +9,11 @@ namespace MPF.Core
|
||||
/// <summary>
|
||||
/// Simple process counter to write to console
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static void ProgressUpdated(object sender, Result value)
|
||||
#else
|
||||
public static void ProgressUpdated(object? sender, Result value)
|
||||
#endif
|
||||
{
|
||||
Console.WriteLine(value.Message);
|
||||
}
|
||||
@@ -17,7 +21,11 @@ namespace MPF.Core
|
||||
/// <summary>
|
||||
/// Simple process counter to write to console
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static void ProgressUpdated(object sender, ProtectionProgress value)
|
||||
#else
|
||||
public static void ProgressUpdated(object? sender, ProtectionProgress value)
|
||||
#endif
|
||||
{
|
||||
Console.WriteLine($"{value.Percentage * 100:N2}%: {value.Filename} - {value.Protection}");
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace MPF.Core.Converters
|
||||
case InternalProgram.DiscImageCreator:
|
||||
return "DiscImageCreator";
|
||||
case InternalProgram.Redumper:
|
||||
return "redumper";
|
||||
return "Redumper";
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Linq;
|
||||
using Microsoft.Management.Infrastructure;
|
||||
using Microsoft.Management.Infrastructure.Generic;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Utilities;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core.Data
|
||||
@@ -14,7 +13,6 @@ namespace MPF.Core.Data
|
||||
/// Represents information for a single drive
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// TODO: This needs to be less Windows-centric. Devices do not always have a single letter that can be used.
|
||||
/// TODO: Can the Aaru models be used instead of the ones I've created here?
|
||||
/// </remarks>
|
||||
public class Drive
|
||||
@@ -96,9 +94,10 @@ namespace MPF.Core.Data
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Windows drive letter
|
||||
/// Read-only access to the drive letter
|
||||
/// </summary>
|
||||
public char Letter => this.Name == null || this.Name.Length == 0 ? '\0' : this.Name[0];
|
||||
/// <remarks>Should only be used in UI applications</remarks>
|
||||
public char? Letter => this.Name?[0] ?? '\0';
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -188,7 +187,7 @@ namespace MPF.Core.Data
|
||||
public static List<Drive> CreateListOfDrives(bool ignoreFixedDrives)
|
||||
{
|
||||
var drives = GetDriveList(ignoreFixedDrives);
|
||||
drives = drives.OrderBy(i => i == null ? '\0' : i.Letter).ToList();
|
||||
drives = drives.OrderBy(i => i == null ? "\0" : i.Name).ToList();
|
||||
return drives;
|
||||
}
|
||||
|
||||
@@ -264,13 +263,9 @@ namespace MPF.Core.Data
|
||||
}
|
||||
|
||||
// Handle optical media by size and filesystem
|
||||
if (this.TotalSize >= 0 && this.TotalSize < 800_000_000 && this.DriveFormat == "CDFS")
|
||||
if (this.TotalSize >= 0 && this.TotalSize <= 800_000_000 && (this.DriveFormat == "CDFS" || this.DriveFormat == "UDF"))
|
||||
return (MediaType.CDROM, null);
|
||||
else if (this.TotalSize >= 0 && this.TotalSize < 400_000_000 && this.DriveFormat == "UDF")
|
||||
return (MediaType.CDROM, null);
|
||||
else if (this.TotalSize >= 800_000_000 && this.TotalSize <= 8_540_000_000 && this.DriveFormat == "CDFS")
|
||||
return (MediaType.DVD, null);
|
||||
else if (this.TotalSize >= 400_000_000 && this.TotalSize <= 8_540_000_000 && this.DriveFormat == "UDF")
|
||||
else if (this.TotalSize > 800_000_000 && this.TotalSize <= 8_540_000_000 && (this.DriveFormat == "CDFS" || this.DriveFormat == "UDF"))
|
||||
return (MediaType.DVD, null);
|
||||
else if (this.TotalSize > 8_540_000_000)
|
||||
return (MediaType.BluRay, null);
|
||||
@@ -285,14 +280,11 @@ namespace MPF.Core.Data
|
||||
/// <returns></returns>
|
||||
public RedumpSystem? GetRedumpSystem(RedumpSystem? defaultValue)
|
||||
{
|
||||
string drivePath = $"{this.Letter}:\\";
|
||||
|
||||
// If we can't read the media in that drive, we can't do anything
|
||||
if (!Directory.Exists(drivePath))
|
||||
if (!Directory.Exists(this.Name))
|
||||
return defaultValue;
|
||||
|
||||
// We're going to assume for floppies, HDDs, and removable drives
|
||||
// TODO: Try to be smarter about this
|
||||
if (this.InternalDriveType != Data.InternalDriveType.Optical)
|
||||
return RedumpSystem.IBMPCcompatible;
|
||||
|
||||
@@ -307,7 +299,7 @@ namespace MPF.Core.Data
|
||||
// Bandai Playdia Quick Interactive System
|
||||
try
|
||||
{
|
||||
List<string> files = Directory.EnumerateFiles(drivePath, "*", SearchOption.TopDirectoryOnly).ToList();
|
||||
List<string> files = Directory.EnumerateFiles(this.Name, "*", SearchOption.TopDirectoryOnly).ToList();
|
||||
|
||||
if (files.Any(f => f.EndsWith(".AJS", StringComparison.OrdinalIgnoreCase))
|
||||
&& files.Any(f => f.EndsWith(".GLB", StringComparison.OrdinalIgnoreCase)))
|
||||
@@ -318,7 +310,7 @@ namespace MPF.Core.Data
|
||||
catch { }
|
||||
|
||||
// Mattel Fisher-Price iXL
|
||||
if (File.Exists(Path.Combine(drivePath, "iXL", "iXLUpdater.exe")))
|
||||
if (File.Exists(Path.Combine(this.Name, "iXL", "iXLUpdater.exe")))
|
||||
{
|
||||
return RedumpSystem.MattelFisherPriceiXL;
|
||||
}
|
||||
@@ -326,8 +318,8 @@ namespace MPF.Core.Data
|
||||
// Microsoft Xbox 360
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "$SystemUpdate"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "$SystemUpdate")).Any()
|
||||
if (Directory.Exists(Path.Combine(this.Name, "$SystemUpdate"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "$SystemUpdate")).Any()
|
||||
&& this.TotalSize <= 500_000_000)
|
||||
{
|
||||
return RedumpSystem.MicrosoftXbox360;
|
||||
@@ -338,8 +330,8 @@ namespace MPF.Core.Data
|
||||
// Microsoft Xbox One
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "MSXC"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "MSXC")).Any())
|
||||
if (Directory.Exists(Path.Combine(this.Name, "MSXC"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "MSXC")).Any())
|
||||
{
|
||||
return RedumpSystem.MicrosoftXboxOne;
|
||||
}
|
||||
@@ -347,35 +339,23 @@ namespace MPF.Core.Data
|
||||
catch { }
|
||||
|
||||
// Sega Dreamcast
|
||||
if (File.Exists(Path.Combine(drivePath, "IP.BIN")))
|
||||
if (File.Exists(Path.Combine(this.Name, "IP.BIN")))
|
||||
{
|
||||
return RedumpSystem.SegaDreamcast;
|
||||
}
|
||||
|
||||
// Sega Mega-CD / Sega-CD
|
||||
if (File.Exists(Path.Combine(drivePath, "_BOOT", "IP.BIN"))
|
||||
|| File.Exists(Path.Combine(drivePath, "_BOOT", "SP.BIN"))
|
||||
|| File.Exists(Path.Combine(drivePath, "_BOOT", "SP_AS.BIN"))
|
||||
|| File.Exists(Path.Combine(drivePath, "FILESYSTEM.BIN")))
|
||||
if (File.Exists(Path.Combine(this.Name, "_BOOT", "IP.BIN"))
|
||||
|| File.Exists(Path.Combine(this.Name, "_BOOT", "SP.BIN"))
|
||||
|| File.Exists(Path.Combine(this.Name, "_BOOT", "SP_AS.BIN"))
|
||||
|| File.Exists(Path.Combine(this.Name, "FILESYSTEM.BIN")))
|
||||
{
|
||||
return RedumpSystem.SegaMegaCDSegaCD;
|
||||
}
|
||||
|
||||
// Sega Saturn
|
||||
try
|
||||
{
|
||||
var sector = ReadSector(0);
|
||||
if (sector != null)
|
||||
{
|
||||
if (sector.StartsWith(Interface.SaturnSectorZeroStart))
|
||||
return RedumpSystem.SegaSaturn;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Sony PlayStation and Sony PlayStation 2
|
||||
string psxExePath = Path.Combine(drivePath, "PSX.EXE");
|
||||
string systemCnfPath = Path.Combine(drivePath, "SYSTEM.CNF");
|
||||
string psxExePath = Path.Combine(this.Name, "PSX.EXE");
|
||||
string systemCnfPath = Path.Combine(this.Name, "SYSTEM.CNF");
|
||||
if (File.Exists(systemCnfPath))
|
||||
{
|
||||
// Check for either BOOT or BOOT2
|
||||
@@ -393,9 +373,9 @@ namespace MPF.Core.Data
|
||||
// Sony PlayStation 3
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "PS3_GAME"))
|
||||
|| Directory.Exists(Path.Combine(drivePath, "PS3_UPDATE"))
|
||||
|| File.Exists(Path.Combine(drivePath, "PS3_DISC.SFB")))
|
||||
if (Directory.Exists(Path.Combine(this.Name, "PS3_GAME"))
|
||||
|| Directory.Exists(Path.Combine(this.Name, "PS3_UPDATE"))
|
||||
|| File.Exists(Path.Combine(this.Name, "PS3_DISC.SFB")))
|
||||
{
|
||||
return RedumpSystem.SonyPlayStation3;
|
||||
}
|
||||
@@ -414,13 +394,13 @@ namespace MPF.Core.Data
|
||||
// Is used as an on-disc update for the base game app without needing to get update from the internet.
|
||||
// "/addcont/GAME_SERIAL/CONTENT_ID/ac.pkg" can be found in Redump entry 97619.
|
||||
// Originally on disc as "/addcont/CUSA00288/FFXIVEXPS400001A/ac.pkg".
|
||||
if (File.Exists(Path.Combine(drivePath, "PS4", "UPDATE", "PS4UPDATE.PUP")))
|
||||
if (File.Exists(Path.Combine(this.Name, "PS4", "UPDATE", "PS4UPDATE.PUP")))
|
||||
{
|
||||
return RedumpSystem.SonyPlayStation4;
|
||||
}
|
||||
|
||||
// V.Tech V.Flash / V.Smile Pro
|
||||
if (File.Exists(Path.Combine(drivePath, "0SYSTEM")))
|
||||
if (File.Exists(Path.Combine(this.Name, "0SYSTEM")))
|
||||
{
|
||||
return RedumpSystem.VTechVFlashVSmilePro;
|
||||
}
|
||||
@@ -430,7 +410,7 @@ namespace MPF.Core.Data
|
||||
#region Computers
|
||||
|
||||
// Sharp X68000
|
||||
if (File.Exists(Path.Combine(drivePath, "COMMAND.X")))
|
||||
if (File.Exists(Path.Combine(this.Name, "COMMAND.X")))
|
||||
{
|
||||
return RedumpSystem.SharpX68000;
|
||||
}
|
||||
@@ -440,7 +420,7 @@ namespace MPF.Core.Data
|
||||
#region Video Formats
|
||||
|
||||
// BD-Video
|
||||
if (Directory.Exists(Path.Combine(drivePath, "BDMV")))
|
||||
if (Directory.Exists(Path.Combine(this.Name, "BDMV")))
|
||||
{
|
||||
// Technically BD-Audio has this as well, but it's hard to split that out right now
|
||||
return RedumpSystem.BDVideo;
|
||||
@@ -449,14 +429,14 @@ namespace MPF.Core.Data
|
||||
// DVD-Audio and DVD-Video
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "AUDIO_TS"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "AUDIO_TS")).Any())
|
||||
if (Directory.Exists(Path.Combine(this.Name, "AUDIO_TS"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "AUDIO_TS")).Any())
|
||||
{
|
||||
return RedumpSystem.DVDAudio;
|
||||
}
|
||||
|
||||
else if (Directory.Exists(Path.Combine(drivePath, "VIDEO_TS"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "VIDEO_TS")).Any())
|
||||
else if (Directory.Exists(Path.Combine(this.Name, "VIDEO_TS"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "VIDEO_TS")).Any())
|
||||
{
|
||||
return RedumpSystem.DVDVideo;
|
||||
}
|
||||
@@ -466,8 +446,8 @@ namespace MPF.Core.Data
|
||||
// HD-DVD-Video
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "HVDVD_TS"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "HVDVD_TS")).Any())
|
||||
if (Directory.Exists(Path.Combine(this.Name, "HVDVD_TS"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "HVDVD_TS")).Any())
|
||||
{
|
||||
return RedumpSystem.HDDVDVideo;
|
||||
}
|
||||
@@ -477,8 +457,8 @@ namespace MPF.Core.Data
|
||||
// VCD
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "VCD"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "VCD")).Any())
|
||||
if (Directory.Exists(Path.Combine(this.Name, "VCD"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "VCD")).Any())
|
||||
{
|
||||
return RedumpSystem.VideoCD;
|
||||
}
|
||||
@@ -542,56 +522,6 @@ namespace MPF.Core.Data
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a sector with a specified size from the drive
|
||||
/// </summary>
|
||||
/// <param name="num">Sector number, non-negative</param>
|
||||
/// <param name="size">Size of a sector in bytes</param>
|
||||
/// <returns>Byte array representing the sector, null on error</returns>
|
||||
#if NET48
|
||||
public byte[] ReadSector(long num, int size = 2048)
|
||||
#else
|
||||
public byte[]? ReadSector(long num, int size = 2048)
|
||||
#endif
|
||||
{
|
||||
// Missing drive leter is not supported
|
||||
if (string.IsNullOrEmpty(this.Name))
|
||||
return null;
|
||||
|
||||
// We don't support negative sectors
|
||||
if (num < 0)
|
||||
return null;
|
||||
|
||||
// Wrap the following in case of device access errors
|
||||
#if NET48
|
||||
Stream fs = null;
|
||||
#else
|
||||
Stream? fs = null;
|
||||
#endif
|
||||
try
|
||||
{
|
||||
// Open the drive as a device
|
||||
fs = File.OpenRead($"\\\\?\\{this.Letter}:");
|
||||
|
||||
// Seek to the start of the sector, if possible
|
||||
long start = num * size;
|
||||
fs.Seek(start, SeekOrigin.Begin);
|
||||
|
||||
// Read and return the sector
|
||||
byte[] buffer = new byte[size];
|
||||
fs.Read(buffer, 0, size);
|
||||
return buffer;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
fs?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh the current drive information based on path
|
||||
/// </summary>
|
||||
@@ -655,7 +585,7 @@ namespace MPF.Core.Data
|
||||
if (mediaType != null && ((mediaType > 0 && mediaType < 11) || (mediaType > 12 && mediaType < 22)))
|
||||
{
|
||||
char devId = (properties["Caption"].Value as string ?? string.Empty)[0];
|
||||
drives.ForEach(d => { if (d?.Letter == devId) { d.InternalDriveType = Data.InternalDriveType.Floppy; } });
|
||||
drives.ForEach(d => { if (d?.Name != null && d.Name[0] == devId) { d.InternalDriveType = Data.InternalDriveType.Floppy; } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
namespace MPF.Core.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Available hashing types
|
||||
/// </summary>
|
||||
public enum Hash
|
||||
{
|
||||
CRC32,
|
||||
CRC64,
|
||||
MD5,
|
||||
SHA1,
|
||||
SHA256,
|
||||
SHA384,
|
||||
SHA512,
|
||||
XxHash32,
|
||||
XxHash64,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drive type for dumping
|
||||
/// </summary>
|
||||
|
||||
@@ -8,14 +8,22 @@ namespace MPF.Core.Data
|
||||
{
|
||||
public class IniFile : IDictionary<string, string>
|
||||
{
|
||||
#if NET48
|
||||
private Dictionary<string, string> _keyValuePairs = new Dictionary<string, string>();
|
||||
#else
|
||||
private Dictionary<string, string> _keyValuePairs = new();
|
||||
#endif
|
||||
|
||||
public string this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
#if NET48
|
||||
if (_keyValuePairs == null)
|
||||
_keyValuePairs = new Dictionary<string, string>();
|
||||
#else
|
||||
_keyValuePairs ??= new Dictionary<string, string>();
|
||||
#endif
|
||||
|
||||
key = key.ToLowerInvariant();
|
||||
if (_keyValuePairs.ContainsKey(key))
|
||||
@@ -25,8 +33,12 @@ namespace MPF.Core.Data
|
||||
}
|
||||
set
|
||||
{
|
||||
#if NET48
|
||||
if (_keyValuePairs == null)
|
||||
_keyValuePairs = new Dictionary<string, string>();
|
||||
#else
|
||||
_keyValuePairs ??= new Dictionary<string, string>();
|
||||
#endif
|
||||
|
||||
key = key.ToLowerInvariant();
|
||||
_keyValuePairs[key] = value;
|
||||
@@ -99,7 +111,7 @@ namespace MPF.Core.Data
|
||||
// Keys are case-insensitive by default
|
||||
try
|
||||
{
|
||||
using (StreamReader sr = new StreamReader(stream))
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
string section = string.Empty;
|
||||
while (!sr.EndOfStream)
|
||||
@@ -125,7 +137,11 @@ namespace MPF.Core.Data
|
||||
}
|
||||
|
||||
// Valid INI lines are in the format key=value
|
||||
#if NET48
|
||||
else if (line.Contains("="))
|
||||
#else
|
||||
else if (line.Contains('='))
|
||||
#endif
|
||||
{
|
||||
// Split the line by '=' for key-value pairs
|
||||
string[] data = line.Split('=');
|
||||
@@ -185,7 +201,7 @@ namespace MPF.Core.Data
|
||||
|
||||
try
|
||||
{
|
||||
using (StreamWriter sw = new StreamWriter(stream))
|
||||
using (var sw = new StreamWriter(stream))
|
||||
{
|
||||
// Order the dictionary by keys to link sections together
|
||||
var orderedKeyValuePairs = _keyValuePairs.OrderBy(kvp => kvp.Key);
|
||||
|
||||
@@ -4,11 +4,7 @@ using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core.Data
|
||||
{
|
||||
#if NET48
|
||||
public class Options
|
||||
#else
|
||||
public class Options
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// All settings in the form of a dictionary
|
||||
@@ -19,6 +15,15 @@ namespace MPF.Core.Data
|
||||
public Dictionary<string, string?> Settings { get; private set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if the program is being run with a clean configuration
|
||||
/// </summary>
|
||||
public bool FirstRun
|
||||
{
|
||||
get { return GetBooleanSetting(Settings, "FirstRun", true); }
|
||||
set { Settings["FirstRun"] = value.ToString(); }
|
||||
}
|
||||
|
||||
#region Internal Program
|
||||
|
||||
/// <summary>
|
||||
@@ -340,6 +345,24 @@ namespace MPF.Core.Data
|
||||
set { Settings["RedumperEnableVerbose"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable BE reading by default with Redumper
|
||||
/// </summary>
|
||||
public bool RedumperUseBEReading
|
||||
{
|
||||
get { return GetBooleanSetting(Settings, "RedumperUseBEReading", false); }
|
||||
set { Settings["RedumperUseBEReading"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable generic drive type by default with Redumper
|
||||
/// </summary>
|
||||
public bool RedumperUseGenericDriveType
|
||||
{
|
||||
get { return GetBooleanSetting(Settings, "RedumperUseGenericDriveType", false); }
|
||||
set { Settings["RedumperUseGenericDriveType"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default number of rereads
|
||||
/// </summary>
|
||||
@@ -452,6 +475,15 @@ namespace MPF.Core.Data
|
||||
set { Settings["ToolsInSeparateWindow"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add the dump filename as a suffix to the auto-generated files
|
||||
/// </summary>
|
||||
public bool AddFilenameSuffix
|
||||
{
|
||||
get { return GetBooleanSetting(Settings, "AddFilenameSuffix", false); }
|
||||
set { Settings["AddFilenameSuffix"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output the compressed JSON version of the submission info
|
||||
/// </summary>
|
||||
@@ -479,6 +511,15 @@ namespace MPF.Core.Data
|
||||
set { Settings["CompressLogFiles"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete unnecessary files to reduce space
|
||||
/// </summary>
|
||||
public bool DeleteUnnecessaryFiles
|
||||
{
|
||||
get { return GetBooleanSetting(Settings, "DeleteUnnecessaryFiles", false); }
|
||||
set { Settings["DeleteUnnecessaryFiles"] = value.ToString(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Skip Options
|
||||
@@ -610,12 +651,16 @@ namespace MPF.Core.Data
|
||||
/// Constructor taking an existing Options object
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
#if NET48
|
||||
public Options(Options source)
|
||||
#else
|
||||
public Options(Options? source)
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
Settings = new Dictionary<string, string>(source.Settings);
|
||||
Settings = new Dictionary<string, string>(source?.Settings ?? new Dictionary<string, string>());
|
||||
#else
|
||||
Settings = new Dictionary<string, string?>(source.Settings);
|
||||
Settings = new Dictionary<string, string?>(source?.Settings ?? new Dictionary<string, string?>());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -642,9 +687,9 @@ namespace MPF.Core.Data
|
||||
/// <param name="defaultValue">Default value to return if no value is found</param>
|
||||
/// <returns>Setting value if possible, default value otherwise</returns>
|
||||
#if NET48
|
||||
private bool GetBooleanSetting(Dictionary<string, string> settings, string key, bool defaultValue)
|
||||
private static bool GetBooleanSetting(Dictionary<string, string> settings, string key, bool defaultValue)
|
||||
#else
|
||||
private bool GetBooleanSetting(Dictionary<string, string?> settings, string key, bool defaultValue)
|
||||
private static bool GetBooleanSetting(Dictionary<string, string?> settings, string key, bool defaultValue)
|
||||
#endif
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
@@ -668,9 +713,9 @@ namespace MPF.Core.Data
|
||||
/// <param name="defaultValue">Default value to return if no value is found</param>
|
||||
/// <returns>Setting value if possible, default value otherwise</returns>
|
||||
#if NET48
|
||||
private int GetInt32Setting(Dictionary<string, string> settings, string key, int defaultValue)
|
||||
private static int GetInt32Setting(Dictionary<string, string> settings, string key, int defaultValue)
|
||||
#else
|
||||
private int GetInt32Setting(Dictionary<string, string?> settings, string key, int defaultValue)
|
||||
private static int GetInt32Setting(Dictionary<string, string?> settings, string key, int defaultValue)
|
||||
#endif
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
@@ -694,9 +739,9 @@ namespace MPF.Core.Data
|
||||
/// <param name="defaultValue">Default value to return if no value is found</param>
|
||||
/// <returns>Setting value if possible, default value otherwise</returns>
|
||||
#if NET48
|
||||
private string GetStringSetting(Dictionary<string, string> settings, string key, string defaultValue)
|
||||
private static string GetStringSetting(Dictionary<string, string> settings, string key, string defaultValue)
|
||||
#else
|
||||
private string? GetStringSetting(Dictionary<string, string?> settings, string key, string? defaultValue)
|
||||
private static string? GetStringSetting(Dictionary<string, string?> settings, string key, string? defaultValue)
|
||||
#endif
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains information specific to an XGD disc
|
||||
/// </summary>
|
||||
public class XgdInfo
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the information in this object is fully instantiated or not
|
||||
/// </summary>
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Raw XMID/XeMID string that all other information is derived from
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string RawXMID { get; private set; }
|
||||
#else
|
||||
public string? RawXMID { get; private set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// XGD1 XMID
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public SabreTools.Models.Xbox.XMID XMID { get; private set; }
|
||||
#else
|
||||
public SabreTools.Models.Xbox.XMID? XMID { get; private set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// XGD2/3 XeMID
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public SabreTools.Models.Xbox.XeMID XeMID { get; private set; }
|
||||
#else
|
||||
public SabreTools.Models.Xbox.XeMID? XeMID { get; private set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Populate a set of XGD information from a Master ID (XMID/XeMID) string
|
||||
/// </summary>
|
||||
/// <param name="xmid">XMID/XeMID string representing the DMI information</param>
|
||||
public XgdInfo(string xmid)
|
||||
{
|
||||
this.Initialized = false;
|
||||
if (string.IsNullOrWhiteSpace(xmid))
|
||||
return;
|
||||
|
||||
this.RawXMID = xmid.TrimEnd('\0');
|
||||
if (string.IsNullOrWhiteSpace(this.RawXMID))
|
||||
return;
|
||||
|
||||
// XGD1 information is 8 characters
|
||||
if (this.RawXMID.Length == 8)
|
||||
this.Initialized = ParseXGD1XMID(this.RawXMID);
|
||||
|
||||
// XGD2/3 information is semi-variable length
|
||||
else if (this.RawXMID.Length == 13 || this.RawXMID.Length == 14 || this.RawXMID.Length == 21 || this.RawXMID.Length == 22)
|
||||
this.Initialized = ParseXGD23XeMID(this.RawXMID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the human-readable serial string
|
||||
/// </summary>
|
||||
/// <returns>Formatted serial string, null on error</returns>
|
||||
#if NET48
|
||||
public string GetSerial()
|
||||
#else
|
||||
public string? GetSerial()
|
||||
#endif
|
||||
{
|
||||
if (!this.Initialized)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
// XGD1 doesn't use PlatformIdentifier
|
||||
if (XMID != null)
|
||||
return $"{XMID.PublisherIdentifier}-{XMID.GameID}";
|
||||
|
||||
// XGD2/3 uses a specific identifier
|
||||
else if (XeMID?.PlatformIdentifier == '2')
|
||||
return $"{XeMID.PublisherIdentifier}-{XeMID.PlatformIdentifier}{XeMID.GameID}";
|
||||
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the human-readable version string
|
||||
/// </summary>
|
||||
/// <returns>Formatted version string, null on error</returns>
|
||||
/// <remarks>This may differ for XGD2/3 in the future</remarks>
|
||||
#if NET48
|
||||
public string GetVersion()
|
||||
#else
|
||||
public string? GetVersion()
|
||||
#endif
|
||||
{
|
||||
if (!this.Initialized)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
// XGD1 doesn't use PlatformIdentifier
|
||||
if (XMID != null)
|
||||
return $"1.{XMID.VersionNumber}";
|
||||
|
||||
// XGD2/3 uses a specific identifier
|
||||
else if (XeMID?.PlatformIdentifier == '2')
|
||||
return $"1.{XeMID.SKU}";
|
||||
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an XGD1 XMID string
|
||||
/// </summary>
|
||||
/// <param name="rawXmid">XMID string to attempt to parse</param>
|
||||
/// <returns>True if the XMID could be parsed, false otherwise</returns>
|
||||
private bool ParseXGD1XMID(string rawXmid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var xmid = new SabreTools.Serialization.Files.XMID().Deserialize(rawXmid);
|
||||
if (xmid == null)
|
||||
return false;
|
||||
|
||||
this.XMID = xmid;
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an XGD2/3 XeMID string
|
||||
/// </summary>
|
||||
/// <param name="rawXemid">XeMID string to attempt to parse</param>
|
||||
/// <returns>True if the XeMID could be parsed, false otherwise</returns>
|
||||
private bool ParseXGD23XeMID(string rawXemid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var xemid = new SabreTools.Serialization.Files.XeMID().Deserialize(rawXemid);
|
||||
if (xemid == null)
|
||||
return false;
|
||||
|
||||
this.XeMID = xemid;
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Determine the region based on the XGD serial character
|
||||
/// </summary>
|
||||
/// <param name="region">Character denoting the region</param>
|
||||
/// <returns>Region, if possible</returns>
|
||||
public static Region? GetRegion(char? region)
|
||||
{
|
||||
switch (region)
|
||||
{
|
||||
case 'W': return Region.World;
|
||||
case 'A': return Region.UnitedStatesOfAmerica;
|
||||
case 'J': return Region.JapanAsia;
|
||||
case 'E': return Region.Europe;
|
||||
case 'K': return Region.USAJapan;
|
||||
case 'L': return Region.USAEurope;
|
||||
case 'H': return Region.JapanEurope;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BurnOutSharp;
|
||||
using BinaryObjectScanner;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Utilities;
|
||||
using MPF.Core.Modules;
|
||||
using MPF.Core.Utilities;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core
|
||||
@@ -65,7 +66,7 @@ namespace MPF.Core
|
||||
public BaseParameters? Parameters { get; private set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
@@ -123,19 +124,23 @@ namespace MPF.Core
|
||||
RedumpSystem? system,
|
||||
MediaType? type,
|
||||
InternalProgram? internalProgram,
|
||||
#if NET48
|
||||
string parameters)
|
||||
#else
|
||||
string? parameters)
|
||||
#endif
|
||||
{
|
||||
// Set options object
|
||||
this.Options = options;
|
||||
Options = options;
|
||||
|
||||
// Output paths
|
||||
this.OutputPath = InfoTool.NormalizeOutputPaths(outputPath, true);
|
||||
OutputPath = InfoTool.NormalizeOutputPaths(outputPath, false);
|
||||
|
||||
// UI information
|
||||
this.Drive = drive;
|
||||
this.System = system ?? options.DefaultSystem;
|
||||
this.Type = type ?? MediaType.NONE;
|
||||
this.InternalProgram = internalProgram ?? options.InternalProgram;
|
||||
Drive = drive;
|
||||
System = system ?? options.DefaultSystem;
|
||||
Type = type ?? MediaType.NONE;
|
||||
InternalProgram = internalProgram ?? options.InternalProgram;
|
||||
|
||||
// Dumping program
|
||||
SetParameters(parameters);
|
||||
@@ -143,98 +148,73 @@ namespace MPF.Core
|
||||
|
||||
#region Public Functionality
|
||||
|
||||
/// <summary>
|
||||
/// Adjust output paths if we're using DiscImageCreator
|
||||
/// </summary>
|
||||
public void AdjustPathsForDiscImageCreator()
|
||||
{
|
||||
// Only DiscImageCreator has issues with paths
|
||||
if (this.Parameters?.InternalProgram != InternalProgram.DiscImageCreator)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
// Normalize the output path
|
||||
string outputPath = InfoTool.NormalizeOutputPaths(this.OutputPath, true);
|
||||
|
||||
// Replace all instances in the output directory
|
||||
var outputDirectory = Path.GetDirectoryName(outputPath);
|
||||
outputDirectory = outputDirectory?.Replace(".", "_");
|
||||
|
||||
// Replace all instances in the output filename
|
||||
string outputFilename = Path.GetFileNameWithoutExtension(outputPath);
|
||||
outputFilename = outputFilename.Replace(".", "_");
|
||||
|
||||
// Get the extension for recreating the path
|
||||
string outputExtension = Path.GetExtension(outputPath).TrimStart('.');
|
||||
|
||||
// Rebuild the output path
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(outputExtension))
|
||||
this.OutputPath = outputFilename;
|
||||
else
|
||||
this.OutputPath = $"{outputFilename}.{outputExtension}";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(outputExtension))
|
||||
this.OutputPath = Path.Combine(outputDirectory, outputFilename);
|
||||
else
|
||||
this.OutputPath = Path.Combine(outputDirectory, $"{outputFilename}.{outputExtension}");
|
||||
}
|
||||
|
||||
// Assign the path to the filename as well for dumping
|
||||
((Modules.DiscImageCreator.Parameters)this.Parameters).Filename = this.OutputPath;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the parameters object based on the internal program and parameters string
|
||||
/// </summary>
|
||||
/// <param name="parameters">String representation of the parameters</param>
|
||||
#if NET48
|
||||
public void SetParameters(string parameters)
|
||||
#else
|
||||
public void SetParameters(string? parameters)
|
||||
#endif
|
||||
{
|
||||
switch (this.InternalProgram)
|
||||
#if NET48
|
||||
switch (InternalProgram)
|
||||
{
|
||||
// Dumping support
|
||||
case InternalProgram.Aaru:
|
||||
this.Parameters = new Modules.Aaru.Parameters(parameters) { ExecutablePath = Options.AaruPath };
|
||||
Parameters = new Modules.Aaru.Parameters(parameters) { ExecutablePath = Options.AaruPath };
|
||||
break;
|
||||
|
||||
case InternalProgram.DiscImageCreator:
|
||||
this.Parameters = new Modules.DiscImageCreator.Parameters(parameters) { ExecutablePath = Options.DiscImageCreatorPath };
|
||||
Parameters = new Modules.DiscImageCreator.Parameters(parameters) { ExecutablePath = Options.DiscImageCreatorPath };
|
||||
break;
|
||||
|
||||
case InternalProgram.Redumper:
|
||||
this.Parameters = new Modules.Redumper.Parameters(parameters) { ExecutablePath = Options.RedumperPath };
|
||||
Parameters = new Modules.Redumper.Parameters(parameters) { ExecutablePath = Options.RedumperPath };
|
||||
break;
|
||||
|
||||
// Verification support only
|
||||
case InternalProgram.CleanRip:
|
||||
this.Parameters = new Modules.CleanRip.Parameters(parameters) { ExecutablePath = null };
|
||||
Parameters = new Modules.CleanRip.Parameters(parameters) { ExecutablePath = null };
|
||||
break;
|
||||
|
||||
case InternalProgram.DCDumper:
|
||||
this.Parameters = null; // TODO: Create correct parameter type when supported
|
||||
Parameters = null; // TODO: Create correct parameter type when supported
|
||||
break;
|
||||
|
||||
case InternalProgram.UmdImageCreator:
|
||||
this.Parameters = new Modules.UmdImageCreator.Parameters(parameters) { ExecutablePath = null };
|
||||
Parameters = new Modules.UmdImageCreator.Parameters(parameters) { ExecutablePath = null };
|
||||
break;
|
||||
|
||||
// This should never happen, but it needs a fallback
|
||||
default:
|
||||
this.Parameters = new Modules.DiscImageCreator.Parameters(parameters) { ExecutablePath = Options.DiscImageCreatorPath };
|
||||
Parameters = new Modules.DiscImageCreator.Parameters(parameters) { ExecutablePath = Options.DiscImageCreatorPath };
|
||||
break;
|
||||
}
|
||||
#else
|
||||
Parameters = InternalProgram switch
|
||||
{
|
||||
// Dumping support
|
||||
InternalProgram.Aaru => new Modules.Aaru.Parameters(parameters) { ExecutablePath = Options.AaruPath },
|
||||
InternalProgram.DiscImageCreator => new Modules.DiscImageCreator.Parameters(parameters) { ExecutablePath = Options.DiscImageCreatorPath },
|
||||
InternalProgram.Redumper => new Modules.Redumper.Parameters(parameters) { ExecutablePath = Options.RedumperPath },
|
||||
|
||||
// Verification support only
|
||||
InternalProgram.CleanRip => new Modules.CleanRip.Parameters(parameters) { ExecutablePath = null },
|
||||
InternalProgram.DCDumper => null, // TODO: Create correct parameter type when supported
|
||||
InternalProgram.UmdImageCreator => new Modules.UmdImageCreator.Parameters(parameters) { ExecutablePath = null },
|
||||
|
||||
// This should never happen, but it needs a fallback
|
||||
_ => new Modules.DiscImageCreator.Parameters(parameters) { ExecutablePath = Options.DiscImageCreatorPath },
|
||||
};
|
||||
#endif
|
||||
|
||||
// Set system and type
|
||||
if (this.Parameters != null)
|
||||
if (Parameters != null)
|
||||
{
|
||||
this.Parameters.System = this.System;
|
||||
this.Parameters.Type = this.Type;
|
||||
Parameters.System = System;
|
||||
Parameters.Type = Type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,25 +237,37 @@ namespace MPF.Core
|
||||
return null;
|
||||
|
||||
// Set the proper parameters
|
||||
switch (this.InternalProgram)
|
||||
#if NET48
|
||||
switch (InternalProgram)
|
||||
{
|
||||
case InternalProgram.Aaru:
|
||||
Parameters = new Modules.Aaru.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
|
||||
Parameters = new Modules.Aaru.Parameters(System, Type, Drive.Name, OutputPath, driveSpeed, Options);
|
||||
break;
|
||||
|
||||
case InternalProgram.DiscImageCreator:
|
||||
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
|
||||
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Name, OutputPath, driveSpeed, Options);
|
||||
break;
|
||||
|
||||
case InternalProgram.Redumper:
|
||||
Parameters = new Modules.Redumper.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
|
||||
Parameters = new Modules.Redumper.Parameters(System, Type, Drive.Name, OutputPath, driveSpeed, Options);
|
||||
break;
|
||||
|
||||
// This should never happen, but it needs a fallback
|
||||
default:
|
||||
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
|
||||
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Name, OutputPath, driveSpeed, Options);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
Parameters = InternalProgram switch
|
||||
{
|
||||
InternalProgram.Aaru => new Modules.Aaru.Parameters(System, Type, Drive.Name, OutputPath, driveSpeed, Options),
|
||||
InternalProgram.DiscImageCreator => new Modules.DiscImageCreator.Parameters(System, Type, Drive.Name, OutputPath, driveSpeed, Options),
|
||||
InternalProgram.Redumper => new Modules.Redumper.Parameters(System, Type, Drive.Name, OutputPath, driveSpeed, Options),
|
||||
|
||||
// This should never happen, but it needs a fallback
|
||||
_ => new Modules.DiscImageCreator.Parameters(System, Type, Drive.Name, OutputPath, driveSpeed, Options),
|
||||
};
|
||||
#endif
|
||||
|
||||
// Generate and return the param string
|
||||
return Parameters.GenerateParameters();
|
||||
@@ -301,7 +293,7 @@ namespace MPF.Core
|
||||
#else
|
||||
public async Task<string?> EjectDisc() =>
|
||||
#endif
|
||||
await RunStandaloneDiscImageCreatorCommand(Modules.DiscImageCreator.CommandStrings.Eject);
|
||||
await RunStandaloneDiscImageCreatorCommand(Modules.DiscImageCreator.CommandStrings.Eject);
|
||||
|
||||
/// <summary>
|
||||
/// Reset the current drive using DiscImageCreator
|
||||
@@ -324,7 +316,7 @@ namespace MPF.Core
|
||||
#endif
|
||||
{
|
||||
// If we don't have parameters
|
||||
if (this.Parameters == null)
|
||||
if (Parameters == null)
|
||||
return Result.Failure("Error! Current configuration is not supported!");
|
||||
|
||||
// Check that we have the basics for dumping
|
||||
@@ -341,19 +333,14 @@ namespace MPF.Core
|
||||
}
|
||||
|
||||
// Execute internal tool
|
||||
progress?.Report(Result.Success($"Executing {this.InternalProgram}... {(Options.ToolsInSeparateWindow ? "please wait!" : "see log for output!")}"));
|
||||
progress?.Report(Result.Success($"Executing {InternalProgram}... {(Options.ToolsInSeparateWindow ? "please wait!" : "see log for output!")}"));
|
||||
|
||||
var directoryName = Path.GetDirectoryName(this.OutputPath);
|
||||
var directoryName = Path.GetDirectoryName(OutputPath);
|
||||
if (!string.IsNullOrWhiteSpace(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
await Task.Run(() => Parameters.ExecuteInternalProgram(Options.ToolsInSeparateWindow));
|
||||
progress?.Report(Result.Success($"{this.InternalProgram} has finished!"));
|
||||
|
||||
// Execute additional tools
|
||||
progress?.Report(Result.Success("Running any additional tools... see log for output!"));
|
||||
result = await Task.Run(() => ExecuteAdditionalTools());
|
||||
progress?.Report(result);
|
||||
progress?.Report(Result.Success($"{InternalProgram} has finished!"));
|
||||
|
||||
// Remove event handler if needed
|
||||
if (!Options.ToolsInSeparateWindow)
|
||||
@@ -371,26 +358,29 @@ namespace MPF.Core
|
||||
/// <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<Result> VerifyAndSaveDumpOutput(
|
||||
#if NET48
|
||||
IProgress<Result> resultProgress = null,
|
||||
IProgress<ProtectionProgress> protectionProgress = null,
|
||||
Func<SubmissionInfo, (bool?, SubmissionInfo)> processUserInfo = null)
|
||||
Func<SubmissionInfo, (bool?, SubmissionInfo)> processUserInfo = null,
|
||||
SubmissionInfo seedInfo = null)
|
||||
#else
|
||||
IProgress<Result>? resultProgress = null,
|
||||
IProgress<ProtectionProgress>? protectionProgress = null,
|
||||
Func<SubmissionInfo?, (bool?, SubmissionInfo?)>? processUserInfo = null)
|
||||
Func<SubmissionInfo?, (bool?, SubmissionInfo?)>? processUserInfo = null,
|
||||
SubmissionInfo? seedInfo = null)
|
||||
#endif
|
||||
{
|
||||
resultProgress?.Report(Result.Success("Gathering submission information... please wait!"));
|
||||
|
||||
// Get the output directory and filename separately
|
||||
var outputDirectory = Path.GetDirectoryName(this.OutputPath);
|
||||
var outputFilename = Path.GetFileName(this.OutputPath);
|
||||
var outputDirectory = Path.GetDirectoryName(OutputPath);
|
||||
var outputFilename = Path.GetFileName(OutputPath);
|
||||
|
||||
// Check to make sure that the output had all the correct files
|
||||
(bool foundFiles, List<string> missingFiles) = InfoTool.FoundAllFiles(outputDirectory, outputFilename, this.Parameters, false);
|
||||
(bool foundFiles, List<string> missingFiles) = InfoTool.FoundAllFiles(outputDirectory, outputFilename, Parameters, false);
|
||||
if (!foundFiles)
|
||||
{
|
||||
resultProgress?.Report(Result.Failure($"There were files missing from the output:\n{string.Join("\n", missingFiles)}"));
|
||||
@@ -399,28 +389,36 @@ namespace MPF.Core
|
||||
|
||||
// Extract the information from the output files
|
||||
resultProgress?.Report(Result.Success("Extracting output information from output files..."));
|
||||
var submissionInfo = await InfoTool.ExtractOutputInformation(
|
||||
this.OutputPath,
|
||||
this.Drive,
|
||||
this.System,
|
||||
this.Type,
|
||||
this.Options,
|
||||
this.Parameters,
|
||||
var submissionInfo = await SubmissionInfoTool.ExtractOutputInformation(
|
||||
OutputPath,
|
||||
Drive,
|
||||
System,
|
||||
Type,
|
||||
Options,
|
||||
Parameters,
|
||||
resultProgress,
|
||||
protectionProgress);
|
||||
resultProgress?.Report(Result.Success("Extracting information complete!"));
|
||||
|
||||
// Inject seed submission info data, if necessary
|
||||
if (seedInfo != null)
|
||||
{
|
||||
resultProgress?.Report(Result.Success("Injecting user-supplied information..."));
|
||||
SubmissionInfoTool.InjectSubmissionInformation(submissionInfo, seedInfo);
|
||||
resultProgress?.Report(Result.Success("Information injection complete!"));
|
||||
}
|
||||
|
||||
// Eject the disc automatically if configured to
|
||||
if (Options.EjectAfterDump == true)
|
||||
{
|
||||
resultProgress?.Report(Result.Success($"Ejecting disc in drive {Drive?.Letter}"));
|
||||
resultProgress?.Report(Result.Success($"Ejecting disc in drive {Drive?.Name}"));
|
||||
await EjectDisc();
|
||||
}
|
||||
|
||||
// Reset the drive automatically if configured to
|
||||
if (this.InternalProgram == InternalProgram.DiscImageCreator && Options.DICResetDriveAfterDump)
|
||||
if (InternalProgram == InternalProgram.DiscImageCreator && Options.DICResetDriveAfterDump)
|
||||
{
|
||||
resultProgress?.Report(Result.Success($"Resetting drive {Drive?.Letter}"));
|
||||
resultProgress?.Report(Result.Success($"Resetting drive {Drive?.Name}"));
|
||||
await ResetDrive();
|
||||
}
|
||||
|
||||
@@ -445,36 +443,42 @@ namespace MPF.Core
|
||||
|
||||
// Format the information for the text output
|
||||
resultProgress?.Report(Result.Success("Formatting information..."));
|
||||
(var formattedValues, var formatResult) = InfoTool.FormatOutputData(submissionInfo, this.Options);
|
||||
(var formattedValues, var formatResult) = InfoTool.FormatOutputData(submissionInfo, Options);
|
||||
if (formattedValues == null)
|
||||
resultProgress?.Report(Result.Success(formatResult));
|
||||
else
|
||||
resultProgress?.Report(Result.Failure(formatResult));
|
||||
|
||||
// Get the filename suffix for auto-generated files
|
||||
var filenameSuffix = Options.AddFilenameSuffix ? Path.GetFileNameWithoutExtension(outputFilename) : null;
|
||||
|
||||
// Write the text output
|
||||
resultProgress?.Report(Result.Success("Writing information to !submissionInfo.txt..."));
|
||||
(bool txtSuccess, string txtResult) = InfoTool.WriteOutputData(outputDirectory, formattedValues);
|
||||
(bool txtSuccess, string txtResult) = InfoTool.WriteOutputData(outputDirectory, filenameSuffix, formattedValues);
|
||||
if (txtSuccess)
|
||||
resultProgress?.Report(Result.Success(txtResult));
|
||||
else
|
||||
resultProgress?.Report(Result.Failure(txtResult));
|
||||
|
||||
// Write the copy protection output
|
||||
if (Options.ScanForProtection && Options.OutputSeparateProtectionFile)
|
||||
if (submissionInfo?.CopyProtection?.FullProtections != null && submissionInfo.CopyProtection.FullProtections.Any())
|
||||
{
|
||||
resultProgress?.Report(Result.Success("Writing protection to !protectionInfo.txt..."));
|
||||
bool scanSuccess = InfoTool.WriteProtectionData(outputDirectory, submissionInfo);
|
||||
if (scanSuccess)
|
||||
resultProgress?.Report(Result.Success("Writing complete!"));
|
||||
else
|
||||
resultProgress?.Report(Result.Failure("Writing could not complete!"));
|
||||
if (Options.ScanForProtection && Options.OutputSeparateProtectionFile)
|
||||
{
|
||||
resultProgress?.Report(Result.Success("Writing protection to !protectionInfo.txt..."));
|
||||
bool scanSuccess = InfoTool.WriteProtectionData(outputDirectory, filenameSuffix, submissionInfo);
|
||||
if (scanSuccess)
|
||||
resultProgress?.Report(Result.Success("Writing complete!"));
|
||||
else
|
||||
resultProgress?.Report(Result.Failure("Writing could not complete!"));
|
||||
}
|
||||
}
|
||||
|
||||
// Write the JSON output, if required
|
||||
if (Options.OutputSubmissionJSON)
|
||||
{
|
||||
resultProgress?.Report(Result.Success($"Writing information to !submissionInfo.json{(Options.IncludeArtifacts ? ".gz" : string.Empty)}..."));
|
||||
bool jsonSuccess = InfoTool.WriteOutputData(outputDirectory, submissionInfo, Options.IncludeArtifacts);
|
||||
bool jsonSuccess = InfoTool.WriteOutputData(outputDirectory, filenameSuffix, submissionInfo, Options.IncludeArtifacts);
|
||||
if (jsonSuccess)
|
||||
resultProgress?.Report(Result.Success("Writing complete!"));
|
||||
else
|
||||
@@ -485,13 +489,24 @@ namespace MPF.Core
|
||||
if (Options.CompressLogFiles)
|
||||
{
|
||||
resultProgress?.Report(Result.Success("Compressing log files..."));
|
||||
(bool compressSuccess, string compressResult) = InfoTool.CompressLogFiles(outputDirectory, outputFilename, this.Parameters);
|
||||
(bool compressSuccess, string compressResult) = InfoTool.CompressLogFiles(outputDirectory, filenameSuffix, outputFilename, Parameters);
|
||||
if (compressSuccess)
|
||||
resultProgress?.Report(Result.Success(compressResult));
|
||||
else
|
||||
resultProgress?.Report(Result.Failure(compressResult));
|
||||
}
|
||||
|
||||
// Delete unnecessary files, if required
|
||||
if (Options.DeleteUnnecessaryFiles)
|
||||
{
|
||||
resultProgress?.Report(Result.Success("Deleting unnecessary files..."));
|
||||
(bool deleteSuccess, string deleteResult) = InfoTool.DeleteUnnecessaryFiles(outputDirectory, outputFilename, Parameters);
|
||||
if (deleteSuccess)
|
||||
resultProgress?.Report(Result.Success(deleteResult));
|
||||
else
|
||||
resultProgress?.Report(Result.Failure(deleteResult));
|
||||
}
|
||||
|
||||
resultProgress?.Report(Result.Success("Submission information process complete!"));
|
||||
return Result.Success();
|
||||
}
|
||||
@@ -516,18 +531,12 @@ namespace MPF.Core
|
||||
return parametersValid && floppyValid && removableDiskValid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run any additional tools given a DumpEnvironment
|
||||
/// </summary>
|
||||
/// <returns>Result instance with the outcome</returns>
|
||||
private Result ExecuteAdditionalTools() => Result.Success("No external tools needed!");
|
||||
|
||||
/// <summary>
|
||||
/// Run internal program async with an input set of parameters
|
||||
/// </summary>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns>Standard output from commandline window</returns>
|
||||
private async Task<string> ExecuteInternalProgram(BaseParameters parameters)
|
||||
private static async Task<string> ExecuteInternalProgram(BaseParameters parameters)
|
||||
{
|
||||
Process childProcess;
|
||||
string output = await Task.Run(() =>
|
||||
@@ -566,14 +575,14 @@ namespace MPF.Core
|
||||
private Result IsValidForDump()
|
||||
{
|
||||
// Validate that everything is good
|
||||
if (this.Parameters == null || !ParametersValid())
|
||||
if (Parameters == null || !ParametersValid())
|
||||
return Result.Failure("Error! Current configuration is not supported!");
|
||||
|
||||
// Fix the output paths, just in case
|
||||
this.OutputPath = InfoTool.NormalizeOutputPaths(this.OutputPath, true);
|
||||
OutputPath = InfoTool.NormalizeOutputPaths(OutputPath, false);
|
||||
|
||||
// Validate that the output path isn't on the dumping drive
|
||||
if (Drive != null && this.OutputPath[0] == Drive.Letter)
|
||||
if (Drive?.Name != null && OutputPath.StartsWith(Drive.Name))
|
||||
return Result.Failure("Error! Cannot output to same drive that is being dumped!");
|
||||
|
||||
// Validate that the required program exists
|
||||
@@ -582,7 +591,7 @@ namespace MPF.Core
|
||||
|
||||
// Validate that the dumping drive doesn't contain the executable
|
||||
string fullExecutablePath = Path.GetFullPath(Parameters.ExecutablePath);
|
||||
if (Drive != null && fullExecutablePath[0] == Drive.Letter)
|
||||
if (Drive?.Name != null && fullExecutablePath.StartsWith(Drive.Name))
|
||||
return Result.Failure("Error! Cannot dump same drive that executable resides on!");
|
||||
|
||||
// Validate that the current configuration is supported
|
||||
@@ -630,13 +639,13 @@ namespace MPF.Core
|
||||
var parameters = new Modules.DiscImageCreator.Parameters(string.Empty)
|
||||
{
|
||||
BaseCommand = command,
|
||||
DriveLetter = Drive.Letter.ToString(),
|
||||
DrivePath = Drive.Name,
|
||||
ExecutablePath = Options.DiscImageCreatorPath,
|
||||
};
|
||||
|
||||
return await ExecuteInternalProgram(parameters);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Hashing;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using MPF.Core.Data;
|
||||
|
||||
namespace MPF.Core.Hashing
|
||||
{
|
||||
/// <summary>
|
||||
/// Available hashing types
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum Hash
|
||||
public sealed class Hasher : IDisposable
|
||||
{
|
||||
CRC32 = 1 << 0,
|
||||
MD5 = 1 << 1,
|
||||
SHA1 = 1 << 2,
|
||||
SHA256 = 1 << 3,
|
||||
SHA384 = 1 << 4,
|
||||
SHA512 = 1 << 5,
|
||||
#region Properties
|
||||
|
||||
// Special combinations
|
||||
Standard = CRC32 | MD5 | SHA1,
|
||||
All = CRC32 | MD5 | SHA1 | SHA256 | SHA384 | SHA512,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Async hashing class wraper
|
||||
/// </summary>
|
||||
public class Hasher
|
||||
{
|
||||
/// <summary>
|
||||
/// Hash type associated with the current state
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public Hash HashType { get; private set; }
|
||||
#else
|
||||
public Hash HashType { get; init; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Current hash in bytes
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public byte[] CurrentHashBytes
|
||||
#else
|
||||
public byte[]? CurrentHashBytes
|
||||
#endif
|
||||
{
|
||||
get
|
||||
{
|
||||
#if NET48
|
||||
switch (_hasher)
|
||||
{
|
||||
case HashAlgorithm ha:
|
||||
return ha.Hash;
|
||||
case NonCryptographicHashAlgorithm ncha:
|
||||
return ncha.GetCurrentHash().Reverse().ToArray();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return (_hasher) switch
|
||||
{
|
||||
HashAlgorithm ha => ha.Hash,
|
||||
NonCryptographicHashAlgorithm ncha => ncha.GetCurrentHash().Reverse().ToArray(),
|
||||
_ => null,
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current hash as a string
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string CurrentHashString => ByteArrayToString(CurrentHashBytes);
|
||||
#else
|
||||
public string? CurrentHashString => ByteArrayToString(CurrentHashBytes);
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Internal hasher being used for processing
|
||||
/// </summary>
|
||||
/// <remarks>May be either a HashAlgorithm or NonCryptographicHashAlgorithm</remarks>
|
||||
#if NET48
|
||||
private object _hasher;
|
||||
#else
|
||||
private object? _hasher;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="hashType">Hash type to instantiate</param>
|
||||
public Hasher(Hash hashType)
|
||||
{
|
||||
this.HashType = hashType;
|
||||
@@ -47,57 +96,256 @@ namespace MPF.Core.Hashing
|
||||
/// </summary>
|
||||
private void GetHasher()
|
||||
{
|
||||
#if NET48
|
||||
switch (HashType)
|
||||
{
|
||||
case Hash.CRC32:
|
||||
_hasher = new Crc32();
|
||||
break;
|
||||
|
||||
case Hash.CRC64:
|
||||
_hasher = new Crc64();
|
||||
break;
|
||||
case Hash.MD5:
|
||||
_hasher = MD5.Create();
|
||||
break;
|
||||
|
||||
case Hash.SHA1:
|
||||
_hasher = SHA1.Create();
|
||||
break;
|
||||
|
||||
case Hash.SHA256:
|
||||
_hasher = SHA256.Create();
|
||||
break;
|
||||
|
||||
case Hash.SHA384:
|
||||
_hasher = SHA384.Create();
|
||||
break;
|
||||
|
||||
case Hash.SHA512:
|
||||
_hasher = SHA512.Create();
|
||||
break;
|
||||
case Hash.XxHash32:
|
||||
_hasher = new XxHash32();
|
||||
break;
|
||||
case Hash.XxHash64:
|
||||
_hasher = new XxHash64();
|
||||
break;
|
||||
}
|
||||
#else
|
||||
_hasher = HashType switch
|
||||
{
|
||||
Hash.CRC32 => new Crc32(),
|
||||
Hash.CRC64 => new Crc64(),
|
||||
Hash.MD5 => MD5.Create(),
|
||||
Hash.SHA1 => SHA1.Create(),
|
||||
Hash.SHA256 => SHA256.Create(),
|
||||
Hash.SHA384 => SHA384.Create(),
|
||||
Hash.SHA512 => SHA512.Create(),
|
||||
Hash.XxHash32 => new XxHash32(),
|
||||
Hash.XxHash64 => new XxHash64(),
|
||||
_ => null,
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_hasher is IDisposable disposable)
|
||||
disposable.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Static Hashing
|
||||
|
||||
/// <summary>
|
||||
/// Get hashes from an input file path
|
||||
/// </summary>
|
||||
/// <param name="filename">Path to the input file</param>
|
||||
/// <returns>True if hashing was successful, false otherwise</returns>
|
||||
#if NET48
|
||||
public static bool GetFileHashes(string filename, out long size, out string crc32, out string md5, out string sha1)
|
||||
#else
|
||||
public static bool GetFileHashes(string filename, out long size, out string? crc32, out string? md5, out string? sha1)
|
||||
#endif
|
||||
{
|
||||
// Set all initial values
|
||||
crc32 = null; md5 = null; sha1 = null;
|
||||
|
||||
// Get all file hashes
|
||||
var fileHashes = GetFileHashes(filename, out size);
|
||||
if (fileHashes == null)
|
||||
return false;
|
||||
|
||||
// Assign the file hashes and return
|
||||
crc32 = fileHashes[Hash.CRC32];
|
||||
md5 = fileHashes[Hash.MD5];
|
||||
sha1 = fileHashes[Hash.SHA1];
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get hashes from an input file path
|
||||
/// </summary>
|
||||
/// <param name="filename">Path to the input file</param>
|
||||
/// <returns>Dictionary containing hashes on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Dictionary<Hash, string> GetFileHashes(string filename, out long size)
|
||||
#else
|
||||
public static Dictionary<Hash, string?>? GetFileHashes(string filename, out long size)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't do anything
|
||||
if (!File.Exists(filename))
|
||||
{
|
||||
size = -1;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Set the file size
|
||||
size = new FileInfo(filename).Length;
|
||||
|
||||
// Create the output dictionary
|
||||
#if NET48
|
||||
var hashDict = new Dictionary<Hash, string>();
|
||||
#else
|
||||
var hashDict = new Dictionary<Hash, string?>();
|
||||
#endif
|
||||
|
||||
// Open the input file
|
||||
var input = File.OpenRead(filename);
|
||||
|
||||
// Return the hashes from the stream
|
||||
return GetStreamHashes(input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get hashes from an input Stream
|
||||
/// </summary>
|
||||
/// <param name="input">Stream to hash</param>
|
||||
/// <returns>Dictionary containing hashes on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Dictionary<Hash, string> GetStreamHashes(Stream input)
|
||||
#else
|
||||
public static Dictionary<Hash, string?>? GetStreamHashes(Stream input)
|
||||
#endif
|
||||
{
|
||||
// Create the output dictionary
|
||||
#if NET48
|
||||
var hashDict = new Dictionary<Hash, string>();
|
||||
#else
|
||||
var hashDict = new Dictionary<Hash, string?>();
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
// Get a list of hashers to run over the buffer
|
||||
var hashers = new Dictionary<Hash, Hasher>
|
||||
{
|
||||
{ Hash.CRC32, new Hasher(Hash.CRC32) },
|
||||
{ Hash.CRC64, new Hasher(Hash.CRC64) },
|
||||
{ Hash.MD5, new Hasher(Hash.MD5) },
|
||||
{ Hash.SHA1, new Hasher(Hash.SHA1) },
|
||||
{ Hash.SHA256, new Hasher(Hash.SHA256) },
|
||||
{ Hash.SHA384, new Hasher(Hash.SHA384) },
|
||||
{ Hash.SHA512, new Hasher(Hash.SHA512) },
|
||||
{ Hash.XxHash32, new Hasher(Hash.XxHash32) },
|
||||
{ Hash.XxHash64, new Hasher(Hash.XxHash64) },
|
||||
};
|
||||
|
||||
// Initialize the hashing helpers
|
||||
var loadBuffer = new ThreadLoadBuffer(input);
|
||||
int buffersize = 3 * 1024 * 1024;
|
||||
byte[] buffer0 = new byte[buffersize];
|
||||
byte[] buffer1 = new byte[buffersize];
|
||||
|
||||
/*
|
||||
Please note that some of the following code is adapted from
|
||||
RomVault. This is a modified version of how RomVault does
|
||||
threaded hashing. As such, some of the terminology and code
|
||||
is the same, though variable names and comments may have
|
||||
been tweaked to better fit this code base.
|
||||
*/
|
||||
|
||||
// Pre load the first buffer
|
||||
long refsize = input.Length;
|
||||
int next = refsize > buffersize ? buffersize : (int)refsize;
|
||||
input.Read(buffer0, 0, next);
|
||||
int current = next;
|
||||
refsize -= next;
|
||||
bool bufferSelect = true;
|
||||
|
||||
while (current > 0)
|
||||
{
|
||||
// Trigger the buffer load on the second buffer
|
||||
next = refsize > buffersize ? buffersize : (int)refsize;
|
||||
if (next > 0)
|
||||
loadBuffer.Trigger(bufferSelect ? buffer1 : buffer0, next);
|
||||
|
||||
byte[] buffer = bufferSelect ? buffer0 : buffer1;
|
||||
|
||||
// Run hashes in parallel
|
||||
Parallel.ForEach(hashers, h => h.Value.Process(buffer, current));
|
||||
|
||||
// Wait for the load buffer worker, if needed
|
||||
if (next > 0)
|
||||
loadBuffer.Wait();
|
||||
|
||||
// Setup for the next hashing step
|
||||
current = next;
|
||||
refsize -= next;
|
||||
bufferSelect = !bufferSelect;
|
||||
}
|
||||
|
||||
// Finalize all hashing helpers
|
||||
loadBuffer.Finish();
|
||||
Parallel.ForEach(hashers, h => h.Value.Terminate());
|
||||
|
||||
// Get the results
|
||||
hashDict[Hash.CRC32] = hashers[Hash.CRC32].CurrentHashString;
|
||||
hashDict[Hash.CRC64] = hashers[Hash.CRC64].CurrentHashString;
|
||||
hashDict[Hash.MD5] = hashers[Hash.MD5].CurrentHashString;
|
||||
hashDict[Hash.SHA1] = hashers[Hash.SHA1].CurrentHashString;
|
||||
hashDict[Hash.SHA256] = hashers[Hash.SHA256].CurrentHashString;
|
||||
hashDict[Hash.SHA384] = hashers[Hash.SHA384].CurrentHashString;
|
||||
hashDict[Hash.SHA512] = hashers[Hash.SHA512].CurrentHashString;
|
||||
hashDict[Hash.XxHash32] = hashers[Hash.XxHash32].CurrentHashString;
|
||||
hashDict[Hash.XxHash64] = hashers[Hash.XxHash64].CurrentHashString;
|
||||
hashDict[Hash.CRC64] = hashers[Hash.CRC64].CurrentHashString;
|
||||
|
||||
// Dispose of the hashers
|
||||
loadBuffer.Dispose();
|
||||
foreach (var hasher in hashers.Values)
|
||||
{
|
||||
hasher.Dispose();
|
||||
}
|
||||
|
||||
return hashDict;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
input.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Hashing
|
||||
|
||||
/// <summary>
|
||||
/// Process a buffer of some length with the internal hash algorithm
|
||||
/// </summary>
|
||||
public void Process(byte[] buffer, int size)
|
||||
{
|
||||
switch (HashType)
|
||||
switch (_hasher)
|
||||
{
|
||||
case Hash.CRC32:
|
||||
(_hasher as NonCryptographicHashAlgorithm)?.Append(buffer);
|
||||
case HashAlgorithm ha:
|
||||
ha.TransformBlock(buffer, 0, size, null, 0);
|
||||
break;
|
||||
|
||||
case Hash.MD5:
|
||||
case Hash.SHA1:
|
||||
case Hash.SHA256:
|
||||
case Hash.SHA384:
|
||||
case Hash.SHA512:
|
||||
(_hasher as HashAlgorithm)?.TransformBlock(buffer, 0, size, null, 0);
|
||||
case NonCryptographicHashAlgorithm ncha:
|
||||
var bufferSpan = new ReadOnlySpan<byte>(buffer, 0, size);
|
||||
ncha.Append(bufferSpan);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -105,68 +353,21 @@ namespace MPF.Core.Hashing
|
||||
/// <summary>
|
||||
/// Finalize the internal hash algorigthm
|
||||
/// </summary>
|
||||
/// <remarks>NonCryptographicHashAlgorithm implementations do not need finalization</remarks>
|
||||
public void Terminate()
|
||||
{
|
||||
byte[] emptyBuffer = new byte[0];
|
||||
switch (HashType)
|
||||
byte[] emptyBuffer = Array.Empty<byte>();
|
||||
switch (_hasher)
|
||||
{
|
||||
case Hash.CRC32:
|
||||
(_hasher as NonCryptographicHashAlgorithm)?.Append(emptyBuffer);
|
||||
break;
|
||||
|
||||
case Hash.MD5:
|
||||
case Hash.SHA1:
|
||||
case Hash.SHA256:
|
||||
case Hash.SHA384:
|
||||
case Hash.SHA512:
|
||||
(_hasher as HashAlgorithm)?.TransformFinalBlock(emptyBuffer, 0, 0);
|
||||
case HashAlgorithm ha:
|
||||
ha.TransformFinalBlock(emptyBuffer, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get internal hash as a byte array
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public byte[] GetHash()
|
||||
#else
|
||||
public byte[]? GetHash()
|
||||
#endif
|
||||
{
|
||||
if (_hasher == null)
|
||||
return null;
|
||||
#endregion
|
||||
|
||||
switch (HashType)
|
||||
{
|
||||
case Hash.CRC32:
|
||||
return (_hasher as NonCryptographicHashAlgorithm)?.GetCurrentHash();
|
||||
|
||||
case Hash.MD5:
|
||||
case Hash.SHA1:
|
||||
case Hash.SHA256:
|
||||
case Hash.SHA384:
|
||||
case Hash.SHA512:
|
||||
return (_hasher as HashAlgorithm)?.Hash;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get internal hash as a string
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string GetHashString()
|
||||
#else
|
||||
public string? GetHashString()
|
||||
#endif
|
||||
{
|
||||
var hash = GetHash();
|
||||
if (hash == null)
|
||||
return null;
|
||||
|
||||
return ByteArrayToString(hash);
|
||||
}
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Convert a byte array to a hex string
|
||||
@@ -194,5 +395,7 @@ namespace MPF.Core.Hashing
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
2794
MPF.Core/InfoTool.cs
2794
MPF.Core/InfoTool.cs
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2023</Copyright>
|
||||
<VersionPrefix>2.7.0</VersionPrefix>
|
||||
<VersionPrefix>2.7.5</VersionPrefix>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
|
||||
@@ -17,14 +17,15 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.8.0" GeneratePathProperty="true">
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.9.0" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Management.Infrastructure" Version="3.0.0-preview.2" />
|
||||
<PackageReference Include="Microsoft.Management.Infrastructure" Version="3.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.1.4" />
|
||||
<PackageReference Include="psxt001z" Version="0.21.0-beta1" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.1.5" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.1.1" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.1.6" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.1.7" />
|
||||
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
|
||||
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
|
||||
<PackageReference Include="System.IO.Hashing" Version="7.0.0" />
|
||||
|
||||
@@ -13,8 +13,9 @@ using SabreTools.Models.CueSheets;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Schemas;
|
||||
|
||||
// Ignore "Type or member is obsolete"
|
||||
#pragma warning disable CS0618
|
||||
#pragma warning disable CS0618 // Ignore "Type or member is obsolete"
|
||||
#pragma warning disable IDE0051 // Remove unused private members
|
||||
#pragma warning disable IDE0059 // Unnecessary assignment of a value
|
||||
|
||||
namespace MPF.Core.Modules.Aaru
|
||||
{
|
||||
@@ -256,11 +257,19 @@ namespace MPF.Core.Modules.Aaru
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public Parameters(string parameters) : base(parameters) { }
|
||||
#else
|
||||
public Parameters(string? parameters) : base(parameters) { }
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Parameters(RedumpSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, Options options)
|
||||
: base(system, type, driveLetter, filename, driveSpeed, options)
|
||||
#if NET48
|
||||
public Parameters(RedumpSystem? system, MediaType? type, string drivePath, string filename, int? driveSpeed, Options options)
|
||||
#else
|
||||
public Parameters(RedumpSystem? system, MediaType? type, string? drivePath, string filename, int? driveSpeed, Options options)
|
||||
#endif
|
||||
: base(system, type, drivePath, filename, driveSpeed, options)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -269,7 +278,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// <inheritdoc/>
|
||||
public override (bool, List<string>) CheckAllOutputFilesExist(string basePath, bool preCheck)
|
||||
{
|
||||
List<string> missingFiles = new List<string>();
|
||||
var missingFiles = new List<string>();
|
||||
switch (this.Type)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
@@ -328,10 +337,16 @@ namespace MPF.Core.Modules.Aaru
|
||||
// TODO: Fill in submission info specifics for Aaru
|
||||
var outputDirectory = Path.GetDirectoryName(basePath);
|
||||
|
||||
// Ensure that required sections exist
|
||||
info = SubmissionInfoTool.EnsureAllSections(info);
|
||||
|
||||
// TODO: Determine if there's an Aaru version anywhere
|
||||
if (info.DumpingInfo == null) info.DumpingInfo = new DumpingInfoSection();
|
||||
#if NET48
|
||||
info.DumpingInfo.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
info.DumpingInfo.DumpingDate = GetFileModifiedDate(basePath + ".cicm.xml")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
#else
|
||||
info.DumpingInfo!.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
#endif
|
||||
info.DumpingInfo.DumpingDate = InfoTool.GetFileModifiedDate(basePath + ".cicm.xml")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
// Deserialize the sidecar, if possible
|
||||
var sidecar = GenerateSidecar(basePath + ".cicm.xml");
|
||||
@@ -362,8 +377,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
var datafile = GenerateDatafile(sidecar, basePath);
|
||||
|
||||
// Fill in the hash data
|
||||
if (info.TracksAndWriteOffsets == null) info.TracksAndWriteOffsets = new TracksAndWriteOffsetsSection();
|
||||
info.TracksAndWriteOffsets.ClrMameProData = GenerateDatfile(datafile);
|
||||
#if NET48
|
||||
info.TracksAndWriteOffsets.ClrMameProData = InfoTool.GenerateDatfile(datafile);
|
||||
#else
|
||||
info.TracksAndWriteOffsets!.ClrMameProData = InfoTool.GenerateDatfile(datafile);
|
||||
#endif
|
||||
|
||||
switch (this.Type)
|
||||
{
|
||||
@@ -377,8 +395,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
if (File.Exists(basePath + ".resume.xml"))
|
||||
errorCount = GetErrorCount(basePath + ".resume.xml");
|
||||
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
info.CommonDiscInfo.ErrorsCount = (errorCount == -1 ? "Error retrieving error count" : errorCount.ToString());
|
||||
#else
|
||||
info.CommonDiscInfo!.ErrorsCount = (errorCount == -1 ? "Error retrieving error count" : errorCount.ToString());
|
||||
#endif
|
||||
|
||||
info.TracksAndWriteOffsets.Cuesheet = GenerateCuesheet(sidecar, basePath) ?? string.Empty;
|
||||
|
||||
@@ -390,12 +411,15 @@ namespace MPF.Core.Modules.Aaru
|
||||
case MediaType.DVD:
|
||||
case MediaType.HDDVD:
|
||||
case MediaType.BluRay:
|
||||
if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
|
||||
|
||||
// Get the individual hash data, as per internal
|
||||
if (GetISOHashValues(datafile, out long size, out var crc32, out var md5, out var sha1))
|
||||
if (InfoTool.GetISOHashValues(datafile, out long size, out var crc32, out var md5, out var sha1))
|
||||
{
|
||||
#if NET48
|
||||
info.SizeAndChecksums.Size = size;
|
||||
#else
|
||||
info.SizeAndChecksums!.CRC32 = crc32;
|
||||
#endif
|
||||
info.SizeAndChecksums.CRC32 = crc32;
|
||||
info.SizeAndChecksums.MD5 = md5;
|
||||
info.SizeAndChecksums.SHA1 = sha1;
|
||||
@@ -414,7 +438,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
if (this.Type == MediaType.DVD)
|
||||
layerbreak = GetLayerbreak(sidecar) ?? string.Empty;
|
||||
else if (this.Type == MediaType.BluRay)
|
||||
#if NET48
|
||||
layerbreak = info.SizeAndChecksums.Size > 25_025_314_816 ? "25025314816" : null;
|
||||
#else
|
||||
layerbreak = info.SizeAndChecksums!.Size > 25_025_314_816 ? "25025314816" : null;
|
||||
#endif
|
||||
|
||||
// If we have a single-layer disc
|
||||
if (string.IsNullOrWhiteSpace(layerbreak))
|
||||
@@ -424,7 +452,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
// If we have a dual-layer disc
|
||||
else
|
||||
{
|
||||
#if NET48
|
||||
info.SizeAndChecksums.Layerbreak = Int64.Parse(layerbreak);
|
||||
#else
|
||||
info.SizeAndChecksums!.Layerbreak = Int64.Parse(layerbreak);
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO: Investigate XGD disc outputs
|
||||
@@ -444,52 +476,60 @@ namespace MPF.Core.Modules.Aaru
|
||||
|
||||
case RedumpSystem.DVDAudio:
|
||||
case RedumpSystem.DVDVideo:
|
||||
if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
|
||||
#if NET48
|
||||
info.CopyProtection.Protection = GetDVDProtection(sidecar) ?? string.Empty;
|
||||
#else
|
||||
info.CopyProtection!.Protection = GetDVDProtection(sidecar) ?? string.Empty;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiPython2:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out var pythonTwoSerial, out Region? pythonTwoRegion, out var pythonTwoDate))
|
||||
if (InfoTool.GetPlayStationExecutableInfo(drive?.Name, out var pythonTwoSerial, out Region? pythonTwoRegion, out var pythonTwoDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = pythonTwoSerial ?? string.Empty;
|
||||
#else
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = pythonTwoSerial ?? string.Empty;
|
||||
#endif
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? pythonTwoRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = pythonTwoDate;
|
||||
}
|
||||
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation2Version(drive?.Letter) ?? string.Empty;
|
||||
#if NET48
|
||||
info.VersionAndEditions.Version = InfoTool.GetPlayStation2Version(drive?.Name) ?? string.Empty;
|
||||
#else
|
||||
info.VersionAndEditions!.Version = InfoTool.GetPlayStation2Version(drive?.Name) ?? string.Empty;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case RedumpSystem.MicrosoftXbox:
|
||||
if (GetXgdAuxInfo(sidecar, out var xgd1DMIHash, out var xgd1PFIHash, out var xgd1SSHash, out var ss, out var xgd1SSVer))
|
||||
{
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd1DMIHash ?? string.Empty;
|
||||
#else
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = xgd1DMIHash ?? string.Empty;
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd1PFIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd1SSHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd1SSVer ?? string.Empty;
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
#if NET48
|
||||
info.Extras.SecuritySectorRanges = ss ?? string.Empty;
|
||||
#else
|
||||
info.Extras!.SecuritySectorRanges = ss ?? string.Empty;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (GetXboxDMIInfo(sidecar, out var serial, out var version, out Region? region))
|
||||
{
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
info.CommonDiscInfo.Serial = serial ?? string.Empty;
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = version ?? string.Empty;
|
||||
#else
|
||||
info.CommonDiscInfo!.Serial = serial ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = version ?? string.Empty;
|
||||
#endif
|
||||
info.CommonDiscInfo.Region = region;
|
||||
}
|
||||
|
||||
@@ -498,41 +538,43 @@ namespace MPF.Core.Modules.Aaru
|
||||
case RedumpSystem.MicrosoftXbox360:
|
||||
if (GetXgdAuxInfo(sidecar, out var xgd23DMIHash, out var xgd23PFIHash, out var xgd23SSHash, out var ss360, out var xgd23SSVer))
|
||||
{
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd23DMIHash ?? string.Empty;
|
||||
#else
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = xgd23DMIHash ?? string.Empty;
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd23PFIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd23SSHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd23SSVer ?? string.Empty;
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
#if NET48
|
||||
info.Extras.SecuritySectorRanges = ss360 ?? string.Empty;
|
||||
#else
|
||||
info.Extras!.SecuritySectorRanges = ss360 ?? string.Empty;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (GetXbox360DMIInfo(sidecar, out var serial360, out var version360, out Region? region360))
|
||||
{
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
info.CommonDiscInfo.Serial = serial360 ?? string.Empty;
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = version360 ?? string.Empty;
|
||||
#else
|
||||
info.CommonDiscInfo!.Serial = serial360 ?? string.Empty;
|
||||
info.VersionAndEditions!.Version = version360 ?? string.Empty;
|
||||
#endif
|
||||
info.CommonDiscInfo.Region = region360;
|
||||
}
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out var playstationSerial, out Region? playstationRegion, out var playstationDate))
|
||||
if (InfoTool.GetPlayStationExecutableInfo(drive?.Name, out var playstationSerial, out Region? playstationRegion, out var playstationDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationSerial ?? string.Empty;
|
||||
#else
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = playstationSerial ?? string.Empty;
|
||||
#endif
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = playstationDate;
|
||||
}
|
||||
@@ -540,65 +582,70 @@ namespace MPF.Core.Modules.Aaru
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation2:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out var playstationTwoSerial, out Region? playstationTwoRegion, out var playstationTwoDate))
|
||||
if (InfoTool.GetPlayStationExecutableInfo(drive?.Name, out var playstationTwoSerial, out Region? playstationTwoRegion, out var playstationTwoDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationTwoSerial ?? string.Empty;
|
||||
#else
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = playstationTwoSerial ?? string.Empty;
|
||||
#endif
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationTwoRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = playstationTwoDate;
|
||||
}
|
||||
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation2Version(drive?.Letter) ?? string.Empty;
|
||||
#if NET48
|
||||
info.VersionAndEditions.Version = InfoTool.GetPlayStation2Version(drive?.Name) ?? string.Empty;
|
||||
#else
|
||||
info.VersionAndEditions!.Version = InfoTool.GetPlayStation2Version(drive?.Name) ?? string.Empty;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation3:
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation3Version(drive?.Letter) ?? string.Empty;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
info.VersionAndEditions.Version = InfoTool.GetPlayStation3Version(drive?.Name) ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = InfoTool.GetPlayStation3Serial(drive?.Name) ?? string.Empty;
|
||||
string firmwareVersion = InfoTool.GetPlayStation3FirmwareVersion(drive?.Name);
|
||||
if (firmwareVersion != null)
|
||||
info.CommonDiscInfo.ContentsSpecialFields[SiteCode.Patches] = $"PS3 Firmware {firmwareVersion}";
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
info.VersionAndEditions!.Version = InfoTool.GetPlayStation3Version(drive?.Name) ?? string.Empty;
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = InfoTool.GetPlayStation3Serial(drive?.Name) ?? string.Empty;
|
||||
string? firmwareVersion = InfoTool.GetPlayStation3FirmwareVersion(drive?.Name);
|
||||
if (firmwareVersion != null)
|
||||
info.CommonDiscInfo!.ContentsSpecialFields![SiteCode.Patches] = $"PS3 Firmware {firmwareVersion}";
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = GetPlayStation3Serial(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation4:
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation4Version(drive?.Letter) ?? string.Empty;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
info.VersionAndEditions.Version = InfoTool.GetPlayStation4Version(drive?.Name) ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = InfoTool.GetPlayStation4Serial(drive?.Name) ?? string.Empty;
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
info.VersionAndEditions!.Version = InfoTool.GetPlayStation4Version(drive?.Name) ?? string.Empty;
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = InfoTool.GetPlayStation4Serial(drive?.Name) ?? string.Empty;
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = GetPlayStation4Serial(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation5:
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation5Version(drive?.Letter) ?? string.Empty;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
info.VersionAndEditions.Version = InfoTool.GetPlayStation5Version(drive?.Name) ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = InfoTool.GetPlayStation5Serial(drive?.Name) ?? string.Empty;
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
info.VersionAndEditions!.Version = InfoTool.GetPlayStation5Version(drive?.Name) ?? string.Empty;
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.InternalSerialName] = InfoTool.GetPlayStation5Serial(drive?.Name) ?? string.Empty;
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = GetPlayStation5Serial(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
#if NET48
|
||||
if (info.Artifacts == null) info.Artifacts = new Dictionary<string, string>();
|
||||
#else
|
||||
info.Artifacts ??= new Dictionary<string, string>();
|
||||
#endif
|
||||
if (File.Exists(basePath + ".cicm.xml"))
|
||||
info.Artifacts["cicm"] = GetBase64(GetFullFile(basePath + ".cicm.xml")) ?? string.Empty;
|
||||
if (File.Exists(basePath + ".ibg"))
|
||||
@@ -621,7 +668,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
public override string? GenerateParameters()
|
||||
#endif
|
||||
{
|
||||
List<string> parameters = new List<string>();
|
||||
var parameters = new List<string>();
|
||||
|
||||
#region Pre-command flags
|
||||
|
||||
@@ -647,8 +694,12 @@ namespace MPF.Core.Modules.Aaru
|
||||
|
||||
#endregion
|
||||
|
||||
#if NET48
|
||||
if (BaseCommand == null)
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
#else
|
||||
BaseCommand ??= CommandStrings.NONE;
|
||||
#endif
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(BaseCommand))
|
||||
parameters.Add(BaseCommand);
|
||||
@@ -1637,7 +1688,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// <inheritdoc/>
|
||||
public override List<string> GetLogFilePaths(string basePath)
|
||||
{
|
||||
List<string> logFiles = new List<string>();
|
||||
var logFiles = new List<string>();
|
||||
switch (this.Type)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
@@ -1737,11 +1788,15 @@ namespace MPF.Core.Modules.Aaru
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetDefaultParameters(char driveLetter, string filename, int? driveSpeed, Options options)
|
||||
#if NET48
|
||||
protected override void SetDefaultParameters(string drivePath, string filename, int? driveSpeed, Options options)
|
||||
#else
|
||||
protected override void SetDefaultParameters(string? drivePath, string filename, int? driveSpeed, Options options)
|
||||
#endif
|
||||
{
|
||||
BaseCommand = $"{CommandStrings.MediaPrefixLong} {CommandStrings.MediaDump}";
|
||||
|
||||
InputValue = $"{driveLetter}:";
|
||||
InputValue = drivePath;
|
||||
OutputValue = filename;
|
||||
|
||||
if (driveSpeed != null)
|
||||
@@ -1814,7 +1869,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
protected override bool ValidateAndSetParameters(string parameters)
|
||||
#else
|
||||
protected override bool ValidateAndSetParameters(string? parameters)
|
||||
#endif
|
||||
{
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
|
||||
@@ -1825,7 +1884,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
// Now split the string into parts for easier validation
|
||||
// https://stackoverflow.com/questions/14655023/split-a-string-that-has-white-spaces-unless-they-are-enclosed-within-quotes
|
||||
parameters = parameters.Trim();
|
||||
List<string> parts = Regex.Matches(parameters, @"[\""].+?[\""]|[^ ]+")
|
||||
List<string> parts = Regex.Matches(parameters, @"[\""].+?[\""]|[^ ]+", RegexOptions.Compiled)
|
||||
.Cast<Match>()
|
||||
.Select(m => m.Value)
|
||||
.ToList();
|
||||
@@ -2332,7 +2391,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Private Extra Methods
|
||||
|
||||
@@ -2342,9 +2401,9 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// <param name="baseCommand">Command string to normalize</param>
|
||||
/// <returns>Normalized command</returns>
|
||||
#if NET48
|
||||
private string NormalizeCommand(List<string> parts, ref int start)
|
||||
private static string NormalizeCommand(List<string> parts, ref int start)
|
||||
#else
|
||||
private string? NormalizeCommand(List<string> parts, ref int start)
|
||||
private static string? NormalizeCommand(List<string> parts, ref int start)
|
||||
#endif
|
||||
{
|
||||
// Invalid start means invalid command
|
||||
@@ -2375,9 +2434,9 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// <param name="baseCommand">Command string to normalize</param>
|
||||
/// <returns>Normalized command</returns>
|
||||
#if NET48
|
||||
private string NormalizeCommand(string baseCommand)
|
||||
private static string NormalizeCommand(string baseCommand)
|
||||
#else
|
||||
private string? NormalizeCommand(string baseCommand)
|
||||
private static string? NormalizeCommand(string baseCommand)
|
||||
#endif
|
||||
{
|
||||
// If the base command is inavlid, just return nulls
|
||||
@@ -2402,6 +2461,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
case CommandStrings.ArchivePrefixShort:
|
||||
case CommandStrings.ArchivePrefixLong:
|
||||
family = CommandStrings.ArchivePrefixLong;
|
||||
#if NET48
|
||||
switch (splitCommand[1])
|
||||
{
|
||||
case CommandStrings.ArchiveInfo:
|
||||
@@ -2411,11 +2471,19 @@ namespace MPF.Core.Modules.Aaru
|
||||
command = null;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
command = splitCommand[1] switch
|
||||
{
|
||||
CommandStrings.ArchiveInfo => CommandStrings.ArchiveInfo,
|
||||
_ => null,
|
||||
};
|
||||
#endif
|
||||
|
||||
break;
|
||||
case CommandStrings.DatabasePrefixShort:
|
||||
case CommandStrings.DatabasePrefixLong:
|
||||
family = CommandStrings.DatabasePrefixLong;
|
||||
#if NET48
|
||||
switch (splitCommand[1])
|
||||
{
|
||||
case CommandStrings.DatabaseStats:
|
||||
@@ -2428,12 +2496,21 @@ namespace MPF.Core.Modules.Aaru
|
||||
command = null;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
command = splitCommand[1] switch
|
||||
{
|
||||
CommandStrings.DatabaseStats => CommandStrings.DatabaseStats,
|
||||
CommandStrings.DatabaseUpdate => CommandStrings.DatabaseUpdate,
|
||||
_ => null,
|
||||
};
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case CommandStrings.DevicePrefixShort:
|
||||
case CommandStrings.DevicePrefixLong:
|
||||
family = CommandStrings.DevicePrefixLong;
|
||||
#if NET48
|
||||
switch (splitCommand[1])
|
||||
{
|
||||
case CommandStrings.DeviceInfo:
|
||||
@@ -2449,6 +2526,15 @@ namespace MPF.Core.Modules.Aaru
|
||||
command = null;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
command = splitCommand[1] switch
|
||||
{
|
||||
CommandStrings.DeviceInfo => CommandStrings.DeviceInfo,
|
||||
CommandStrings.DeviceList => CommandStrings.DeviceList,
|
||||
CommandStrings.DeviceReport => CommandStrings.DeviceReport,
|
||||
_ => null,
|
||||
};
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
@@ -2456,6 +2542,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
case CommandStrings.FilesystemPrefixShortAlt:
|
||||
case CommandStrings.FilesystemPrefixLong:
|
||||
family = CommandStrings.FilesystemPrefixLong;
|
||||
#if NET48
|
||||
switch (splitCommand[1])
|
||||
{
|
||||
case CommandStrings.FilesystemExtract:
|
||||
@@ -2475,12 +2562,24 @@ namespace MPF.Core.Modules.Aaru
|
||||
command = null;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
command = splitCommand[1] switch
|
||||
{
|
||||
CommandStrings.FilesystemExtract => CommandStrings.FilesystemExtract,
|
||||
CommandStrings.FilesystemInfo => CommandStrings.FilesystemInfo,
|
||||
CommandStrings.FilesystemListShort => CommandStrings.FilesystemListLong,
|
||||
CommandStrings.FilesystemListLong => CommandStrings.FilesystemListLong,
|
||||
CommandStrings.FilesystemOptions => CommandStrings.FilesystemOptions,
|
||||
_ => null,
|
||||
};
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case CommandStrings.ImagePrefixShort:
|
||||
case CommandStrings.ImagePrefixLong:
|
||||
family = CommandStrings.ImagePrefixLong;
|
||||
#if NET48
|
||||
switch (splitCommand[1])
|
||||
{
|
||||
case CommandStrings.ImageChecksumShort:
|
||||
@@ -2519,12 +2618,31 @@ namespace MPF.Core.Modules.Aaru
|
||||
command = null;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
command = splitCommand[1] switch
|
||||
{
|
||||
CommandStrings.ImageChecksumShort => CommandStrings.ImageChecksumLong,
|
||||
CommandStrings.ImageChecksumLong => CommandStrings.ImageChecksumLong,
|
||||
CommandStrings.ImageCompareShort => CommandStrings.ImageCompareLong,
|
||||
CommandStrings.ImageCompareLong => CommandStrings.ImageCompareLong,
|
||||
CommandStrings.ImageConvert => CommandStrings.ImageConvert,
|
||||
CommandStrings.ImageCreateSidecar => CommandStrings.ImageCreateSidecar,
|
||||
CommandStrings.ImageDecode => CommandStrings.ImageDecode,
|
||||
CommandStrings.ImageEntropy => CommandStrings.ImageEntropy,
|
||||
CommandStrings.ImageInfo => CommandStrings.ImageInfo,
|
||||
CommandStrings.ImageOptions => CommandStrings.ImageOptions,
|
||||
CommandStrings.ImagePrint => CommandStrings.ImagePrint,
|
||||
CommandStrings.ImageVerify => CommandStrings.ImageVerify,
|
||||
_ => null,
|
||||
};
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case CommandStrings.MediaPrefixShort:
|
||||
case CommandStrings.MediaPrefixLong:
|
||||
family = CommandStrings.MediaPrefixLong;
|
||||
#if NET48
|
||||
switch (splitCommand[1])
|
||||
{
|
||||
case CommandStrings.MediaDump:
|
||||
@@ -2540,6 +2658,15 @@ namespace MPF.Core.Modules.Aaru
|
||||
command = null;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
command = splitCommand[1] switch
|
||||
{
|
||||
CommandStrings.MediaDump => CommandStrings.MediaDump,
|
||||
CommandStrings.MediaInfo => CommandStrings.MediaInfo,
|
||||
CommandStrings.MediaScan => CommandStrings.MediaScan,
|
||||
_ => null,
|
||||
};
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
@@ -2554,6 +2681,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
else
|
||||
{
|
||||
family = null;
|
||||
#if NET48
|
||||
switch (splitCommand[0])
|
||||
{
|
||||
case CommandStrings.Configure:
|
||||
@@ -2575,6 +2703,17 @@ namespace MPF.Core.Modules.Aaru
|
||||
command = null;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
command = splitCommand[0] switch
|
||||
{
|
||||
CommandStrings.Configure => CommandStrings.Configure,
|
||||
CommandStrings.Formats => CommandStrings.Formats,
|
||||
CommandStrings.ListEncodings => CommandStrings.ListEncodings,
|
||||
CommandStrings.ListNamespaces => CommandStrings.ListNamespaces,
|
||||
CommandStrings.Remote => CommandStrings.Remote,
|
||||
_ => null,
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
// If the command itself is invalid, then return null
|
||||
@@ -2598,7 +2737,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// <param name="trackType">TrackTypeTrackType to convert</param>
|
||||
/// <param name="bytesPerSector">Sector size to help with specific subtypes</param>
|
||||
/// <returns>CueTrackDataType representing the input data</returns>
|
||||
private CueTrackDataType ConvertToDataType(TrackTypeTrackType trackType, uint bytesPerSector)
|
||||
private static CueTrackDataType ConvertToDataType(TrackTypeTrackType trackType, uint bytesPerSector)
|
||||
{
|
||||
switch (trackType)
|
||||
{
|
||||
@@ -2629,7 +2768,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="trackFlagsType">TrackFlagsType containing flag data</param>
|
||||
/// <returns>CueTrackFlag representing the flags</returns>
|
||||
private CueTrackFlag ConvertToTrackFlag(TrackFlagsType trackFlagsType)
|
||||
private static CueTrackFlag ConvertToTrackFlag(TrackFlagsType trackFlagsType)
|
||||
{
|
||||
if (trackFlagsType == null)
|
||||
return 0;
|
||||
@@ -2655,9 +2794,9 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// <param name="basePath">Base path for determining file names</param>
|
||||
/// <returns>String containing the cuesheet, null on error</returns>
|
||||
#if NET48
|
||||
private string GenerateCuesheet(CICMMetadataType cicmSidecar, string basePath)
|
||||
private static string GenerateCuesheet(CICMMetadataType cicmSidecar, string basePath)
|
||||
#else
|
||||
private string? GenerateCuesheet(CICMMetadataType? cicmSidecar, string basePath)
|
||||
private static string? GenerateCuesheet(CICMMetadataType? cicmSidecar, string basePath)
|
||||
#endif
|
||||
{
|
||||
// If the object is null, we can't get information from it
|
||||
@@ -2669,7 +2808,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
var cueFiles = new List<CueFile>();
|
||||
var cueSheet = new CueSheet
|
||||
{
|
||||
Performer = string.Join(", ", cicmSidecar.Performer ?? new string[0]),
|
||||
Performer = string.Join(", ", cicmSidecar.Performer ?? Array.Empty<string>()),
|
||||
};
|
||||
|
||||
// Only care about OpticalDisc types
|
||||
@@ -2694,7 +2833,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
foreach (TrackType track in opticalDisc.Track)
|
||||
{
|
||||
// Create cue track entry
|
||||
CueTrack cueTrack = new CueTrack
|
||||
var cueTrack = new CueTrack
|
||||
{
|
||||
Number = (int)(track.Sequence?.TrackNumber ?? 0),
|
||||
DataType = ConvertToDataType(track.TrackType1, track.BytesPerSector),
|
||||
@@ -2703,7 +2842,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
};
|
||||
|
||||
// Create cue file entry
|
||||
CueFile cueFile = new CueFile
|
||||
var cueFile = new CueFile
|
||||
{
|
||||
FileName = GenerateTrackName(basePath, (int)totalTracks, cueTrack.Number, opticalDisc.DiscType),
|
||||
FileType = CueFileType.BINARY,
|
||||
@@ -2922,8 +3061,8 @@ namespace MPF.Core.Modules.Aaru
|
||||
return null;
|
||||
|
||||
// Required variables
|
||||
Datafile datafile = new Datafile();
|
||||
List<Rom> roms = new List<Rom>();
|
||||
var datafile = new Datafile();
|
||||
var roms = new List<Rom>();
|
||||
|
||||
// Process OpticalDisc, if possible
|
||||
if (cicmSidecar.OpticalDisc != null && cicmSidecar.OpticalDisc.Length > 0)
|
||||
@@ -3176,7 +3315,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
}
|
||||
|
||||
// Now generate the byte array data
|
||||
List<byte> pvdData = new List<byte>();
|
||||
var pvdData = new List<byte>();
|
||||
pvdData.AddRange(new string(' ', 13).ToCharArray().Select(c => (byte)c));
|
||||
pvdData.AddRange(GeneratePVDDateTimeBytes(creation));
|
||||
pvdData.AddRange(GeneratePVDDateTimeBytes(modification));
|
||||
@@ -3247,7 +3386,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
return null;
|
||||
|
||||
string pvdLine = $"{row} : ";
|
||||
#if NET48
|
||||
pvdLine += BitConverter.ToString(bytes.Slice(0, 8).ToArray()).Replace("-", " ");
|
||||
#else
|
||||
pvdLine += BitConverter.ToString(bytes[..8].ToArray()).Replace("-", " ");
|
||||
#endif
|
||||
pvdLine += " ";
|
||||
pvdLine += BitConverter.ToString(bytes.Slice(8, 8).ToArray().ToArray()).Replace("-", " ");
|
||||
pvdLine += " ";
|
||||
@@ -3287,7 +3430,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
if (xtr == null)
|
||||
return null;
|
||||
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(CICMMetadataType));
|
||||
var serializer = new XmlSerializer(typeof(CICMMetadataType));
|
||||
return serializer.Deserialize(xtr) as CICMMetadataType;
|
||||
}
|
||||
|
||||
@@ -3394,7 +3537,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
long? totalErrors = null;
|
||||
|
||||
// Parse the resume XML file
|
||||
using (StreamReader sr = File.OpenText(resume))
|
||||
using (var sr = File.OpenText(resume))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -7,6 +6,8 @@ using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
#pragma warning disable IDE0051 // Remove unused private members
|
||||
|
||||
namespace MPF.Core.Modules.CleanRip
|
||||
{
|
||||
/// <summary>
|
||||
@@ -22,11 +23,19 @@ namespace MPF.Core.Modules.CleanRip
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public Parameters(string parameters) : base(parameters) { }
|
||||
#else
|
||||
public Parameters(string? parameters) : base(parameters) { }
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Parameters(RedumpSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, Options options)
|
||||
: base(system, type, driveLetter, filename, driveSpeed, options)
|
||||
#if NET48
|
||||
public Parameters(RedumpSystem? system, MediaType? type, string drivePath, string filename, int? driveSpeed, Options options)
|
||||
#else
|
||||
public Parameters(RedumpSystem? system, MediaType? type, string? drivePath, string filename, int? driveSpeed, Options options)
|
||||
#endif
|
||||
: base(system, type, drivePath, filename, driveSpeed, options)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -35,7 +44,7 @@ namespace MPF.Core.Modules.CleanRip
|
||||
/// <inheritdoc/>
|
||||
public override (bool, List<string>) CheckAllOutputFilesExist(string basePath, bool preCheck)
|
||||
{
|
||||
List<string> missingFiles = new List<string>();
|
||||
var missingFiles = new List<string>();
|
||||
switch (this.Type)
|
||||
{
|
||||
case MediaType.DVD: // Only added here to help users; not strictly correct
|
||||
@@ -66,18 +75,27 @@ namespace MPF.Core.Modules.CleanRip
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive? drive, bool includeArtifacts)
|
||||
#endif
|
||||
{
|
||||
// Ensure that required sections exist
|
||||
info = SubmissionInfoTool.EnsureAllSections(info);
|
||||
|
||||
// TODO: Determine if there's a CleanRip version anywhere
|
||||
if (info.DumpingInfo == null) info.DumpingInfo = new DumpingInfoSection();
|
||||
#if NET48
|
||||
info.DumpingInfo.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
info.DumpingInfo.DumpingDate = GetFileModifiedDate(basePath + "-dumpinfo.txt")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
#else
|
||||
info.DumpingInfo!.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
#endif
|
||||
info.DumpingInfo.DumpingDate = InfoTool.GetFileModifiedDate(basePath + "-dumpinfo.txt")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
var datafile = GenerateCleanripDatafile(basePath + ".iso", basePath + "-dumpinfo.txt");
|
||||
|
||||
// Get the individual hash data, as per internal
|
||||
if (GetISOHashValues(datafile, out long size, out var crc32, out var md5, out var sha1))
|
||||
if (InfoTool.GetISOHashValues(datafile, out long size, out var crc32, out var md5, out var sha1))
|
||||
{
|
||||
if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
|
||||
#if NET48
|
||||
info.SizeAndChecksums.Size = size;
|
||||
#else
|
||||
info.SizeAndChecksums!.Size = size;
|
||||
#endif
|
||||
info.SizeAndChecksums.CRC32 = crc32;
|
||||
info.SizeAndChecksums.MD5 = md5;
|
||||
info.SizeAndChecksums.SHA1 = sha1;
|
||||
@@ -94,23 +112,23 @@ namespace MPF.Core.Modules.CleanRip
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
if (File.Exists(basePath + ".bca"))
|
||||
{
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
#if NET48
|
||||
info.Extras.BCA = GetBCA(basePath + ".bca");
|
||||
}
|
||||
#else
|
||||
info.Extras!.BCA = GetBCA(basePath + ".bca");
|
||||
#endif
|
||||
|
||||
if (GetGameCubeWiiInformation(basePath + "-dumpinfo.txt", out Region? gcRegion, out var gcVersion, out var gcName))
|
||||
{
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
info.CommonDiscInfo.Region = gcRegion ?? info.CommonDiscInfo.Region;
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = gcVersion ?? info.VersionAndEditions.Version;
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.Region = gcRegion ?? info.CommonDiscInfo.Region;
|
||||
info.VersionAndEditions.Version = gcVersion ?? info.VersionAndEditions.Version;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalName] = gcName ?? string.Empty;
|
||||
#else
|
||||
info.CommonDiscInfo!.Region = gcRegion ?? info.CommonDiscInfo.Region;
|
||||
info.VersionAndEditions!.Version = gcVersion ?? info.VersionAndEditions.Version;
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.InternalName] = gcName ?? string.Empty;
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -119,7 +137,12 @@ namespace MPF.Core.Modules.CleanRip
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
#if NET48
|
||||
if (info.Artifacts == null) info.Artifacts = new Dictionary<string, string>();
|
||||
#else
|
||||
info.Artifacts ??= new Dictionary<string, string>();
|
||||
#endif
|
||||
|
||||
if (File.Exists(basePath + ".bca"))
|
||||
info.Artifacts["bca"] = GetBase64(GetFullFile(basePath + ".bca", binary: true)) ?? string.Empty;
|
||||
if (File.Exists(basePath + "-dumpinfo.txt"))
|
||||
@@ -130,7 +153,7 @@ namespace MPF.Core.Modules.CleanRip
|
||||
/// <inheritdoc/>
|
||||
public override List<string> GetLogFilePaths(string basePath)
|
||||
{
|
||||
List<string> logFiles = new List<string>();
|
||||
var logFiles = new List<string>();
|
||||
switch (this.Type)
|
||||
{
|
||||
case MediaType.DVD: // Only added here to help users; not strictly correct
|
||||
@@ -167,7 +190,7 @@ namespace MPF.Core.Modules.CleanRip
|
||||
if (!File.Exists(dumpinfo))
|
||||
return null;
|
||||
|
||||
using (StreamReader sr = File.OpenText(dumpinfo))
|
||||
using (var sr = File.OpenText(dumpinfo))
|
||||
{
|
||||
long size = new FileInfo(iso).Length;
|
||||
string crc = string.Empty;
|
||||
@@ -186,12 +209,21 @@ namespace MPF.Core.Modules.CleanRip
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
#if NET48
|
||||
else if (line.StartsWith("CRC32"))
|
||||
crc = line.Substring(7).ToLowerInvariant();
|
||||
else if (line.StartsWith("MD5"))
|
||||
md5 = line.Substring(5);
|
||||
else if (line.StartsWith("SHA-1"))
|
||||
sha1 = line.Substring(7);
|
||||
#else
|
||||
else if (line.StartsWith("CRC32"))
|
||||
crc = line[7..].ToLowerInvariant();
|
||||
else if (line.StartsWith("MD5"))
|
||||
md5 = line[5..];
|
||||
else if (line.StartsWith("SHA-1"))
|
||||
sha1 = line[7..];
|
||||
#endif
|
||||
}
|
||||
|
||||
return new Datafile
|
||||
@@ -263,7 +295,7 @@ namespace MPF.Core.Modules.CleanRip
|
||||
if (!File.Exists(dumpinfo))
|
||||
return null;
|
||||
|
||||
using (StreamReader sr = File.OpenText(dumpinfo))
|
||||
using (var sr = File.OpenText(dumpinfo))
|
||||
{
|
||||
long size = new FileInfo(iso).Length;
|
||||
string crc = string.Empty;
|
||||
@@ -282,12 +314,21 @@ namespace MPF.Core.Modules.CleanRip
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
#if NET48
|
||||
else if (line.StartsWith("CRC32"))
|
||||
crc = line.Substring(7).ToLowerInvariant();
|
||||
else if (line.StartsWith("MD5"))
|
||||
md5 = line.Substring(5);
|
||||
else if (line.StartsWith("SHA-1"))
|
||||
sha1 = line.Substring(7);
|
||||
#else
|
||||
else if (line.StartsWith("CRC32"))
|
||||
crc = line[7..].ToLowerInvariant();
|
||||
else if (line.StartsWith("MD5"))
|
||||
md5 = line[5..];
|
||||
else if (line.StartsWith("SHA-1"))
|
||||
sha1 = line[7..];
|
||||
#endif
|
||||
}
|
||||
|
||||
return $"<rom name=\"{Path.GetFileName(iso)}\" size=\"{size}\" crc=\"{crc}\" md5=\"{md5}\" sha1=\"{sha1}\" />";
|
||||
@@ -320,7 +361,7 @@ namespace MPF.Core.Modules.CleanRip
|
||||
if (!File.Exists(dumpinfo))
|
||||
return false;
|
||||
|
||||
using (StreamReader sr = File.OpenText(dumpinfo))
|
||||
using (var sr = File.OpenText(dumpinfo))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -338,15 +379,27 @@ namespace MPF.Core.Modules.CleanRip
|
||||
}
|
||||
else if (line.StartsWith("Version"))
|
||||
{
|
||||
#if NET48
|
||||
version = line.Substring("Version: ".Length);
|
||||
#else
|
||||
version = line["Version: ".Length..];
|
||||
#endif
|
||||
}
|
||||
else if (line.StartsWith("Internal Name"))
|
||||
{
|
||||
#if NET48
|
||||
name = line.Substring("Internal Name: ".Length);
|
||||
#else
|
||||
name = line["Internal Name: ".Length..];
|
||||
#endif
|
||||
}
|
||||
else if (line.StartsWith("Filename"))
|
||||
{
|
||||
#if NET48
|
||||
string serial = line.Substring("Filename: ".Length);
|
||||
#else
|
||||
string serial = line["Filename: ".Length..];
|
||||
#endif
|
||||
|
||||
// char gameType = serial[0];
|
||||
// string gameid = serial[1] + serial[2];
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Hashing;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core.Modules.UmdImageCreator
|
||||
@@ -21,11 +22,19 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public Parameters(string parameters) : base(parameters) { }
|
||||
#else
|
||||
public Parameters(string? parameters) : base(parameters) { }
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Parameters(RedumpSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, Options options)
|
||||
: base(system, type, driveLetter, filename, driveSpeed, options)
|
||||
#if NET48
|
||||
public Parameters(RedumpSystem? system, MediaType? type, string drivePath, string filename, int? driveSpeed, Options options)
|
||||
#else
|
||||
public Parameters(RedumpSystem? system, MediaType? type, string? drivePath, string filename, int? driveSpeed, Options options)
|
||||
#endif
|
||||
: base(system, type, drivePath, filename, driveSpeed, options)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -34,7 +43,7 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
/// <inheritdoc/>
|
||||
public override (bool, List<string>) CheckAllOutputFilesExist(string basePath, bool preCheck)
|
||||
{
|
||||
List<string> missingFiles = new List<string>();
|
||||
var missingFiles = new List<string>();
|
||||
switch (this.Type)
|
||||
{
|
||||
case MediaType.UMD:
|
||||
@@ -67,22 +76,34 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive? drive, bool includeArtifacts)
|
||||
#endif
|
||||
{
|
||||
// Ensure that required sections exist
|
||||
info = SubmissionInfoTool.EnsureAllSections(info);
|
||||
|
||||
// TODO: Determine if there's a UMDImageCreator version anywhere
|
||||
if (info.DumpingInfo == null) info.DumpingInfo = new DumpingInfoSection();
|
||||
#if NET48
|
||||
info.DumpingInfo.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
info.DumpingInfo.DumpingDate = GetFileModifiedDate(basePath + "_disc.txt")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
#else
|
||||
info.DumpingInfo!.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
#endif
|
||||
info.DumpingInfo.DumpingDate = InfoTool.GetFileModifiedDate(basePath + "_disc.txt")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
// Extract info based generically on MediaType
|
||||
switch (this.Type)
|
||||
{
|
||||
case MediaType.UMD:
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
#if NET48
|
||||
info.Extras.PVD = GetPVD(basePath + "_mainInfo.txt") ?? string.Empty;
|
||||
#else
|
||||
info.Extras!.PVD = GetPVD(basePath + "_mainInfo.txt") ?? string.Empty;
|
||||
#endif
|
||||
|
||||
if (GetFileHashes(basePath + ".iso", out long filesize, out var crc32, out var md5, out var sha1))
|
||||
if (Hasher.GetFileHashes(basePath + ".iso", out long filesize, out var crc32, out var md5, out var sha1))
|
||||
{
|
||||
if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
|
||||
#if NET48
|
||||
info.SizeAndChecksums.Size = filesize;
|
||||
#else
|
||||
info.SizeAndChecksums!.Size = filesize;
|
||||
#endif
|
||||
info.SizeAndChecksums.CRC32 = crc32;
|
||||
info.SizeAndChecksums.MD5 = md5;
|
||||
info.SizeAndChecksums.SHA1 = sha1;
|
||||
@@ -90,13 +111,17 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
|
||||
if (GetUMDAuxInfo(basePath + "_disc.txt", out var title, out DiscCategory? umdcat, out var umdversion, out var umdlayer, out long umdsize))
|
||||
{
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
info.CommonDiscInfo.Title = title ?? string.Empty;
|
||||
info.CommonDiscInfo.Category = umdcat ?? DiscCategory.Games;
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = umdversion ?? string.Empty;
|
||||
if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
|
||||
info.SizeAndChecksums.Size = umdsize;
|
||||
#else
|
||||
info.CommonDiscInfo!.Title = title ?? string.Empty;
|
||||
info.CommonDiscInfo.Category = umdcat ?? DiscCategory.Games;
|
||||
info.VersionAndEditions!.Version = umdversion ?? string.Empty;
|
||||
info.SizeAndChecksums!.Size = umdsize;
|
||||
#endif
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(umdlayer))
|
||||
info.SizeAndChecksums.Layerbreak = Int64.Parse(umdlayer ?? "-1");
|
||||
@@ -108,7 +133,12 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
#if NET48
|
||||
if (info.Artifacts == null) info.Artifacts = new Dictionary<string, string>();
|
||||
#else
|
||||
info.Artifacts ??= new Dictionary<string, string>();
|
||||
#endif
|
||||
|
||||
if (File.Exists(basePath + "_disc.txt"))
|
||||
info.Artifacts["disc"] = GetBase64(GetFullFile(basePath + "_disc.txt")) ?? string.Empty;
|
||||
if (File.Exists(basePath + "_drive.txt"))
|
||||
@@ -125,7 +155,7 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
/// <inheritdoc/>
|
||||
public override List<string> GetLogFilePaths(string basePath)
|
||||
{
|
||||
List<string> logFiles = new List<string>();
|
||||
var logFiles = new List<string>();
|
||||
switch (this.Type)
|
||||
{
|
||||
case MediaType.UMD:
|
||||
@@ -165,7 +195,7 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
if (!File.Exists(mainInfo))
|
||||
return null;
|
||||
|
||||
using (StreamReader sr = File.OpenText(mainInfo))
|
||||
using (var sr = File.OpenText(mainInfo))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -207,7 +237,7 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
if (!File.Exists(disc))
|
||||
return false;
|
||||
|
||||
using (StreamReader sr = File.OpenText(disc))
|
||||
using (var sr = File.OpenText(disc))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -220,11 +250,15 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
break;
|
||||
|
||||
if (line.StartsWith("TITLE") && title == null)
|
||||
#if NET48
|
||||
title = line.Substring("TITLE: ".Length);
|
||||
#else
|
||||
title = line["TITLE: ".Length..];
|
||||
#endif
|
||||
else if (line.StartsWith("DISC_VERSION") && umdversion == null)
|
||||
umdversion = line.Split(' ')[1];
|
||||
else if (line.StartsWith("pspUmdTypes"))
|
||||
umdcat = GetUMDCategory(line.Split(' ')[1]);
|
||||
umdcat = InfoTool.GetUMDCategory(line.Split(' ')[1]);
|
||||
else if (line.StartsWith("L0 length"))
|
||||
umdlayer = line.Split(' ')[2];
|
||||
else if (line.StartsWith("FileSize:"))
|
||||
@@ -232,7 +266,7 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
}
|
||||
|
||||
// If the L0 length is the size of the full disc, there's no layerbreak
|
||||
if (Int64.TryParse(umdlayer, out long umdlayerValue) && umdlayerValue * 2048 == umdsize)
|
||||
if (Int64.TryParse(umdlayer, out long umdlayerValue) && umdlayerValue * 2048 == umdsize)
|
||||
umdlayer = null;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -4,8 +4,8 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using BinaryObjectScanner;
|
||||
using BinaryObjectScanner.Protection;
|
||||
using BurnOutSharp;
|
||||
using psxt001z;
|
||||
|
||||
namespace MPF.Core
|
||||
@@ -95,8 +95,16 @@ namespace MPF.Core
|
||||
/// </summary>
|
||||
/// <param name="path">Path to scan for anti-modchip strings</param>
|
||||
/// <returns>Anti-modchip existence if possible, false on error</returns>
|
||||
#if NET48
|
||||
public static async Task<bool> GetPlayStationAntiModchipDetected(string path)
|
||||
#else
|
||||
public static async Task<bool> GetPlayStationAntiModchipDetected(string? path)
|
||||
#endif
|
||||
{
|
||||
// If there is no valid path
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return false;
|
||||
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
@@ -107,7 +115,7 @@ namespace MPF.Core
|
||||
try
|
||||
{
|
||||
byte[] fileContent = File.ReadAllBytes(file);
|
||||
string protection = antiModchip.CheckContents(file, fileContent, false);
|
||||
var protection = antiModchip.CheckContents(file, fileContent, false);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
return true;
|
||||
}
|
||||
@@ -154,7 +162,7 @@ namespace MPF.Core
|
||||
foundProtections = foundProtections.Where(p => p != "ActiveMARK");
|
||||
|
||||
// Cactus Data Shield
|
||||
if (foundProtections.Any(p => Regex.IsMatch(p, @"Cactus Data Shield [0-9]{3} .+")) && foundProtections.Any(p => p == "Cactus Data Shield 200"))
|
||||
if (foundProtections.Any(p => Regex.IsMatch(p, @"Cactus Data Shield [0-9]{3} .+", RegexOptions.Compiled)) && foundProtections.Any(p => p == "Cactus Data Shield 200"))
|
||||
foundProtections = foundProtections.Where(p => p != "Cactus Data Shield 200");
|
||||
|
||||
// CD-Check
|
||||
@@ -184,7 +192,7 @@ namespace MPF.Core
|
||||
// JoWood X-Prot
|
||||
if (foundProtections.Any(p => p.StartsWith("JoWood X-Prot")))
|
||||
{
|
||||
if (foundProtections.Any(p => Regex.IsMatch(p, @"JoWood X-Prot [0-9]\.[0-9]\.[0-9]\.[0-9]{2}")))
|
||||
if (foundProtections.Any(p => Regex.IsMatch(p, @"JoWood X-Prot [0-9]\.[0-9]\.[0-9]\.[0-9]{2}", RegexOptions.Compiled)))
|
||||
{
|
||||
foundProtections = foundProtections.Where(p => p != "JoWood X-Prot")
|
||||
.Where(p => p != "JoWood X-Prot v1.0-v1.3")
|
||||
@@ -233,28 +241,28 @@ namespace MPF.Core
|
||||
// SafeDisc
|
||||
if (foundProtections.Any(p => p.StartsWith("SafeDisc")))
|
||||
{
|
||||
if (foundProtections.Any(p => Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}")))
|
||||
if (foundProtections.Any(p => Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled)))
|
||||
{
|
||||
foundProtections = foundProtections.Where(p => !p.StartsWith("Macrovision Protected Application"))
|
||||
.Where(p => !p.StartsWith("Macrovision Protection File"))
|
||||
.Where(p => !p.StartsWith("Macrovision Security Driver"))
|
||||
.Where(p => p != "SafeDisc")
|
||||
.Where(p => !(Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}-[0-9]\.[0-9]{2}\.[0-9]{3}")))
|
||||
.Where(p => !(Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}/+")))
|
||||
.Where(p => !(Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}-[0-9]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled)))
|
||||
.Where(p => !(Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}/+", RegexOptions.Compiled)))
|
||||
.Where(p => p != "SafeDisc 1/Lite")
|
||||
.Where(p => p != "SafeDisc 2+");
|
||||
}
|
||||
else if (foundProtections.Any(p => Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}-[0-9]\.[0-9]{2}\.[0-9]{3}")))
|
||||
else if (foundProtections.Any(p => Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}-[0-9]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled)))
|
||||
{
|
||||
foundProtections = foundProtections.Where(p => !p.StartsWith("Macrovision Protected Application"))
|
||||
.Where(p => !p.StartsWith("Macrovision Protection File"))
|
||||
.Where(p => !p.StartsWith("Macrovision Security Driver"))
|
||||
.Where(p => p != "SafeDisc")
|
||||
.Where(p => !(Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}/+")))
|
||||
.Where(p => !(Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}/+", RegexOptions.Compiled)))
|
||||
.Where(p => p != "SafeDisc 1/Lite")
|
||||
.Where(p => p != "SafeDisc 2+");
|
||||
}
|
||||
else if (foundProtections.Any(p => Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}/+")))
|
||||
else if (foundProtections.Any(p => Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}/+", RegexOptions.Compiled)))
|
||||
{
|
||||
foundProtections = foundProtections.Where(p => !p.StartsWith("Macrovision Protected Application"))
|
||||
.Where(p => !p.StartsWith("Macrovision Protection File"))
|
||||
@@ -294,7 +302,7 @@ namespace MPF.Core
|
||||
// StarForce
|
||||
if (foundProtections.Any(p => p.StartsWith("StarForce")))
|
||||
{
|
||||
if (foundProtections.Any(p => Regex.IsMatch(p, @"StarForce [0-9]+\..+")))
|
||||
if (foundProtections.Any(p => Regex.IsMatch(p, @"StarForce [0-9]+\..+", RegexOptions.Compiled)))
|
||||
{
|
||||
foundProtections = foundProtections.Where(p => p != "StarForce")
|
||||
.Where(p => p != "StarForce 3-5")
|
||||
|
||||
1924
MPF.Core/SubmissionInfoTool.cs
Normal file
1924
MPF.Core/SubmissionInfoTool.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,11 @@ namespace MPF.Core.UI.ViewModels
|
||||
/// <summary>
|
||||
/// List of Redump-supported Regions
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static readonly List<Region> RedumpRegions = new List<Region>
|
||||
#else
|
||||
private static readonly List<Region> RedumpRegions = new()
|
||||
#endif
|
||||
{
|
||||
Region.Argentina,
|
||||
Region.Asia,
|
||||
@@ -129,7 +133,11 @@ namespace MPF.Core.UI.ViewModels
|
||||
/// <summary>
|
||||
/// List of Redump-supported Languages
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static readonly List<Language> RedumpLanguages = new List<Language>
|
||||
#else
|
||||
private static readonly List<Language> RedumpLanguages = new()
|
||||
#endif
|
||||
{
|
||||
Language.Afrikaans,
|
||||
Language.Albanian,
|
||||
@@ -191,10 +199,14 @@ namespace MPF.Core.UI.ViewModels
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public DiscInformationViewModel(Options options, SubmissionInfo submissionInfo)
|
||||
#else
|
||||
public DiscInformationViewModel(Options options, SubmissionInfo? submissionInfo)
|
||||
#endif
|
||||
{
|
||||
Options = options;
|
||||
SubmissionInfo = submissionInfo.Clone() as SubmissionInfo ?? new SubmissionInfo();
|
||||
SubmissionInfo = submissionInfo?.Clone() as SubmissionInfo ?? new SubmissionInfo();
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
@@ -4,11 +4,11 @@ using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BurnOutSharp;
|
||||
using BinaryObjectScanner;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Utilities;
|
||||
using MPF.Core.UI.ComboBoxItems;
|
||||
using MPF.Core.Utilities;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core.UI.ViewModels
|
||||
@@ -104,7 +104,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_optionsMenuItemEnabled = value;
|
||||
TriggerPropertyChanged("OptionsMenuItemEnabled");
|
||||
TriggerPropertyChanged(nameof(OptionsMenuItemEnabled));
|
||||
}
|
||||
}
|
||||
private bool _optionsMenuItemEnabled;
|
||||
@@ -118,7 +118,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_currentSystem = value;
|
||||
TriggerPropertyChanged("CurrentSystem");
|
||||
TriggerPropertyChanged(nameof(CurrentSystem));
|
||||
}
|
||||
}
|
||||
private RedumpSystem? _currentSystem;
|
||||
@@ -132,7 +132,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_systemTypeComboBoxEnabled = value;
|
||||
TriggerPropertyChanged("SystemTypeComboBoxEnabled");
|
||||
TriggerPropertyChanged(nameof(SystemTypeComboBoxEnabled));
|
||||
}
|
||||
}
|
||||
private bool _systemTypeComboBoxEnabled;
|
||||
@@ -146,7 +146,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_currentMediaType = value;
|
||||
TriggerPropertyChanged("CurrentMediaType");
|
||||
TriggerPropertyChanged(nameof(CurrentMediaType));
|
||||
}
|
||||
}
|
||||
private MediaType? _currentMediaType;
|
||||
@@ -160,7 +160,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_mediaTypeComboBoxEnabled = value;
|
||||
TriggerPropertyChanged("MediaTypeComboBoxEnabled");
|
||||
TriggerPropertyChanged(nameof(MediaTypeComboBoxEnabled));
|
||||
}
|
||||
}
|
||||
private bool _mediaTypeComboBoxEnabled;
|
||||
@@ -174,7 +174,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_outputPath = value;
|
||||
TriggerPropertyChanged("OutputPath");
|
||||
TriggerPropertyChanged(nameof(OutputPath));
|
||||
}
|
||||
}
|
||||
private string _outputPath;
|
||||
@@ -188,7 +188,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_outputPathTextBoxEnabled = value;
|
||||
TriggerPropertyChanged("OutputPathTextBoxEnabled");
|
||||
TriggerPropertyChanged(nameof(OutputPathTextBoxEnabled));
|
||||
}
|
||||
}
|
||||
private bool _outputPathTextBoxEnabled;
|
||||
@@ -202,7 +202,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_outputPathBrowseButtonEnabled = value;
|
||||
TriggerPropertyChanged("OutputPathBrowseButtonEnabled");
|
||||
TriggerPropertyChanged(nameof(OutputPathBrowseButtonEnabled));
|
||||
}
|
||||
}
|
||||
private bool _outputPathBrowseButtonEnabled;
|
||||
@@ -220,7 +220,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_currentDrive = value;
|
||||
TriggerPropertyChanged("CurrentDrive");
|
||||
TriggerPropertyChanged(nameof(CurrentDrive));
|
||||
}
|
||||
}
|
||||
#if NET48
|
||||
@@ -238,7 +238,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_driveLetterComboBoxEnabled = value;
|
||||
TriggerPropertyChanged("DriveLetterComboBoxEnabled");
|
||||
TriggerPropertyChanged(nameof(DriveLetterComboBoxEnabled));
|
||||
}
|
||||
}
|
||||
private bool _driveLetterComboBoxEnabled;
|
||||
@@ -252,7 +252,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_driveSpeed = value;
|
||||
TriggerPropertyChanged("DriveSpeed");
|
||||
TriggerPropertyChanged(nameof(DriveSpeed));
|
||||
}
|
||||
}
|
||||
private int _driveSpeed;
|
||||
@@ -266,7 +266,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_driveSpeedComboBoxEnabled = value;
|
||||
TriggerPropertyChanged("DriveSpeedComboBoxEnabled");
|
||||
TriggerPropertyChanged(nameof(DriveSpeedComboBoxEnabled));
|
||||
}
|
||||
}
|
||||
private bool _driveSpeedComboBoxEnabled;
|
||||
@@ -280,7 +280,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_currentProgram = value;
|
||||
TriggerPropertyChanged("CurrentProgram");
|
||||
TriggerPropertyChanged(nameof(CurrentProgram));
|
||||
}
|
||||
}
|
||||
private InternalProgram _currentProgram;
|
||||
@@ -294,7 +294,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_dumpingProgramComboBoxEnabled = value;
|
||||
TriggerPropertyChanged("DumpingProgramComboBoxEnabled");
|
||||
TriggerPropertyChanged(nameof(DumpingProgramComboBoxEnabled));
|
||||
}
|
||||
}
|
||||
private bool _dumpingProgramComboBoxEnabled;
|
||||
@@ -308,7 +308,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_parameters = value;
|
||||
TriggerPropertyChanged("Parameters");
|
||||
TriggerPropertyChanged(nameof(Parameters));
|
||||
}
|
||||
}
|
||||
private string _parameters;
|
||||
@@ -322,7 +322,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_parametersCheckBoxEnabled = value;
|
||||
TriggerPropertyChanged("ParametersCheckBoxEnabled");
|
||||
TriggerPropertyChanged(nameof(ParametersCheckBoxEnabled));
|
||||
}
|
||||
}
|
||||
private bool _parametersCheckBoxEnabled;
|
||||
@@ -336,7 +336,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_enableParametersCheckBoxEnabled = value;
|
||||
TriggerPropertyChanged("EnableParametersCheckBoxEnabled");
|
||||
TriggerPropertyChanged(nameof(EnableParametersCheckBoxEnabled));
|
||||
}
|
||||
}
|
||||
private bool _enableParametersCheckBoxEnabled;
|
||||
@@ -350,7 +350,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_startStopButtonEnabled = value;
|
||||
TriggerPropertyChanged("StartStopButtonEnabled");
|
||||
TriggerPropertyChanged(nameof(StartStopButtonEnabled));
|
||||
}
|
||||
}
|
||||
private bool _startStopButtonEnabled;
|
||||
@@ -364,7 +364,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_startStopButtonText = (value as string) ?? string.Empty;
|
||||
TriggerPropertyChanged("StartStopButtonText");
|
||||
TriggerPropertyChanged(nameof(StartStopButtonText));
|
||||
}
|
||||
}
|
||||
private string _startStopButtonText;
|
||||
@@ -378,7 +378,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_mediaScanButtonEnabled = value;
|
||||
TriggerPropertyChanged("MediaScanButtonEnabled");
|
||||
TriggerPropertyChanged(nameof(MediaScanButtonEnabled));
|
||||
}
|
||||
}
|
||||
private bool _mediaScanButtonEnabled;
|
||||
@@ -392,7 +392,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_updateVolumeLabelEnabled = value;
|
||||
TriggerPropertyChanged("UpdateVolumeLabelEnabled");
|
||||
TriggerPropertyChanged(nameof(UpdateVolumeLabelEnabled));
|
||||
}
|
||||
}
|
||||
private bool _updateVolumeLabelEnabled;
|
||||
@@ -406,7 +406,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_copyProtectScanButtonEnabled = value;
|
||||
TriggerPropertyChanged("CopyProtectScanButtonEnabled");
|
||||
TriggerPropertyChanged(nameof(CopyProtectScanButtonEnabled));
|
||||
}
|
||||
}
|
||||
private bool _copyProtectScanButtonEnabled;
|
||||
@@ -420,7 +420,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_status = value;
|
||||
TriggerPropertyChanged("Status");
|
||||
TriggerPropertyChanged(nameof(Status));
|
||||
}
|
||||
}
|
||||
private string _status;
|
||||
@@ -434,7 +434,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_logPanelExpanded = value;
|
||||
TriggerPropertyChanged("LogPanelExpanded");
|
||||
TriggerPropertyChanged(nameof(LogPanelExpanded));
|
||||
}
|
||||
}
|
||||
private bool _logPanelExpanded;
|
||||
@@ -452,7 +452,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_drives = value;
|
||||
TriggerPropertyChanged("Drives");
|
||||
TriggerPropertyChanged(nameof(Drives));
|
||||
}
|
||||
}
|
||||
private List<Drive> _drives;
|
||||
@@ -466,7 +466,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_driveSpeeds = value;
|
||||
TriggerPropertyChanged("DriveSpeeds");
|
||||
TriggerPropertyChanged(nameof(DriveSpeeds));
|
||||
}
|
||||
}
|
||||
private List<int> _driveSpeeds;
|
||||
@@ -484,7 +484,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_mediaTypes = value;
|
||||
TriggerPropertyChanged("MediaTypes");
|
||||
TriggerPropertyChanged(nameof(MediaTypes));
|
||||
}
|
||||
}
|
||||
#if NET48
|
||||
@@ -502,7 +502,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_systems = value;
|
||||
TriggerPropertyChanged("Systems");
|
||||
TriggerPropertyChanged(nameof(Systems));
|
||||
}
|
||||
}
|
||||
private List<RedumpSystemComboBoxItem> _systems;
|
||||
@@ -516,7 +516,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_internalPrograms = value;
|
||||
TriggerPropertyChanged("InternalPrograms");
|
||||
TriggerPropertyChanged(nameof(InternalPrograms));
|
||||
}
|
||||
}
|
||||
private List<Element<InternalProgram>> _internalPrograms;
|
||||
@@ -544,11 +544,13 @@ namespace MPF.Core.UI.ViewModels
|
||||
SystemTypeComboBoxEnabled = true;
|
||||
MediaTypeComboBoxEnabled = true;
|
||||
OutputPathTextBoxEnabled = true;
|
||||
OutputPathBrowseButtonEnabled = true;
|
||||
DriveLetterComboBoxEnabled = true;
|
||||
DumpingProgramComboBoxEnabled = true;
|
||||
StartStopButtonEnabled = true;
|
||||
StartStopButtonText = Interface.StartDumping;
|
||||
MediaScanButtonEnabled = true;
|
||||
EnableParametersCheckBoxEnabled = true;
|
||||
LogPanelExpanded = _options.OpenLogWindowAtStartup;
|
||||
|
||||
MediaTypes = new List<Element<MediaType>>();
|
||||
@@ -585,14 +587,14 @@ namespace MPF.Core.UI.ViewModels
|
||||
private void TriggerPropertyChanged(string propertyName)
|
||||
{
|
||||
// Disable event handlers temporarily
|
||||
CanExecuteSelectionChanged = false;
|
||||
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
|
||||
DisableEventHandlers();
|
||||
|
||||
// If the property change event is initialized
|
||||
if (PropertyChanged != null)
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
|
||||
// Reenable event handlers
|
||||
CanExecuteSelectionChanged = true;
|
||||
// Reenable event handlers, if necessary
|
||||
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -606,7 +608,8 @@ namespace MPF.Core.UI.ViewModels
|
||||
private void PopulateDrives()
|
||||
{
|
||||
// Disable other UI updates
|
||||
CanExecuteSelectionChanged = false;
|
||||
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
|
||||
DisableEventHandlers();
|
||||
|
||||
VerboseLogLn("Scanning for drives..");
|
||||
|
||||
@@ -615,19 +618,19 @@ namespace MPF.Core.UI.ViewModels
|
||||
this.UpdateVolumeLabelEnabled = true;
|
||||
|
||||
// If we have a selected drive, keep track of it
|
||||
char? lastSelectedDrive = this.CurrentDrive?.Letter;
|
||||
char? lastSelectedDrive = this.CurrentDrive?.Name?[0] ?? null;
|
||||
|
||||
// Populate the list of drives and add it to the combo box
|
||||
Drives = Drive.CreateListOfDrives(this.Options.IgnoreFixedDrives);
|
||||
|
||||
if (Drives.Count > 0)
|
||||
{
|
||||
VerboseLogLn($"Found {Drives.Count} drives: {string.Join(", ", Drives.Select(d => d.Letter))}");
|
||||
VerboseLogLn($"Found {Drives.Count} drives: {string.Join(", ", Drives.Select(d => d.Name))}");
|
||||
|
||||
// Check for the last selected drive, if possible
|
||||
int index = -1;
|
||||
if (lastSelectedDrive != null)
|
||||
index = Drives.FindIndex(d => d.MarkedActive && d.Letter == lastSelectedDrive);
|
||||
index = Drives.FindIndex(d => d.MarkedActive && (d.Name?[0] ?? '\0') == lastSelectedDrive);
|
||||
|
||||
// Check for active optical drives
|
||||
if (index == -1)
|
||||
@@ -662,8 +665,8 @@ namespace MPF.Core.UI.ViewModels
|
||||
this.CopyProtectScanButtonEnabled = false;
|
||||
}
|
||||
|
||||
// Reenable UI updates
|
||||
CanExecuteSelectionChanged = true;
|
||||
// Reenable event handlers, if necessary
|
||||
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -672,7 +675,8 @@ namespace MPF.Core.UI.ViewModels
|
||||
private void PopulateMediaType()
|
||||
{
|
||||
// Disable other UI updates
|
||||
CanExecuteSelectionChanged = false;
|
||||
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
|
||||
DisableEventHandlers();
|
||||
|
||||
if (this.CurrentSystem != null)
|
||||
{
|
||||
@@ -692,8 +696,8 @@ namespace MPF.Core.UI.ViewModels
|
||||
this.CurrentMediaType = null;
|
||||
}
|
||||
|
||||
// Reenable UI updates
|
||||
CanExecuteSelectionChanged = true;
|
||||
// Reenable event handlers, if necessary
|
||||
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -702,7 +706,8 @@ namespace MPF.Core.UI.ViewModels
|
||||
private void PopulateInternalPrograms()
|
||||
{
|
||||
// Disable other UI updates
|
||||
CanExecuteSelectionChanged = false;
|
||||
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
|
||||
DisableEventHandlers();
|
||||
|
||||
// Get the current internal program
|
||||
InternalProgram internalProgram = this.Options.InternalProgram;
|
||||
@@ -715,8 +720,8 @@ namespace MPF.Core.UI.ViewModels
|
||||
int currentIndex = InternalPrograms.FindIndex(m => m == internalProgram);
|
||||
this.CurrentProgram = (currentIndex > -1 ? InternalPrograms[currentIndex].Value : InternalPrograms[0].Value);
|
||||
|
||||
// Reenable UI updates
|
||||
CanExecuteSelectionChanged = true;
|
||||
// Reenable event handlers, if necessary
|
||||
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -797,7 +802,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
/// <summary>
|
||||
/// Build a dummy SubmissionInfo
|
||||
/// </summary>
|
||||
public SubmissionInfo CreateDebugSubmissionInfo()
|
||||
public static SubmissionInfo CreateDebugSubmissionInfo()
|
||||
{
|
||||
return new SubmissionInfo()
|
||||
{
|
||||
@@ -960,13 +965,13 @@ namespace MPF.Core.UI.ViewModels
|
||||
|
||||
if (_environment != null && _environment.Options.EjectAfterDump)
|
||||
{
|
||||
VerboseLogLn($"Ejecting disc in drive {_environment.Drive?.Letter}");
|
||||
VerboseLogLn($"Ejecting disc in drive {_environment.Drive?.Name}");
|
||||
await _environment.EjectDisc();
|
||||
}
|
||||
|
||||
if (_environment != null && this.Options.DICResetDriveAfterDump)
|
||||
{
|
||||
VerboseLogLn($"Resetting drive {_environment.Drive?.Letter}");
|
||||
VerboseLogLn($"Resetting drive {_environment.Drive?.Name}");
|
||||
await _environment.ResetDrive();
|
||||
}
|
||||
}
|
||||
@@ -977,13 +982,23 @@ namespace MPF.Core.UI.ViewModels
|
||||
/// </summary>
|
||||
/// <param name="savedSettings">Indicates if the settings were saved or not</param>
|
||||
/// <param name="newOptions">Options representing the new, saved values</param>
|
||||
#if NET48
|
||||
public void UpdateOptions(bool savedSettings, Data.Options newOptions)
|
||||
#else
|
||||
public void UpdateOptions(bool savedSettings, Data.Options? newOptions)
|
||||
#endif
|
||||
{
|
||||
// Get which options to save
|
||||
var optionsToSave = savedSettings ? newOptions : Options;
|
||||
|
||||
// Ensure the first run flag is unset
|
||||
var continuingOptions = new Data.Options(optionsToSave);
|
||||
continuingOptions.FirstRun = false;
|
||||
this.Options = continuingOptions;
|
||||
|
||||
// If settings were changed, reinitialize the UI
|
||||
if (savedSettings)
|
||||
{
|
||||
this.Options = new Data.Options(newOptions);
|
||||
InitializeUIValues(removeEventHandlers: true, rescanDrives: true);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -998,14 +1013,15 @@ namespace MPF.Core.UI.ViewModels
|
||||
public void InitializeUIValues(bool removeEventHandlers, bool rescanDrives)
|
||||
{
|
||||
// Disable the dumping button
|
||||
this.StartStopButtonEnabled = false;
|
||||
StartStopButtonEnabled = false;
|
||||
|
||||
// Safely uncheck the parameters box, just in case
|
||||
if (this.ParametersCheckBoxEnabled == true)
|
||||
if (ParametersCheckBoxEnabled == true)
|
||||
{
|
||||
this.CanExecuteSelectionChanged = false;
|
||||
this.ParametersCheckBoxEnabled = false;
|
||||
this.CanExecuteSelectionChanged = true;
|
||||
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
|
||||
DisableEventHandlers();
|
||||
ParametersCheckBoxEnabled = false;
|
||||
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
|
||||
}
|
||||
|
||||
// Remove event handlers to ensure ordering
|
||||
@@ -1015,7 +1031,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
// Populate the list of drives and determine the system
|
||||
if (rescanDrives)
|
||||
{
|
||||
this.Status = "Creating drive list, please wait!";
|
||||
Status = "Creating drive list, please wait!";
|
||||
PopulateDrives();
|
||||
}
|
||||
else
|
||||
@@ -1041,7 +1057,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
EnableEventHandlers();
|
||||
|
||||
// Enable the dumping button, if necessary
|
||||
this.StartStopButtonEnabled = ShouldEnableDumpingButton();
|
||||
StartStopButtonEnabled = ShouldEnableDumpingButton();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1056,9 +1072,10 @@ namespace MPF.Core.UI.ViewModels
|
||||
// Safely uncheck the parameters box, just in case
|
||||
if (this.ParametersCheckBoxEnabled == true)
|
||||
{
|
||||
this.CanExecuteSelectionChanged = false;
|
||||
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged;
|
||||
this.DisableEventHandlers();
|
||||
this.ParametersCheckBoxEnabled = false;
|
||||
this.CanExecuteSelectionChanged = true;
|
||||
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
|
||||
}
|
||||
|
||||
// Remove event handlers to ensure ordering
|
||||
@@ -1106,8 +1123,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
/// <param name="text">Text to write to the log</param>
|
||||
private void Log(string text)
|
||||
{
|
||||
if (_logger != null)
|
||||
_logger(LogLevel.USER, text);
|
||||
_logger?.Invoke(LogLevel.USER, text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1122,8 +1138,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
/// <param name="text">Text to write to the log</param>
|
||||
private void ErrorLog(string text)
|
||||
{
|
||||
if (_logger != null)
|
||||
_logger(LogLevel.ERROR, text);
|
||||
_logger?.Invoke(LogLevel.ERROR, text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1138,8 +1153,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
/// <param name="text">Text to write to the log</param>
|
||||
private void SecretLog(string text)
|
||||
{
|
||||
if (_logger != null)
|
||||
_logger(LogLevel.SECRET, text);
|
||||
_logger?.Invoke(LogLevel.SECRET, text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1195,7 +1209,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
// If the drive is marked active, try to read from it
|
||||
else if (this.CurrentDrive.MarkedActive)
|
||||
{
|
||||
VerboseLog($"Trying to detect media type for drive {this.CurrentDrive.Letter} [{this.CurrentDrive.DriveFormat}] using size and filesystem.. ");
|
||||
VerboseLog($"Trying to detect media type for drive {this.CurrentDrive.Name} [{this.CurrentDrive.DriveFormat}] using size and filesystem.. ");
|
||||
(MediaType? detectedMediaType, var errorMessage) = this.CurrentDrive.GetMediaType(this.CurrentSystem);
|
||||
|
||||
// If we got an error message, post it to the log
|
||||
@@ -1255,7 +1269,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
}
|
||||
else if (!this.Options.SkipSystemDetection)
|
||||
{
|
||||
VerboseLog($"Trying to detect system for drive {this.CurrentDrive.Letter}.. ");
|
||||
VerboseLog($"Trying to detect system for drive {this.CurrentDrive.Name}.. ");
|
||||
var currentSystem = this.CurrentDrive?.GetRedumpSystem(this.Options.DefaultSystem) ?? this.Options.DefaultSystem;
|
||||
VerboseLogLn(currentSystem == null ? "unable to detect." : ($"detected {currentSystem.LongName()}."));
|
||||
|
||||
@@ -1423,7 +1437,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
// Catch this in case there's an input path issue
|
||||
try
|
||||
{
|
||||
int driveIndex = Drives.Select(d => d.Letter).ToList().IndexOf(_environment.Parameters?.InputPath?[0] ?? default(char));
|
||||
int driveIndex = Drives.Select(d => d.Name?[0] ?? '\0').ToList().IndexOf(_environment.Parameters?.InputPath?[0] ?? default);
|
||||
this.CurrentDrive = (driveIndex != -1 ? Drives[driveIndex] : Drives[0]);
|
||||
}
|
||||
catch { }
|
||||
@@ -1437,7 +1451,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
// Disable change handling
|
||||
DisableEventHandlers();
|
||||
|
||||
this.OutputPath = InfoTool.NormalizeOutputPaths(_environment.Parameters?.OutputPath, true);
|
||||
this.OutputPath = InfoTool.NormalizeOutputPaths(_environment.Parameters?.OutputPath, false);
|
||||
|
||||
if (MediaTypes != null)
|
||||
{
|
||||
@@ -1460,14 +1474,18 @@ namespace MPF.Core.UI.ViewModels
|
||||
#endif
|
||||
{
|
||||
// Determine current environment, just in case
|
||||
#if NET48
|
||||
if (_environment == null)
|
||||
_environment = DetermineEnvironment();
|
||||
#else
|
||||
_environment ??= DetermineEnvironment();
|
||||
#endif
|
||||
|
||||
// If we don't have a valid drive
|
||||
if (this.CurrentDrive == null || this.CurrentDrive.Letter == default(char))
|
||||
if (this.CurrentDrive?.Name == null)
|
||||
return (null, "No valid drive found!");
|
||||
|
||||
VerboseLogLn($"Scanning for copy protection in {this.CurrentDrive.Letter}");
|
||||
VerboseLogLn($"Scanning for copy protection in {this.CurrentDrive.Name}");
|
||||
|
||||
var tempContent = this.Status;
|
||||
this.Status = "Scanning for copy protection... this might take a while!";
|
||||
@@ -1478,7 +1496,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
|
||||
var progress = new Progress<ProtectionProgress>();
|
||||
progress.ProgressChanged += ProgressUpdated;
|
||||
var (protections, error) = await Protection.RunProtectionScanOnPath(this.CurrentDrive.Letter + ":\\", this.Options, progress);
|
||||
var (protections, error) = await Protection.RunProtectionScanOnPath(this.CurrentDrive.Name, this.Options, progress);
|
||||
var output = Protection.FormatProtections(protections);
|
||||
|
||||
// If SmartE is detected on the current disc, remove `/sf` from the flags for DIC only -- Disabled until further notice
|
||||
@@ -1490,7 +1508,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
//}
|
||||
|
||||
if (string.IsNullOrEmpty(error))
|
||||
LogLn($"Detected the following protections in {this.CurrentDrive.Letter}:\r\n\r\n{output}");
|
||||
LogLn($"Detected the following protections in {this.CurrentDrive.Name}:\r\n\r\n{output}");
|
||||
else
|
||||
ErrorLogLn($"Path could not be scanned! Exception information:\r\n\r\n{error}");
|
||||
|
||||
@@ -1545,28 +1563,51 @@ namespace MPF.Core.UI.ViewModels
|
||||
VerboseLogLn($"Supported media speeds: {string.Join(", ", this.DriveSpeeds)}");
|
||||
|
||||
// Set the selected speed
|
||||
#if NET48
|
||||
int speed;
|
||||
switch (this.CurrentMediaType)
|
||||
switch (CurrentMediaType)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
case MediaType.GDROM:
|
||||
speed = this.Options.PreferredDumpSpeedCD;
|
||||
speed = Options.PreferredDumpSpeedCD;
|
||||
break;
|
||||
case MediaType.DVD:
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
speed = this.Options.PreferredDumpSpeedDVD;
|
||||
speed = Options.PreferredDumpSpeedDVD;
|
||||
break;
|
||||
case MediaType.HDDVD:
|
||||
speed = this.Options.PreferredDumpSpeedHDDVD;
|
||||
speed = Options.PreferredDumpSpeedHDDVD;
|
||||
break;
|
||||
case MediaType.BluRay:
|
||||
speed = this.Options.PreferredDumpSpeedBD;
|
||||
speed = Options.PreferredDumpSpeedBD;
|
||||
break;
|
||||
default:
|
||||
speed = this.Options.PreferredDumpSpeedCD;
|
||||
speed = Options.PreferredDumpSpeedCD;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
int speed = (CurrentMediaType) switch
|
||||
{
|
||||
// CD dump speed
|
||||
MediaType.CDROM => Options.PreferredDumpSpeedCD,
|
||||
MediaType.GDROM => Options.PreferredDumpSpeedCD,
|
||||
|
||||
// DVD dump speed
|
||||
MediaType.DVD => Options.PreferredDumpSpeedDVD,
|
||||
MediaType.NintendoGameCubeGameDisc => Options.PreferredDumpSpeedDVD,
|
||||
MediaType.NintendoWiiOpticalDisc => Options.PreferredDumpSpeedDVD,
|
||||
|
||||
// HD-DVD dump speed
|
||||
MediaType.HDDVD => Options.PreferredDumpSpeedHDDVD,
|
||||
|
||||
// BD dump speed
|
||||
MediaType.BluRay => Options.PreferredDumpSpeedBD,
|
||||
|
||||
// Default
|
||||
_ => Options.PreferredDumpSpeedCD,
|
||||
};
|
||||
#endif
|
||||
|
||||
VerboseLogLn($"Setting drive speed to: {speed}");
|
||||
this.DriveSpeed = speed;
|
||||
@@ -1580,7 +1621,8 @@ namespace MPF.Core.UI.ViewModels
|
||||
return Drives != null
|
||||
&& Drives.Count > 0
|
||||
&& this.CurrentSystem != null
|
||||
&& this.CurrentMediaType != null;
|
||||
&& this.CurrentMediaType != null
|
||||
&& Tools.ProgramSupportsMedia(this.CurrentProgram, this.CurrentMediaType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1779,7 +1821,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Progress Reporting
|
||||
|
||||
@@ -1794,7 +1836,11 @@ namespace MPF.Core.UI.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
#if NET48
|
||||
value = value ?? string.Empty;
|
||||
#else
|
||||
value ??= string.Empty;
|
||||
#endif
|
||||
LogLn(value);
|
||||
}
|
||||
catch { }
|
||||
@@ -1812,7 +1858,11 @@ namespace MPF.Core.UI.ViewModels
|
||||
var message = value?.Message;
|
||||
|
||||
// Update the label with only the first line of output
|
||||
#if NET48
|
||||
if (message != null && message.Contains("\n"))
|
||||
#else
|
||||
if (message != null && message.Contains('\n'))
|
||||
#endif
|
||||
this.Status = value?.Message?.Split('\n')[0] + " (See log output)";
|
||||
else
|
||||
this.Status = value?.Message ?? string.Empty;
|
||||
@@ -1838,6 +1888,6 @@ namespace MPF.Core.UI.ViewModels
|
||||
VerboseLogLn(message);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MPF.Core.Data;
|
||||
@@ -7,10 +8,32 @@ using SabreTools.RedumpLib.Web;
|
||||
|
||||
namespace MPF.Core.UI.ViewModels
|
||||
{
|
||||
public class OptionsViewModel
|
||||
public class OptionsViewModel : INotifyPropertyChanged
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Title for the window
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string Title
|
||||
#else
|
||||
public string? Title
|
||||
#endif
|
||||
{
|
||||
get => _title;
|
||||
set
|
||||
{
|
||||
_title = value;
|
||||
TriggerPropertyChanged(nameof(Title));
|
||||
}
|
||||
}
|
||||
#if NET48
|
||||
private string _title;
|
||||
#else
|
||||
private string? _title;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Current set of options
|
||||
/// </summary>
|
||||
@@ -21,7 +44,14 @@ namespace MPF.Core.UI.ViewModels
|
||||
/// </summary>
|
||||
public bool SavedSettings { get; set; }
|
||||
|
||||
#endregion
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
#else
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lists
|
||||
|
||||
@@ -77,5 +107,18 @@ namespace MPF.Core.UI.ViewModels
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Property Updates
|
||||
|
||||
/// <summary>
|
||||
/// Trigger a property changed event
|
||||
/// </summary>
|
||||
private void TriggerPropertyChanged(string propertyName)
|
||||
{
|
||||
// If the property change event is initialized
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace MPF.Core.Utilities
|
||||
/// Process any standalone arguments for the program
|
||||
/// </summary>
|
||||
/// <returns>True if one of the arguments was processed, false otherwise</returns>
|
||||
public static bool ProcessStandaloneArguments(string[] args)
|
||||
public static bool? ProcessStandaloneArguments(string[] args)
|
||||
{
|
||||
// Help options
|
||||
if (args.Length == 0 || args[0] == "-h" || args[0] == "-?")
|
||||
@@ -90,9 +90,9 @@ namespace MPF.Core.Utilities
|
||||
/// Load the current set of options from application arguments
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static (Options, string, int) LoadFromArguments(string[] args, int startIndex = 0)
|
||||
public static (Options, SubmissionInfo, string, int) LoadFromArguments(string[] args, int startIndex = 0)
|
||||
#else
|
||||
public static (Options, string?, int) LoadFromArguments(string[] args, int startIndex = 0)
|
||||
public static (Options, SubmissionInfo?, string?, int) LoadFromArguments(string[] args, int startIndex = 0)
|
||||
#endif
|
||||
{
|
||||
// Create the output values with defaults
|
||||
@@ -101,13 +101,18 @@ namespace MPF.Core.Utilities
|
||||
RedumpUsername = null,
|
||||
RedumpPassword = null,
|
||||
InternalProgram = InternalProgram.NONE,
|
||||
AddFilenameSuffix = false,
|
||||
OutputSubmissionJSON = false,
|
||||
CompressLogFiles = false,
|
||||
DeleteUnnecessaryFiles = false,
|
||||
};
|
||||
|
||||
// Create the submission info to return, if necessary
|
||||
#if NET48
|
||||
SubmissionInfo info = null;
|
||||
string parsedPath = null;
|
||||
#else
|
||||
SubmissionInfo? info = null;
|
||||
string? parsedPath = null;
|
||||
#endif
|
||||
|
||||
@@ -116,17 +121,30 @@ namespace MPF.Core.Utilities
|
||||
|
||||
// If we have no arguments, just return
|
||||
if (args == null || args.Length == 0)
|
||||
return (options, null, 0);
|
||||
return (options, null, null, 0);
|
||||
|
||||
// If we have an invalid start index, just return
|
||||
if (startIndex < 0 || startIndex >= args.Length)
|
||||
return (options, null, startIndex);
|
||||
return (options, null, null, startIndex);
|
||||
|
||||
// Loop through the arguments and parse out values
|
||||
for (; startIndex < args.Length; startIndex++)
|
||||
{
|
||||
// Use specific program
|
||||
if (args[startIndex].StartsWith("-u=") || args[startIndex].StartsWith("--use="))
|
||||
{
|
||||
string internalProgram = args[startIndex].Split('=')[1];
|
||||
options.InternalProgram = EnumConverter.ToInternalProgram(internalProgram);
|
||||
}
|
||||
else if (args[startIndex] == "-u" || args[startIndex] == "--use")
|
||||
{
|
||||
string internalProgram = args[startIndex + 1];
|
||||
options.InternalProgram = EnumConverter.ToInternalProgram(internalProgram);
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Redump login
|
||||
if (args[startIndex].StartsWith("-c=") || args[startIndex].StartsWith("--credentials="))
|
||||
else if (args[startIndex].StartsWith("-c=") || args[startIndex].StartsWith("--credentials="))
|
||||
{
|
||||
string[] credentials = args[startIndex].Split('=')[1].Split(';');
|
||||
options.RedumpUsername = credentials[0];
|
||||
@@ -139,17 +157,10 @@ namespace MPF.Core.Utilities
|
||||
startIndex += 2;
|
||||
}
|
||||
|
||||
// Use specific program
|
||||
else if (args[startIndex].StartsWith("-u=") || args[startIndex].StartsWith("--use="))
|
||||
// Pull all information (requires Redump login)
|
||||
else if (args[startIndex].Equals("-a") || args[startIndex].Equals("--pull-all"))
|
||||
{
|
||||
string internalProgram = args[startIndex].Split('=')[1];
|
||||
options.InternalProgram = EnumConverter.ToInternalProgram(internalProgram);
|
||||
}
|
||||
else if (args[startIndex] == "-u" || args[startIndex] == "--use")
|
||||
{
|
||||
string internalProgram = args[startIndex + 1];
|
||||
options.InternalProgram = EnumConverter.ToInternalProgram(internalProgram);
|
||||
startIndex++;
|
||||
options.PullAllInformation = true;
|
||||
}
|
||||
|
||||
// Use a device path for physical checks
|
||||
@@ -175,6 +186,25 @@ namespace MPF.Core.Utilities
|
||||
protectFile = true;
|
||||
}
|
||||
|
||||
// Include seed info file
|
||||
else if (args[startIndex].StartsWith("-l=") || args[startIndex].StartsWith("--load-seed="))
|
||||
{
|
||||
string seedInfo = args[startIndex].Split('=')[1];
|
||||
info = SubmissionInfoTool.CreateFromFile(seedInfo);
|
||||
}
|
||||
else if (args[startIndex] == "-l" || args[startIndex] == "--load-seed")
|
||||
{
|
||||
string seedInfo = args[startIndex + 1];
|
||||
info = SubmissionInfoTool.CreateFromFile(seedInfo);
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Add filename suffix
|
||||
else if (args[startIndex].Equals("-x") || args[startIndex].Equals("--suffix"))
|
||||
{
|
||||
options.AddFilenameSuffix = true;
|
||||
}
|
||||
|
||||
// Output submission JSON
|
||||
else if (args[startIndex].Equals("-j") || args[startIndex].Equals("--json"))
|
||||
{
|
||||
@@ -187,6 +217,12 @@ namespace MPF.Core.Utilities
|
||||
options.CompressLogFiles = true;
|
||||
}
|
||||
|
||||
// Delete unnecessary files files
|
||||
else if (args[startIndex].Equals("-d") || args[startIndex].Equals("--delete"))
|
||||
{
|
||||
options.DeleteUnnecessaryFiles = true;
|
||||
}
|
||||
|
||||
// Default, we fall out
|
||||
else
|
||||
{
|
||||
@@ -198,7 +234,7 @@ namespace MPF.Core.Utilities
|
||||
options.ScanForProtection = scan && !string.IsNullOrWhiteSpace(parsedPath);
|
||||
options.OutputSeparateProtectionFile = scan && protectFile && !string.IsNullOrWhiteSpace(parsedPath);
|
||||
|
||||
return (options, parsedPath, startIndex);
|
||||
return (options, info, parsedPath, startIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -206,15 +242,20 @@ namespace MPF.Core.Utilities
|
||||
/// </summary>
|
||||
public static List<string> PrintSupportedArguments()
|
||||
{
|
||||
var supportedArguments = new List<string>();
|
||||
|
||||
supportedArguments.Add("-u, --use <program> Dumping program output type [REQUIRED]");
|
||||
supportedArguments.Add("-c, --credentials <user> <pw> Redump username and password");
|
||||
supportedArguments.Add("-p, --path <drivepath> Physical drive path for additional checks");
|
||||
supportedArguments.Add("-s, --scan Enable copy protection scan (requires --path)");
|
||||
supportedArguments.Add("-f, --protect-file Output protection to separate file (requires --scan)");
|
||||
supportedArguments.Add("-j, --json Enable submission JSON output");
|
||||
supportedArguments.Add("-z, --zip Enable log file compression");
|
||||
var supportedArguments = new List<string>
|
||||
{
|
||||
"-u, --use <program> Dumping program output type [REQUIRED]",
|
||||
"-c, --credentials <user> <pw> Redump username and password",
|
||||
"-a, --pull-all Pull all information from Redump (requires --credentials)",
|
||||
"-p, --path <drivepath> Physical drive path for additional checks",
|
||||
"-s, --scan Enable copy protection scan (requires --path)",
|
||||
"-f, --protect-file Output protection to separate file (requires --scan)",
|
||||
"-l, --load-seed <path> Load a seed submission JSON for user information",
|
||||
"-x, --suffix Enable adding filename suffix",
|
||||
"-j, --json Enable submission JSON output",
|
||||
"-z, --zip Enable log file compression",
|
||||
"-d, --delete Enable unnecessary file deletion",
|
||||
};
|
||||
|
||||
return supportedArguments;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace MPF.Core.Utilities
|
||||
return Result.Failure("Please select a valid system");
|
||||
|
||||
// If we're on an unsupported type, update the status accordingly
|
||||
#if NET48
|
||||
switch (type)
|
||||
{
|
||||
// Fully supported types
|
||||
@@ -116,6 +117,132 @@ namespace MPF.Core.Utilities
|
||||
default:
|
||||
return Result.Failure($"{type.LongName()} media are not supported for dumping");
|
||||
}
|
||||
#else
|
||||
return type switch
|
||||
{
|
||||
// Fully supported types
|
||||
MediaType.BluRay
|
||||
or MediaType.CDROM
|
||||
or MediaType.DVD
|
||||
or MediaType.FloppyDisk
|
||||
or MediaType.HardDisk
|
||||
or MediaType.CompactFlash
|
||||
or MediaType.SDCard
|
||||
or MediaType.FlashDrive
|
||||
or MediaType.HDDVD => Result.Success($"{type.LongName()} ready to dump"),
|
||||
|
||||
// Partially supported types
|
||||
MediaType.GDROM
|
||||
or MediaType.NintendoGameCubeGameDisc
|
||||
or MediaType.NintendoWiiOpticalDisc => Result.Success($"{type.LongName()} partially supported for dumping"),
|
||||
|
||||
// Special case for other supported tools
|
||||
MediaType.UMD => Result.Failure($"{type.LongName()} supported for submission info parsing"),
|
||||
|
||||
// Specifically unknown type
|
||||
MediaType.NONE => Result.Failure($"Please select a valid media type"),
|
||||
|
||||
// Undumpable but recognized types
|
||||
_ => Result.Failure($"{type.LongName()} media are not supported for dumping"),
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns false if a given InternalProgram does not support a given MediaType
|
||||
/// </summary>
|
||||
public static bool ProgramSupportsMedia(InternalProgram program, MediaType? type)
|
||||
{
|
||||
// If the media type is not set, return false
|
||||
if (type == null || type == MediaType.NONE)
|
||||
return false;
|
||||
|
||||
#if NET48
|
||||
switch (program)
|
||||
{
|
||||
case InternalProgram.Redumper:
|
||||
switch (type)
|
||||
{
|
||||
// Formats considered at least partially dumpable by Redumper
|
||||
case MediaType.BluRay:
|
||||
case MediaType.CDROM:
|
||||
case MediaType.DVD:
|
||||
case MediaType.GDROM:
|
||||
case MediaType.HDDVD:
|
||||
return true;
|
||||
|
||||
// All other formats considered unsupported
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case InternalProgram.Aaru:
|
||||
case InternalProgram.DiscImageCreator:
|
||||
switch (type)
|
||||
{
|
||||
// Formats considered at least partially supported
|
||||
case MediaType.BluRay:
|
||||
case MediaType.CDROM:
|
||||
case MediaType.DVD:
|
||||
case MediaType.FloppyDisk:
|
||||
case MediaType.HardDisk:
|
||||
case MediaType.CompactFlash:
|
||||
case MediaType.SDCard:
|
||||
case MediaType.FlashDrive:
|
||||
case MediaType.HDDVD:
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
return true;
|
||||
|
||||
// All other formats considered unsupported
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
// All other InternalPrograms are not used for dumping
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return (program) switch
|
||||
{
|
||||
// Aaru
|
||||
InternalProgram.Aaru when type == MediaType.BluRay => true,
|
||||
InternalProgram.Aaru when type == MediaType.CDROM => true,
|
||||
InternalProgram.Aaru when type == MediaType.CompactFlash => true,
|
||||
InternalProgram.Aaru when type == MediaType.DVD => true,
|
||||
InternalProgram.Aaru when type == MediaType.GDROM => true,
|
||||
InternalProgram.Aaru when type == MediaType.FlashDrive => true,
|
||||
InternalProgram.Aaru when type == MediaType.FloppyDisk => true,
|
||||
InternalProgram.Aaru when type == MediaType.HardDisk => true,
|
||||
InternalProgram.Aaru when type == MediaType.HDDVD => true,
|
||||
InternalProgram.Aaru when type == MediaType.NintendoGameCubeGameDisc => true,
|
||||
InternalProgram.Aaru when type == MediaType.NintendoWiiOpticalDisc => true,
|
||||
InternalProgram.Aaru when type == MediaType.SDCard => true,
|
||||
|
||||
// DiscImageCreator
|
||||
InternalProgram.DiscImageCreator when type == MediaType.BluRay => true,
|
||||
InternalProgram.DiscImageCreator when type == MediaType.CDROM => true,
|
||||
InternalProgram.DiscImageCreator when type == MediaType.CompactFlash => true,
|
||||
InternalProgram.DiscImageCreator when type == MediaType.DVD => true,
|
||||
InternalProgram.DiscImageCreator when type == MediaType.GDROM => true,
|
||||
InternalProgram.DiscImageCreator when type == MediaType.FlashDrive => true,
|
||||
InternalProgram.DiscImageCreator when type == MediaType.FloppyDisk => true,
|
||||
InternalProgram.DiscImageCreator when type == MediaType.HardDisk => true,
|
||||
InternalProgram.DiscImageCreator when type == MediaType.HDDVD => true,
|
||||
InternalProgram.DiscImageCreator when type == MediaType.NintendoGameCubeGameDisc => true,
|
||||
InternalProgram.DiscImageCreator when type == MediaType.NintendoWiiOpticalDisc => true,
|
||||
InternalProgram.DiscImageCreator when type == MediaType.SDCard => true,
|
||||
|
||||
// Redumper
|
||||
InternalProgram.Redumper when type == MediaType.BluRay => true,
|
||||
InternalProgram.Redumper when type == MediaType.CDROM => true,
|
||||
InternalProgram.Redumper when type == MediaType.DVD => true,
|
||||
InternalProgram.Redumper when type == MediaType.GDROM => true,
|
||||
InternalProgram.Redumper when type == MediaType.HDDVD => true,
|
||||
|
||||
// Default
|
||||
_ => false,
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -143,7 +270,7 @@ namespace MPF.Core.Utilities
|
||||
if (assemblyVersion == null)
|
||||
return (false, "Assembly version could not be determined", null);
|
||||
|
||||
string version = $"{assemblyVersion.Major}.{assemblyVersion.Minor}" + (assemblyVersion.Build != 0 ? $".{assemblyVersion.Build}" : string.Empty);
|
||||
string version = $"{assemblyVersion.Major}.{assemblyVersion.Minor}.{assemblyVersion.Build}";
|
||||
|
||||
// Get the latest tag from GitHub
|
||||
var (tag, url) = GetRemoteVersionAndUrl();
|
||||
@@ -197,7 +324,7 @@ namespace MPF.Core.Utilities
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
using (System.Net.WebClient wc = new System.Net.WebClient())
|
||||
using (var wc = new System.Net.WebClient())
|
||||
{
|
||||
wc.Headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0";
|
||||
|
||||
@@ -211,7 +338,7 @@ namespace MPF.Core.Utilities
|
||||
return (latestTag, releaseUrl);
|
||||
}
|
||||
#else
|
||||
using (System.Net.Http.HttpClient hc = new System.Net.Http.HttpClient())
|
||||
using (var hc = new System.Net.Http.HttpClient())
|
||||
{
|
||||
// TODO: Figure out a better way than having this hardcoded...
|
||||
string url = "https://api.github.com/repos/SabreTools/MPF/releases/latest";
|
||||
|
||||
@@ -43,21 +43,37 @@ namespace MPF.Test.Core.Converters
|
||||
/// Generate a test set of DriveType values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of DriveType values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateDriveTypeMappingTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateDriveTypeMappingTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
foreach (DriveType driveType in Enum.GetValues(typeof(DriveType)))
|
||||
{
|
||||
if (_mappableDriveTypes.Contains(driveType))
|
||||
#if NET48
|
||||
testData.Add(new object[] { driveType, false });
|
||||
#else
|
||||
testData.Add(new object?[] { driveType, false });
|
||||
#endif
|
||||
else
|
||||
#if NET48
|
||||
testData.Add(new object[] { driveType, true });
|
||||
#else
|
||||
testData.Add(new object?[] { driveType, true });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Convert to Long Name
|
||||
|
||||
@@ -79,18 +95,30 @@ namespace MPF.Test.Core.Converters
|
||||
/// Generate a test set of InternalProgram values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of InternalProgram values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateInternalProgramTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateInternalProgramTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null } };
|
||||
#endif
|
||||
foreach (InternalProgram? internalProgram in Enum.GetValues(typeof(InternalProgram)))
|
||||
{
|
||||
#if NET48
|
||||
testData.Add(new object[] { internalProgram });
|
||||
#else
|
||||
testData.Add(new object?[] { internalProgram });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
// TODO: Add from-string tests
|
||||
}
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
using MPF.Core.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Test.Core.Data
|
||||
{
|
||||
public class XgdInfoTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData("1234567")]
|
||||
[InlineData("1234567\0")]
|
||||
[InlineData("123456789")]
|
||||
public void UnmatchedStringTests(string invalidString)
|
||||
{
|
||||
XgdInfo xgdInfo = new XgdInfo(invalidString);
|
||||
Assert.False(xgdInfo.Initialized);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("AV00100W", "AV", "001", "00", 'W')]
|
||||
[InlineData("AV00100W\0", "AV", "001", "00", 'W')]
|
||||
public void XGD1ValidTests(string validString, string publisher, string gameId, string version, char regionIdentifier)
|
||||
{
|
||||
XgdInfo xgdInfo = new XgdInfo(validString);
|
||||
|
||||
Assert.True(xgdInfo.Initialized);
|
||||
Assert.Equal(publisher, xgdInfo.XMID.PublisherIdentifier);
|
||||
Assert.Equal(gameId, xgdInfo.XMID.GameID);
|
||||
Assert.Equal(version, xgdInfo.XMID.VersionNumber);
|
||||
Assert.Equal(regionIdentifier, xgdInfo.XMID.RegionIdentifier);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
// Invalid publisher identifier
|
||||
[InlineData("ZZ000000")]
|
||||
[InlineData("ZZ000000\0")]
|
||||
// Invalid region identifier
|
||||
[InlineData("AV00000Z")]
|
||||
[InlineData("AV00000Z\0")]
|
||||
public void XGD1InvalidTests(string invalidString)
|
||||
{
|
||||
XgdInfo xgdInfo = new XgdInfo(invalidString);
|
||||
Assert.False(xgdInfo.Initialized);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("AV200100W0F11", "AV", "001", "00", 'W', "0", 'F', "11", null)]
|
||||
[InlineData("AV200100W0F11\0", "AV", "001", "00", 'W', "0", 'F', "11", null)]
|
||||
[InlineData("AV200100W01F11", "AV", "001", "00", 'W', "01", 'F', "11", null)]
|
||||
[InlineData("AV200100W01F11\0", "AV", "001", "00", 'W', "01", 'F', "11", null)]
|
||||
[InlineData("AV200100W0F11DEADBEEF", "AV", "001", "00", 'W', "0", 'F', "11", "DEADBEEF")]
|
||||
[InlineData("AV200100W0F11DEADBEEF\0", "AV", "001", "00", 'W', "0", 'F', "11", "DEADBEEF")]
|
||||
[InlineData("AV200100W01F11DEADBEEF", "AV", "001", "00", 'W', "01", 'F', "11", "DEADBEEF")]
|
||||
[InlineData("AV200100W01F11DEADBEEF\0", "AV", "001", "00", 'W', "01", 'F', "11", "DEADBEEF")]
|
||||
public void XGD23ValidTests(string validString, string publisher, string gameId, string sku, char regionIdentifier, string baseVersion, char mediaSubtype, string discNumber, string cert)
|
||||
{
|
||||
XgdInfo xgdInfo = new XgdInfo(validString);
|
||||
|
||||
Assert.True(xgdInfo.Initialized);
|
||||
Assert.Equal(publisher, xgdInfo.XeMID.PublisherIdentifier);
|
||||
Assert.Equal('2', xgdInfo.XeMID.PlatformIdentifier);
|
||||
Assert.Equal(gameId, xgdInfo.XeMID.GameID);
|
||||
Assert.Equal(sku, xgdInfo.XeMID.SKU);
|
||||
Assert.Equal(regionIdentifier, xgdInfo.XeMID.RegionIdentifier);
|
||||
Assert.Equal(baseVersion, xgdInfo.XeMID.BaseVersion);
|
||||
Assert.Equal(mediaSubtype, xgdInfo.XeMID.MediaSubtypeIdentifier);
|
||||
Assert.Equal(discNumber, xgdInfo.XeMID.DiscNumberIdentifier);
|
||||
Assert.Equal(cert, xgdInfo.XeMID.CertificationSubmissionIdentifier);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
// Invalid publisher identifier
|
||||
[InlineData("ZZ00000000000")]
|
||||
[InlineData("ZZ00000000000\0")]
|
||||
[InlineData("ZZ000000000000")]
|
||||
[InlineData("ZZ000000000000\0")]
|
||||
[InlineData("ZZ0000000000000000000")]
|
||||
[InlineData("ZZ0000000000000000000\0")]
|
||||
[InlineData("ZZ00000000000000000000")]
|
||||
[InlineData("ZZ00000000000000000000\0")]
|
||||
// Invalid platform identifier
|
||||
[InlineData("AV90000000000")]
|
||||
[InlineData("AV90000000000\0")]
|
||||
[InlineData("AV900000000000")]
|
||||
[InlineData("AV900000000000\0")]
|
||||
[InlineData("AV9000000000000000000")]
|
||||
[InlineData("AV9000000000000000000\0")]
|
||||
[InlineData("AV90000000000000000000")]
|
||||
[InlineData("AV90000000000000000000\0")]
|
||||
// Invalid region identifier
|
||||
[InlineData("AV200000Z0000")]
|
||||
[InlineData("AV200000Z0000\0")]
|
||||
[InlineData("AV200000Z00000")]
|
||||
[InlineData("AV200000Z00000\0")]
|
||||
[InlineData("AV200000Z000000000000")]
|
||||
[InlineData("AV200000Z000000000000\0")]
|
||||
[InlineData("AV200000Z0000000000000")]
|
||||
[InlineData("AV200000Z0000000000000\0")]
|
||||
// Invalid media subtype identifier
|
||||
[InlineData("AV200000W0A00")]
|
||||
[InlineData("AV200000W0A00\0")]
|
||||
[InlineData("AV200000W00A00")]
|
||||
[InlineData("AV200000W00A00\0")]
|
||||
[InlineData("AV200000W00A000000000")]
|
||||
[InlineData("AV200000W00A000000000\0")]
|
||||
[InlineData("AV200000W00A0000000000")]
|
||||
[InlineData("AV200000W00A0000000000\0")]
|
||||
public void XGD23InvalidTests(string invalidString)
|
||||
{
|
||||
XgdInfo xgdInfo = new XgdInfo(invalidString);
|
||||
Assert.False(xgdInfo.Initialized);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,15 +143,31 @@ namespace MPF.Test.Core.Utilities
|
||||
/// Generate a test set of MediaType values that support drive speeds
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of MediaType values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateSupportDriveSpeedsTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateSupportDriveSpeedsTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, false } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
#endif
|
||||
foreach (MediaType mediaType in Enum.GetValues(typeof(MediaType)))
|
||||
{
|
||||
if (_supportDriveSpeeds.Contains(mediaType))
|
||||
#if NET48
|
||||
testData.Add(new object[] { mediaType, true });
|
||||
#else
|
||||
testData.Add(new object?[] { mediaType, true });
|
||||
#endif
|
||||
else
|
||||
#if NET48
|
||||
testData.Add(new object[] { mediaType, false });
|
||||
#else
|
||||
testData.Add(new object?[] { mediaType, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -161,15 +177,31 @@ namespace MPF.Test.Core.Utilities
|
||||
/// Generate a test set of RedumpSystem values that are considered Audio
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateAudioSystemsTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateAudioSystemsTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, false } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
#endif
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
if (_audioSystems.Contains(redumpSystem))
|
||||
#if NET48
|
||||
testData.Add(new object[] { redumpSystem, true });
|
||||
#else
|
||||
testData.Add(new object?[] { redumpSystem, true });
|
||||
#endif
|
||||
else
|
||||
#if NET48
|
||||
testData.Add(new object[] { redumpSystem, false });
|
||||
#else
|
||||
testData.Add(new object?[] { redumpSystem, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -179,15 +211,31 @@ namespace MPF.Test.Core.Utilities
|
||||
/// Generate a test set of RedumpSystem values that are considered markers
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateMarkerSystemsTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateMarkerSystemsTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, false } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
#endif
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
if (_markerSystems.Contains(redumpSystem))
|
||||
#if NET48
|
||||
testData.Add(new object[] { redumpSystem, true });
|
||||
#else
|
||||
testData.Add(new object?[] { redumpSystem, true });
|
||||
#endif
|
||||
else
|
||||
#if NET48
|
||||
testData.Add(new object[] { redumpSystem, false });
|
||||
#else
|
||||
testData.Add(new object?[] { redumpSystem, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -197,15 +245,31 @@ namespace MPF.Test.Core.Utilities
|
||||
/// Generate a test set of RedumpSystem values that are considered markers
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateReversedRingcodeSystemsTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateReversedRingcodeSystemsTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, false } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
#endif
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
if (_reverseRingcodeSystems.Contains(redumpSystem))
|
||||
#if NET48
|
||||
testData.Add(new object[] { redumpSystem, true });
|
||||
#else
|
||||
testData.Add(new object?[] { redumpSystem, true });
|
||||
#endif
|
||||
else
|
||||
#if NET48
|
||||
testData.Add(new object[] { redumpSystem, false });
|
||||
#else
|
||||
testData.Add(new object?[] { redumpSystem, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -215,15 +279,31 @@ namespace MPF.Test.Core.Utilities
|
||||
/// Generate a test set of RedumpSystem values that are considered XGD
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateXGDSystemsTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateXGDSystemsTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, false } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
#endif
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
if (_xgdSystems.Contains(redumpSystem))
|
||||
#if NET48
|
||||
testData.Add(new object[] { redumpSystem, true });
|
||||
#else
|
||||
testData.Add(new object?[] { redumpSystem, true });
|
||||
#endif
|
||||
else
|
||||
#if NET48
|
||||
testData.Add(new object[] { redumpSystem, false });
|
||||
#else
|
||||
testData.Add(new object?[] { redumpSystem, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
|
||||
@@ -42,10 +42,14 @@ namespace MPF.Test.Library
|
||||
long layerbreak,
|
||||
long layerbreak2,
|
||||
long layerbreak3,
|
||||
#if NET48
|
||||
string expected)
|
||||
#else
|
||||
string? expected)
|
||||
#endif
|
||||
{
|
||||
// TODO: Add tests around BDU
|
||||
string actual = InfoTool.GetFixedMediaType(mediaType, null, size, layerbreak, layerbreak2, layerbreak3);
|
||||
var actual = InfoTool.GetFixedMediaType(mediaType, null, size, layerbreak, layerbreak2, layerbreak3);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
@@ -58,7 +62,11 @@ namespace MPF.Test.Library
|
||||
[InlineData("superhero\\blah.rev.bin", "superhero\\blah.rev.bin")]
|
||||
[InlineData("super&hero\\blah.bin", "super&hero\\blah.bin")]
|
||||
[InlineData("superhero\\blah&foo.bin", "superhero\\blah&foo.bin")]
|
||||
#if NET48
|
||||
public void NormalizeOutputPathsTest(string outputPath, string expectedPath)
|
||||
#else
|
||||
public void NormalizeOutputPathsTest(string? outputPath, string? expectedPath)
|
||||
#endif
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(expectedPath))
|
||||
expectedPath = Path.GetFullPath(expectedPath);
|
||||
@@ -71,7 +79,7 @@ namespace MPF.Test.Library
|
||||
public void ProcessSpecialFieldsCompleteTest()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
SubmissionInfo info = new SubmissionInfo()
|
||||
var info = new SubmissionInfo()
|
||||
{
|
||||
CommonDiscInfo = new CommonDiscInfoSection()
|
||||
{
|
||||
@@ -119,7 +127,7 @@ namespace MPF.Test.Library
|
||||
public void ProcessSpecialFieldsNullObjectTest()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
SubmissionInfo info = new SubmissionInfo()
|
||||
var info = new SubmissionInfo()
|
||||
{
|
||||
CommonDiscInfo = null,
|
||||
};
|
||||
@@ -135,7 +143,7 @@ namespace MPF.Test.Library
|
||||
public void ProcessSpecialFieldsNullCommentsContentsTest()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
SubmissionInfo info = new SubmissionInfo()
|
||||
var info = new SubmissionInfo()
|
||||
{
|
||||
CommonDiscInfo = new CommonDiscInfoSection()
|
||||
{
|
||||
@@ -183,7 +191,7 @@ namespace MPF.Test.Library
|
||||
public void ProcessSpecialFieldsNullDictionariesTest()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
SubmissionInfo info = new SubmissionInfo()
|
||||
var info = new SubmissionInfo()
|
||||
{
|
||||
CommonDiscInfo = new CommonDiscInfoSection()
|
||||
{
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MPF\MPF.csproj" />
|
||||
</ItemGroup>
|
||||
@@ -14,18 +18,18 @@
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.1.1" />
|
||||
<PackageReference Include="xunit" Version="2.5.1" />
|
||||
<PackageReference Include="xunit" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.3.0" />
|
||||
<PackageReference Include="xunit.assert" Version="2.5.1" />
|
||||
<PackageReference Include="xunit.core" Version="2.5.1" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.5.1" />
|
||||
<PackageReference Include="xunit.extensibility.execution" Version="2.5.1" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.5.1">
|
||||
<PackageReference Include="xunit.analyzers" Version="1.4.0" />
|
||||
<PackageReference Include="xunit.assert" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.core" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.extensibility.execution" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.5.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.1">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Modules.DiscImageCreator;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
@@ -20,7 +21,7 @@ namespace MPF.Test.Modules
|
||||
public void ParametersFromSystemAndTypeTest(RedumpSystem? knownSystem, MediaType? mediaType, string expected)
|
||||
{
|
||||
var options = new Options();
|
||||
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, options);
|
||||
var actual = new Parameters(knownSystem, mediaType, "D:\\", "disc.bin", 16, options);
|
||||
Assert.Equal(expected, actual.BaseCommand);
|
||||
}
|
||||
|
||||
@@ -31,9 +32,9 @@ namespace MPF.Test.Modules
|
||||
public void ParametersFromOptionsSpecialDefaultTest(RedumpSystem? knownSystem, MediaType? mediaType,string[] expected)
|
||||
{
|
||||
var options = new Options();
|
||||
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, options);
|
||||
var actual = new Parameters(knownSystem, mediaType, "D:\\", "disc.bin", 16, options);
|
||||
|
||||
HashSet<string> expectedSet = new HashSet<string>(expected ?? new string[0]);
|
||||
var expectedSet = new HashSet<string>(expected ?? Array.Empty<string>());
|
||||
HashSet<string> actualSet = GenerateUsedKeys(actual);
|
||||
Assert.Equal(expectedSet, actualSet);
|
||||
}
|
||||
@@ -44,9 +45,9 @@ namespace MPF.Test.Modules
|
||||
public void ParametersFromOptionsC2RereadTest(RedumpSystem? knownSystem, MediaType? mediaType, int rereadC2, string[] expected)
|
||||
{
|
||||
var options = new Options { DICRereadCount = rereadC2 };
|
||||
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, options);
|
||||
var actual = new Parameters(knownSystem, mediaType, "D:\\", "disc.bin", 16, options);
|
||||
|
||||
HashSet<string> expectedSet = new HashSet<string>(expected ?? new string[0]);
|
||||
var expectedSet = new HashSet<string>(expected ?? Array.Empty<string>());
|
||||
HashSet<string> actualSet = GenerateUsedKeys(actual);
|
||||
|
||||
Assert.Equal(expectedSet, actualSet);
|
||||
@@ -64,9 +65,9 @@ namespace MPF.Test.Modules
|
||||
public void ParametersFromOptionsDVDRereadTest(RedumpSystem? knownSystem, MediaType? mediaType, int rereadDVDBD, string[] expected)
|
||||
{
|
||||
var options = new Options { DICDVDRereadCount = rereadDVDBD };
|
||||
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, options);
|
||||
var actual = new Parameters(knownSystem, mediaType, "D:\\", "disc.bin", 16, options);
|
||||
|
||||
HashSet<string> expectedSet = new HashSet<string>(expected ?? new string[0]);
|
||||
var expectedSet = new HashSet<string>(expected ?? Array.Empty<string>());
|
||||
HashSet<string> actualSet = GenerateUsedKeys(actual);
|
||||
|
||||
Assert.Equal(expectedSet, actualSet);
|
||||
@@ -88,9 +89,9 @@ namespace MPF.Test.Modules
|
||||
public void ParametersFromOptionsMultiSectorReadTest(RedumpSystem? knownSystem, MediaType? mediaType, bool multiSectorRead, string[] expected)
|
||||
{
|
||||
var options = new Options { DICMultiSectorRead = multiSectorRead };
|
||||
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, options);
|
||||
var actual = new Parameters(knownSystem, mediaType, "D:\\", "disc.bin", 16, options);
|
||||
|
||||
HashSet<string> expectedSet = new HashSet<string>(expected ?? new string[0]);
|
||||
var expectedSet = new HashSet<string>(expected ?? Array.Empty<string>());
|
||||
HashSet<string> actualSet = GenerateUsedKeys(actual);
|
||||
Assert.Equal(expectedSet, actualSet);
|
||||
if (expectedSet.Count != 1 && multiSectorRead)
|
||||
@@ -109,9 +110,9 @@ namespace MPF.Test.Modules
|
||||
public void ParametersFromOptionsParanoidModeTest(RedumpSystem? knownSystem, MediaType? mediaType, bool paranoidMode, string[] expected)
|
||||
{
|
||||
var options = new Options { DICParanoidMode = paranoidMode };
|
||||
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, options);
|
||||
var actual = new Parameters(knownSystem, mediaType, "D:\\", "disc.bin", 16, options);
|
||||
|
||||
HashSet<string> expectedSet = new HashSet<string>(expected ?? new string[0]);
|
||||
var expectedSet = new HashSet<string>(expected ?? Array.Empty<string>());
|
||||
HashSet<string> actualSet = GenerateUsedKeys(actual);
|
||||
Assert.Equal(expectedSet, actualSet);
|
||||
if (paranoidMode)
|
||||
@@ -160,9 +161,13 @@ namespace MPF.Test.Modules
|
||||
[InlineData(MediaType.FloppyDisk, ".img")]
|
||||
[InlineData(MediaType.Cassette, ".wav")]
|
||||
[InlineData(MediaType.NONE, null)]
|
||||
#if NET48
|
||||
public void MediaTypeToExtensionTest(MediaType? mediaType, string expected)
|
||||
#else
|
||||
public void MediaTypeToExtensionTest(MediaType? mediaType, string? expected)
|
||||
#endif
|
||||
{
|
||||
string actual = Converters.Extension(mediaType);
|
||||
var actual = Converters.Extension(mediaType);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
@@ -214,7 +219,7 @@ namespace MPF.Test.Modules
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
[Fact]
|
||||
public void DiscImageCreatorAudioParametersTest()
|
||||
@@ -226,7 +231,7 @@ namespace MPF.Test.Modules
|
||||
Assert.NotNull(parametersObject);
|
||||
|
||||
// Validate that the same set of parameters are generated on the output
|
||||
string newParameters = parametersObject.GenerateParameters();
|
||||
var newParameters = parametersObject.GenerateParameters();
|
||||
Assert.NotNull(newParameters);
|
||||
Assert.Equal(originalParameters, newParameters);
|
||||
}
|
||||
@@ -241,7 +246,7 @@ namespace MPF.Test.Modules
|
||||
Assert.NotNull(parametersObject);
|
||||
|
||||
// Validate that the same set of parameters are generated on the output
|
||||
string newParameters = parametersObject.GenerateParameters();
|
||||
var newParameters = parametersObject.GenerateParameters();
|
||||
Assert.NotNull(newParameters);
|
||||
Assert.Equal(originalParameters, newParameters);
|
||||
}
|
||||
@@ -253,7 +258,7 @@ namespace MPF.Test.Modules
|
||||
/// <returns>HashSet representing the strings</returns>
|
||||
private static HashSet<string> GenerateUsedKeys(Parameters parameters)
|
||||
{
|
||||
HashSet<string> usedKeys = new HashSet<string>();
|
||||
var usedKeys = new HashSet<string>();
|
||||
if (parameters?.Keys == null)
|
||||
return usedKeys;
|
||||
|
||||
|
||||
@@ -95,15 +95,31 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of DiscType values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of DiscType values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateDiscTypeMappingTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateDiscTypeMappingTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
foreach (DiscType? discType in Enum.GetValues(typeof(DiscType)))
|
||||
{
|
||||
if (_mappableDiscTypes.Contains(discType))
|
||||
#if NET48
|
||||
testData.Add(new object[] { discType, false });
|
||||
#else
|
||||
testData.Add(new object?[] { discType, false });
|
||||
#endif
|
||||
else
|
||||
#if NET48
|
||||
testData.Add(new object[] { discType, true });
|
||||
#else
|
||||
testData.Add(new object?[] { discType, true });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -113,12 +129,24 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of RedumpSystem values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateRedumpSystemMappingTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateRedumpSystemMappingTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null } };
|
||||
#endif
|
||||
foreach (RedumpSystem? redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
#if NET48
|
||||
testData.Add(new object[] { redumpSystem });
|
||||
#else
|
||||
testData.Add(new object?[] { redumpSystem });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -128,16 +156,32 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of mappable media types
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of MediaTypes</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateMediaTypeMappingTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateMediaTypeMappingTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
|
||||
foreach (MediaType? mediaType in Enum.GetValues(typeof(MediaType)))
|
||||
{
|
||||
if (_mappableMediaTypes.Contains(mediaType))
|
||||
#if NET48
|
||||
testData.Add(new object[] { mediaType, false });
|
||||
#else
|
||||
testData.Add(new object?[] { mediaType, false });
|
||||
#endif
|
||||
else
|
||||
#if NET48
|
||||
testData.Add(new object[] { mediaType, true });
|
||||
#else
|
||||
testData.Add(new object?[] { mediaType, true });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -156,7 +200,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateDiscCategoryTestData))]
|
||||
public void DiscCategoryLongNameTest(DiscCategory? discCategory, bool expectNull)
|
||||
{
|
||||
string actual = discCategory.LongName();
|
||||
var actual = discCategory.LongName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -168,12 +212,24 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of DiscCategory values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of DiscCategory values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateDiscCategoryTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateDiscCategoryTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
foreach (DiscCategory? discCategory in Enum.GetValues(typeof(DiscCategory)))
|
||||
{
|
||||
#if NET48
|
||||
testData.Add(new object[] { discCategory, false });
|
||||
#else
|
||||
testData.Add(new object?[] { discCategory, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -192,7 +248,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateDiscTypeTestData))]
|
||||
public void DiscTypeLongNameTest(DiscType? discType, bool expectNull)
|
||||
{
|
||||
string actual = discType.LongName();
|
||||
var actual = discType.LongName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -204,15 +260,31 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of DiscType values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of DiscType values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateDiscTypeTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateDiscTypeTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
foreach (DiscType? discType in Enum.GetValues(typeof(DiscType)))
|
||||
{
|
||||
if (discType == DiscType.NONE)
|
||||
#if NET48
|
||||
testData.Add(new object[] { discType, true });
|
||||
#else
|
||||
testData.Add(new object?[] { discType, true });
|
||||
#endif
|
||||
else
|
||||
#if NET48
|
||||
testData.Add(new object[] { discType, false });
|
||||
#else
|
||||
testData.Add(new object?[] { discType, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -231,7 +303,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateLanguageTestData))]
|
||||
public void LanguageLongNameTest(Language? language, bool expectNull)
|
||||
{
|
||||
string actual = language.LongName();
|
||||
var actual = language.LongName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -248,7 +320,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateLanguageTestData))]
|
||||
public void LanguageShortNameTest(Language? language, bool expectNull)
|
||||
{
|
||||
string actual = language.ShortName();
|
||||
var actual = language.ShortName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -268,7 +340,7 @@ namespace MPF.Test.RedumpLib
|
||||
int totalCount = 0;
|
||||
foreach (Language? language in fullLanguages)
|
||||
{
|
||||
string code = language.TwoLetterCode();
|
||||
var code = language.TwoLetterCode();
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
continue;
|
||||
|
||||
@@ -295,7 +367,7 @@ namespace MPF.Test.RedumpLib
|
||||
int totalCount = 0;
|
||||
foreach (Language? language in fullLanguages)
|
||||
{
|
||||
string code = language.ThreeLetterCode();
|
||||
var code = language.ThreeLetterCode();
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
continue;
|
||||
|
||||
@@ -322,7 +394,7 @@ namespace MPF.Test.RedumpLib
|
||||
int totalCount = 0;
|
||||
foreach (Language? language in fullLanguages)
|
||||
{
|
||||
string code = language.ThreeLetterCodeAlt();
|
||||
var code = language.ThreeLetterCodeAlt();
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
continue;
|
||||
|
||||
@@ -341,12 +413,24 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of Language values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of Language values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateLanguageTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateLanguageTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
foreach (Language? language in Enum.GetValues(typeof(Language)))
|
||||
{
|
||||
#if NET48
|
||||
testData.Add(new object[] { language, false });
|
||||
#else
|
||||
testData.Add(new object?[] { language, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -365,7 +449,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateLanguageSelectionTestData))]
|
||||
public void LanguageSelectionLongNameTest(LanguageSelection? languageSelection, bool expectNull)
|
||||
{
|
||||
string actual = languageSelection.LongName();
|
||||
var actual = languageSelection.LongName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -377,12 +461,24 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of LanguageSelection values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of LanguageSelection values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateLanguageSelectionTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateLanguageSelectionTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
foreach (LanguageSelection? languageSelection in Enum.GetValues(typeof(LanguageSelection)))
|
||||
{
|
||||
#if NET48
|
||||
testData.Add(new object[] { languageSelection, false });
|
||||
#else
|
||||
testData.Add(new object?[] { languageSelection, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -401,7 +497,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateMediaTypeTestData))]
|
||||
public void MediaTypeLongNameTest(MediaType? mediaType, bool expectNull)
|
||||
{
|
||||
string actual = mediaType.LongName();
|
||||
var actual = mediaType.LongName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -418,7 +514,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateMediaTypeTestData))]
|
||||
public void MediaTypeShortNameTest(MediaType? mediaType, bool expectNull)
|
||||
{
|
||||
string actual = mediaType.ShortName();
|
||||
var actual = mediaType.ShortName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -430,12 +526,24 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of MediaType values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of MediaType values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateMediaTypeTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateMediaTypeTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
foreach (MediaType? mediaType in Enum.GetValues(typeof(MediaType)))
|
||||
{
|
||||
#if NET48
|
||||
testData.Add(new object[] { mediaType, false });
|
||||
#else
|
||||
testData.Add(new object?[] { mediaType, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -454,7 +562,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateRegionTestData))]
|
||||
public void RegionLongNameTest(Region? region, bool expectNull)
|
||||
{
|
||||
string actual = region.LongName();
|
||||
var actual = region.LongName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -471,7 +579,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateRegionTestData))]
|
||||
public void RegionShortNameTest(Region? region, bool expectNull)
|
||||
{
|
||||
string actual = region.ShortName();
|
||||
var actual = region.ShortName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -491,7 +599,7 @@ namespace MPF.Test.RedumpLib
|
||||
int totalCount = 0;
|
||||
foreach (Region? region in fullRegions)
|
||||
{
|
||||
string code = region.ShortName();
|
||||
var code = region.ShortName();
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
continue;
|
||||
|
||||
@@ -510,12 +618,24 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of Region values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of Region values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateRegionTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateRegionTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
foreach (Region? region in Enum.GetValues(typeof(Region)))
|
||||
{
|
||||
#if NET48
|
||||
testData.Add(new object[] { region, false });
|
||||
#else
|
||||
testData.Add(new object?[] { region, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -534,7 +654,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateSiteCodeTestData))]
|
||||
public void SiteCodeLongNameTest(SiteCode? siteCode, bool expectNull)
|
||||
{
|
||||
string actual = siteCode.LongName();
|
||||
var actual = siteCode.LongName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -551,7 +671,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateSiteCodeTestData))]
|
||||
public void SiteCodeShortNameTest(SiteCode? siteCode, bool expectNull)
|
||||
{
|
||||
string actual = siteCode.ShortName();
|
||||
var actual = siteCode.ShortName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -563,12 +683,24 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of SiteCode values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of SiteCode values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateSiteCodeTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateSiteCodeTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode)))
|
||||
{
|
||||
#if NET48
|
||||
testData.Add(new object[] { siteCode, false });
|
||||
#else
|
||||
testData.Add(new object?[] { siteCode, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -587,7 +719,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateRedumpSystemTestData))]
|
||||
public void RedumpSystemLongNameTest(RedumpSystem? redumpSystem, bool expectNull)
|
||||
{
|
||||
string actual = redumpSystem.LongName();
|
||||
var actual = redumpSystem.LongName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -622,16 +754,28 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of RedumpSystem values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of RedumpSystem values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateRedumpSystemTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateRedumpSystemTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
foreach (RedumpSystem? redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
// We want to skip all markers for this
|
||||
if (redumpSystem.IsMarker())
|
||||
continue;
|
||||
|
||||
#if NET48
|
||||
testData.Add(new object[] { redumpSystem, false });
|
||||
#else
|
||||
testData.Add(new object?[] { redumpSystem, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -650,7 +794,7 @@ namespace MPF.Test.RedumpLib
|
||||
[MemberData(nameof(GenerateSystemCategoryTestData))]
|
||||
public void SystemCategoryLongNameTest(SystemCategory? systemCategory, bool expectNull)
|
||||
{
|
||||
string actual = systemCategory.LongName();
|
||||
var actual = systemCategory.LongName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
@@ -662,15 +806,31 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of SystemCategory values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of SystemCategory values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateSystemCategoryTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateSystemCategoryTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, true } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
#endif
|
||||
foreach (SystemCategory? systemCategory in Enum.GetValues(typeof(SystemCategory)))
|
||||
{
|
||||
if (systemCategory == SystemCategory.NONE)
|
||||
#if NET48
|
||||
testData.Add(new object[] { systemCategory, true });
|
||||
#else
|
||||
testData.Add(new object?[] { systemCategory, true });
|
||||
#endif
|
||||
else
|
||||
#if NET48
|
||||
testData.Add(new object[] { systemCategory, false });
|
||||
#else
|
||||
testData.Add(new object?[] { systemCategory, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -701,12 +861,24 @@ namespace MPF.Test.RedumpLib
|
||||
/// Generate a test set of YesNo values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of YesNo values</returns>
|
||||
#if NET48
|
||||
public static List<object[]> GenerateYesNoTestData()
|
||||
#else
|
||||
public static List<object?[]> GenerateYesNoTestData()
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
var testData = new List<object[]>() { new object[] { null, false } };
|
||||
#else
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
#endif
|
||||
foreach (YesNo? yesNo in Enum.GetValues(typeof(YesNo)))
|
||||
{
|
||||
#if NET48
|
||||
testData.Add(new object[] { yesNo, false });
|
||||
#else
|
||||
testData.Add(new object?[] { yesNo, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return testData;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using psxt001z;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
|
||||
@@ -30,11 +30,18 @@ namespace MPF.UI.Core
|
||||
}
|
||||
}
|
||||
|
||||
#if NET48
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
#else
|
||||
public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
#endif
|
||||
{
|
||||
// If it's an IElement but ends up null
|
||||
var element = value as IElement;
|
||||
if (element == null)
|
||||
#if NET48
|
||||
if (!(value is IElement element))
|
||||
#else
|
||||
if (value is not IElement element)
|
||||
#endif
|
||||
return null;
|
||||
|
||||
switch (element)
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace WPFCustomMessageBox
|
||||
/// Global parameter to enable (true) or disable (false) the removal of the title bar icon.
|
||||
/// If you are using a custom window style, the icon removal may cause issues like displaying two title bar (the default windows one and the custom one).
|
||||
/// </summary>
|
||||
public static bool RemoveTitleBarIcon = true;
|
||||
private static readonly bool RemoveTitleBarIcon = true;
|
||||
|
||||
/// <summary>
|
||||
/// Displays a message box that has a message and returns a result.
|
||||
@@ -173,7 +173,11 @@ namespace WPFCustomMessageBox
|
||||
/// </param>
|
||||
/// <param name="timeoutResult">If the message box closes automatically due to the <paramref name="timeout"/> being exceeded, this result is returned.</param>
|
||||
/// <returns>A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.</returns>
|
||||
#if NET48
|
||||
public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
|
||||
#else
|
||||
public static MessageBoxResult Show(Window owner, string? messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
|
||||
#endif
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
@@ -515,11 +519,15 @@ namespace WPFCustomMessageBox
|
||||
/// <param name="timeout">The message box will close automatically after given milliseconds</param>
|
||||
/// <param name="timeoutResult">If the message box closes automatically due to <paramref name="timeout"/> being exceeded, this result is returned.</param>
|
||||
/// <returns>A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.</returns>
|
||||
#if NET48
|
||||
private static MessageBoxResult ShowOKMessage(Window owner, string messageBoxText, string caption, string okButtonText, string cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
|
||||
#else
|
||||
private static MessageBoxResult ShowOKMessage(Window? owner, string? messageBoxText, string caption, string? okButtonText, string? cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
|
||||
#endif
|
||||
{
|
||||
MessageBoxButton buttonLayout = string.IsNullOrEmpty(cancelButtonText) ? MessageBoxButton.OK : MessageBoxButton.OKCancel;
|
||||
|
||||
CustomMessageBoxWindow msg = new CustomMessageBoxWindow(owner, messageBoxText, caption, buttonLayout, icon, RemoveTitleBarIcon);
|
||||
var msg = new CustomMessageBoxWindow(owner, messageBoxText, caption, buttonLayout, icon, RemoveTitleBarIcon);
|
||||
if (!string.IsNullOrEmpty(okButtonText))
|
||||
msg.OkButtonText = okButtonText;
|
||||
if (!string.IsNullOrEmpty(cancelButtonText))
|
||||
@@ -545,11 +553,15 @@ namespace WPFCustomMessageBox
|
||||
/// <param name="timeout">The message box will close automatically after given milliseconds</param>
|
||||
/// <param name="timeoutResult">If the message box closes automatically due to <paramref name="timeout"/> being exceeded, this result is returned.</param>
|
||||
/// <returns>A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.</returns>
|
||||
#if NET48
|
||||
private static MessageBoxResult ShowYesNoMessage(Window owner, string messageBoxText, string caption, string yesButtonText, string noButtonText, string cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
|
||||
#else
|
||||
private static MessageBoxResult ShowYesNoMessage(Window? owner, string? messageBoxText, string caption, string? yesButtonText, string? noButtonText, string? cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
|
||||
#endif
|
||||
{
|
||||
MessageBoxButton buttonLayout = string.IsNullOrEmpty(cancelButtonText) ? MessageBoxButton.YesNo : MessageBoxButton.YesNoCancel;
|
||||
|
||||
CustomMessageBoxWindow msg = new CustomMessageBoxWindow(owner, messageBoxText, caption, buttonLayout, icon, RemoveTitleBarIcon);
|
||||
var msg = new CustomMessageBoxWindow(owner, messageBoxText, caption, buttonLayout, icon, RemoveTitleBarIcon);
|
||||
if (!string.IsNullOrEmpty(yesButtonText))
|
||||
msg.YesButtonText = yesButtonText;
|
||||
if (!string.IsNullOrEmpty(noButtonText))
|
||||
@@ -566,14 +578,14 @@ namespace WPFCustomMessageBox
|
||||
{
|
||||
if (timeout.HasValue && timeout.Value <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("timeout", string.Format("Timeout must be greater than 0."));
|
||||
throw new ArgumentOutOfRangeException(nameof(timeout), string.Format("Timeout must be greater than 0."));
|
||||
}
|
||||
|
||||
if (timeout.HasValue)
|
||||
{
|
||||
//System.Threading.Timer timer = null;
|
||||
//timer = new System.Threading.Timer(s => { msg.Close(); timer.Dispose(); }, null, timeout.Value, System.Threading.Timeout.Infinite);
|
||||
System.Timers.Timer timer = new System.Timers.Timer(timeout.Value) { AutoReset = false };
|
||||
var timer = new System.Timers.Timer(timeout.Value) { AutoReset = false };
|
||||
timer.Elapsed += delegate {
|
||||
Application.Current.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
|
||||
@@ -10,9 +10,13 @@ namespace WPFCustomMessageBox
|
||||
/// </summary>
|
||||
internal partial class CustomMessageBoxWindow : Window
|
||||
{
|
||||
private bool _removeTitleBarIcon = true;
|
||||
private readonly bool _removeTitleBarIcon = true;
|
||||
|
||||
#if NET48
|
||||
public string Caption
|
||||
#else
|
||||
public string? Caption
|
||||
#endif
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -24,7 +28,11 @@ namespace WPFCustomMessageBox
|
||||
}
|
||||
}
|
||||
|
||||
#if NET48
|
||||
public string Message
|
||||
#else
|
||||
public string? Message
|
||||
#endif
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -36,7 +44,11 @@ namespace WPFCustomMessageBox
|
||||
}
|
||||
}
|
||||
|
||||
#if NET48
|
||||
public string OkButtonText
|
||||
#else
|
||||
public string? OkButtonText
|
||||
#endif
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -48,7 +60,11 @@ namespace WPFCustomMessageBox
|
||||
}
|
||||
}
|
||||
|
||||
#if NET48
|
||||
public string CancelButtonText
|
||||
#else
|
||||
public string? CancelButtonText
|
||||
#endif
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -60,7 +76,11 @@ namespace WPFCustomMessageBox
|
||||
}
|
||||
}
|
||||
|
||||
#if NET48
|
||||
public string YesButtonText
|
||||
#else
|
||||
public string? YesButtonText
|
||||
#endif
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -72,7 +92,11 @@ namespace WPFCustomMessageBox
|
||||
}
|
||||
}
|
||||
|
||||
#if NET48
|
||||
public string NoButtonText
|
||||
#else
|
||||
public string? NoButtonText
|
||||
#endif
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -86,7 +110,11 @@ namespace WPFCustomMessageBox
|
||||
|
||||
public MessageBoxResult Result { get; set; }
|
||||
|
||||
#if NET48
|
||||
internal CustomMessageBoxWindow(Window owner, string message, string caption = null, MessageBoxButton? button = null, MessageBoxImage? image = null, bool removeTitleBarIcon = true)
|
||||
#else
|
||||
internal CustomMessageBoxWindow(Window? owner, string? message, string? caption = null, MessageBoxButton? button = null, MessageBoxImage? image = null, bool removeTitleBarIcon = true)
|
||||
#endif
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
@@ -95,7 +123,7 @@ namespace WPFCustomMessageBox
|
||||
ShowActivated = true;
|
||||
ShowInTaskbar = true;
|
||||
|
||||
if (owner != null)
|
||||
if (owner != null && owner.IsLoaded)
|
||||
{
|
||||
Owner = owner;
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
@@ -109,7 +137,7 @@ namespace WPFCustomMessageBox
|
||||
if (image.HasValue)
|
||||
DisplayImage(image.Value);
|
||||
else
|
||||
Image_MessageBox.Visibility = System.Windows.Visibility.Collapsed;
|
||||
Image_MessageBox.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
protected override void OnSourceInitialized(EventArgs e)
|
||||
@@ -126,39 +154,39 @@ namespace WPFCustomMessageBox
|
||||
{
|
||||
case MessageBoxButton.OKCancel:
|
||||
// Hide all but OK, Cancel
|
||||
Button_OK.Visibility = System.Windows.Visibility.Visible;
|
||||
Button_OK.Visibility = Visibility.Visible;
|
||||
Button_OK.Focus();
|
||||
Button_Cancel.Visibility = System.Windows.Visibility.Visible;
|
||||
Button_Cancel.Visibility = Visibility.Visible;
|
||||
|
||||
Button_Yes.Visibility = System.Windows.Visibility.Collapsed;
|
||||
Button_No.Visibility = System.Windows.Visibility.Collapsed;
|
||||
Button_Yes.Visibility = Visibility.Collapsed;
|
||||
Button_No.Visibility = Visibility.Collapsed;
|
||||
break;
|
||||
case MessageBoxButton.YesNo:
|
||||
// Hide all but Yes, No
|
||||
Button_Yes.Visibility = System.Windows.Visibility.Visible;
|
||||
Button_Yes.Visibility = Visibility.Visible;
|
||||
Button_Yes.Focus();
|
||||
Button_No.Visibility = System.Windows.Visibility.Visible;
|
||||
Button_No.Visibility = Visibility.Visible;
|
||||
|
||||
Button_OK.Visibility = System.Windows.Visibility.Collapsed;
|
||||
Button_Cancel.Visibility = System.Windows.Visibility.Collapsed;
|
||||
Button_OK.Visibility = Visibility.Collapsed;
|
||||
Button_Cancel.Visibility = Visibility.Collapsed;
|
||||
break;
|
||||
case MessageBoxButton.YesNoCancel:
|
||||
// Hide only OK
|
||||
Button_Yes.Visibility = System.Windows.Visibility.Visible;
|
||||
Button_Yes.Visibility = Visibility.Visible;
|
||||
Button_Yes.Focus();
|
||||
Button_No.Visibility = System.Windows.Visibility.Visible;
|
||||
Button_Cancel.Visibility = System.Windows.Visibility.Visible;
|
||||
Button_No.Visibility = Visibility.Visible;
|
||||
Button_Cancel.Visibility = Visibility.Visible;
|
||||
|
||||
Button_OK.Visibility = System.Windows.Visibility.Collapsed;
|
||||
Button_OK.Visibility = Visibility.Collapsed;
|
||||
break;
|
||||
default:
|
||||
// Hide all but OK
|
||||
Button_OK.Visibility = System.Windows.Visibility.Visible;
|
||||
Button_OK.Visibility = Visibility.Visible;
|
||||
Button_OK.Focus();
|
||||
|
||||
Button_Yes.Visibility = System.Windows.Visibility.Collapsed;
|
||||
Button_No.Visibility = System.Windows.Visibility.Collapsed;
|
||||
Button_Cancel.Visibility = System.Windows.Visibility.Collapsed;
|
||||
Button_Yes.Visibility = Visibility.Collapsed;
|
||||
Button_No.Visibility = Visibility.Collapsed;
|
||||
Button_Cancel.Visibility = Visibility.Collapsed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -187,7 +215,7 @@ namespace WPFCustomMessageBox
|
||||
}
|
||||
|
||||
Image_MessageBox.Source = icon.ToImageSource();
|
||||
Image_MessageBox.Visibility = System.Windows.Visibility.Visible;
|
||||
Image_MessageBox.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void Button_OK_Click(object sender, RoutedEventArgs e)
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace WPFCustomMessageBox
|
||||
const int SWP_NOMOVE = 0x0002;
|
||||
const int SWP_NOZORDER = 0x0004;
|
||||
const int SWP_FRAMECHANGED = 0x0020;
|
||||
const uint WM_SETICON = 0x0080;
|
||||
//const uint WM_SETICON = 0x0080;
|
||||
|
||||
|
||||
internal static ImageSource ToImageSource(this Icon icon)
|
||||
@@ -60,7 +60,11 @@ namespace WPFCustomMessageBox
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
#if NET48
|
||||
internal static string TryAddKeyboardAccellerator(this string input)
|
||||
#else
|
||||
internal static string? TryAddKeyboardAccellerator(this string? input)
|
||||
#endif
|
||||
{
|
||||
if (input == null)
|
||||
return input;
|
||||
@@ -84,7 +88,7 @@ namespace WPFCustomMessageBox
|
||||
IntPtr hwnd = new WindowInteropHelper(window).Handle;
|
||||
// Change the extended window style to not show a window icon
|
||||
int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
|
||||
_ = SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
|
||||
// Update the window's non-client area to reflect the changes
|
||||
SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
<UseWPF>true</UseWPF>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2023</Copyright>
|
||||
<VersionPrefix>2.7.0</VersionPrefix>
|
||||
<VersionPrefix>2.7.5</VersionPrefix>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -6,39 +6,63 @@ namespace MPF.UI.Core
|
||||
/// <summary>
|
||||
/// Represents all required mapping values for the UI
|
||||
/// </summary>
|
||||
public class Theme
|
||||
public abstract class Theme
|
||||
{
|
||||
#region Application-Wide
|
||||
|
||||
/// <summary>
|
||||
/// SolidColorBrush used to paint the active window's border.
|
||||
/// </summary>
|
||||
public SolidColorBrush ActiveBorderBrush { get; set; }
|
||||
#if NET48
|
||||
public SolidColorBrush ActiveBorderBrush { get; protected set; }
|
||||
#else
|
||||
public SolidColorBrush? ActiveBorderBrush { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// SolidColorBrush that paints the face of a three-dimensional display element.
|
||||
/// </summary>
|
||||
public SolidColorBrush ControlBrush { get; set; }
|
||||
#if NET48
|
||||
public SolidColorBrush ControlBrush { get; protected set; }
|
||||
#else
|
||||
public SolidColorBrush? ControlBrush { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// SolidColorBrush that paints text in a three-dimensional display element.
|
||||
/// </summary>
|
||||
public SolidColorBrush ControlTextBrush { get; set; }
|
||||
#if NET48
|
||||
public SolidColorBrush ControlTextBrush { get; protected set; }
|
||||
#else
|
||||
public SolidColorBrush? ControlTextBrush { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// SolidColorBrush that paints disabled text.
|
||||
/// </summary>
|
||||
public SolidColorBrush GrayTextBrush { get; set; }
|
||||
#if NET48
|
||||
public SolidColorBrush GrayTextBrush { get; protected set; }
|
||||
#else
|
||||
public SolidColorBrush? GrayTextBrush { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// SolidColorBrush that paints the background of a window's client area.
|
||||
/// </summary>
|
||||
public SolidColorBrush WindowBrush { get; set; }
|
||||
#if NET48
|
||||
public SolidColorBrush WindowBrush { get; protected set; }
|
||||
#else
|
||||
public SolidColorBrush? WindowBrush { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// SolidColorBrush that paints the text in the client area of a window.
|
||||
/// </summary>
|
||||
public SolidColorBrush WindowTextBrush { get; set; }
|
||||
#if NET48
|
||||
public SolidColorBrush WindowTextBrush { get; protected set; }
|
||||
#else
|
||||
public SolidColorBrush? WindowTextBrush { get; protected set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -47,22 +71,38 @@ namespace MPF.UI.Core
|
||||
/// <summary>
|
||||
/// Brush for the Button.Disabled.Background resource
|
||||
/// </summary>
|
||||
public Brush Button_Disabled_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush Button_Disabled_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? Button_Disabled_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the Button.MouseOver.Background resource
|
||||
/// </summary>
|
||||
public Brush Button_MouseOver_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush Button_MouseOver_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? Button_MouseOver_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the Button.Pressed.Background resource
|
||||
/// </summary>
|
||||
public Brush Button_Pressed_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush Button_Pressed_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? Button_Pressed_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the Button.Static.Background resource
|
||||
/// </summary>
|
||||
public Brush Button_Static_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush Button_Static_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? Button_Static_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -71,62 +111,110 @@ namespace MPF.UI.Core
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.Disabled.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_Disabled_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_Disabled_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_Disabled_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.Disabled.Editable.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_Disabled_Editable_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_Disabled_Editable_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_Disabled_Editable_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.Disabled.Editable.Button.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_Disabled_Editable_Button_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_Disabled_Editable_Button_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_Disabled_Editable_Button_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.MouseOver.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_MouseOver_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_MouseOver_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_MouseOver_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.MouseOver.Editable.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_MouseOver_Editable_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_MouseOver_Editable_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_MouseOver_Editable_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.MouseOver.Editable.Button.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_MouseOver_Editable_Button_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_MouseOver_Editable_Button_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_MouseOver_Editable_Button_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.Pressed.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_Pressed_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_Pressed_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_Pressed_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.Pressed.Editable.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_Pressed_Editable_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_Pressed_Editable_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_Pressed_Editable_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.Pressed.Editable.Button.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_Pressed_Editable_Button_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_Pressed_Editable_Button_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_Pressed_Editable_Button_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.Static.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_Static_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_Static_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_Static_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.Static.Editable.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_Static_Editable_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_Static_Editable_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_Static_Editable_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the ComboBox.Static.Editable.Button.Background resource
|
||||
/// </summary>
|
||||
public Brush ComboBox_Static_Editable_Button_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ComboBox_Static_Editable_Button_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ComboBox_Static_Editable_Button_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -135,7 +223,11 @@ namespace MPF.UI.Core
|
||||
/// <summary>
|
||||
/// Brush for the CustomMessageBox.Static.Background resource
|
||||
/// </summary>
|
||||
public Brush CustomMessageBox_Static_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush CustomMessageBox_Static_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? CustomMessageBox_Static_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -144,12 +236,20 @@ namespace MPF.UI.Core
|
||||
/// <summary>
|
||||
/// Brush for the MenuItem.SubMenu.Background resource
|
||||
/// </summary>
|
||||
public Brush MenuItem_SubMenu_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush MenuItem_SubMenu_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? MenuItem_SubMenu_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the MenuItem.SubMenu.Border resource
|
||||
/// </summary>
|
||||
public Brush MenuItem_SubMenu_Border { get; set; }
|
||||
#if NET48
|
||||
public Brush MenuItem_SubMenu_Border { get; protected set; }
|
||||
#else
|
||||
public Brush? MenuItem_SubMenu_Border { get; protected set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -158,7 +258,11 @@ namespace MPF.UI.Core
|
||||
/// <summary>
|
||||
/// Brush for the ProgressBar.Background resource
|
||||
/// </summary>
|
||||
public Brush ProgressBar_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ProgressBar_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ProgressBar_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -167,7 +271,11 @@ namespace MPF.UI.Core
|
||||
/// <summary>
|
||||
/// Brush for the ScrollViewer.ScrollBar.Background resource
|
||||
/// </summary>
|
||||
public Brush ScrollViewer_ScrollBar_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush ScrollViewer_ScrollBar_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? ScrollViewer_ScrollBar_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -176,17 +284,29 @@ namespace MPF.UI.Core
|
||||
/// <summary>
|
||||
/// Brush for the TabItem.Selected.Background resource
|
||||
/// </summary>
|
||||
public Brush TabItem_Selected_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush TabItem_Selected_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? TabItem_Selected_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the TabItem.Static.Background resource
|
||||
/// </summary>
|
||||
public Brush TabItem_Static_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush TabItem_Static_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? TabItem_Static_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Brush for the TabItem.Static.Border resource
|
||||
/// </summary>
|
||||
public Brush TabItem_Static_Border { get; set; }
|
||||
#if NET48
|
||||
public Brush TabItem_Static_Border { get; protected set; }
|
||||
#else
|
||||
public Brush? TabItem_Static_Border { get; protected set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -195,7 +315,11 @@ namespace MPF.UI.Core
|
||||
/// <summary>
|
||||
/// Brush for the TextBox.Static.Background resource
|
||||
/// </summary>
|
||||
public Brush TextBox_Static_Background { get; set; }
|
||||
#if NET48
|
||||
public Brush TextBox_Static_Background { get; protected set; }
|
||||
#else
|
||||
public Brush? TextBox_Static_Background { get; protected set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -29,7 +29,11 @@ namespace MPF.UI.Core.UserControls
|
||||
/// <summary>
|
||||
/// Cached value of the last line written
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private Run lastLine = null;
|
||||
#else
|
||||
private Run? lastLine = null;
|
||||
#endif
|
||||
|
||||
public LogOutput()
|
||||
{
|
||||
@@ -164,12 +168,17 @@ namespace MPF.UI.Core.UserControls
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
#if NET48
|
||||
if (lastLine == null) lastLine = new Run();
|
||||
#else
|
||||
lastLine ??= new Run();
|
||||
#endif
|
||||
lastLine.Text = logLine.Text;
|
||||
lastLine.Foreground = logLine.GetForegroundColor();
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
@@ -183,12 +192,12 @@ namespace MPF.UI.Core.UserControls
|
||||
/// </summary>
|
||||
private void SaveInlines()
|
||||
{
|
||||
using (StreamWriter tw = new StreamWriter(File.OpenWrite("console.log")))
|
||||
using (var sw = new StreamWriter(File.OpenWrite("console.log")))
|
||||
{
|
||||
foreach (var inline in _paragraph.Inlines)
|
||||
{
|
||||
if (inline is Run run)
|
||||
tw.Write(run.Text);
|
||||
sw.Write(run.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,16 @@ namespace MPF.UI.Core.Windows
|
||||
/// <summary>
|
||||
/// Read-only access to the current disc information view model
|
||||
/// </summary>
|
||||
public DiscInformationViewModel DiscInformationViewModel => DataContext as DiscInformationViewModel;
|
||||
public DiscInformationViewModel DiscInformationViewModel => DataContext as DiscInformationViewModel ?? new DiscInformationViewModel(new Options(), new SubmissionInfo());
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public DiscInformationWindow(Options options, SubmissionInfo submissionInfo)
|
||||
#else
|
||||
public DiscInformationWindow(Options options, SubmissionInfo? submissionInfo)
|
||||
#endif
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new DiscInformationViewModel(options, submissionInfo);
|
||||
@@ -47,7 +51,11 @@ namespace MPF.UI.Core.Windows
|
||||
/// <summary>
|
||||
/// Manipulate fields based on the current disc
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private void ManipulateFields(Options options, SubmissionInfo submissionInfo)
|
||||
#else
|
||||
private void ManipulateFields(Options options, SubmissionInfo? submissionInfo)
|
||||
#endif
|
||||
{
|
||||
// Enable tabs in all fields, if required
|
||||
if (options.EnableTabsInInputFields)
|
||||
@@ -115,63 +123,71 @@ namespace MPF.UI.Core.Windows
|
||||
/// </summary>
|
||||
/// TODO: Figure out how to bind the PartiallyMatchedIDs array to a text box
|
||||
/// TODO: Convert visibility to a binding
|
||||
#if NET48
|
||||
private void HideReadOnlyFields(SubmissionInfo submissionInfo)
|
||||
#else
|
||||
private void HideReadOnlyFields(SubmissionInfo? submissionInfo)
|
||||
#endif
|
||||
{
|
||||
if (submissionInfo?.FullyMatchedID == null)
|
||||
// If there's no submission information
|
||||
if (submissionInfo == null)
|
||||
return;
|
||||
|
||||
if (submissionInfo.FullyMatchedID == null)
|
||||
FullyMatchedID.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.PartiallyMatchedIDs == null)
|
||||
if (submissionInfo.PartiallyMatchedIDs == null)
|
||||
PartiallyMatchedIDs.Visibility = Visibility.Collapsed;
|
||||
else
|
||||
PartiallyMatchedIDs.Text = string.Join(", ", submissionInfo.PartiallyMatchedIDs);
|
||||
if (submissionInfo?.CopyProtection?.AntiModchip == null)
|
||||
if (submissionInfo.CopyProtection?.AntiModchip == null)
|
||||
AntiModchip.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.TracksAndWriteOffsets?.OtherWriteOffsets == null)
|
||||
if (submissionInfo.TracksAndWriteOffsets?.OtherWriteOffsets == null)
|
||||
DiscOffset.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.DMIHash) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.Keys?.Contains(SiteCode.DMIHash) != true)
|
||||
DMIHash.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.EDC?.EDC == null)
|
||||
if (submissionInfo.EDC?.EDC == null)
|
||||
EDC.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo?.CommonDiscInfo?.ErrorsCount))
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.CommonDiscInfo?.ErrorsCount))
|
||||
ErrorsCount.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo?.CommonDiscInfo?.EXEDateBuildDate))
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.CommonDiscInfo?.EXEDateBuildDate))
|
||||
EXEDateBuildDate.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.Filename) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.Filename) != true)
|
||||
Filename.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.Header))
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.Header))
|
||||
Header.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.InternalName) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.InternalName) != true)
|
||||
InternalName.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.InternalSerialName) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.InternalSerialName) != true)
|
||||
InternalSerialName.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.Multisession) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.Multisession) != true)
|
||||
Multisession.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CopyProtection?.LibCrypt == null)
|
||||
if (submissionInfo.CopyProtection?.LibCrypt == null)
|
||||
LibCrypt.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo?.CopyProtection?.LibCryptData))
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.CopyProtection?.LibCryptData))
|
||||
LibCryptData.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.PFIHash) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.PFIHash) != true)
|
||||
PFIHash.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.PIC))
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.PIC))
|
||||
PIC.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.PVD))
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.PVD))
|
||||
PVD.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.RingNonZeroDataStart) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.RingNonZeroDataStart) != true)
|
||||
RingNonZeroDataStart.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo?.CopyProtection?.SecuROMData))
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.CopyProtection?.SecuROMData))
|
||||
SecuROMData.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.SSHash) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.SSHash) != true)
|
||||
SSHash.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo?.Extras?.SecuritySectorRanges))
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.SecuritySectorRanges))
|
||||
SecuritySectorRanges.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.SSVersion) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.SSVersion) != true)
|
||||
SSVersion.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.UniversalHash) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.UniversalHash) != true)
|
||||
UniversalHash.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.VolumeLabel) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.VolumeLabel) != true)
|
||||
VolumeLabel.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.XeMID) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.XeMID) != true)
|
||||
XeMID.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.XMID) != true)
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.XMID) != true)
|
||||
XMID.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
@@ -179,7 +195,11 @@ namespace MPF.UI.Core.Windows
|
||||
/// Update visible fields and sections based on the media type
|
||||
/// </summary>
|
||||
/// TODO: See if these can be done by binding
|
||||
#if NET48
|
||||
private void UpdateFromDiscType(SubmissionInfo submissionInfo)
|
||||
#else
|
||||
private void UpdateFromDiscType(SubmissionInfo? submissionInfo)
|
||||
#endif
|
||||
{
|
||||
// Sony-printed discs have layers in the opposite order
|
||||
var system = submissionInfo?.CommonDiscInfo?.System;
|
||||
@@ -326,7 +346,11 @@ namespace MPF.UI.Core.Windows
|
||||
/// Update visible fields and sections based on the system type
|
||||
/// </summary>
|
||||
/// TODO: See if these can be done by binding
|
||||
#if NET48
|
||||
private void UpdateFromSystemType(SubmissionInfo submissionInfo)
|
||||
#else
|
||||
private void UpdateFromSystemType(SubmissionInfo? submissionInfo)
|
||||
#endif
|
||||
{
|
||||
var system = submissionInfo?.CommonDiscInfo?.System;
|
||||
switch (system)
|
||||
@@ -337,7 +361,7 @@ namespace MPF.UI.Core.Windows
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace MPF.UI.Core.Windows
|
||||
/// <summary>
|
||||
/// Read-only access to the current main view model
|
||||
/// </summary>
|
||||
public MainViewModel MainViewModel => DataContext as MainViewModel;
|
||||
public MainViewModel MainViewModel => DataContext as MainViewModel ?? new MainViewModel();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
@@ -45,14 +45,18 @@ namespace MPF.UI.Core.Windows
|
||||
MainViewModel.Init(LogOutput.EnqueueLog, DisplayUserMessage, ShowDiscInformationWindow);
|
||||
|
||||
// Set the UI color scheme according to the options
|
||||
if (MainViewModel.Options.EnableDarkMode)
|
||||
EnableDarkMode();
|
||||
else
|
||||
EnableLightMode();
|
||||
ApplyTheme();
|
||||
|
||||
// Check for updates, if necessary
|
||||
if (MainViewModel.Options.CheckForUpdatesOnStartup)
|
||||
CheckForUpdates(showIfSame: false);
|
||||
|
||||
// Handle first-run, if necessary
|
||||
if (MainViewModel.Options.FirstRun)
|
||||
{
|
||||
// Show the options window
|
||||
ShowOptionsWindow("Welcome to MPF, Explore the Options");
|
||||
}
|
||||
}
|
||||
|
||||
#region UI Functionality
|
||||
@@ -95,8 +99,10 @@ namespace MPF.UI.Core.Windows
|
||||
{
|
||||
// Get the current path, if possible
|
||||
string currentPath = MainViewModel.OutputPath;
|
||||
if (string.IsNullOrWhiteSpace(currentPath))
|
||||
if (string.IsNullOrWhiteSpace(currentPath) && !string.IsNullOrWhiteSpace(MainViewModel.Options.DefaultOutputPath))
|
||||
currentPath = Path.Combine(MainViewModel.Options.DefaultOutputPath, "track.bin");
|
||||
else if (string.IsNullOrWhiteSpace(currentPath))
|
||||
currentPath = "track.bin";
|
||||
if (string.IsNullOrWhiteSpace(currentPath))
|
||||
currentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "track.bin");
|
||||
|
||||
@@ -104,7 +110,7 @@ namespace MPF.UI.Core.Windows
|
||||
currentPath = Path.GetFullPath(currentPath);
|
||||
|
||||
// Get the directory
|
||||
string directory = Path.GetDirectoryName(currentPath);
|
||||
var directory = Path.GetDirectoryName(currentPath);
|
||||
|
||||
// Get the filename
|
||||
string filename = Path.GetFileName(currentPath);
|
||||
@@ -128,14 +134,14 @@ namespace MPF.UI.Core.Windows
|
||||
/// <param name="showIfSame">True to show the box even if it's the same, false to only show if it's different</param>
|
||||
public void CheckForUpdates(bool showIfSame)
|
||||
{
|
||||
(bool different, string message, string url) = MainViewModel.CheckForUpdates();
|
||||
(bool different, string message, var url) = MainViewModel.CheckForUpdates();
|
||||
|
||||
// If we have a new version, put it in the clipboard
|
||||
if (different)
|
||||
Clipboard.SetText(url);
|
||||
|
||||
if (showIfSame || different)
|
||||
CustomMessageBox.Show(message, "Version Update Check", MessageBoxButton.OK, different ? MessageBoxImage.Exclamation : MessageBoxImage.Information);
|
||||
CustomMessageBox.Show(this, message, "Version Update Check", MessageBoxButton.OK, different ? MessageBoxImage.Exclamation : MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -204,10 +210,14 @@ namespace MPF.UI.Core.Windows
|
||||
/// </summary>
|
||||
/// <param name="submissionInfo">SubmissionInfo object to display and possibly change</param>
|
||||
/// <returns>Dialog open result</returns>
|
||||
#if NET48
|
||||
public (bool?, SubmissionInfo) ShowDiscInformationWindow(SubmissionInfo submissionInfo)
|
||||
#else
|
||||
public (bool?, SubmissionInfo?) ShowDiscInformationWindow(SubmissionInfo? submissionInfo)
|
||||
#endif
|
||||
{
|
||||
if (MainViewModel.Options.ShowDiscEjectReminder)
|
||||
CustomMessageBox.Show("It is now safe to eject the disc", "Eject", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
CustomMessageBox.Show(this, "It is now safe to eject the disc", "Eject", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
|
||||
var discInformationWindow = new DiscInformationWindow(MainViewModel.Options, submissionInfo)
|
||||
{
|
||||
@@ -217,19 +227,33 @@ namespace MPF.UI.Core.Windows
|
||||
ShowInTaskbar = true,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
};
|
||||
|
||||
discInformationWindow.Closed += delegate { this.Activate(); };
|
||||
bool? result = discInformationWindow.ShowDialog();
|
||||
|
||||
// Copy back the submission info changes, if necessary
|
||||
if (result == true)
|
||||
#if NET48
|
||||
submissionInfo = discInformationWindow.DiscInformationViewModel.SubmissionInfo.Clone() as SubmissionInfo;
|
||||
#else
|
||||
submissionInfo = (discInformationWindow.DiscInformationViewModel.SubmissionInfo.Clone() as SubmissionInfo)!;
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
return (result, submissionInfo);
|
||||
#else
|
||||
return (result, submissionInfo!);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the Options window
|
||||
/// </summary>
|
||||
public void ShowOptionsWindow()
|
||||
#if NET48
|
||||
public void ShowOptionsWindow(string title = null)
|
||||
#else
|
||||
public void ShowOptionsWindow(string? title = null)
|
||||
#endif
|
||||
{
|
||||
var optionsWindow = new OptionsWindow(MainViewModel.Options)
|
||||
{
|
||||
@@ -237,27 +261,26 @@ namespace MPF.UI.Core.Windows
|
||||
Owner = this,
|
||||
ShowActivated = true,
|
||||
ShowInTaskbar = true,
|
||||
Title = title ?? "Options",
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
};
|
||||
|
||||
optionsWindow.Closed += delegate { this.Activate(); };
|
||||
optionsWindow.Closed += OnOptionsUpdated;
|
||||
optionsWindow.Show();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recolor all UI elements for light mode
|
||||
/// Set the UI color scheme according to the options
|
||||
/// </summary>
|
||||
private static void EnableLightMode()
|
||||
private void ApplyTheme()
|
||||
{
|
||||
var theme = new LightModeTheme();
|
||||
theme.Apply();
|
||||
}
|
||||
Theme theme;
|
||||
if (MainViewModel.Options.EnableDarkMode)
|
||||
theme = new DarkModeTheme();
|
||||
else
|
||||
theme = new LightModeTheme();
|
||||
|
||||
/// <summary>
|
||||
/// Recolor all UI elements for dark mode
|
||||
/// </summary>
|
||||
private static void EnableDarkMode()
|
||||
{
|
||||
var theme = new DarkModeTheme();
|
||||
theme.Apply();
|
||||
}
|
||||
|
||||
@@ -268,11 +291,23 @@ namespace MPF.UI.Core.Windows
|
||||
/// <summary>
|
||||
/// Handler for OptionsWindow OnUpdated event
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public void OnOptionsUpdated(object sender, EventArgs e)
|
||||
#else
|
||||
public void OnOptionsUpdated(object? sender, EventArgs e)
|
||||
#endif
|
||||
{
|
||||
bool savedSettings = (sender as OptionsWindow)?.OptionsViewModel?.SavedSettings ?? false;
|
||||
var options = (sender as OptionsWindow).OptionsViewModel.Options;
|
||||
// Get the options window
|
||||
var optionsWindow = (sender as OptionsWindow);
|
||||
if (optionsWindow?.OptionsViewModel == null)
|
||||
return;
|
||||
|
||||
bool savedSettings = optionsWindow.OptionsViewModel.SavedSettings;
|
||||
var options = optionsWindow.OptionsViewModel.Options;
|
||||
MainViewModel.UpdateOptions(savedSettings, options);
|
||||
|
||||
// Set the UI color scheme according to the options
|
||||
ApplyTheme();
|
||||
}
|
||||
|
||||
#region Menu Bar
|
||||
@@ -283,7 +318,7 @@ namespace MPF.UI.Core.Windows
|
||||
public void AboutClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
string aboutText = MainViewModel.CreateAboutText();
|
||||
CustomMessageBox.Show(aboutText, "About", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
CustomMessageBox.Show(this, aboutText, "About", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -319,14 +354,14 @@ namespace MPF.UI.Core.Windows
|
||||
/// </summary>
|
||||
public async void CopyProtectScanButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
(string output, string error) = await MainViewModel.ScanAndShowProtection();
|
||||
var (output, error) = await MainViewModel.ScanAndShowProtection();
|
||||
|
||||
if (!MainViewModel.LogPanelExpanded)
|
||||
{
|
||||
if (string.IsNullOrEmpty(error))
|
||||
CustomMessageBox.Show(output, "Detected Protection(s)", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
if (!string.IsNullOrEmpty(output) && string.IsNullOrEmpty(error))
|
||||
CustomMessageBox.Show(this, output, "Detected Protection(s)", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
else
|
||||
CustomMessageBox.Show("An exception occurred, see the log for details", "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
CustomMessageBox.Show(this, "An exception occurred, see the log for details", "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
xmlns:core="clr-namespace:MPF.UI.Core"
|
||||
xmlns:coreWindows="clr-namespace:MPF.UI.Core.Windows"
|
||||
mc:Ignorable="d"
|
||||
Title="Options" Width="515.132" WindowStyle="None"
|
||||
Width="515.132" WindowStyle="None"
|
||||
WindowStartupLocation="CenterOwner" ResizeMode="CanMinimize" SizeToContent="Height"
|
||||
BorderBrush="DarkGray" BorderThickness="2">
|
||||
|
||||
@@ -32,7 +32,11 @@
|
||||
<Image Grid.Column="0" Source="/Images/Icon.ico" Height="20" Width="20" Margin="1" />
|
||||
<Label Grid.Column="1" Grid.ColumnSpan="4" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" MouseDown="TitleMouseDown">
|
||||
<Label.Content>
|
||||
<TextBlock TextAlignment="Center"><Bold>Options</Bold></TextBlock>
|
||||
<TextBlock>
|
||||
<TextBlock.Inlines>
|
||||
<Run FontWeight="Bold" Text="{Binding Title, Mode=OneWay}"/>
|
||||
</TextBlock.Inlines>
|
||||
</TextBlock>
|
||||
</Label.Content>
|
||||
<Label.ContextMenu>
|
||||
<ContextMenu Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
|
||||
@@ -63,28 +67,84 @@
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
|
||||
<TabControl Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
|
||||
Foreground="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"
|
||||
Style="{DynamicResource CustomTabControlStyle}">
|
||||
<TabItem Header="User Interface" Style="{DynamicResource CustomTabItemStyle}">
|
||||
<UniformGrid Columns="2" Rows="3">
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Dark Mode"
|
||||
IsChecked="{Binding Options.EnableDarkMode}"
|
||||
ToolTip="(Experimental) Enable dark mode across the entire application" Margin="0,4"
|
||||
/>
|
||||
<CheckBox VerticalAlignment="Center" Content="Check for Updates on Startup"
|
||||
IsChecked="{Binding Options.CheckForUpdatesOnStartup}"
|
||||
ToolTip="Check for updates when the application starts" 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"
|
||||
/>
|
||||
</UniformGrid>
|
||||
<TabItem Header="General" Style="{DynamicResource CustomTabItemStyle}">
|
||||
<StackPanel>
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="User Interface">
|
||||
<UniformGrid Columns="2" Rows="2">
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Dark Mode"
|
||||
IsChecked="{Binding Options.EnableDarkMode}"
|
||||
ToolTip="(Experimental) Enable dark mode across the entire application" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Check for Updates on Startup"
|
||||
IsChecked="{Binding Options.CheckForUpdatesOnStartup}"
|
||||
ToolTip="Check for updates when the application starts" 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"
|
||||
/>
|
||||
</UniformGrid>
|
||||
</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"
|
||||
/>
|
||||
|
||||
<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"
|
||||
/>
|
||||
<Label/>
|
||||
<!-- Empty label for padding -->
|
||||
|
||||
<Label VerticalAlignment="Center" Content="Default System:" HorizontalAlignment="Right" />
|
||||
<ComboBox x:Name="DefaultSystemComboBox" Height="22" Width="200" HorizontalAlignment="Left"
|
||||
ItemsSource="{Binding Systems}" SelectedItem="{Binding Options.DefaultSystem, Converter={StaticResource ElementConverter}, Mode=TwoWay}"
|
||||
SelectedIndex="0" Style="{DynamicResource CustomComboBoxStyle}">
|
||||
<ComboBox.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type ComboBoxItem}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsHeader}" Value="True">
|
||||
<Setter Property="IsEnabled" Value="False"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ComboBox.ItemContainerStyle>
|
||||
</ComboBox>
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Logging">
|
||||
<UniformGrid Columns="2" Rows="1">
|
||||
<CheckBox VerticalAlignment="Center" Content="Verbose Logging"
|
||||
IsChecked="{Binding Options.VerboseLogging}"
|
||||
ToolTip="Display all logging statements" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Auto-Open Log"
|
||||
IsChecked="{Binding Options.OpenLogWindowAtStartup}"
|
||||
ToolTip="Open the log panel when the program launches" Margin="0,4"
|
||||
/>
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
</StackPanel>
|
||||
</TabItem>
|
||||
|
||||
|
||||
<TabItem Header="Paths" Style="{DynamicResource CustomTabItemStyle}">
|
||||
<Grid Margin="5,5,5,5">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -135,47 +195,12 @@
|
||||
<TabItem Header="Dumping" Style="{DynamicResource CustomTabItemStyle}">
|
||||
<StackPanel>
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Dumping">
|
||||
<UniformGrid Columns="2" Rows="9">
|
||||
<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"
|
||||
/>
|
||||
|
||||
<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"
|
||||
/>
|
||||
|
||||
<Label VerticalAlignment="Center" Content="Default System:" HorizontalAlignment="Right" />
|
||||
<ComboBox x:Name="DefaultSystemComboBox" Height="22" Width="200" HorizontalAlignment="Left"
|
||||
ItemsSource="{Binding Systems}" SelectedItem="{Binding Options.DefaultSystem, Converter={StaticResource ElementConverter}, Mode=TwoWay}"
|
||||
SelectedIndex="0" Style="{DynamicResource CustomComboBoxStyle}">
|
||||
<ComboBox.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type ComboBoxItem}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsHeader}" Value="True">
|
||||
<Setter Property="IsEnabled" Value="False"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ComboBox.ItemContainerStyle>
|
||||
</ComboBox>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="No Fixed Drives"
|
||||
IsChecked="{Binding Options.IgnoreFixedDrives}"
|
||||
ToolTip="Ignore hard drives and other fixed drives" Margin="0,4"
|
||||
/>
|
||||
|
||||
<UniformGrid Columns="2" Rows="7">
|
||||
<CheckBox VerticalAlignment="Center" Content="Show Separate Window"
|
||||
IsChecked="{Binding Options.ToolsInSeparateWindow}"
|
||||
ToolTip="Show program output in separate command window instead of in the log. Enable this if you have a weaker system as there is an increased processing load otherwise." Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Protection Scan"
|
||||
IsChecked="{Binding Options.ScanForProtection}"
|
||||
ToolTip="Enable automatic checking for copy protection on dumped media" Margin="0,4,0,0"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Output Protection File"
|
||||
IsChecked="{Binding Options.OutputSeparateProtectionFile}" IsEnabled="{Binding Options.ScanForProtection}"
|
||||
ToolTip="Output protection information to a separate file" Margin="0,4,0,0"
|
||||
@@ -216,6 +241,11 @@
|
||||
ToolTip="Enable adding placeholder text in the output for required and optional fields" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Add Filename Suffix"
|
||||
IsChecked="{Binding Options.AddFilenameSuffix}"
|
||||
ToolTip="Enable appending the output filename to the generated files" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Output Submission JSON"
|
||||
IsChecked="{Binding Options.OutputSubmissionJSON}"
|
||||
ToolTip="Enable outputting a compressed JSON version of the submission info" Margin="0,4"
|
||||
@@ -230,9 +260,38 @@
|
||||
IsChecked="{Binding Options.CompressLogFiles}"
|
||||
ToolTip="Compress output log files to reduce space" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Delete Unnecessary Files"
|
||||
IsChecked="{Binding Options.DeleteUnnecessaryFiles}"
|
||||
ToolTip="Delete unnecesary output files to reduce space" Margin="0,4"
|
||||
/>
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
|
||||
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Protection">
|
||||
<UniformGrid Columns="2" Rows="2">
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Protection Scan"
|
||||
IsChecked="{Binding Options.ScanForProtection}"
|
||||
ToolTip="Enable automatic checking for copy protection on dumped media" Margin="0,4,0,0"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Scan Archive Contents"
|
||||
IsChecked="{Binding Options.ScanArchivesForProtection}"
|
||||
ToolTip="Enable scanning archive contents during protection scanning (may drastically increase scanning time but is more accurate)" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Include Executable Packers"
|
||||
IsChecked="{Binding Options.ScanPackersForProtection}"
|
||||
ToolTip="Include executable packers in outputted protections" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Include Debug Information"
|
||||
IsChecked="{Binding Options.IncludeDebugProtectionInformation}"
|
||||
ToolTip="Include debug information during protection scans" Margin="0,4"
|
||||
/>
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Default Speeds" Grid.ColumnSpan="2">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -247,7 +306,7 @@
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="CD" />
|
||||
<Slider x:Name="DumpSpeedCDSlider" Grid.Row="0" Grid.Column="1" Minimum="1" Maximum="72" IsSnapToTickEnabled="True" TickPlacement="BottomRight"
|
||||
Ticks="{Binding Source={x:Static core:Constants.SpeedsForCDAsCollection}}"
|
||||
@@ -280,142 +339,121 @@
|
||||
</StackPanel>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Protection Scanning" Style="{DynamicResource CustomTabItemStyle}">
|
||||
<TabItem Header="Programs" Style="{DynamicResource CustomTabItemStyle}">
|
||||
<StackPanel>
|
||||
<UniformGrid Columns="2" Rows="2">
|
||||
<CheckBox VerticalAlignment="Center" Content="Scan Archive Contents"
|
||||
IsChecked="{Binding Options.ScanArchivesForProtection}"
|
||||
ToolTip="Enable scanning archive contents during protection scanning (may drastically increase scanning time but is more accurate)" Margin="0,4"
|
||||
/>
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Aaru">
|
||||
<UniformGrid Columns="2" Rows="3">
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Debug Output"
|
||||
IsChecked="{Binding Options.AaruEnableDebug}"
|
||||
ToolTip="Enable debug output in logs" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Include Executable Packers"
|
||||
IsChecked="{Binding Options.ScanPackersForProtection}"
|
||||
ToolTip="Include executable packers in outputted protections" Margin="0,4"
|
||||
/>
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Verbose Output"
|
||||
IsChecked="{Binding Options.AaruEnableVerbose}"
|
||||
ToolTip="Enable verbose output in logs" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Include Debug Information"
|
||||
IsChecked="{Binding Options.IncludeDebugProtectionInformation}"
|
||||
ToolTip="Include debug information during protection scans" Margin="0,4"
|
||||
/>
|
||||
</UniformGrid>
|
||||
<CheckBox VerticalAlignment="Center" Content="Force Dumping"
|
||||
IsChecked="{Binding Options.AaruForceDumping}"
|
||||
ToolTip="Enable forcing dump even if there are issues" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Strip Personal Data"
|
||||
IsChecked="{Binding Options.AaruStripPersonalData}"
|
||||
ToolTip="Enable stripping of personally identifiable information from metadata" Margin="0,4,0,0"
|
||||
/>
|
||||
|
||||
<Label Content="Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
|
||||
Text="{Binding Options.AaruRereadCount}"
|
||||
ToolTip="Specifies how many rereads are attempted for sector and subchannel errors"
|
||||
/>
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="DiscImageCreator">
|
||||
<UniformGrid Columns="2" Rows="6">
|
||||
<CheckBox VerticalAlignment="Center" Content="Quiet Mode"
|
||||
IsChecked="{Binding Options.DICQuietMode}"
|
||||
ToolTip="Disable sounds (beeps) during and after operations" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Paranoid Mode"
|
||||
IsChecked="{Binding Options.DICParanoidMode}"
|
||||
ToolTip="Enable pedantic and super-safe flags" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Use CMI Flag"
|
||||
IsChecked="{Binding Options.DICUseCMIFlag}"
|
||||
ToolTip="Enable the CMI flag for supported disc types (DVD/HD-DVD only)" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Reset After Dump"
|
||||
IsChecked="{Binding Options.DICResetDriveAfterDump}"
|
||||
ToolTip="Reset disc drives after dumping; useful for some older machines" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Multi-Sector Read"
|
||||
IsChecked="{Binding Options.DICMultiSectorRead}"
|
||||
ToolTip="Enable the /mr flag for BD drive dumping" Margin="0,4"
|
||||
/>
|
||||
<Label/> <!-- Empty label for padding -->
|
||||
|
||||
<Label Content="Multi-Sector Read Value:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
|
||||
Text="{Binding Options.DICMultiSectorReadValue}" IsEnabled="{Binding Options.DICMultiSectorRead}"
|
||||
ToolTip="Set the default value for the /mr flag"
|
||||
/>
|
||||
|
||||
<Label Content="CD Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
|
||||
Text="{Binding Options.DICRereadCount}"
|
||||
ToolTip="Specifies how many rereads are attempted on C2 error [CD only]"
|
||||
/>
|
||||
|
||||
<Label Content="DVD/HD-DVD/BD Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
|
||||
Text="{Binding Options.DICDVDRereadCount}"
|
||||
ToolTip="Specifies how many rereads are attempted on read error [DVD/HD-DVD/BD only]"
|
||||
/>
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Redumper">
|
||||
<UniformGrid Columns="2" Rows="3">
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Debug Output"
|
||||
IsChecked="{Binding Options.RedumperEnableDebug}"
|
||||
ToolTip="Enable debug output in logs" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Verbose Output"
|
||||
IsChecked="{Binding Options.RedumperEnableVerbose}"
|
||||
ToolTip="Enable verbose output in logs" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable BE Drive Reading"
|
||||
IsChecked="{Binding Options.RedumperUseBEReading}"
|
||||
ToolTip="Enable setting drive read method to BE_CDDA by default" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Set Generic Drive Type"
|
||||
IsChecked="{Binding Options.RedumperUseGenericDriveType}"
|
||||
ToolTip="Enable setting drive type to Generic by default" Margin="0,4"
|
||||
/>
|
||||
|
||||
<Label Content="Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
|
||||
Text="{Binding Options.RedumperRereadCount}"
|
||||
ToolTip="Specifies how many rereads are attempted on read error"
|
||||
/>
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
</StackPanel>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Aaru" Style="{DynamicResource CustomTabItemStyle}">
|
||||
<UniformGrid Columns="2" Rows="3">
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Debug Output"
|
||||
IsChecked="{Binding Options.AaruEnableDebug}"
|
||||
ToolTip="Enable debug output in logs" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Verbose Output"
|
||||
IsChecked="{Binding Options.AaruEnableVerbose}"
|
||||
ToolTip="Enable verbose output in logs" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Force Dumping"
|
||||
IsChecked="{Binding Options.AaruForceDumping}"
|
||||
ToolTip="Enable forcing dump even if there are issues" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Strip Personal Data"
|
||||
IsChecked="{Binding Options.AaruStripPersonalData}"
|
||||
ToolTip="Enable stripping of personally identifiable information from metadata" Margin="0,4,0,0"
|
||||
/>
|
||||
|
||||
<Label Content="Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
|
||||
Text="{Binding Options.AaruRereadCount}"
|
||||
ToolTip="Specifies how many rereads are attempted for sector and subchannel errors"
|
||||
/>
|
||||
</UniformGrid>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="DiscImageCreator" Style="{DynamicResource CustomTabItemStyle}">
|
||||
<UniformGrid Columns="2" Rows="6">
|
||||
<CheckBox VerticalAlignment="Center" Content="Quiet Mode"
|
||||
IsChecked="{Binding Options.DICQuietMode}"
|
||||
ToolTip="Disable sounds (beeps) during and after operations" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Paranoid Mode"
|
||||
IsChecked="{Binding Options.DICParanoidMode}"
|
||||
ToolTip="Enable pedantic and super-safe flags" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Use CMI Flag"
|
||||
IsChecked="{Binding Options.DICUseCMIFlag}"
|
||||
ToolTip="Enable the CMI flag for supported disc types (DVD/HD-DVD only)" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Reset After Dump"
|
||||
IsChecked="{Binding Options.DICResetDriveAfterDump}"
|
||||
ToolTip="Reset disc drives after dumping; useful for some older machines" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Multi-Sector Read"
|
||||
IsChecked="{Binding Options.DICMultiSectorRead}"
|
||||
ToolTip="Enable the /mr flag for BD drive dumping" Margin="0,4"
|
||||
/>
|
||||
<Label/> <!-- Empty label for padding -->
|
||||
|
||||
<Label Content="Multi-Sector Read Value:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
|
||||
Text="{Binding Options.DICMultiSectorReadValue}" IsEnabled="{Binding Options.DICMultiSectorRead}"
|
||||
ToolTip="Set the default value for the /mr flag"
|
||||
/>
|
||||
|
||||
<Label Content="CD Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
|
||||
Text="{Binding Options.DICRereadCount}"
|
||||
ToolTip="Specifies how many rereads are attempted on C2 error [CD only]"
|
||||
/>
|
||||
|
||||
<Label Content="DVD/HD-DVD/BD Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
|
||||
Text="{Binding Options.DICDVDRereadCount}"
|
||||
ToolTip="Specifies how many rereads are attempted on read error [DVD/HD-DVD/BD only]"
|
||||
/>
|
||||
</UniformGrid>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Redumper" Style="{DynamicResource CustomTabItemStyle}">
|
||||
<UniformGrid Columns="2" Rows="2">
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Debug Output"
|
||||
IsChecked="{Binding Options.RedumperEnableDebug}"
|
||||
ToolTip="Enable debug output in logs" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Enable Verbose Output"
|
||||
IsChecked="{Binding Options.RedumperEnableVerbose}"
|
||||
ToolTip="Enable verbose output in logs" Margin="0,4"
|
||||
/>
|
||||
|
||||
<Label Content="Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox VerticalAlignment="Center" VerticalContentAlignment="Center"
|
||||
Text="{Binding Options.RedumperRereadCount}"
|
||||
ToolTip="Specifies how many rereads are attempted on read error"
|
||||
/>
|
||||
</UniformGrid>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Logging" Style="{DynamicResource CustomTabItemStyle}">
|
||||
<UniformGrid Columns="2">
|
||||
<CheckBox VerticalAlignment="Center" Content="Verbose Logging"
|
||||
IsChecked="{Binding Options.VerboseLogging}"
|
||||
ToolTip="Display all logging statements" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Auto-Open Log"
|
||||
IsChecked="{Binding Options.OpenLogWindowAtStartup}"
|
||||
ToolTip="Open the log panel when the program launches" Margin="0,4"
|
||||
/>
|
||||
</UniformGrid>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Login Info" Style="{DynamicResource CustomTabItemStyle}">
|
||||
<StackPanel>
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Redump Credentials">
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Redump">
|
||||
<UniformGrid Columns="5">
|
||||
<Label VerticalAlignment="Center" HorizontalAlignment="Right" Content="Username" />
|
||||
<TextBox x:Name="RedumpUsernameTextBox" Height="22" HorizontalAlignment="Stretch"
|
||||
@@ -441,12 +479,14 @@
|
||||
<!-- Accept / Cancel -->
|
||||
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<UniformGrid Columns="4" Margin="5,5,5,5" Height="28">
|
||||
<Label/> <!-- Empty label for padding -->
|
||||
<Label/>
|
||||
<!-- Empty label for padding -->
|
||||
<Button Name="AcceptButton" Height="25" Width="80" IsDefault="True" Content="Accept"
|
||||
Style="{DynamicResource CustomButtonStyle}" />
|
||||
<Button Name="CancelButton" Height="25" Width="80" IsCancel="True" Content="Cancel"
|
||||
Style="{DynamicResource CustomButtonStyle}" />
|
||||
<Label/> <!-- Empty label for padding -->
|
||||
<Label/>
|
||||
<!-- Empty label for padding -->
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
</StackPanel>
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace MPF.UI.Core.Windows
|
||||
/// <summary>
|
||||
/// Read-only access to the current options view model
|
||||
/// </summary>
|
||||
public OptionsViewModel OptionsViewModel => DataContext as OptionsViewModel;
|
||||
public OptionsViewModel OptionsViewModel => DataContext as OptionsViewModel ?? new OptionsViewModel(new Options());
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
@@ -33,6 +33,7 @@ namespace MPF.UI.Core.Windows
|
||||
// Add handlers
|
||||
AaruPathButton.Click += BrowseForPathClick;
|
||||
DiscImageCreatorPathButton.Click += BrowseForPathClick;
|
||||
RedumperPathButton.Click += BrowseForPathClick;
|
||||
DefaultOutputPathButton.Click += BrowseForPathClick;
|
||||
|
||||
AcceptButton.Click += OnAcceptClick;
|
||||
@@ -41,25 +42,44 @@ namespace MPF.UI.Core.Windows
|
||||
RedumpLoginTestButton.Click += OnRedumpTestClick;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OptionsWindow OnContentRendered event
|
||||
/// </summary>
|
||||
protected override void OnContentRendered(EventArgs e)
|
||||
{
|
||||
base.OnContentRendered(e);
|
||||
|
||||
// Set the window title
|
||||
OptionsViewModel.Title = this.Title;
|
||||
}
|
||||
|
||||
#region UI Commands
|
||||
|
||||
/// <summary>
|
||||
/// Browse and set a path based on the invoking button
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private void BrowseForPath(Window parent, System.Windows.Controls.Button button)
|
||||
#else
|
||||
private void BrowseForPath(Window parent, System.Windows.Controls.Button? button)
|
||||
#endif
|
||||
{
|
||||
// If the button is null, we can't do anything
|
||||
if (button == null)
|
||||
return;
|
||||
|
||||
// Strips button prefix to obtain the setting name
|
||||
#if NET48
|
||||
string pathSettingName = button.Name.Substring(0, button.Name.IndexOf("Button"));
|
||||
#else
|
||||
string pathSettingName = button.Name[..button.Name.IndexOf("Button")];
|
||||
#endif
|
||||
|
||||
// TODO: hack for now, then we'll see
|
||||
bool shouldBrowseForPath = pathSettingName == "DefaultOutputPath";
|
||||
|
||||
string currentPath = TextBoxForPathSetting(parent, pathSettingName)?.Text;
|
||||
string initialDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
var currentPath = TextBoxForPathSetting(parent, pathSettingName)?.Text;
|
||||
var initialDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
if (!shouldBrowseForPath && !string.IsNullOrEmpty(currentPath))
|
||||
initialDirectory = Path.GetDirectoryName(Path.GetFullPath(currentPath));
|
||||
|
||||
@@ -88,7 +108,9 @@ namespace MPF.UI.Core.Windows
|
||||
if (exists)
|
||||
{
|
||||
OptionsViewModel.Options[pathSettingName] = path;
|
||||
TextBoxForPathSetting(parent, pathSettingName).Text = path;
|
||||
var textBox = TextBoxForPathSetting(parent, pathSettingName);
|
||||
if (textBox != null)
|
||||
textBox.Text = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -108,18 +130,30 @@ namespace MPF.UI.Core.Windows
|
||||
/// </summary>
|
||||
/// <param name="name">Setting name to find</param>
|
||||
/// <returns>TextBox for that setting</returns>
|
||||
private System.Windows.Controls.TextBox TextBoxForPathSetting(Window parent, string name) =>
|
||||
#if NET48
|
||||
private static System.Windows.Controls.TextBox TextBoxForPathSetting(Window parent, string name) =>
|
||||
#else
|
||||
private static System.Windows.Controls.TextBox? TextBoxForPathSetting(Window parent, string name) =>
|
||||
#endif
|
||||
parent.FindName(name + "TextBox") as System.Windows.Controls.TextBox;
|
||||
|
||||
/// <summary>
|
||||
/// Create an open folder dialog box
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static FolderBrowserDialog CreateFolderBrowserDialog() => new FolderBrowserDialog();
|
||||
#else
|
||||
private static FolderBrowserDialog CreateFolderBrowserDialog() => new();
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Create an open file dialog box
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static OpenFileDialog CreateOpenFileDialog(string initialDirectory)
|
||||
#else
|
||||
private static OpenFileDialog CreateOpenFileDialog(string? initialDirectory)
|
||||
#endif
|
||||
{
|
||||
return new OpenFileDialog()
|
||||
{
|
||||
@@ -142,7 +176,7 @@ namespace MPF.UI.Core.Windows
|
||||
#if NET48
|
||||
(bool? success, string message) = OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password);
|
||||
#else
|
||||
(bool? success, string message) = await OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password);
|
||||
(bool? success, string? message) = await OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password);
|
||||
#endif
|
||||
|
||||
if (success == true)
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace MPF
|
||||
namespace MPF
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This application is not fully MVVM. The following steps are needed to get there:
|
||||
/// - Use commands instead of event handlers, where at all possible
|
||||
/// - Reduce the amount of manual UI adjustments needed, instead binding to the view models
|
||||
/// </remarks>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
public partial class App : System.Windows.Application { }
|
||||
}
|
||||
|
||||
@@ -11,10 +11,14 @@
|
||||
<Description>Frontend for various dumping programs</Description>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2023</Copyright>
|
||||
<VersionPrefix>2.7.0</VersionPrefix>
|
||||
<VersionPrefix>2.7.5</VersionPrefix>
|
||||
<InternalsVisibleTo>MPF.Test</InternalsVisibleTo>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\Icon.ico" />
|
||||
</ItemGroup>
|
||||
@@ -29,7 +33,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.8.0" GeneratePathProperty="true">
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.9.0" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.1.1" />
|
||||
|
||||
91
appveyor.yml
91
appveyor.yml
@@ -1,5 +1,5 @@
|
||||
# version format
|
||||
version: 2.7.0-{build}
|
||||
version: 2.7.5-{build}
|
||||
|
||||
# pull request template
|
||||
pull_requests:
|
||||
@@ -49,78 +49,27 @@ after_build:
|
||||
|
||||
# Aaru
|
||||
- ps: appveyor DownloadFile https://github.com/aaru-dps/Aaru/releases/download/v5.3.2/aaru-5.3.2_windows_x64.zip
|
||||
- 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Debug\net48\win7-x64\publish\Programs\Aaru *
|
||||
- 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Debug\net6.0-windows\win-x64\publish\Programs\Aaru *
|
||||
- 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Debug\net7.0-windows\win-x64\publish\Programs\Aaru *
|
||||
# - 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Release\net48\win7-x64\publish\Programs\Aaru *
|
||||
# - 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Release\net6.0-windows\win-x64\publish\Programs\Aaru *
|
||||
# - 7z x aaru-5.3.2_windows_x64.zip -oMPF\bin\Release\net7.0-windows\win-x64\publish\Programs\Aaru *
|
||||
|
||||
# DiscImageCreator
|
||||
- ps: appveyor DownloadFile https://github.com/saramibreak/DiscImageCreator/files/11660558/DiscImageCreator_20230606.zip
|
||||
- 7z e DiscImageCreator_20230606.zip -oMPF\bin\Debug\net48\win7-x64\publish\Programs\Creator Release_ANSI\*
|
||||
- 7z e DiscImageCreator_20230606.zip -oMPF\bin\Debug\net6.0-windows\win-x64\publish\Programs\Creator Release_ANSI\*
|
||||
- 7z e DiscImageCreator_20230606.zip -oMPF\bin\Debug\net7.0-windows\win-x64\publish\Programs\Creator Release_ANSI\*
|
||||
# - 7z e DiscImageCreator_20230606.zip -oMPF\bin\Release\net48\win7-x64\publish\Programs\Creator Release_ANSI\*
|
||||
# - 7z e DiscImageCreator_20230606.zip -oMPF\bin\Release\net6.0-windows\win-x64\publish\Programs\Creator Release_ANSI\*
|
||||
# - 7z e DiscImageCreator_20230606.zip -oMPF\bin\Release\net7.0-windows\win-x64\publish\Programs\Creator Release_ANSI\*
|
||||
|
||||
# Redumper
|
||||
- ps: appveyor DownloadFile https://github.com/superg/redumper/releases/download/build_221/redumper-2023.10.02_build221-win64.zip
|
||||
- 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Debug\net48\win7-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
|
||||
- 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Debug\net6.0-windows\win-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
|
||||
- 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Debug\net7.0-windows\win-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
|
||||
# - 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Release\net48\win7-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
|
||||
# - 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Release\net6.0-windows\win-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
|
||||
# - 7z e redumper-2023.10.02_build221-win64.zip -oMPF\bin\Release\net7.0-windows\win-x64\publish\Programs\Redumper redumper-2023.10.02_build221-win64\bin\*
|
||||
- ps: appveyor DownloadFile https://github.com/superg/redumper/releases/download/build_247/redumper-2023.11.01_build247-win64.zip
|
||||
- 7z e redumper-2023.11.01_build247-win64.zip -oMPF\bin\Debug\net6.0-windows\win-x64\publish\Programs\Redumper redumper-2023.11.01_build247-win64\bin\*
|
||||
|
||||
# Create MPF Debug archives
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Debug\net48\win7-x64\publish\
|
||||
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net48_debug.zip *
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Debug\net6.0-windows\win-x64\publish\
|
||||
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_debug.zip *
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Debug\net7.0-windows\win-x64\publish\
|
||||
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_debug.zip *
|
||||
|
||||
# # Create MPF Release archives
|
||||
# - cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Release\net48\win7-x64\publish\
|
||||
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net48_release.zip *
|
||||
# - cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Release\net6.0-windows\win-x64\publish\
|
||||
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_release.zip *
|
||||
# - cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Release\net7.0-windows\win-x64\publish\
|
||||
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_release.zip *
|
||||
|
||||
# Create MPF.Check Debug archives
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net48\win7-x64\publish\
|
||||
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net48_debug.zip *
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net6.0\win-x64\publish\
|
||||
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_debug.zip *
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net6.0\linux-x64\publish\
|
||||
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_linux-x64_debug.zip *
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net6.0\osx-x64\publish\
|
||||
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_osx-x64_debug.zip *
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net7.0\win-x64\publish\
|
||||
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_debug.zip *
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net7.0\linux-x64\publish\
|
||||
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_linux-x64_debug.zip *
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Debug\net7.0\osx-x64\publish\
|
||||
- 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_osx-x64_debug.zip *
|
||||
|
||||
# # Create MPF.Check Release archives
|
||||
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net48\win7-x64\publish\
|
||||
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net48_release.zip *
|
||||
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net6.0\win-x64\publish\
|
||||
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_release.zip *
|
||||
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net6.0\linux-x64\publish\
|
||||
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_linux-x64_release.zip *
|
||||
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net6.0\osx-x64\publish\
|
||||
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_osx-x64_release.zip *
|
||||
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net7.0\win-x64\publish\
|
||||
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_release.zip *
|
||||
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net7.0\linux-x64\publish\
|
||||
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_linux-x64_release.zip *
|
||||
# - cd %APPVEYOR_BUILD_FOLDER%\MPF.Check\bin\Release\net7.0\osx-x64\publish\
|
||||
# - 7z a -tzip %APPVEYOR_BUILD_FOLDER%\MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_osx-x64_release.zip *
|
||||
|
||||
# success/failure tracking
|
||||
on_success:
|
||||
@@ -132,46 +81,12 @@ on_failure:
|
||||
|
||||
# artifact linking
|
||||
artifacts:
|
||||
- path: MPF_%APPVEYOR_BUILD_NUMBER%_net48_debug.zip
|
||||
name: MPF (.NET Framework 4.8, Debug)
|
||||
- path: MPF_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_debug.zip
|
||||
name: MPF (.NET 6.0, Debug, Windows x64)
|
||||
- path: MPF_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_debug.zip
|
||||
name: MPF (.NET 7.0, Debug, Windows x64)
|
||||
|
||||
# - path: MPF_%APPVEYOR_BUILD_NUMBER%_net48_release.zip
|
||||
# name: MPF (.NET Framework 4.8, Release)
|
||||
# - path: MPF_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_release.zip
|
||||
# name: MPF (.NET 6.0, Release, Windows x64)
|
||||
# - path: MPF_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_release.zip
|
||||
# name: MPF (.NET 7.0, Release, Windows x64)
|
||||
|
||||
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net48_debug.zip
|
||||
name: MPF Check (.NET Framework 4.8, Debug)
|
||||
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_debug.zip
|
||||
name: MPF.Check (.NET 6.0, Debug, Windows x64)
|
||||
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_linux-x64_debug.zip
|
||||
name: MPF.Check (.NET 6.0, Debug, Linux x64)
|
||||
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_osx-x64_debug.zip
|
||||
name: MPF.Check (.NET 6.0, Debug, OSX x64)
|
||||
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_debug.zip
|
||||
name: MPF.Check (.NET 7.0, Debug, Windows x64)
|
||||
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_linux-x64_debug.zip
|
||||
name: MPF.Check (.NET 7.0, Debug, Linux x64)
|
||||
- path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_osx-x64_debug.zip
|
||||
name: MPF.Check (.NET 7.0, Debug, OSX x64)
|
||||
|
||||
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net48_release.zip
|
||||
# name: MPF Check (.NET Framework 4.8, Release)
|
||||
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_win-x64_release.zip
|
||||
# name: MPF.Check (.NET 6.0, Release, Windows x64)
|
||||
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_linux-x64_release.zip
|
||||
# name: MPF.Check (.NET 6.0, Release, Linux x64)
|
||||
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net6.0_osx-x64_release.zip
|
||||
# name: MPF.Check (.NET 6.0, Release, OSX x64)
|
||||
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_win-x64_release.zip
|
||||
# name: MPF.Check (.NET 7.0, Release, Windows x64)
|
||||
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_linux-x64_release.zip
|
||||
# name: MPF.Check (.NET 7.0, Release, Linux x64)
|
||||
# - path: MPF.Check_%APPVEYOR_BUILD_NUMBER%_net7.0_osx-x64_release.zip
|
||||
# name: MPF.Check (.NET 7.0, Release, OSX x64)
|
||||
|
||||
Reference in New Issue
Block a user