mirror of
https://github.com/SabreTools/MPF.git
synced 2026-02-05 21:29:24 +00:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d7355aee1 | ||
|
|
6e9a6724c3 | ||
|
|
be35acfb48 | ||
|
|
f1a46c2e82 | ||
|
|
872959c889 | ||
|
|
b848a401f8 | ||
|
|
ee4762f8b3 | ||
|
|
d68bcfb96a | ||
|
|
d2433e4749 | ||
|
|
56ec0e7057 | ||
|
|
26e5d33d17 | ||
|
|
8b8b51ace4 | ||
|
|
f350904441 | ||
|
|
8e8e3368d0 | ||
|
|
4d8153dba1 | ||
|
|
e4e4b5ecde | ||
|
|
8373a6b8f5 | ||
|
|
45c51ebc80 | ||
|
|
af27085cc1 | ||
|
|
82e3707dce | ||
|
|
85192e8d3e | ||
|
|
6f784a352e | ||
|
|
ee707cf1af | ||
|
|
a14c998b3b | ||
|
|
004208df6a | ||
|
|
2f765146d1 | ||
|
|
a7d548f7ce | ||
|
|
fbdb9875f3 | ||
|
|
39a524e3cc | ||
|
|
9740ca3a7a | ||
|
|
f8d81972bf | ||
|
|
fe9302a553 | ||
|
|
c0ed7a7a0e | ||
|
|
b0b48743ac | ||
|
|
47e79dab31 | ||
|
|
90edc42fdf | ||
|
|
45db365705 | ||
|
|
952828dddd | ||
|
|
4a1e953ffd | ||
|
|
25740c2936 | ||
|
|
3696257940 |
@@ -1,3 +1,45 @@
|
||||
### 3.0.1 (2023-11-30)
|
||||
|
||||
- Add Bandai Pippin detection
|
||||
- Zip manufacturer files for Redumper
|
||||
- Fix BE flag logic bug in DIC
|
||||
- Support ancient .NET in Core
|
||||
- Support ancient .NET in UI Core
|
||||
- Support C# 12 syntax
|
||||
- Support ancient .NET in Check
|
||||
- Support ancient .NET in UI
|
||||
- Fix TLS for older .NET
|
||||
- Perform more ancient .NET support work
|
||||
- Prepare XAML for ancient .NET support
|
||||
- Suppress deprecation warnings
|
||||
- Fix reversed ringcode test
|
||||
- Add C#12 syntax to tests
|
||||
- Trim PS3 serial and add unrelated notes
|
||||
- Update RedumpLib and use moved methods
|
||||
- Perform some post-move cleanup
|
||||
- More C# 12 cleanup in Core
|
||||
- Update to BinaryObjectScanner 3.0.1
|
||||
- Update Xunit packages
|
||||
- Get Core building with Framework 4.0
|
||||
- Get UI.Core building with Framework 4.0
|
||||
- Get Check building with Framework 4.0
|
||||
- Use TryGetValue on dictionaries
|
||||
- Support proper async in .NET Framework 4.0
|
||||
- Temporarily remove .NET Framework 4.0
|
||||
- Update to BinaryObjectScanner 3.0.2
|
||||
- Re-enable .NET Framework 4.0 building in Core
|
||||
- Re-enable .NET Framework 4.0 building in UI.Core
|
||||
- Re-enable .NET Framework 4.0 building in Check
|
||||
- Support .NET Framework 3.5
|
||||
- Update compatibility libraries
|
||||
- Support .NET Framework 2.0
|
||||
- Support .NET Framework 3.5 in UI.Core
|
||||
- Get UI building with Framework 4.0
|
||||
- Temporarily remove .NET Framework 4.0 from UI
|
||||
- Get UI building with Framework 4.0 again
|
||||
- Support .NET Framework 3.5 in UI
|
||||
- Update Redumper to build 268
|
||||
|
||||
### 3.0.0 (2023-11-14)
|
||||
|
||||
- Remove .NET Framework 4.8 from build
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||
<OutputType>Exe</OutputType>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.0.1</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Title>MPF Check</Title>
|
||||
<Description>Validator for various dumping programs</Description>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2023</Copyright>
|
||||
<VersionPrefix>3.0.0</VersionPrefix>
|
||||
<Description>Validator for various dumping programs</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2019-2023</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -21,10 +31,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BinaryObjectScanner" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="3.0.0" GeneratePathProperty="true">
|
||||
<PackageReference Include="BinaryObjectScanner" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="3.0.2" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.2.0" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -45,8 +45,12 @@ namespace MPF.Check
|
||||
protectionProgress.ProgressChanged += ConsoleLogger.ProgressUpdated;
|
||||
|
||||
// Validate the supplied credentials
|
||||
#if NETFRAMEWORK
|
||||
(bool? _, string? message) = RedumpWebClient.ValidateCredentials(options.RedumpUsername ?? string.Empty, options.RedumpPassword ?? string.Empty);
|
||||
#else
|
||||
(bool? _, string? message) = RedumpHttpClient.ValidateCredentials(options.RedumpUsername ?? string.Empty, options.RedumpPassword ?? string.Empty).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
if (!string.IsNullOrWhiteSpace(message))
|
||||
#endif
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
Console.WriteLine(message);
|
||||
|
||||
// Loop through all the rest of the args
|
||||
@@ -64,13 +68,19 @@ namespace MPF.Check
|
||||
|
||||
// Now populate an environment
|
||||
Drive? drive = null;
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
drive = Drive.Create(null, path);
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
drive = Drive.Create(null, path!);
|
||||
|
||||
var env = new DumpEnvironment(options, filepath, drive, knownSystem, mediaType, internalProgram: null, parameters: null);
|
||||
|
||||
// Finally, attempt to do the output dance
|
||||
#if NET40
|
||||
var resultTask = env.VerifyAndSaveDumpOutput(resultProgress, protectionProgress);
|
||||
resultTask.Wait();
|
||||
var result = resultTask.Result;
|
||||
#else
|
||||
var result = env.VerifyAndSaveDumpOutput(resultProgress, protectionProgress).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
#endif
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
using System;
|
||||
#if NET20 || NET35
|
||||
using System.Collections.Generic;
|
||||
#else
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using MPF.Core.Data;
|
||||
@@ -34,7 +38,11 @@ namespace MPF.Core.Converters
|
||||
/// <summary>
|
||||
/// Long name method cache
|
||||
/// </summary>
|
||||
private static readonly ConcurrentDictionary<Type, MethodInfo?> LongNameMethods = new();
|
||||
#if NET20 || NET35
|
||||
private static readonly Dictionary<Type, MethodInfo?> LongNameMethods = [];
|
||||
#else
|
||||
private static readonly ConcurrentDictionary<Type, MethodInfo?> LongNameMethods = [];
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of a generic enumerable value
|
||||
@@ -50,11 +58,14 @@ namespace MPF.Core.Converters
|
||||
|
||||
if (!LongNameMethods.TryGetValue(sourceType, out var method))
|
||||
{
|
||||
method = typeof(Extensions).GetMethod("LongName", new[] { typeof(Nullable<>).MakeGenericType(sourceType) });
|
||||
if (method == null)
|
||||
method = typeof(EnumConverter).GetMethod("LongName", new[] { typeof(Nullable<>).MakeGenericType(sourceType) });
|
||||
method = typeof(Extensions).GetMethod("LongName", [typeof(Nullable<>).MakeGenericType(sourceType)]);
|
||||
method ??= typeof(EnumConverter).GetMethod("LongName", [typeof(Nullable<>).MakeGenericType(sourceType)]);
|
||||
|
||||
#if NET20 || NET35
|
||||
LongNameMethods[sourceType] = method;
|
||||
#else
|
||||
LongNameMethods.TryAdd(sourceType, method);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (method != null)
|
||||
@@ -99,7 +110,7 @@ namespace MPF.Core.Converters
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Convert From String
|
||||
|
||||
|
||||
@@ -14,21 +14,33 @@ namespace MPF.Core.Data
|
||||
public const string StopDumping = "Stop Dumping";
|
||||
|
||||
// Byte arrays for signatures
|
||||
public static readonly byte[] SaturnSectorZeroStart = new byte[] { 0x53, 0x45, 0x47, 0x41, 0x20, 0x53, 0x45, 0x47, 0x41, 0x53, 0x41, 0x54, 0x55, 0x52, 0x4E, 0x20 };
|
||||
public static readonly byte[] SaturnSectorZeroStart = [0x53, 0x45, 0x47, 0x41, 0x20, 0x53, 0x45, 0x47, 0x41, 0x53, 0x41, 0x54, 0x55, 0x52, 0x4E, 0x20];
|
||||
|
||||
// Lists of known drive speed ranges
|
||||
#if NET20 || NET35 || NET40
|
||||
public static IList<int> CD { get; } = new List<int> { 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72 };
|
||||
public static IList<int> DVD { get; } = CD.Where(s => s <= 24).ToList();
|
||||
public static IList<int> HDDVD { get; } = CD.Where(s => s <= 24).ToList();
|
||||
public static IList<int> BD { get; } = CD.Where(s => s <= 16).ToList();
|
||||
public static IList<int> Unknown { get; } = new List<int> { 1 };
|
||||
#else
|
||||
public static IReadOnlyList<int> CD { get; } = new List<int> { 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72 };
|
||||
public static IReadOnlyList<int> DVD { get; } = CD.Where(s => s <= 24).ToList();
|
||||
public static IReadOnlyList<int> HDDVD { get; } = CD.Where(s => s <= 24).ToList();
|
||||
public static IReadOnlyList<int> BD { get; } = CD.Where(s => s <= 16).ToList();
|
||||
public static IReadOnlyList<int> Unknown { get; } = new List<int> { 1 };
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Get list of all drive speeds for a given MediaType
|
||||
/// </summary>
|
||||
/// <param name="type">MediaType? that represents the current item</param>
|
||||
/// <returns>Read-only list of drive speeds</returns>
|
||||
#if NET20 || NET35 || NET40
|
||||
public static IList<int> GetSpeedsForMediaType(MediaType? type)
|
||||
#else
|
||||
public static IReadOnlyList<int> GetSpeedsForMediaType(MediaType? type)
|
||||
#endif
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
@@ -49,65 +61,6 @@ namespace MPF.Core.Data
|
||||
/// </summary>
|
||||
public static class Template
|
||||
{
|
||||
// Manual information
|
||||
|
||||
public const string TitleField = "Title";
|
||||
public const string ForeignTitleField = "Foreign Title (Non-latin)";
|
||||
public const string DiscNumberField = "Disc Number / Letter";
|
||||
public const string DiscTitleField = "Disc Title";
|
||||
public const string SystemField = "System";
|
||||
public const string MediaTypeField = "Media Type";
|
||||
public const string CategoryField = "Category";
|
||||
public const string RegionField = "Region";
|
||||
public const string LanguagesField = "Languages";
|
||||
public const string PlaystationLanguageSelectionViaField = "Language Selection Via";
|
||||
public const string DiscSerialField = "Disc Serial";
|
||||
public const string BarcodeField = "Barcode";
|
||||
public const string CommentsField = "Comments";
|
||||
public const string ContentsField = "Contents";
|
||||
public const string VersionField = "Version";
|
||||
public const string EditionField = "Edition/Release";
|
||||
public const string PlayStation3WiiDiscKeyField = "Disc Key";
|
||||
public const string PlayStation3DiscIDField = "Disc ID";
|
||||
public const string GameCubeWiiBCAField = "BCA";
|
||||
public const string CopyProtectionField = "Copy Protection";
|
||||
public const string MasteringRingField = "Mastering Code (laser branded/etched)";
|
||||
public const string MasteringSIDField = "Mastering SID Code";
|
||||
public const string MouldSIDField = "Mould SID Code";
|
||||
public const string AdditionalMouldField = "Additional Mould";
|
||||
public const string ToolstampField = "Toolstamp or Mastering Code (engraved/stamped)";
|
||||
|
||||
// Automatic Information
|
||||
|
||||
public const string DumpingProgramField = "Dumping Program";
|
||||
public const string DumpingDateField = "Date";
|
||||
public const string DumpingDriveManufacturer = "Manufacturer";
|
||||
public const string DumpingDriveModel = "Model";
|
||||
public const string DumpingDriveFirmware = "Firmware";
|
||||
public const string ReportedDiscType = "Reported Disc Type";
|
||||
public const string PVDField = "Primary Volume Descriptor (PVD)";
|
||||
public const string DATField = "DAT";
|
||||
public const string SizeField = "Size";
|
||||
public const string CRC32Field = "CRC32";
|
||||
public const string MD5Field = "MD5";
|
||||
public const string SHA1Field = "SHA1";
|
||||
public const string FullyMatchingIDField = "Fully Matching ID";
|
||||
public const string PartiallyMatchingIDsField = "Partially Matching IDs";
|
||||
public const string ErrorCountField = "Error Count";
|
||||
public const string CuesheetField = "Cuesheet";
|
||||
public const string SubIntentionField = "SubIntention Data (SecuROM/LibCrypt)";
|
||||
public const string WriteOffsetField = "Write Offset";
|
||||
public const string LayerbreakField = "Layerbreak";
|
||||
public const string EXEDateBuildDate = "EXE/Build Date";
|
||||
public const string HeaderField = "Header";
|
||||
public const string PICField = "Permanent Information & Control (PIC)";
|
||||
public const string PlayStationEDCField = "EDC";
|
||||
public const string PlayStationAntiModchipField = "Anti-modchip";
|
||||
public const string PlayStationLibCryptField = "LibCrypt";
|
||||
public const string XBOXSSRanges = "Security Sector Ranges";
|
||||
|
||||
// Default values
|
||||
|
||||
public const string RequiredValue = "(REQUIRED)";
|
||||
public const string RequiredIfExistsValue = "(REQUIRED, IF EXISTS)";
|
||||
public const string OptionalValue = "(OPTIONAL)";
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using Microsoft.Management.Infrastructure;
|
||||
using Microsoft.Management.Infrastructure.Generic;
|
||||
#endif
|
||||
using MPF.Core.Converters;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
@@ -61,17 +63,17 @@ namespace MPF.Core.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
string volumeLabel = Template.DiscNotDetected;
|
||||
string? volumeLabel = Template.DiscNotDetected;
|
||||
if (this.MarkedActive)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(this.VolumeLabel))
|
||||
if (string.IsNullOrEmpty(this.VolumeLabel))
|
||||
volumeLabel = "track";
|
||||
else
|
||||
volumeLabel = this.VolumeLabel;
|
||||
}
|
||||
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
volumeLabel = volumeLabel.Replace(c, '_');
|
||||
volumeLabel = volumeLabel?.Replace(c, '_');
|
||||
|
||||
return volumeLabel;
|
||||
}
|
||||
@@ -104,12 +106,12 @@ namespace MPF.Core.Data
|
||||
};
|
||||
|
||||
// If we have an invalid device path, return null
|
||||
if (string.IsNullOrWhiteSpace(devicePath))
|
||||
if (string.IsNullOrEmpty(devicePath))
|
||||
return null;
|
||||
|
||||
// Sanitize a Windows-formatted long device path
|
||||
if (devicePath.StartsWith("\\\\.\\"))
|
||||
devicePath = devicePath["\\\\.\\".Length..];
|
||||
devicePath = devicePath.Substring("\\\\.\\".Length);
|
||||
|
||||
// Create and validate the drive info object
|
||||
var driveInfo = new DriveInfo(devicePath);
|
||||
@@ -159,7 +161,7 @@ namespace MPF.Core.Data
|
||||
public static List<Drive> CreateListOfDrives(bool ignoreFixedDrives)
|
||||
{
|
||||
var drives = GetDriveList(ignoreFixedDrives);
|
||||
drives = drives.OrderBy(i => i == null ? "\0" : i.Name).ToList();
|
||||
drives = [.. drives.OrderBy(i => i == null ? "\0" : i.Name)];
|
||||
return drives;
|
||||
}
|
||||
|
||||
@@ -249,7 +251,7 @@ namespace MPF.Core.Data
|
||||
public RedumpSystem? GetRedumpSystem(RedumpSystem? defaultValue)
|
||||
{
|
||||
// If we can't read the media in that drive, we can't do anything
|
||||
if (!Directory.Exists(this.Name))
|
||||
if (string.IsNullOrEmpty(this.Name) || !Directory.Exists(this.Name))
|
||||
return defaultValue;
|
||||
|
||||
// We're going to assume for floppies, HDDs, and removable drives
|
||||
@@ -267,7 +269,11 @@ namespace MPF.Core.Data
|
||||
// Bandai Playdia Quick Interactive System
|
||||
try
|
||||
{
|
||||
#if NET20 || NET35
|
||||
List<string> files = [.. Directory.GetFiles(this.Name, "*", SearchOption.TopDirectoryOnly)];
|
||||
#else
|
||||
List<string> files = Directory.EnumerateFiles(this.Name, "*", SearchOption.TopDirectoryOnly).ToList();
|
||||
#endif
|
||||
|
||||
if (files.Any(f => f.EndsWith(".AJS", StringComparison.OrdinalIgnoreCase))
|
||||
&& files.Any(f => f.EndsWith(".GLB", StringComparison.OrdinalIgnoreCase)))
|
||||
@@ -277,8 +283,18 @@ namespace MPF.Core.Data
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Bandai Pippin
|
||||
if (File.Exists(Path.Combine(this.Name, "PippinAuthenticationFile")))
|
||||
{
|
||||
return RedumpSystem.BandaiPippin;
|
||||
}
|
||||
|
||||
// Mattel Fisher-Price iXL
|
||||
#if NET20 || NET35
|
||||
if (File.Exists(Path.Combine(Path.Combine(this.Name, "iXL"), "iXLUpdater.exe")))
|
||||
#else
|
||||
if (File.Exists(Path.Combine(this.Name, "iXL", "iXLUpdater.exe")))
|
||||
#endif
|
||||
{
|
||||
return RedumpSystem.MattelFisherPriceiXL;
|
||||
}
|
||||
@@ -287,7 +303,11 @@ namespace MPF.Core.Data
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(this.Name, "$SystemUpdate"))
|
||||
#if NET20 || NET35
|
||||
&& Directory.GetFiles(Path.Combine(this.Name, "$SystemUpdate")).Any()
|
||||
#else
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "$SystemUpdate")).Any()
|
||||
#endif
|
||||
&& this.TotalSize <= 500_000_000)
|
||||
{
|
||||
return RedumpSystem.MicrosoftXbox360;
|
||||
@@ -299,7 +319,11 @@ namespace MPF.Core.Data
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(this.Name, "MSXC"))
|
||||
#if NET20 || NET35
|
||||
&& Directory.GetFiles(Path.Combine(this.Name, "MSXC")).Any())
|
||||
#else
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "MSXC")).Any())
|
||||
#endif
|
||||
{
|
||||
return RedumpSystem.MicrosoftXboxOne;
|
||||
}
|
||||
@@ -313,10 +337,17 @@ namespace MPF.Core.Data
|
||||
}
|
||||
|
||||
// Sega Mega-CD / Sega-CD
|
||||
#if NET20 || NET35
|
||||
if (File.Exists(Path.Combine(Path.Combine(this.Name, "_BOOT"), "IP.BIN"))
|
||||
|| File.Exists(Path.Combine(Path.Combine(this.Name, "_BOOT"), "SP.BIN"))
|
||||
|| File.Exists(Path.Combine(Path.Combine(this.Name, "_BOOT"), "SP_AS.BIN"))
|
||||
|| File.Exists(Path.Combine(this.Name, "FILESYSTEM.BIN")))
|
||||
#else
|
||||
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")))
|
||||
#endif
|
||||
{
|
||||
return RedumpSystem.SegaMegaCDSegaCD;
|
||||
}
|
||||
@@ -362,7 +393,11 @@ 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 NET20 || NET35
|
||||
if (File.Exists(Path.Combine(Path.Combine(Path.Combine(this.Name, "PS4"), "UPDATE"), "PS4UPDATE.PUP")))
|
||||
#else
|
||||
if (File.Exists(Path.Combine(this.Name, "PS4", "UPDATE", "PS4UPDATE.PUP")))
|
||||
#endif
|
||||
{
|
||||
return RedumpSystem.SonyPlayStation4;
|
||||
}
|
||||
@@ -373,7 +408,7 @@ namespace MPF.Core.Data
|
||||
return RedumpSystem.VTechVFlashVSmilePro;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Computers
|
||||
|
||||
@@ -398,13 +433,21 @@ namespace MPF.Core.Data
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(this.Name, "AUDIO_TS"))
|
||||
#if NET20 || NET35
|
||||
&& Directory.GetFiles(Path.Combine(this.Name, "AUDIO_TS")).Any())
|
||||
#else
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "AUDIO_TS")).Any())
|
||||
#endif
|
||||
{
|
||||
return RedumpSystem.DVDAudio;
|
||||
}
|
||||
|
||||
else if (Directory.Exists(Path.Combine(this.Name, "VIDEO_TS"))
|
||||
#if NET20 || NET35
|
||||
&& Directory.GetFiles(Path.Combine(this.Name, "VIDEO_TS")).Any())
|
||||
#else
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "VIDEO_TS")).Any())
|
||||
#endif
|
||||
{
|
||||
return RedumpSystem.DVDVideo;
|
||||
}
|
||||
@@ -415,7 +458,11 @@ namespace MPF.Core.Data
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(this.Name, "HVDVD_TS"))
|
||||
#if NET20 || NET35
|
||||
&& Directory.GetFiles(Path.Combine(this.Name, "HVDVD_TS")).Any())
|
||||
#else
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "HVDVD_TS")).Any())
|
||||
#endif
|
||||
{
|
||||
return RedumpSystem.HDDVDVideo;
|
||||
}
|
||||
@@ -426,14 +473,18 @@ namespace MPF.Core.Data
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(this.Name, "VCD"))
|
||||
#if NET20 || NET35
|
||||
&& Directory.GetFiles(Path.Combine(this.Name, "VCD")).Any())
|
||||
#else
|
||||
&& Directory.EnumerateFiles(Path.Combine(this.Name, "VCD")).Any())
|
||||
#endif
|
||||
{
|
||||
return RedumpSystem.VideoCD;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
// Default return
|
||||
return defaultValue;
|
||||
@@ -446,11 +497,11 @@ namespace MPF.Core.Data
|
||||
public RedumpSystem? GetRedumpSystemFromVolumeLabel()
|
||||
{
|
||||
// If the volume label is empty, we can't do anything
|
||||
if (string.IsNullOrWhiteSpace(this.VolumeLabel))
|
||||
if (string.IsNullOrEmpty(this.VolumeLabel))
|
||||
return null;
|
||||
|
||||
// Audio CD
|
||||
if (this.VolumeLabel.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
|
||||
if (this.VolumeLabel!.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.AudioCD;
|
||||
|
||||
// Microsoft Xbox
|
||||
@@ -499,7 +550,7 @@ namespace MPF.Core.Data
|
||||
this.PopulateFromDriveInfo(driveInfo);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
@@ -541,6 +592,7 @@ namespace MPF.Core.Data
|
||||
}
|
||||
|
||||
// Find and update all floppy drives
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
CimSession session = CimSession.Create(null);
|
||||
@@ -561,6 +613,7 @@ namespace MPF.Core.Data
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
#endif
|
||||
|
||||
return drives;
|
||||
}
|
||||
|
||||
@@ -6,14 +6,18 @@
|
||||
public enum Hash
|
||||
{
|
||||
CRC32,
|
||||
#if NET6_0_OR_GREATER
|
||||
CRC64,
|
||||
#endif
|
||||
MD5,
|
||||
SHA1,
|
||||
SHA256,
|
||||
SHA384,
|
||||
SHA512,
|
||||
#if NET6_0_OR_GREATER
|
||||
XxHash32,
|
||||
XxHash64,
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -8,23 +8,23 @@ namespace MPF.Core.Data
|
||||
{
|
||||
public class IniFile : IDictionary<string, string>
|
||||
{
|
||||
private Dictionary<string, string> _keyValuePairs = new();
|
||||
private Dictionary<string, string> _keyValuePairs = [];
|
||||
|
||||
public string this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
_keyValuePairs ??= new Dictionary<string, string>();
|
||||
_keyValuePairs ??= [];
|
||||
|
||||
key = key.ToLowerInvariant();
|
||||
if (_keyValuePairs.ContainsKey(key))
|
||||
return _keyValuePairs[key];
|
||||
if (_keyValuePairs.TryGetValue(key, out string? val))
|
||||
return val;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
set
|
||||
{
|
||||
_keyValuePairs ??= new Dictionary<string, string>();
|
||||
_keyValuePairs ??= [];
|
||||
|
||||
key = key.ToLowerInvariant();
|
||||
_keyValuePairs[key] = value;
|
||||
@@ -102,13 +102,13 @@ namespace MPF.Core.Data
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
|
||||
// Empty lines are skipped
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
if (string.IsNullOrEmpty(line))
|
||||
{
|
||||
// No-op, we don't process empty lines
|
||||
}
|
||||
|
||||
// Comments start with ';'
|
||||
else if (line.StartsWith(";"))
|
||||
else if (line!.StartsWith(";"))
|
||||
{
|
||||
// No-op, we don't process comments
|
||||
}
|
||||
@@ -127,7 +127,7 @@ namespace MPF.Core.Data
|
||||
|
||||
// If the value field contains an '=', we need to put them back in
|
||||
string key = data[0].Trim();
|
||||
string value = string.Join("=", data.Skip(1)).Trim();
|
||||
string value = string.Join("=", data.Skip(1).ToArray()).Trim();
|
||||
|
||||
// Section names are prepended to the key with a '.' separating
|
||||
if (!string.IsNullOrEmpty(section))
|
||||
@@ -196,7 +196,7 @@ namespace MPF.Core.Data
|
||||
|
||||
// If the key contains an '.', we need to put them back in
|
||||
string newSection = data[0].Trim();
|
||||
key = string.Join(".", data.Skip(1)).Trim();
|
||||
key = string.Join(".", data.Skip(1).ToArray()).Trim();
|
||||
|
||||
// If we have a new section, write it out
|
||||
if (!string.Equals(newSection, section, StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
@@ -598,7 +598,7 @@ namespace MPF.Core.Data
|
||||
/// <summary>
|
||||
/// Determine if a complete set of Redump credentials might exist
|
||||
/// </summary>
|
||||
public bool HasRedumpLogin { get => !string.IsNullOrWhiteSpace(RedumpUsername) && !string.IsNullOrWhiteSpace(RedumpPassword); }
|
||||
public bool HasRedumpLogin { get => !string.IsNullOrEmpty(RedumpUsername) && !string.IsNullOrEmpty(RedumpPassword); }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
using System;
|
||||
#if NET20 || NET35
|
||||
using System.Collections.Generic;
|
||||
#else
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -10,7 +14,11 @@ namespace MPF.Core.Data
|
||||
/// <summary>
|
||||
/// Internal queue to hold data to process
|
||||
/// </summary>
|
||||
#if NET20 || NET35
|
||||
private readonly Queue<T> InternalQueue;
|
||||
#else
|
||||
private readonly ConcurrentQueue<T> InternalQueue;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Custom processing step for dequeued data
|
||||
@@ -24,10 +32,20 @@ namespace MPF.Core.Data
|
||||
|
||||
public ProcessingQueue(Action<T> customProcessing)
|
||||
{
|
||||
#if NET20 || NET35
|
||||
this.InternalQueue = new Queue<T>();
|
||||
#else
|
||||
this.InternalQueue = new ConcurrentQueue<T>();
|
||||
#endif
|
||||
this.CustomProcessing = customProcessing;
|
||||
this.TokenSource = new CancellationTokenSource();
|
||||
#if NET20 || NET35
|
||||
Task.Run(() => ProcessQueue());
|
||||
#elif NET40
|
||||
Task.Factory.StartNew(() => ProcessQueue());
|
||||
#else
|
||||
Task.Run(() => ProcessQueue(), this.TokenSource.Token);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -39,7 +57,7 @@ namespace MPF.Core.Data
|
||||
/// Enqueue a new item for processing
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public void Enqueue(T item)
|
||||
public void Enqueue(T? item)
|
||||
{
|
||||
// Only accept new data when not cancelled
|
||||
if (item != null && !this.TokenSource.IsCancellationRequested)
|
||||
@@ -54,7 +72,11 @@ namespace MPF.Core.Data
|
||||
while (true)
|
||||
{
|
||||
// Nothing in the queue means we get to idle
|
||||
#if NET20 || NET35
|
||||
if (InternalQueue.Count == 0)
|
||||
#else
|
||||
if (InternalQueue.IsEmpty)
|
||||
#endif
|
||||
{
|
||||
if (this.TokenSource.IsCancellationRequested)
|
||||
break;
|
||||
@@ -63,12 +85,17 @@ namespace MPF.Core.Data
|
||||
continue;
|
||||
}
|
||||
|
||||
#if NET20 || NET35
|
||||
// Get the next item from the queue and invoke the lambda, if possible
|
||||
this.CustomProcessing?.Invoke(this.InternalQueue.Dequeue());
|
||||
#else
|
||||
// Get the next item from the queue
|
||||
if (!this.InternalQueue.TryDequeue(out var nextItem))
|
||||
continue;
|
||||
|
||||
// Invoke the lambda, if possible
|
||||
this.CustomProcessing?.Invoke(nextItem);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
namespace MPF.Core.Data
|
||||
using System;
|
||||
|
||||
namespace MPF.Core.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic success/failure result object, with optional message
|
||||
/// </summary>
|
||||
public class Result
|
||||
public class Result : System.EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal representation of success
|
||||
@@ -44,6 +46,11 @@
|
||||
/// <param name="message">String to add as a message</param>
|
||||
public static Result Failure(string? message) => new(false, message ?? string.Empty);
|
||||
|
||||
internal static Result Success(object value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Results can be compared to boolean values based on the success value
|
||||
/// </summary>
|
||||
|
||||
@@ -4,10 +4,10 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BinaryObjectScanner;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Modules;
|
||||
using MPF.Core.Utilities;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core
|
||||
@@ -65,7 +65,11 @@ namespace MPF.Core
|
||||
/// <summary>
|
||||
/// Generic way of reporting a message
|
||||
/// </summary>
|
||||
#if NET20 || NET35 || NET40
|
||||
public EventHandler<BaseParameters.StringEventArgs>? ReportStatus;
|
||||
#else
|
||||
public EventHandler<string>? ReportStatus;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Queue of items that need to be logged
|
||||
@@ -75,12 +79,20 @@ namespace MPF.Core
|
||||
/// <summary>
|
||||
/// Event handler for data returned from a process
|
||||
/// </summary>
|
||||
#if NET20 || NET35 || NET40
|
||||
private void OutputToLog(object? proc, BaseParameters.StringEventArgs args) => outputQueue?.Enqueue(args.Value);
|
||||
#else
|
||||
private void OutputToLog(object? proc, string args) => outputQueue?.Enqueue(args);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Process the outputs in the queue
|
||||
/// </summary>
|
||||
#if NET20 || NET35 || NET40
|
||||
private void ProcessOutputs(string nextOutput) => ReportStatus?.Invoke(this, new BaseParameters.StringEventArgs { Value = nextOutput });
|
||||
#else
|
||||
private void ProcessOutputs(string nextOutput) => ReportStatus?.Invoke(this, nextOutput);
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -207,7 +219,11 @@ namespace MPF.Core
|
||||
/// Execute the initial invocation of the dumping programs
|
||||
/// </summary>
|
||||
/// <param name="progress">Optional result progress callback</param>
|
||||
#if NET40
|
||||
public Result Run(IProgress<Result>? progress = null)
|
||||
#else
|
||||
public async Task<Result> Run(IProgress<Result>? progress = null)
|
||||
#endif
|
||||
{
|
||||
// If we don't have parameters
|
||||
if (Parameters == null)
|
||||
@@ -230,10 +246,15 @@ namespace MPF.Core
|
||||
progress?.Report(Result.Success($"Executing {InternalProgram}... {(Options.ToolsInSeparateWindow ? "please wait!" : "see log for output!")}"));
|
||||
|
||||
var directoryName = Path.GetDirectoryName(OutputPath);
|
||||
if (!string.IsNullOrWhiteSpace(directoryName))
|
||||
if (!string.IsNullOrEmpty(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
#if NET40
|
||||
var executeTask = Task.Factory.StartNew(() => Parameters.ExecuteInternalProgram(Options.ToolsInSeparateWindow));
|
||||
executeTask.Wait();
|
||||
#else
|
||||
await Task.Run(() => Parameters.ExecuteInternalProgram(Options.ToolsInSeparateWindow));
|
||||
#endif
|
||||
progress?.Report(Result.Success($"{InternalProgram} has finished!"));
|
||||
|
||||
// Remove event handler if needed
|
||||
@@ -256,7 +277,7 @@ namespace MPF.Core
|
||||
/// <returns>Result instance with the outcome</returns>
|
||||
public async Task<Result> VerifyAndSaveDumpOutput(
|
||||
IProgress<Result>? resultProgress = null,
|
||||
IProgress<ProtectionProgress>? protectionProgress = null,
|
||||
IProgress<BinaryObjectScanner.ProtectionProgress>? protectionProgress = null,
|
||||
Func<SubmissionInfo?, (bool?, SubmissionInfo?)>? processUserInfo = null,
|
||||
SubmissionInfo? seedInfo = null)
|
||||
{
|
||||
@@ -267,10 +288,10 @@ namespace MPF.Core
|
||||
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, Parameters, false);
|
||||
(bool foundFiles, List<string> missingFiles) = Parameters.FoundAllFiles(outputDirectory, outputFilename, false);
|
||||
if (!foundFiles)
|
||||
{
|
||||
resultProgress?.Report(Result.Failure($"There were files missing from the output:\n{string.Join("\n", missingFiles)}"));
|
||||
resultProgress?.Report(Result.Failure($"There were files missing from the output:\n{string.Join("\n", [.. missingFiles])}"));
|
||||
return Result.Failure("Error! Please check output directory as dump may be incomplete!");
|
||||
}
|
||||
|
||||
@@ -291,7 +312,7 @@ namespace MPF.Core
|
||||
if (seedInfo != null)
|
||||
{
|
||||
resultProgress?.Report(Result.Success("Injecting user-supplied information..."));
|
||||
SubmissionInfoTool.InjectSubmissionInformation(submissionInfo, seedInfo);
|
||||
Builder.InjectSubmissionInformation(submissionInfo, seedInfo);
|
||||
resultProgress?.Report(Result.Success("Information injection complete!"));
|
||||
}
|
||||
|
||||
@@ -325,12 +346,12 @@ namespace MPF.Core
|
||||
|
||||
// Process special fields for site codes
|
||||
resultProgress?.Report(Result.Success("Processing site codes..."));
|
||||
InfoTool.ProcessSpecialFields(submissionInfo);
|
||||
Formatter.ProcessSpecialFields(submissionInfo);
|
||||
resultProgress?.Report(Result.Success("Processing complete!"));
|
||||
|
||||
// Format the information for the text output
|
||||
resultProgress?.Report(Result.Success("Formatting information..."));
|
||||
(var formattedValues, var formatResult) = InfoTool.FormatOutputData(submissionInfo, Options);
|
||||
(var formattedValues, var formatResult) = Formatter.FormatOutputData(submissionInfo, Options.EnableRedumpCompatibility);
|
||||
if (formattedValues == null)
|
||||
resultProgress?.Report(Result.Success(formatResult));
|
||||
else
|
||||
@@ -426,14 +447,18 @@ namespace MPF.Core
|
||||
private static async Task<string> ExecuteInternalProgram(BaseParameters parameters)
|
||||
{
|
||||
Process childProcess;
|
||||
#if NET40
|
||||
string output = await Task.Factory.StartNew(() =>
|
||||
#else
|
||||
string output = await Task.Run(() =>
|
||||
#endif
|
||||
{
|
||||
childProcess = new Process()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = parameters.ExecutablePath,
|
||||
Arguments = parameters.GenerateParameters(),
|
||||
FileName = parameters.ExecutablePath!,
|
||||
Arguments = parameters.GenerateParameters()!,
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardInput = true,
|
||||
@@ -477,7 +502,7 @@ namespace MPF.Core
|
||||
return Result.Failure($"Error! {Parameters.ExecutablePath} does not exist!");
|
||||
|
||||
// Validate that the dumping drive doesn't contain the executable
|
||||
string fullExecutablePath = Path.GetFullPath(Parameters.ExecutablePath);
|
||||
string fullExecutablePath = Path.GetFullPath(Parameters.ExecutablePath!);
|
||||
if (Drive?.Name != null && fullExecutablePath.StartsWith(Drive.Name))
|
||||
return Result.Failure("Error! Cannot dump same drive that executable resides on!");
|
||||
|
||||
@@ -492,7 +517,7 @@ namespace MPF.Core
|
||||
private bool RequiredProgramsExist()
|
||||
{
|
||||
// Validate that the path is configured
|
||||
if (string.IsNullOrWhiteSpace(Options.DiscImageCreatorPath))
|
||||
if (string.IsNullOrEmpty(Options.DiscImageCreatorPath))
|
||||
return false;
|
||||
|
||||
// Validate that the required program exists
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
#if NET6_0_OR_GREATER
|
||||
using System.IO.Hashing;
|
||||
#endif
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
@@ -16,7 +18,11 @@ namespace MPF.Core.Hashing
|
||||
/// <summary>
|
||||
/// Hash type associated with the current state
|
||||
/// </summary>
|
||||
#if NETFRAMEWORK || NETCOREAPP3_1
|
||||
public Hash HashType { get; private set; }
|
||||
#else
|
||||
public Hash HashType { get; init; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Current hash in bytes
|
||||
@@ -71,14 +77,18 @@ namespace MPF.Core.Hashing
|
||||
_hasher = HashType switch
|
||||
{
|
||||
Hash.CRC32 => new Crc32(),
|
||||
#if NET6_0_OR_GREATER
|
||||
Hash.CRC64 => new Crc64(),
|
||||
#endif
|
||||
Hash.MD5 => MD5.Create(),
|
||||
Hash.SHA1 => SHA1.Create(),
|
||||
Hash.SHA256 => SHA256.Create(),
|
||||
Hash.SHA384 => SHA384.Create(),
|
||||
Hash.SHA512 => SHA512.Create(),
|
||||
#if NET6_0_OR_GREATER
|
||||
Hash.XxHash32 => new XxHash32(),
|
||||
Hash.XxHash64 => new XxHash64(),
|
||||
#endif
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
@@ -156,14 +166,18 @@ namespace MPF.Core.Hashing
|
||||
var hashers = new Dictionary<Hash, Hasher>
|
||||
{
|
||||
{ Hash.CRC32, new Hasher(Hash.CRC32) },
|
||||
#if NET6_0_OR_GREATER
|
||||
{ Hash.CRC64, new Hasher(Hash.CRC64) },
|
||||
#endif
|
||||
{ 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) },
|
||||
#if NET6_0_OR_GREATER
|
||||
{ Hash.XxHash32, new Hasher(Hash.XxHash32) },
|
||||
{ Hash.XxHash64, new Hasher(Hash.XxHash64) },
|
||||
#endif
|
||||
};
|
||||
|
||||
// Initialize the hashing helpers
|
||||
@@ -197,8 +211,16 @@ namespace MPF.Core.Hashing
|
||||
|
||||
byte[] buffer = bufferSelect ? buffer0 : buffer1;
|
||||
|
||||
// Run hashes in parallel
|
||||
#if NET20 || NET35
|
||||
// Run hashers sequentially on each chunk
|
||||
foreach (var h in hashers)
|
||||
{
|
||||
h.Value.Process(buffer, current);
|
||||
}
|
||||
#else
|
||||
// Run hashers in parallel on each chunk
|
||||
Parallel.ForEach(hashers, h => h.Value.Process(buffer, current));
|
||||
#endif
|
||||
|
||||
// Wait for the load buffer worker, if needed
|
||||
if (next > 0)
|
||||
@@ -212,19 +234,29 @@ namespace MPF.Core.Hashing
|
||||
|
||||
// Finalize all hashing helpers
|
||||
loadBuffer.Finish();
|
||||
#if NET20 || NET35
|
||||
foreach (var h in hashers)
|
||||
{
|
||||
h.Value.Terminate();
|
||||
}
|
||||
#else
|
||||
Parallel.ForEach(hashers, h => h.Value.Terminate());
|
||||
#endif
|
||||
|
||||
// Get the results
|
||||
hashDict[Hash.CRC32] = hashers[Hash.CRC32].CurrentHashString;
|
||||
#if NET6_0_OR_GREATER
|
||||
hashDict[Hash.CRC64] = hashers[Hash.CRC64].CurrentHashString;
|
||||
#endif
|
||||
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;
|
||||
#if NET6_0_OR_GREATER
|
||||
hashDict[Hash.XxHash32] = hashers[Hash.XxHash32].CurrentHashString;
|
||||
hashDict[Hash.XxHash64] = hashers[Hash.XxHash64].CurrentHashString;
|
||||
hashDict[Hash.CRC64] = hashers[Hash.CRC64].CurrentHashString;
|
||||
#endif
|
||||
|
||||
// Dispose of the hashers
|
||||
loadBuffer.Dispose();
|
||||
@@ -245,7 +277,7 @@ namespace MPF.Core.Hashing
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Hashing
|
||||
|
||||
@@ -260,7 +292,12 @@ namespace MPF.Core.Hashing
|
||||
ha.TransformBlock(buffer, 0, size, null, 0);
|
||||
break;
|
||||
case NonCryptographicHashAlgorithm ncha:
|
||||
#if NET20 || NET35 || NET40
|
||||
byte[] bufferSpan = new byte[size];
|
||||
Array.Copy(buffer, bufferSpan, size);
|
||||
#else
|
||||
var bufferSpan = new ReadOnlySpan<byte>(buffer, 0, size);
|
||||
#endif
|
||||
ncha.Append(bufferSpan);
|
||||
break;
|
||||
}
|
||||
@@ -272,7 +309,7 @@ namespace MPF.Core.Hashing
|
||||
/// <remarks>NonCryptographicHashAlgorithm implementations do not need finalization</remarks>
|
||||
public void Terminate()
|
||||
{
|
||||
byte[] emptyBuffer = Array.Empty<byte>();
|
||||
byte[] emptyBuffer = [];
|
||||
switch (_hasher)
|
||||
{
|
||||
case HashAlgorithm ha:
|
||||
|
||||
184
MPF.Core/Hashing/OptimizedCRC.cs
Normal file
184
MPF.Core/Hashing/OptimizedCRC.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
#if NETFRAMEWORK || NETCOREAPP3_1 || NET5_0
|
||||
|
||||
/*
|
||||
|
||||
Copyright (c) 2012-2015 Eugene Larchenko (spct@mail.ru)
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
//namespace OptimizedCRC
|
||||
namespace MPF.Core.Hashing
|
||||
{
|
||||
/// <summary>
|
||||
/// Shell class to trick older versions into using CRC-32 properly
|
||||
/// </summary>
|
||||
internal abstract class NonCryptographicHashAlgorithm
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, appends the contents of source to
|
||||
/// the data already processed for the current hash computation.
|
||||
/// </summary>
|
||||
/// <param name="source">The data to process.</param>
|
||||
public abstract void Append(byte[] source);
|
||||
#else
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, appends the contents of source to
|
||||
/// the data already processed for the current hash computation.
|
||||
/// </summary>
|
||||
/// <param name="source">The data to process.</param>
|
||||
public abstract void Append(ReadOnlySpan<byte> source);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current computed hash value without modifying accumulated state.
|
||||
/// </summary>
|
||||
/// <returns>The hash value for the data already provided.</returns>
|
||||
public abstract byte[] GetCurrentHash();
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// Some changes have been made to this code to make it more similar to the System.IO.Hashing implementations
|
||||
/// </remarks>
|
||||
internal class Crc32 : NonCryptographicHashAlgorithm, IDisposable
|
||||
{
|
||||
private const uint kCrcPoly = 0xEDB88320;
|
||||
private const uint kInitial = 0xFFFFFFFF;
|
||||
private const int CRC_NUM_TABLES = 8;
|
||||
private static readonly uint[] Table;
|
||||
|
||||
static Crc32()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
Table = new uint[256 * CRC_NUM_TABLES];
|
||||
int i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
uint r = (uint)i;
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
}
|
||||
Table[i] = r;
|
||||
}
|
||||
for (; i < 256 * CRC_NUM_TABLES; i++)
|
||||
{
|
||||
uint r = Table[i - 256];
|
||||
Table[i] = Table[r & 0xFF] ^ (r >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public uint UnsignedValue;
|
||||
|
||||
public Crc32()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset CRC
|
||||
/// </summary>
|
||||
public void Init()
|
||||
{
|
||||
UnsignedValue = kInitial;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override byte[] GetCurrentHash()
|
||||
{
|
||||
return BitConverter.GetBytes(~UnsignedValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35 || NET40
|
||||
public override void Append(byte[] source)
|
||||
{
|
||||
Update(source, 0, source.Length);
|
||||
}
|
||||
#else
|
||||
public override void Append(ReadOnlySpan<byte> source)
|
||||
{
|
||||
byte[] sourceBytes = source.ToArray();
|
||||
Update(sourceBytes, 0, sourceBytes.Length);
|
||||
}
|
||||
#endif
|
||||
|
||||
private void Update(byte[] data, int offset, int count)
|
||||
{
|
||||
_ = new ArraySegment<byte>(data, offset, count); // check arguments
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var table = Table;
|
||||
|
||||
uint crc = UnsignedValue;
|
||||
|
||||
for (; (offset & 7) != 0 && count != 0; count--)
|
||||
{
|
||||
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
|
||||
}
|
||||
|
||||
if (count >= 8)
|
||||
{
|
||||
/*
|
||||
* Idea from 7-zip project sources (http://7-zip.org/sdk.html)
|
||||
*/
|
||||
|
||||
int end = (count - 8) & ~7;
|
||||
count -= end;
|
||||
end += offset;
|
||||
|
||||
while (offset != end)
|
||||
{
|
||||
crc ^= (uint)(data[offset] + (data[offset + 1] << 8) + (data[offset + 2] << 16) + (data[offset + 3] << 24));
|
||||
uint high = (uint)(data[offset + 4] + (data[offset + 5] << 8) + (data[offset + 6] << 16) + (data[offset + 7] << 24));
|
||||
offset += 8;
|
||||
|
||||
crc = table[(byte)crc + 0x700]
|
||||
^ table[(byte)(crc >>= 8) + 0x600]
|
||||
^ table[(byte)(crc >>= 8) + 0x500]
|
||||
^ table[/*(byte)*/(crc >> 8) + 0x400]
|
||||
^ table[(byte)(high) + 0x300]
|
||||
^ table[(byte)(high >>= 8) + 0x200]
|
||||
^ table[(byte)(high >>= 8) + 0x100]
|
||||
^ table[/*(byte)*/(high >> 8) + 0x000];
|
||||
}
|
||||
}
|
||||
|
||||
while (count-- != 0)
|
||||
{
|
||||
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
|
||||
}
|
||||
|
||||
UnsignedValue = crc;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
UnsignedValue = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,32 +1,63 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.0.1</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2023</Copyright>
|
||||
<VersionPrefix>3.0.0</VersionPrefix>
|
||||
<Description>Common code for all MPF implementations</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2019-2023</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="MPF.Test" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Support for old .NET versions -->
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))">
|
||||
<PackageReference Include="MinAsyncBridge" Version="0.12.4" />
|
||||
<PackageReference Include="MinTasksExtensionsBridge" Version="0.3.4" />
|
||||
<PackageReference Include="MinThreadingBridge" Version="0.11.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`))">
|
||||
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net4`)) AND !$(TargetFramework.StartsWith(`net40`))">
|
||||
<PackageReference Include="IndexRange" Version="1.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net452`))">
|
||||
<PackageReference Include="Microsoft.Net.Http" Version="2.2.29" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))">
|
||||
<PackageReference Include="Microsoft.Management.Infrastructure" Version="3.0.0" />
|
||||
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`))">
|
||||
<PackageReference Include="System.IO.Hashing" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BinaryObjectScanner" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="3.0.0" GeneratePathProperty="true">
|
||||
<PackageReference Include="BinaryObjectScanner" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="3.0.2" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Management.Infrastructure" Version="3.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="psxt001z" Version="0.21.0-beta2" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.2.0" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.2.0" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.2.0" />
|
||||
<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="8.0.0" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
|
||||
<PackageReference Include="psxt001z.Library" Version="0.21.0-beta3" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.3.0" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.3.1" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -10,11 +10,11 @@ using System.Xml.Serialization;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using SabreTools.Models.CueSheets;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Schemas;
|
||||
|
||||
#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
|
||||
@@ -202,7 +202,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
var outputDirectory = Path.GetDirectoryName(basePath);
|
||||
|
||||
// Ensure that required sections exist
|
||||
info = SubmissionInfoTool.EnsureAllSections(info);
|
||||
info = Builder.EnsureAllSections(info);
|
||||
|
||||
// TODO: Determine if there's an Aaru version anywhere
|
||||
info.DumpingInfo!.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
@@ -223,12 +223,12 @@ namespace MPF.Core.Modules.Aaru
|
||||
if (GetDiscType(sidecar, out var discType, out var discSubType))
|
||||
{
|
||||
string fullDiscType = string.Empty;
|
||||
if (!string.IsNullOrWhiteSpace(discType) && !string.IsNullOrWhiteSpace(discSubType))
|
||||
if (!string.IsNullOrEmpty(discType) && !string.IsNullOrEmpty(discSubType))
|
||||
fullDiscType = $"{discType} ({discSubType})";
|
||||
else if (!string.IsNullOrWhiteSpace(discType) && string.IsNullOrWhiteSpace(discSubType))
|
||||
fullDiscType = discType;
|
||||
else if (string.IsNullOrWhiteSpace(discType) && !string.IsNullOrWhiteSpace(discSubType))
|
||||
fullDiscType = discSubType;
|
||||
else if (!string.IsNullOrEmpty(discType) && string.IsNullOrEmpty(discSubType))
|
||||
fullDiscType = discType!;
|
||||
else if (string.IsNullOrEmpty(discType) && !string.IsNullOrEmpty(discSubType))
|
||||
fullDiscType = discSubType!;
|
||||
|
||||
info.DumpingInfo.ReportedDiscType = fullDiscType;
|
||||
}
|
||||
@@ -285,7 +285,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
layerbreak = info.SizeAndChecksums!.Size > 25_025_314_816 ? "25025314816" : null;
|
||||
|
||||
// If we have a single-layer disc
|
||||
if (string.IsNullOrWhiteSpace(layerbreak))
|
||||
if (string.IsNullOrEmpty(layerbreak))
|
||||
{
|
||||
// Currently no-op
|
||||
}
|
||||
@@ -409,7 +409,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
info.Artifacts ??= new Dictionary<string, string>();
|
||||
info.Artifacts ??= [];
|
||||
if (File.Exists(basePath + ".cicm.xml"))
|
||||
info.Artifacts["cicm"] = GetBase64(GetFullFile(basePath + ".cicm.xml")) ?? string.Empty;
|
||||
if (File.Exists(basePath + ".ibg"))
|
||||
@@ -456,7 +456,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
|
||||
BaseCommand ??= CommandStrings.NONE;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(BaseCommand))
|
||||
if (!string.IsNullOrEmpty(BaseCommand))
|
||||
parameters.Add(BaseCommand);
|
||||
else
|
||||
return null;
|
||||
@@ -1082,7 +1082,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
case CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageVerify:
|
||||
case CommandStrings.MediaPrefixLong + " " + CommandStrings.MediaInfo:
|
||||
case CommandStrings.MediaPrefixLong + " " + CommandStrings.MediaScan:
|
||||
if (string.IsNullOrWhiteSpace(InputValue))
|
||||
if (string.IsNullOrEmpty(InputValue))
|
||||
return null;
|
||||
|
||||
parameters.Add($"\"{InputValue}\"");
|
||||
@@ -1090,7 +1090,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
|
||||
// Two input values
|
||||
case CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageCompareLong:
|
||||
if (string.IsNullOrWhiteSpace(Input1Value) || string.IsNullOrWhiteSpace(Input2Value))
|
||||
if (string.IsNullOrEmpty(Input1Value) || string.IsNullOrEmpty(Input2Value))
|
||||
return null;
|
||||
|
||||
parameters.Add($"\"{Input1Value}\"");
|
||||
@@ -1101,7 +1101,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
case CommandStrings.FilesystemPrefixLong + " " + CommandStrings.FilesystemExtract:
|
||||
case CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageConvert:
|
||||
case CommandStrings.MediaPrefixLong + " " + CommandStrings.MediaDump:
|
||||
if (string.IsNullOrWhiteSpace(InputValue) || string.IsNullOrWhiteSpace(OutputValue))
|
||||
if (string.IsNullOrEmpty(InputValue) || string.IsNullOrEmpty(OutputValue))
|
||||
return null;
|
||||
|
||||
parameters.Add($"\"{InputValue}\"");
|
||||
@@ -1111,14 +1111,14 @@ namespace MPF.Core.Modules.Aaru
|
||||
// Remote host value only
|
||||
case CommandStrings.DevicePrefixLong + " " + CommandStrings.DeviceList:
|
||||
case CommandStrings.Remote:
|
||||
if (string.IsNullOrWhiteSpace(RemoteHostValue))
|
||||
if (string.IsNullOrEmpty(RemoteHostValue))
|
||||
return null;
|
||||
|
||||
parameters.Add($"\"{RemoteHostValue}\"");
|
||||
break;
|
||||
}
|
||||
|
||||
return string.Join(" ", parameters);
|
||||
return string.Join(" ", [.. parameters]);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -1128,48 +1128,42 @@ namespace MPF.Core.Modules.Aaru
|
||||
{
|
||||
#region Archive Family
|
||||
|
||||
[CommandStrings.ArchivePrefixLong + " " + CommandStrings.ArchiveInfo] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.ArchivePrefixLong + " " + CommandStrings.ArchiveInfo] = [],
|
||||
|
||||
#endregion
|
||||
|
||||
#region Database Family
|
||||
|
||||
[CommandStrings.DatabasePrefixLong + " " + CommandStrings.DatabaseStats] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.DatabasePrefixLong + " " + CommandStrings.DatabaseStats] = [],
|
||||
|
||||
[CommandStrings.DatabasePrefixLong + " " + CommandStrings.DatabaseUpdate] = new List<string>()
|
||||
{
|
||||
[CommandStrings.DatabasePrefixLong + " " + CommandStrings.DatabaseUpdate] =
|
||||
[
|
||||
FlagStrings.ClearLong,
|
||||
FlagStrings.ClearAllLong,
|
||||
},
|
||||
],
|
||||
|
||||
#endregion
|
||||
|
||||
#region Device Family
|
||||
|
||||
[CommandStrings.DevicePrefixLong + " " + CommandStrings.DeviceInfo] = new List<string>()
|
||||
{
|
||||
[CommandStrings.DevicePrefixLong + " " + CommandStrings.DeviceInfo] =
|
||||
[
|
||||
FlagStrings.OutputPrefixLong,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.DevicePrefixLong + " " + CommandStrings.DeviceList] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.DevicePrefixLong + " " + CommandStrings.DeviceList] = [],
|
||||
|
||||
[CommandStrings.DevicePrefixLong + " " + CommandStrings.DeviceReport] = new List<string>()
|
||||
{
|
||||
[CommandStrings.DevicePrefixLong + " " + CommandStrings.DeviceReport] =
|
||||
[
|
||||
FlagStrings.TrapDiscLong,
|
||||
},
|
||||
],
|
||||
|
||||
#endregion
|
||||
|
||||
#region Filesystem Family
|
||||
|
||||
[CommandStrings.FilesystemPrefixLong + " " + CommandStrings.FilesystemExtract] = new List<string>()
|
||||
{
|
||||
[CommandStrings.FilesystemPrefixLong + " " + CommandStrings.FilesystemExtract] =
|
||||
[
|
||||
FlagStrings.EncodingLong,
|
||||
FlagStrings.EncodingShort,
|
||||
FlagStrings.ExtendedAttributesLong,
|
||||
@@ -1178,10 +1172,10 @@ namespace MPF.Core.Modules.Aaru
|
||||
FlagStrings.NamespaceShort,
|
||||
FlagStrings.OptionsLong,
|
||||
FlagStrings.OptionsShort,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.FilesystemPrefixLong + " " + CommandStrings.FilesystemInfo] = new List<string>()
|
||||
{
|
||||
[CommandStrings.FilesystemPrefixLong + " " + CommandStrings.FilesystemInfo] =
|
||||
[
|
||||
FlagStrings.EncodingLong,
|
||||
FlagStrings.EncodingShort,
|
||||
FlagStrings.ExtendedAttributesLong,
|
||||
@@ -1190,10 +1184,10 @@ namespace MPF.Core.Modules.Aaru
|
||||
FlagStrings.NamespaceShort,
|
||||
FlagStrings.OptionsLong,
|
||||
FlagStrings.OptionsShort,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.FilesystemPrefixLong + " " + CommandStrings.FilesystemListLong] = new List<string>()
|
||||
{
|
||||
[CommandStrings.FilesystemPrefixLong + " " + CommandStrings.FilesystemListLong] =
|
||||
[
|
||||
FlagStrings.EncodingLong,
|
||||
FlagStrings.EncodingShort,
|
||||
FlagStrings.FilesystemsLong,
|
||||
@@ -1202,18 +1196,16 @@ namespace MPF.Core.Modules.Aaru
|
||||
FlagStrings.LongFormatShort,
|
||||
FlagStrings.PartitionsLong,
|
||||
FlagStrings.PartitionsShort,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.FilesystemPrefixLong + " " + CommandStrings.FilesystemOptions] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.FilesystemPrefixLong + " " + CommandStrings.FilesystemOptions] = [],
|
||||
|
||||
#endregion
|
||||
|
||||
#region Image Family
|
||||
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageChecksumLong] = new List<string>()
|
||||
{
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageChecksumLong] =
|
||||
[
|
||||
FlagStrings.Adler32Long,
|
||||
FlagStrings.Adler32Short,
|
||||
FlagStrings.CRC16Long,
|
||||
@@ -1235,14 +1227,12 @@ namespace MPF.Core.Modules.Aaru
|
||||
FlagStrings.SpamSumShort,
|
||||
FlagStrings.WholeDiscLong,
|
||||
FlagStrings.WholeDiscShort,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageCompareLong] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageCompareLong] = [],
|
||||
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageConvert] = new List<string>()
|
||||
{
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageConvert] =
|
||||
[
|
||||
FlagStrings.CommentsLong,
|
||||
FlagStrings.CountLong,
|
||||
FlagStrings.CountShort,
|
||||
@@ -1275,20 +1265,20 @@ namespace MPF.Core.Modules.Aaru
|
||||
FlagStrings.ResumeFileShort,
|
||||
FlagStrings.XMLSidecarLong,
|
||||
FlagStrings.XMLSidecarShort,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageCreateSidecar] = new List<string>()
|
||||
{
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageCreateSidecar] =
|
||||
[
|
||||
FlagStrings.BlockSizeLong,
|
||||
FlagStrings.BlockSizeShort,
|
||||
FlagStrings.EncodingLong,
|
||||
FlagStrings.EncodingShort,
|
||||
FlagStrings.TapeLong,
|
||||
FlagStrings.TapeShort,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageDecode] = new List<string>()
|
||||
{
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageDecode] =
|
||||
[
|
||||
FlagStrings.DiskTagsLong,
|
||||
FlagStrings.DiskTagsShort,
|
||||
FlagStrings.LengthLong,
|
||||
@@ -1297,28 +1287,24 @@ namespace MPF.Core.Modules.Aaru
|
||||
FlagStrings.SectorTagsShort,
|
||||
FlagStrings.StartLong,
|
||||
FlagStrings.StartShort,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageEntropy] = new List<string>()
|
||||
{
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageEntropy] =
|
||||
[
|
||||
FlagStrings.DuplicatedSectorsLong,
|
||||
FlagStrings.DuplicatedSectorsShort,
|
||||
FlagStrings.SeparatedTracksLong,
|
||||
FlagStrings.SeparatedTracksShort,
|
||||
FlagStrings.WholeDiscLong,
|
||||
FlagStrings.WholeDiscShort,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageInfo] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageInfo] = [],
|
||||
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageOptions] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageOptions] = [],
|
||||
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImagePrint] = new List<string>()
|
||||
{
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImagePrint] =
|
||||
[
|
||||
FlagStrings.LengthLong,
|
||||
FlagStrings.LengthShort,
|
||||
FlagStrings.LongSectorsLong,
|
||||
@@ -1327,22 +1313,22 @@ namespace MPF.Core.Modules.Aaru
|
||||
FlagStrings.StartShort,
|
||||
FlagStrings.WidthLong,
|
||||
FlagStrings.WidthShort,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageVerify] = new List<string>()
|
||||
{
|
||||
[CommandStrings.ImagePrefixLong + " " + CommandStrings.ImageVerify] =
|
||||
[
|
||||
FlagStrings.VerifyDiscLong,
|
||||
FlagStrings.VerifyDiscShort,
|
||||
FlagStrings.VerifySectorsLong,
|
||||
FlagStrings.VerifySectorsShort,
|
||||
},
|
||||
],
|
||||
|
||||
#endregion
|
||||
|
||||
#region Media Family
|
||||
|
||||
[CommandStrings.MediaPrefixLong + " " + CommandStrings.MediaDump] = new List<string>()
|
||||
{
|
||||
[CommandStrings.MediaPrefixLong + " " + CommandStrings.MediaDump] =
|
||||
[
|
||||
FlagStrings.EjectLong,
|
||||
FlagStrings.EncodingLong,
|
||||
FlagStrings.EncodingShort,
|
||||
@@ -1380,29 +1366,29 @@ namespace MPF.Core.Modules.Aaru
|
||||
FlagStrings.UseBufferedReadsLong,
|
||||
FlagStrings.XMLSidecarLong,
|
||||
FlagStrings.XMLSidecarShort,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.MediaPrefixLong + " " + CommandStrings.MediaInfo] = new List<string>()
|
||||
{
|
||||
[CommandStrings.MediaPrefixLong + " " + CommandStrings.MediaInfo] =
|
||||
[
|
||||
FlagStrings.OutputPrefixLong,
|
||||
FlagStrings.OutputPrefixShort,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.MediaPrefixLong + " " + CommandStrings.MediaScan] = new List<string>()
|
||||
{
|
||||
[CommandStrings.MediaPrefixLong + " " + CommandStrings.MediaScan] =
|
||||
[
|
||||
FlagStrings.ImgBurnLogLong,
|
||||
FlagStrings.ImgBurnLogShort,
|
||||
FlagStrings.MHDDLogLong,
|
||||
FlagStrings.MHDDLogShort,
|
||||
FlagStrings.UseBufferedReadsLong,
|
||||
},
|
||||
],
|
||||
|
||||
#endregion
|
||||
|
||||
#region Standalone Commands
|
||||
|
||||
[CommandStrings.NONE] = new List<string>()
|
||||
{
|
||||
[CommandStrings.NONE] =
|
||||
[
|
||||
FlagStrings.DebugLong,
|
||||
FlagStrings.DebugShort,
|
||||
FlagStrings.HelpLong,
|
||||
@@ -1411,27 +1397,17 @@ namespace MPF.Core.Modules.Aaru
|
||||
FlagStrings.VerboseLong,
|
||||
FlagStrings.VerboseShort,
|
||||
FlagStrings.VersionLong,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.Configure] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Configure] = [],
|
||||
|
||||
[CommandStrings.Formats] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Formats] = [],
|
||||
|
||||
[CommandStrings.ListEncodings] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.ListEncodings] = [],
|
||||
|
||||
[CommandStrings.ListNamespaces] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.ListNamespaces] = [],
|
||||
|
||||
[CommandStrings.Remote] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Remote] = [],
|
||||
|
||||
#endregion
|
||||
};
|
||||
@@ -1500,7 +1476,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
{
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
|
||||
flags = new Dictionary<string, bool?>();
|
||||
flags = [];
|
||||
|
||||
BlockSizeValue = null;
|
||||
CommentsValue = null;
|
||||
@@ -1625,12 +1601,12 @@ namespace MPF.Core.Modules.Aaru
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
|
||||
// The string has to be valid by itself first
|
||||
if (string.IsNullOrWhiteSpace(parameters))
|
||||
if (string.IsNullOrEmpty(parameters))
|
||||
return false;
|
||||
|
||||
// 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();
|
||||
parameters = parameters!.Trim();
|
||||
List<string> parts = Regex.Matches(parameters, @"[\""].+?[\""]|[^ ]+", RegexOptions.Compiled)
|
||||
.Cast<Match>()
|
||||
.Select(m => m.Value)
|
||||
@@ -1670,7 +1646,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
|
||||
// Determine what the commandline should look like given the first item
|
||||
BaseCommand = NormalizeCommand(parts, ref start);
|
||||
if (string.IsNullOrWhiteSpace(BaseCommand))
|
||||
if (string.IsNullOrEmpty(BaseCommand))
|
||||
return false;
|
||||
|
||||
// Set the start position
|
||||
@@ -2175,7 +2151,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
private static string? NormalizeCommand(string baseCommand)
|
||||
{
|
||||
// If the base command is inavlid, just return nulls
|
||||
if (string.IsNullOrWhiteSpace(baseCommand))
|
||||
if (string.IsNullOrEmpty(baseCommand))
|
||||
return null;
|
||||
|
||||
// Split the command otherwise
|
||||
@@ -2297,11 +2273,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
}
|
||||
|
||||
// If the command itself is invalid, then return null
|
||||
if (string.IsNullOrWhiteSpace(command))
|
||||
if (string.IsNullOrEmpty(command))
|
||||
return null;
|
||||
|
||||
// Combine the result
|
||||
if (!string.IsNullOrWhiteSpace(family))
|
||||
if (!string.IsNullOrEmpty(family))
|
||||
return $"{family} {command}";
|
||||
else
|
||||
return command;
|
||||
@@ -2384,7 +2360,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
var cueFiles = new List<CueFile>();
|
||||
var cueSheet = new CueSheet
|
||||
{
|
||||
Performer = string.Join(", ", cicmSidecar.Performer ?? Array.Empty<string>()),
|
||||
Performer = string.Join(", ", cicmSidecar.Performer ?? []),
|
||||
};
|
||||
|
||||
// Only care about OpticalDisc types
|
||||
@@ -2466,14 +2442,14 @@ namespace MPF.Core.Modules.Aaru
|
||||
}
|
||||
}
|
||||
|
||||
cueTrack.Indices = cueIndicies.ToArray();
|
||||
cueTrack.Indices = [.. cueIndicies];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default if index data missing from sidecar
|
||||
cueTrack.Indices = new CueIndex[]
|
||||
{
|
||||
new CueIndex
|
||||
new()
|
||||
{
|
||||
Index = 1,
|
||||
Minutes = 0,
|
||||
@@ -2492,7 +2468,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
}
|
||||
|
||||
// If we have a cuesheet to write out, do so
|
||||
cueSheet.Files = cueFiles.ToArray();
|
||||
cueSheet.Files = [.. cueFiles];
|
||||
if (cueSheet != null && cueSheet != default)
|
||||
{
|
||||
var ms = new SabreTools.Serialization.Streams.CueSheet().Serialize(cueSheet);
|
||||
@@ -2722,7 +2698,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
|
||||
// Assign the roms to a new game
|
||||
datafile.Games = new Game[1];
|
||||
datafile.Games[0] = new Game { Roms = roms.ToArray() };
|
||||
datafile.Games[0] = new Game { Roms = [.. roms] };
|
||||
|
||||
return datafile;
|
||||
}
|
||||
@@ -2777,12 +2753,28 @@ namespace MPF.Core.Modules.Aaru
|
||||
|
||||
// Build each row in consecutive order
|
||||
string pvd = string.Empty;
|
||||
pvd += GenerateSectorOutputLine("0320", new ReadOnlySpan<byte>(pvdData, 0, 16));
|
||||
pvd += GenerateSectorOutputLine("0330", new ReadOnlySpan<byte>(pvdData, 16, 16));
|
||||
pvd += GenerateSectorOutputLine("0340", new ReadOnlySpan<byte>(pvdData, 32, 16));
|
||||
pvd += GenerateSectorOutputLine("0350", new ReadOnlySpan<byte>(pvdData, 48, 16));
|
||||
pvd += GenerateSectorOutputLine("0360", new ReadOnlySpan<byte>(pvdData, 64, 16));
|
||||
pvd += GenerateSectorOutputLine("0370", new ReadOnlySpan<byte>(pvdData, 80, 16));
|
||||
#if NET20 || NET35 || NET40
|
||||
byte[] pvdLine = new byte[16];
|
||||
Array.Copy(pvdData, 0, pvdLine, 0, 16);
|
||||
pvd += GenerateSectorOutputLine("0320", pvdLine);
|
||||
Array.Copy(pvdData, 16, pvdLine, 0, 16);
|
||||
pvd += GenerateSectorOutputLine("0330", pvdLine);
|
||||
Array.Copy(pvdData, 32, pvdLine, 0, 16);
|
||||
pvd += GenerateSectorOutputLine("0340", pvdLine);
|
||||
Array.Copy(pvdData, 48, pvdLine, 0, 16);
|
||||
pvd += GenerateSectorOutputLine("0350", pvdLine);
|
||||
Array.Copy(pvdData, 64, pvdLine, 0, 16);
|
||||
pvd += GenerateSectorOutputLine("0360", pvdLine);
|
||||
Array.Copy(pvdData, 80, pvdLine, 0, 16);
|
||||
pvd += GenerateSectorOutputLine("0370", pvdLine);
|
||||
#else
|
||||
pvd += GenerateSectorOutputLine("0320", new ReadOnlySpan<byte>(pvdData, 0, 16).ToArray());
|
||||
pvd += GenerateSectorOutputLine("0330", new ReadOnlySpan<byte>(pvdData, 16, 16).ToArray());
|
||||
pvd += GenerateSectorOutputLine("0340", new ReadOnlySpan<byte>(pvdData, 32, 16).ToArray());
|
||||
pvd += GenerateSectorOutputLine("0350", new ReadOnlySpan<byte>(pvdData, 48, 16).ToArray());
|
||||
pvd += GenerateSectorOutputLine("0360", new ReadOnlySpan<byte>(pvdData, 64, 16).ToArray());
|
||||
pvd += GenerateSectorOutputLine("0370", new ReadOnlySpan<byte>(pvdData, 80, 16).ToArray());
|
||||
#endif
|
||||
|
||||
return pvd;
|
||||
}
|
||||
@@ -2883,7 +2875,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
pvdData.AddRange(new string((char)0, 14).ToCharArray().Select(c => (byte)c));
|
||||
|
||||
// Return the filled array
|
||||
return pvdData.ToArray();
|
||||
return [.. pvdData];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2924,27 +2916,27 @@ namespace MPF.Core.Modules.Aaru
|
||||
// Get and return the byte array
|
||||
List<byte> dateTimeList = dateTimeString.ToCharArray().Select(c => (byte)c).ToList();
|
||||
dateTimeList.Add(timeZoneNumber);
|
||||
return dateTimeList.ToArray();
|
||||
return [.. dateTimeList];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a single 16-byte sector line from a byte array
|
||||
/// </summary>
|
||||
/// <param name="row">Row ID for outputting</param>
|
||||
/// <param name="bytes">Byte span representing the data to write</param>
|
||||
/// <param name="bytes">Bytes representing the data to write</param>
|
||||
/// <returns>Formatted string representing the sector line</returns>
|
||||
private static string? GenerateSectorOutputLine(string row, ReadOnlySpan<byte> bytes)
|
||||
private static string? GenerateSectorOutputLine(string row, byte[] bytes)
|
||||
{
|
||||
// If the data isn't correct, return null
|
||||
if (bytes == null || bytes.Length != 16)
|
||||
return null;
|
||||
|
||||
string pvdLine = $"{row} : ";
|
||||
pvdLine += BitConverter.ToString(bytes[..8].ToArray()).Replace("-", " ");
|
||||
pvdLine += BitConverter.ToString(bytes.Take(8).ToArray()).Replace("-", " ");
|
||||
pvdLine += " ";
|
||||
pvdLine += BitConverter.ToString(bytes.Slice(8, 8).ToArray().ToArray()).Replace("-", " ");
|
||||
pvdLine += BitConverter.ToString(bytes.Skip(8).Take(8).ToArray()).Replace("-", " ");
|
||||
pvdLine += " ";
|
||||
pvdLine += Encoding.ASCII.GetString(bytes.ToArray()).Replace((char)0, '.').Replace('?', '.');
|
||||
pvdLine += Encoding.ASCII.GetString([.. bytes]).Replace((char)0, '.').Replace('?', '.');
|
||||
pvdLine += "\n";
|
||||
|
||||
return pvdLine;
|
||||
@@ -2965,7 +2957,9 @@ namespace MPF.Core.Modules.Aaru
|
||||
XmlReader xtr = XmlReader.Create(cicmSidecar, new XmlReaderSettings
|
||||
{
|
||||
CheckCharacters = false,
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
DtdProcessing = DtdProcessing.Ignore,
|
||||
#endif
|
||||
IgnoreComments = true,
|
||||
IgnoreWhitespace = true,
|
||||
ValidationFlags = XmlSchemaValidationFlags.None,
|
||||
@@ -3032,7 +3026,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
// Loop through each OpticalDisc in the metadata
|
||||
foreach (OpticalDiscType opticalDisc in cicmSidecar.OpticalDisc)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(opticalDisc.CopyProtection))
|
||||
if (!string.IsNullOrEmpty(opticalDisc.CopyProtection))
|
||||
copyrightProtectionSystemType += $", {opticalDisc.CopyProtection}";
|
||||
}
|
||||
|
||||
@@ -3084,9 +3078,9 @@ namespace MPF.Core.Modules.Aaru
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
|
||||
// Initialize on seeing the open tag
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
if (string.IsNullOrEmpty(line))
|
||||
continue;
|
||||
else if (line.StartsWith("<BadBlocks>"))
|
||||
else if (line!.StartsWith("<BadBlocks>"))
|
||||
totalErrors = 0;
|
||||
else if (line.StartsWith("</BadBlocks>"))
|
||||
return totalErrors ?? -1;
|
||||
@@ -3400,6 +3394,6 @@ namespace MPF.Core.Modules.Aaru
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,27 @@ namespace MPF.Core.Modules
|
||||
{
|
||||
#region Event Handlers
|
||||
|
||||
#if NET20 || NET35 || NET40
|
||||
/// <summary>
|
||||
/// Wrapper event args class for old .NET
|
||||
/// </summary>
|
||||
public class StringEventArgs : EventArgs
|
||||
{
|
||||
public string? Value { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Geneeic way of reporting a message
|
||||
/// </summary>
|
||||
/// <param name="message">String value to report</param>
|
||||
public EventHandler<StringEventArgs>? ReportStatus;
|
||||
#else
|
||||
/// <summary>
|
||||
/// Geneeic way of reporting a message
|
||||
/// </summary>
|
||||
/// <param name="message">String value to report</param>
|
||||
public EventHandler<string>? ReportStatus;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -32,7 +48,7 @@ namespace MPF.Core.Modules
|
||||
/// <summary>
|
||||
/// Set of flags to pass to the executable
|
||||
/// </summary>
|
||||
protected Dictionary<string, bool?> flags = new();
|
||||
protected Dictionary<string, bool?> flags = [];
|
||||
protected internal IEnumerable<string> Keys => flags.Keys;
|
||||
|
||||
/// <summary>
|
||||
@@ -42,8 +58,8 @@ namespace MPF.Core.Modules
|
||||
{
|
||||
get
|
||||
{
|
||||
if (flags.ContainsKey(key))
|
||||
return flags[key];
|
||||
if (flags.TryGetValue(key, out bool? val))
|
||||
return val;
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -216,9 +232,9 @@ namespace MPF.Core.Modules
|
||||
return false;
|
||||
if (this.BaseCommand == null)
|
||||
return false;
|
||||
if (!CommandSupport.ContainsKey(this.BaseCommand))
|
||||
if (!CommandSupport.TryGetValue(this.BaseCommand, out var supported))
|
||||
return false;
|
||||
return CommandSupport[this.BaseCommand].Contains(flag);
|
||||
return supported.Contains(flag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -246,7 +262,7 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="parameters">String possibly representing parameters</param>
|
||||
/// <returns>True if the parameters were set correctly, false otherwise</returns>
|
||||
protected virtual bool ValidateAndSetParameters(string? parameters) => !string.IsNullOrWhiteSpace(parameters);
|
||||
protected virtual bool ValidateAndSetParameters(string? parameters) => !string.IsNullOrEmpty(parameters);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -261,7 +277,7 @@ namespace MPF.Core.Modules
|
||||
// Create the start info
|
||||
var startInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = ExecutablePath,
|
||||
FileName = ExecutablePath!,
|
||||
Arguments = GenerateParameters() ?? "",
|
||||
CreateNoWindow = !separateWindow,
|
||||
UseShellExecute = separateWindow,
|
||||
@@ -278,8 +294,13 @@ namespace MPF.Core.Modules
|
||||
// Start processing tasks, if necessary
|
||||
if (!separateWindow)
|
||||
{
|
||||
#if NET40
|
||||
Logging.OutputToLog(process.StandardOutput, this, ReportStatus);
|
||||
Logging.OutputToLog(process.StandardError, this, ReportStatus);
|
||||
#else
|
||||
_ = Logging.OutputToLog(process.StandardOutput, this, ReportStatus);
|
||||
_ = Logging.OutputToLog(process.StandardError, this, ReportStatus);
|
||||
#endif
|
||||
}
|
||||
|
||||
process.WaitForExit();
|
||||
@@ -302,7 +323,7 @@ namespace MPF.Core.Modules
|
||||
{ }
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Parameter Parsing
|
||||
|
||||
@@ -910,7 +931,7 @@ namespace MPF.Core.Modules
|
||||
|
||||
return null;
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(parts[i + 1]))
|
||||
else if (string.IsNullOrEmpty(parts[i + 1]))
|
||||
{
|
||||
if (missingAllowed)
|
||||
this[longFlagString] = true;
|
||||
@@ -1104,7 +1125,7 @@ namespace MPF.Core.Modules
|
||||
return null;
|
||||
|
||||
if (trimLength > -1)
|
||||
hex = hex[..trimLength];
|
||||
hex = hex.Substring(0, trimLength);
|
||||
|
||||
return Regex.Replace(hex, ".{32}", "$0\n", RegexOptions.Compiled);
|
||||
}
|
||||
@@ -1115,8 +1136,6 @@ namespace MPF.Core.Modules
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,9 @@ using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
#pragma warning disable IDE0051 // Remove unused private members
|
||||
|
||||
namespace MPF.Core.Modules.CleanRip
|
||||
{
|
||||
/// <summary>
|
||||
@@ -64,7 +63,7 @@ namespace MPF.Core.Modules.CleanRip
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive? drive, bool includeArtifacts)
|
||||
{
|
||||
// Ensure that required sections exist
|
||||
info = SubmissionInfoTool.EnsureAllSections(info);
|
||||
info = Builder.EnsureAllSections(info);
|
||||
|
||||
// TODO: Determine if there's a CleanRip version anywhere
|
||||
info.DumpingInfo!.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
@@ -107,7 +106,7 @@ namespace MPF.Core.Modules.CleanRip
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
info.Artifacts ??= new Dictionary<string, string>();
|
||||
info.Artifacts ??= [];
|
||||
|
||||
if (File.Exists(basePath + ".bca"))
|
||||
info.Artifacts["bca"] = GetBase64(GetFullFile(basePath + ".bca", binary: true)) ?? string.Empty;
|
||||
@@ -168,28 +167,28 @@ namespace MPF.Core.Modules.CleanRip
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
if (string.IsNullOrEmpty(line))
|
||||
continue;
|
||||
else if (line.StartsWith("CRC32"))
|
||||
crc = line[7..].ToLowerInvariant();
|
||||
else if (line!.StartsWith("CRC32"))
|
||||
crc = line.Substring(7).ToLowerInvariant();
|
||||
else if (line.StartsWith("MD5"))
|
||||
md5 = line[5..];
|
||||
md5 = line.Substring(5);
|
||||
else if (line.StartsWith("SHA-1"))
|
||||
sha1 = line[7..];
|
||||
sha1 = line.Substring(7);
|
||||
}
|
||||
|
||||
return new Datafile
|
||||
{
|
||||
Games = new Game[]
|
||||
{
|
||||
new Game
|
||||
Games =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Roms = new Rom[]
|
||||
{
|
||||
Roms =
|
||||
[
|
||||
new Rom { Name = Path.GetFileName(iso), Size = size.ToString(), Crc = crc, Md5 = md5, Sha1 = sha1 },
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
catch
|
||||
@@ -254,14 +253,14 @@ namespace MPF.Core.Modules.CleanRip
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
if (string.IsNullOrEmpty(line))
|
||||
continue;
|
||||
else if (line.StartsWith("CRC32"))
|
||||
crc = line[7..].ToLowerInvariant();
|
||||
else if (line!.StartsWith("CRC32"))
|
||||
crc = line.Substring(7).ToLowerInvariant();
|
||||
else if (line.StartsWith("MD5"))
|
||||
md5 = line[5..];
|
||||
md5 = line.Substring(5);
|
||||
else if (line.StartsWith("SHA-1"))
|
||||
sha1 = line[7..];
|
||||
sha1 = line.Substring(7);
|
||||
}
|
||||
|
||||
return $"<rom name=\"{Path.GetFileName(iso)}\" size=\"{size}\" crc=\"{crc}\" md5=\"{md5}\" sha1=\"{sha1}\" />";
|
||||
@@ -300,21 +299,21 @@ namespace MPF.Core.Modules.CleanRip
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
if (string.IsNullOrEmpty(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (line.StartsWith("Version"))
|
||||
else if (line!.StartsWith("Version"))
|
||||
{
|
||||
version = line["Version: ".Length..];
|
||||
version = line.Substring("Version: ".Length);
|
||||
}
|
||||
else if (line.StartsWith("Internal Name"))
|
||||
{
|
||||
name = line["Internal Name: ".Length..];
|
||||
name = line.Substring("Internal Name: ".Length);
|
||||
}
|
||||
else if (line.StartsWith("Filename"))
|
||||
{
|
||||
string serial = line["Filename: ".Length..];
|
||||
string serial = line.Substring("Filename: ".Length);
|
||||
|
||||
// char gameType = serial[0];
|
||||
// string gameid = serial[1] + serial[2];
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Utilities;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core.Modules.DiscImageCreator
|
||||
@@ -384,7 +384,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
var outputDirectory = Path.GetDirectoryName(basePath);
|
||||
|
||||
// Ensure that required sections exist
|
||||
info = SubmissionInfoTool.EnsureAllSections(info);
|
||||
info = Builder.EnsureAllSections(info);
|
||||
|
||||
// Get the dumping program and version
|
||||
var (dicCmd, dicVersion) = GetCommandFilePathAndVersion(basePath);
|
||||
@@ -442,7 +442,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
// Attempt to get multisession data
|
||||
string cdMultiSessionInfo = GetMultisessionInformation($"{basePath}_disc.txt") ?? string.Empty;
|
||||
if (!string.IsNullOrWhiteSpace(cdMultiSessionInfo))
|
||||
if (!string.IsNullOrEmpty(cdMultiSessionInfo))
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.Multisession] = cdMultiSessionInfo;
|
||||
|
||||
break;
|
||||
@@ -543,7 +543,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
case RedumpSystem.MicrosoftXbox:
|
||||
|
||||
string xmidString;
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
xmidString = GetXGD1XMID($"{basePath}_DMI.bin");
|
||||
else
|
||||
xmidString = GetXGD1XMID(Path.Combine(outputDirectory, $"{basePath}_DMI.bin"));
|
||||
@@ -592,7 +592,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
case RedumpSystem.MicrosoftXbox360:
|
||||
string xemidString;
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
xemidString = GetXGD23XeMID($"{basePath}_DMI.bin");
|
||||
else
|
||||
xemidString = GetXGD23XeMID(Path.Combine(outputDirectory, $"{basePath}_DMI.bin"));
|
||||
@@ -646,7 +646,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
// Take only the first 16 lines for GD-ROM
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16).ToArray());
|
||||
|
||||
if (GetGDROMBuildInfo(info.Extras.Header, out var gdSerial, out var gdVersion, out var gdDate))
|
||||
{
|
||||
@@ -664,7 +664,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
// Take only the last 16 lines for Sega CD
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Skip(16));
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Skip(16).ToArray());
|
||||
|
||||
if (GetSegaCDBuildInfo(info.Extras.Header, out var scdSerial, out var fixedDate))
|
||||
{
|
||||
@@ -682,7 +682,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
// Take only the first 16 lines for GD-ROM
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16).ToArray());
|
||||
|
||||
if (GetGDROMBuildInfo(info.Extras.Header, out var gdSerial, out var gdVersion, out var gdDate))
|
||||
{
|
||||
@@ -702,7 +702,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
// Take only the first 16 lines for GD-ROM
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16).ToArray());
|
||||
|
||||
if (GetGDROMBuildInfo(info.Extras.Header, out var gdSerial, out var gdVersion, out var gdDate))
|
||||
{
|
||||
@@ -722,7 +722,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
// Take only the first 16 lines for GD-ROM
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16).ToArray());
|
||||
|
||||
if (GetGDROMBuildInfo(info.Extras.Header, out var gdSerial, out var gdVersion, out var gdDate))
|
||||
{
|
||||
@@ -742,7 +742,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
// Take only the first 16 lines for GD-ROM
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16).ToArray());
|
||||
|
||||
if (GetGDROMBuildInfo(info.Extras.Header, out var gdSerial, out var gdVersion, out var gdDate))
|
||||
{
|
||||
@@ -760,7 +760,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
// Take only the first 16 lines for Saturn
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16).ToArray());
|
||||
|
||||
if (GetSaturnBuildInfo(info.Extras.Header, out var saturnSerial, out var saturnVersion, out var buildDate))
|
||||
{
|
||||
@@ -825,7 +825,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
info.Artifacts ??= new Dictionary<string, string>();
|
||||
info.Artifacts ??= [];
|
||||
|
||||
//if (File.Exists($"{basePath}.c2"))
|
||||
// info.Artifacts["c2"] = Convert.ToBase64String(File.ReadAllBytes($"{basePath}.c2")) ?? string.Empty;
|
||||
@@ -887,7 +887,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
BaseCommand ??= CommandStrings.NONE;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(BaseCommand))
|
||||
if (!string.IsNullOrEmpty(BaseCommand))
|
||||
parameters.Add(BaseCommand);
|
||||
else
|
||||
return null;
|
||||
@@ -1016,7 +1016,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
// BE Opcode
|
||||
if (IsFlagSupported(FlagStrings.BEOpcode))
|
||||
{
|
||||
if (this[FlagStrings.BEOpcode] == true && this[FlagStrings.D8Opcode] == false)
|
||||
if (this[FlagStrings.BEOpcode] == true && this[FlagStrings.D8Opcode] != true)
|
||||
{
|
||||
parameters.Add(FlagStrings.BEOpcode);
|
||||
if (BEOpcodeValue != null
|
||||
@@ -1360,7 +1360,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
parameters.Add(FlagStrings.VideoNowXP);
|
||||
}
|
||||
|
||||
return string.Join(" ", parameters);
|
||||
return string.Join(" ", [.. parameters]);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -1368,8 +1368,8 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
{
|
||||
return new Dictionary<string, List<string>>()
|
||||
{
|
||||
[CommandStrings.Audio] = new List<string>()
|
||||
{
|
||||
[CommandStrings.Audio] =
|
||||
[
|
||||
FlagStrings.BEOpcode,
|
||||
FlagStrings.C2Opcode,
|
||||
FlagStrings.D8Opcode,
|
||||
@@ -1385,23 +1385,21 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
FlagStrings.ScanSectorProtect,
|
||||
FlagStrings.SkipSector,
|
||||
FlagStrings.SubchannelReadLevel,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.BluRay] = new List<string>()
|
||||
{
|
||||
[CommandStrings.BluRay] =
|
||||
[
|
||||
FlagStrings.DatExpand,
|
||||
FlagStrings.DisableBeep,
|
||||
FlagStrings.DVDReread,
|
||||
FlagStrings.ForceUnitAccess,
|
||||
FlagStrings.UseAnchorVolumeDescriptorPointer,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.Close] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Close] = [],
|
||||
|
||||
[CommandStrings.CompactDisc] = new List<string>()
|
||||
{
|
||||
[CommandStrings.CompactDisc] =
|
||||
[
|
||||
FlagStrings.AddOffset,
|
||||
FlagStrings.AMSF,
|
||||
FlagStrings.AtariJaguar,
|
||||
@@ -1426,10 +1424,10 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
FlagStrings.VideoNow,
|
||||
FlagStrings.VideoNowColor,
|
||||
FlagStrings.VideoNowXP,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.Data] = new List<string>()
|
||||
{
|
||||
[CommandStrings.Data] =
|
||||
[
|
||||
FlagStrings.BEOpcode,
|
||||
FlagStrings.C2Opcode,
|
||||
FlagStrings.D8Opcode,
|
||||
@@ -1445,10 +1443,10 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
FlagStrings.ScanSectorProtect,
|
||||
FlagStrings.SkipSector,
|
||||
FlagStrings.SubchannelReadLevel,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.DigitalVideoDisc] = new List<string>()
|
||||
{
|
||||
[CommandStrings.DigitalVideoDisc] =
|
||||
[
|
||||
FlagStrings.CopyrightManagementInformation,
|
||||
FlagStrings.DatExpand,
|
||||
FlagStrings.DisableBeep,
|
||||
@@ -1463,28 +1461,24 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
FlagStrings.ScanFileProtect,
|
||||
FlagStrings.SkipSector,
|
||||
FlagStrings.UseAnchorVolumeDescriptorPointer,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.Disk] = new List<string>()
|
||||
{
|
||||
[CommandStrings.Disk] =
|
||||
[
|
||||
FlagStrings.DatExpand,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.DriveSpeed] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.DriveSpeed] = [],
|
||||
|
||||
[CommandStrings.Eject] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Eject] = [],
|
||||
|
||||
[CommandStrings.Floppy] = new List<string>()
|
||||
{
|
||||
[CommandStrings.Floppy] =
|
||||
[
|
||||
FlagStrings.DatExpand,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.GDROM] = new List<string>()
|
||||
{
|
||||
[CommandStrings.GDROM] =
|
||||
[
|
||||
FlagStrings.BEOpcode,
|
||||
FlagStrings.C2Opcode,
|
||||
FlagStrings.D8Opcode,
|
||||
@@ -1495,40 +1489,28 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
FlagStrings.NoFixSubQ,
|
||||
FlagStrings.NoFixSubRtoW,
|
||||
FlagStrings.SubchannelReadLevel,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.MDS] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.MDS] = [],
|
||||
|
||||
[CommandStrings.Merge] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Merge] = [],
|
||||
|
||||
[CommandStrings.Reset] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Reset] = [],
|
||||
|
||||
[CommandStrings.SACD] = new List<string>()
|
||||
{
|
||||
[CommandStrings.SACD] =
|
||||
[
|
||||
FlagStrings.DatExpand,
|
||||
FlagStrings.DisableBeep,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.Start] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Start] = [],
|
||||
|
||||
[CommandStrings.Stop] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Stop] = [],
|
||||
|
||||
[CommandStrings.Sub] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Sub] = [],
|
||||
|
||||
[CommandStrings.Swap] = new List<string>()
|
||||
{
|
||||
[CommandStrings.Swap] =
|
||||
[
|
||||
FlagStrings.AddOffset,
|
||||
FlagStrings.BEOpcode,
|
||||
FlagStrings.C2Opcode,
|
||||
@@ -1549,48 +1531,44 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
FlagStrings.VideoNow,
|
||||
FlagStrings.VideoNowColor,
|
||||
FlagStrings.VideoNowXP,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.Tape] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Tape] = [],
|
||||
|
||||
[CommandStrings.Version] = new List<string>()
|
||||
{
|
||||
},
|
||||
[CommandStrings.Version] = [],
|
||||
|
||||
[CommandStrings.XBOX] = new List<string>()
|
||||
{
|
||||
[CommandStrings.XBOX] =
|
||||
[
|
||||
FlagStrings.DatExpand,
|
||||
FlagStrings.DisableBeep,
|
||||
FlagStrings.DVDReread,
|
||||
FlagStrings.ForceUnitAccess,
|
||||
FlagStrings.NoSkipSS,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.XBOXSwap] = new List<string>()
|
||||
{
|
||||
[CommandStrings.XBOXSwap] =
|
||||
[
|
||||
FlagStrings.DatExpand,
|
||||
FlagStrings.DisableBeep,
|
||||
FlagStrings.ForceUnitAccess,
|
||||
FlagStrings.NoSkipSS,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.XGD2Swap] = new List<string>()
|
||||
{
|
||||
[CommandStrings.XGD2Swap] =
|
||||
[
|
||||
FlagStrings.DatExpand,
|
||||
FlagStrings.DisableBeep,
|
||||
FlagStrings.ForceUnitAccess,
|
||||
FlagStrings.NoSkipSS,
|
||||
},
|
||||
],
|
||||
|
||||
[CommandStrings.XGD3Swap] = new List<string>()
|
||||
{
|
||||
[CommandStrings.XGD3Swap] =
|
||||
[
|
||||
FlagStrings.DatExpand,
|
||||
FlagStrings.DisableBeep,
|
||||
FlagStrings.ForceUnitAccess,
|
||||
FlagStrings.NoSkipSS,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1813,7 +1791,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
StartLBAValue = null;
|
||||
EndLBAValue = null;
|
||||
|
||||
flags = new Dictionary<string, bool?>();
|
||||
flags = [];
|
||||
|
||||
AddOffsetValue = null;
|
||||
BEOpcodeValue = null;
|
||||
@@ -1935,12 +1913,12 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
|
||||
// The string has to be valid by itself first
|
||||
if (string.IsNullOrWhiteSpace(parameters))
|
||||
if (string.IsNullOrEmpty(parameters))
|
||||
return false;
|
||||
|
||||
// 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();
|
||||
parameters = parameters!.Trim();
|
||||
List<string> parts = Regex.Matches(parameters, @"[\""].+?[\""]|[^ ]+", RegexOptions.Compiled)
|
||||
.Cast<Match>()
|
||||
.Select(m => m.Value)
|
||||
@@ -2578,7 +2556,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
private static (string?, string?) GetCommandFilePathAndVersion(string basePath)
|
||||
{
|
||||
// If we have an invalid base path, we can do nothing
|
||||
if (string.IsNullOrWhiteSpace(basePath))
|
||||
if (string.IsNullOrEmpty(basePath))
|
||||
return (null, null);
|
||||
|
||||
// Generate the matching regex based on the base path
|
||||
@@ -2587,12 +2565,12 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
// Find the first match for the command file
|
||||
var parentDirectory = Path.GetDirectoryName(basePath);
|
||||
if (string.IsNullOrWhiteSpace(parentDirectory))
|
||||
if (string.IsNullOrEmpty(parentDirectory))
|
||||
return (null, null);
|
||||
|
||||
var currentFiles = Directory.GetFiles(parentDirectory);
|
||||
var commandPath = currentFiles.FirstOrDefault(f => cmdFilenameRegex.IsMatch(f));
|
||||
if (string.IsNullOrWhiteSpace(commandPath))
|
||||
if (string.IsNullOrEmpty(commandPath))
|
||||
return (null, null);
|
||||
|
||||
// Extract the version string
|
||||
@@ -2697,25 +2675,25 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
if (line.StartsWith("DiscType:"))
|
||||
{
|
||||
// DiscType: <discType>
|
||||
string identifier = line["DiscType: ".Length..];
|
||||
string identifier = line.Substring("DiscType: ".Length);
|
||||
discTypeOrBookTypeSet.Add(identifier);
|
||||
}
|
||||
else if (line.StartsWith("DiscTypeIdentifier:"))
|
||||
{
|
||||
// DiscTypeIdentifier: <discType>
|
||||
string identifier = line["DiscTypeIdentifier: ".Length..];
|
||||
string identifier = line.Substring("DiscTypeIdentifier: ".Length);
|
||||
discTypeOrBookTypeSet.Add(identifier);
|
||||
}
|
||||
else if (line.StartsWith("DiscTypeSpecific:"))
|
||||
{
|
||||
// DiscTypeSpecific: <discType>
|
||||
string identifier = line["DiscTypeSpecific: ".Length..];
|
||||
string identifier = line.Substring("DiscTypeSpecific: ".Length);
|
||||
discTypeOrBookTypeSet.Add(identifier);
|
||||
}
|
||||
else if (line.StartsWith("BookType:"))
|
||||
{
|
||||
// BookType: <discType>
|
||||
string identifier = line["BookType: ".Length..];
|
||||
string identifier = line.Substring("BookType: ".Length);
|
||||
discTypeOrBookTypeSet.Add(identifier);
|
||||
}
|
||||
|
||||
@@ -2724,7 +2702,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
// Create the output string
|
||||
if (discTypeOrBookTypeSet.Any())
|
||||
discTypeOrBookType = string.Join(", ", discTypeOrBookTypeSet.OrderBy(s => s));
|
||||
discTypeOrBookType = string.Join(", ", [.. discTypeOrBookTypeSet.OrderBy(s => s)]);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2767,9 +2745,9 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
break;
|
||||
|
||||
if (line.StartsWith("CopyrightProtectionType"))
|
||||
copyrightProtectionSystemType = line["CopyrightProtectionType: ".Length..];
|
||||
copyrightProtectionSystemType = line.Substring("CopyrightProtectionType: ".Length);
|
||||
else if (line.StartsWith("RegionManagementInformation"))
|
||||
region = line["RegionManagementInformation: ".Length..];
|
||||
region = line.Substring("RegionManagementInformation: ".Length);
|
||||
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
@@ -2792,7 +2770,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
|
||||
if (line.StartsWith("DecryptedDiscKey"))
|
||||
{
|
||||
decryptedDiscKey = line["DecryptedDiscKey[020]: ".Length..];
|
||||
decryptedDiscKey = line.Substring("DecryptedDiscKey[020]: ".Length);
|
||||
}
|
||||
else if (line.StartsWith("LBA:"))
|
||||
{
|
||||
@@ -2805,7 +2783,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
var match = Regex.Match(line, @"^LBA:\s*[0-9]+, Filename: (.*?), No TitleKey$", RegexOptions.Compiled);
|
||||
string matchedFilename = match.Groups[1].Value;
|
||||
if (matchedFilename.EndsWith(";1"))
|
||||
matchedFilename = matchedFilename[..^2];
|
||||
matchedFilename = matchedFilename.Substring(0, matchedFilename.Length - 2);
|
||||
|
||||
vobKeys += $"{matchedFilename} Title Key: No Title Key\n";
|
||||
}
|
||||
@@ -2814,7 +2792,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
var match = Regex.Match(line, @"^LBA:\s*[0-9]+, Filename: (.*?), EncryptedTitleKey: .*?, DecryptedTitleKey: (.*?)$", RegexOptions.Compiled);
|
||||
string matchedFilename = match.Groups[1].Value;
|
||||
if (matchedFilename.EndsWith(";1"))
|
||||
matchedFilename = matchedFilename[..^2];
|
||||
matchedFilename = matchedFilename.Substring(0, matchedFilename.Length - 2);
|
||||
|
||||
vobKeys += $"{matchedFilename} Title Key: {match.Groups[2].Value}\n";
|
||||
}
|
||||
@@ -2876,14 +2854,14 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
{
|
||||
totalErrors ??= 0;
|
||||
|
||||
if (Int64.TryParse(line["Total errors: ".Length..].Trim(), out long te))
|
||||
if (Int64.TryParse(line.Substring("Total errors: ".Length).Trim(), out long te))
|
||||
totalErrors += te;
|
||||
}
|
||||
else if (line.StartsWith("Total warnings"))
|
||||
{
|
||||
totalErrors ??= 0;
|
||||
|
||||
if (Int64.TryParse(line["Total warnings: ".Length..].Trim(), out long tw))
|
||||
if (Int64.TryParse(line.Substring("Total warnings: ".Length).Trim(), out long tw))
|
||||
totalErrors += tw;
|
||||
}
|
||||
}
|
||||
@@ -2908,18 +2886,18 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
serial = null; version = null; date = null;
|
||||
|
||||
// If the input header is null, we can't do a thing
|
||||
if (string.IsNullOrWhiteSpace(segaHeader))
|
||||
if (string.IsNullOrEmpty(segaHeader))
|
||||
return false;
|
||||
|
||||
// Now read it in cutting it into lines for easier parsing
|
||||
try
|
||||
{
|
||||
string[] header = segaHeader.Split('\n');
|
||||
string versionLine = header[4][58..];
|
||||
string dateLine = header[5][58..];
|
||||
serial = versionLine[..10].TrimEnd();
|
||||
string[] header = segaHeader!.Split('\n');
|
||||
string versionLine = header[4].Substring(58);
|
||||
string dateLine = header[5].Substring(58);
|
||||
serial = versionLine.Substring(0, 10).TrimEnd();
|
||||
version = versionLine.Substring(10, 6).TrimStart('V', 'v');
|
||||
date = dateLine[..8];
|
||||
date = dateLine.Substring(0, 8);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
@@ -2956,17 +2934,17 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
if (string.IsNullOrEmpty(manufacturer) && line.StartsWith("VendorId"))
|
||||
{
|
||||
// VendorId: <manufacturer>
|
||||
manufacturer = line["VendorId: ".Length..];
|
||||
manufacturer = line.Substring("VendorId: ".Length);
|
||||
}
|
||||
else if (string.IsNullOrEmpty(model) && line.StartsWith("ProductId"))
|
||||
{
|
||||
// ProductId: <model>
|
||||
model = line["ProductId: ".Length..];
|
||||
model = line.Substring("ProductId: ".Length);
|
||||
}
|
||||
else if (string.IsNullOrEmpty(firmware) && line.StartsWith("ProductRevisionLevel"))
|
||||
{
|
||||
// ProductRevisionLevel: <firmware>
|
||||
firmware = line["ProductRevisionLevel: ".Length..];
|
||||
firmware = line.Substring("ProductRevisionLevel: ".Length);
|
||||
}
|
||||
|
||||
line = sr.ReadLine();
|
||||
@@ -3117,7 +3095,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
// TODO: Are there any examples of 3+ session discs?
|
||||
|
||||
// Read the first session lead-out
|
||||
var firstSessionLeadOutLengthString = line?["Lead-out length of 1st session: ".Length..];
|
||||
var firstSessionLeadOutLengthString = line?.Substring("Lead-out length of 1st session: ".Length);
|
||||
line = sr.ReadLine()?.Trim();
|
||||
if (line == null)
|
||||
return null;
|
||||
@@ -3126,12 +3104,12 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
string? secondSessionLeadInLengthString = null;
|
||||
while (line?.StartsWith("Lead-in length") == false)
|
||||
{
|
||||
secondSessionLeadInLengthString = line?["Lead-in length of 2nd session: ".Length..];
|
||||
secondSessionLeadInLengthString = line?.Substring("Lead-in length of 2nd session: ".Length);
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
|
||||
// Read the second session pregap
|
||||
var secondSessionPregapLengthString = line?["Pregap length of 1st track of 2nd session: ".Length..];
|
||||
var secondSessionPregapLengthString = line?.Substring("Pregap length of 1st track of 2nd session: ".Length);
|
||||
|
||||
// Calculate the session gap total
|
||||
if (!int.TryParse(firstSessionLeadOutLengthString, out int firstSessionLeadOutLength))
|
||||
@@ -3348,18 +3326,18 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
serial = null; version = null; date = null;
|
||||
|
||||
// If the input header is null, we can't do a thing
|
||||
if (string.IsNullOrWhiteSpace(segaHeader))
|
||||
if (string.IsNullOrEmpty(segaHeader))
|
||||
return false;
|
||||
|
||||
// Now read it in cutting it into lines for easier parsing
|
||||
try
|
||||
{
|
||||
string[] header = segaHeader.Split('\n');
|
||||
string serialVersionLine = header[2][58..];
|
||||
string dateLine = header[3][58..];
|
||||
serial = serialVersionLine[..10].Trim();
|
||||
string[] header = segaHeader!.Split('\n');
|
||||
string serialVersionLine = header[2].Substring(58);
|
||||
string dateLine = header[3].Substring(58);
|
||||
serial = serialVersionLine.Substring(0, 10).Trim();
|
||||
version = serialVersionLine.Substring(10, 6).TrimStart('V', 'v');
|
||||
date = dateLine[..8];
|
||||
date = dateLine.Substring(0, 8);
|
||||
date = $"{date[0]}{date[1]}{date[2]}{date[3]}-{date[4]}{date[5]}-{date[6]}{date[7]}";
|
||||
return true;
|
||||
}
|
||||
@@ -3381,23 +3359,23 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
serial = null; date = null;
|
||||
|
||||
// If the input header is null, we can't do a thing
|
||||
if (string.IsNullOrWhiteSpace(segaHeader))
|
||||
if (string.IsNullOrEmpty(segaHeader))
|
||||
return false;
|
||||
|
||||
// Now read it in cutting it into lines for easier parsing
|
||||
try
|
||||
{
|
||||
string[] header = segaHeader.Split('\n');
|
||||
string serialVersionLine = header[8][58..];
|
||||
string dateLine = header[1][58..];
|
||||
string[] header = segaHeader!.Split('\n');
|
||||
string serialVersionLine = header[8].Substring(58);
|
||||
string dateLine = header[1].Substring(58);
|
||||
serial = serialVersionLine.Substring(3, 8).TrimEnd('-', ' ');
|
||||
date = dateLine[8..].Trim();
|
||||
date = dateLine.Substring(8).Trim();
|
||||
|
||||
// Properly format the date string, if possible
|
||||
string[] dateSplit = date.Split('.');
|
||||
|
||||
if (dateSplit.Length == 1)
|
||||
dateSplit = new string[] { date[..4], date[4..] };
|
||||
dateSplit = [date.Substring(0, 4), date.Substring(4)];
|
||||
|
||||
string month = dateSplit[1];
|
||||
dateSplit[1] = month switch
|
||||
|
||||
@@ -11,13 +11,15 @@ namespace MPF.Core.Modules.Redumper
|
||||
public const string BluRay = "bd"; // Synonym for CD
|
||||
public const string SACD = "sacd"; // Synonym for CD
|
||||
public const string Dump = "dump";
|
||||
public const string Info = "info";
|
||||
public const string Protection = "protection";
|
||||
public const string Refine = "refine";
|
||||
public const string Split = "split";
|
||||
public const string Verify = "verify";
|
||||
public const string DVDKey = "dvdkey";
|
||||
public const string DVDIsoKey = "dvdisokey";
|
||||
public const string Protection = "protection";
|
||||
public const string Split = "split";
|
||||
public const string Hash = "hash";
|
||||
public const string Info = "info";
|
||||
public const string Skeleton = "skeleton";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -5,11 +5,9 @@ using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Utilities;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
#pragma warning disable IDE0051 // Remove unused private members
|
||||
|
||||
namespace MPF.Core.Modules.Redumper
|
||||
{
|
||||
/// <summary>
|
||||
@@ -255,7 +253,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive? drive, bool includeArtifacts)
|
||||
{
|
||||
// Ensure that required sections exist
|
||||
info = SubmissionInfoTool.EnsureAllSections(info);
|
||||
info = Builder.EnsureAllSections(info);
|
||||
|
||||
// Get the dumping program and version
|
||||
info.DumpingInfo!.DumpingProgram = $"{EnumConverter.LongName(this.InternalProgram)} {GetVersion($"{basePath}.log") ?? "Unknown Version"}";
|
||||
@@ -291,7 +289,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
// Attempt to get multisession data
|
||||
string cdMultiSessionInfo = GetMultisessionInformation($"{basePath}.log") ?? string.Empty;
|
||||
if (!string.IsNullOrWhiteSpace(cdMultiSessionInfo))
|
||||
if (!string.IsNullOrEmpty(cdMultiSessionInfo))
|
||||
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.Multisession] = cdMultiSessionInfo;
|
||||
|
||||
// Attempt to get the universal hash, if it's an audio disc
|
||||
@@ -419,7 +417,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
// Take only the first 16 lines for Saturn
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16).ToArray());
|
||||
|
||||
if (GetSaturnBuildInfo(info.Extras.Header, out var saturnSerial, out var saturnVersion, out var buildDate))
|
||||
{
|
||||
@@ -480,7 +478,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
info.Artifacts ??= new Dictionary<string, string>();
|
||||
info.Artifacts ??= [];
|
||||
|
||||
if (File.Exists($"{basePath}.cdtext"))
|
||||
info.Artifacts["cdtext"] = GetBase64(GetFullFile($"{basePath}.cdtext")) ?? string.Empty;
|
||||
@@ -525,7 +523,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
{
|
||||
var parameters = new List<string>();
|
||||
|
||||
ModeValues ??= new List<string> { CommandStrings.NONE };
|
||||
ModeValues ??= [CommandStrings.NONE];
|
||||
|
||||
// Modes
|
||||
parameters.AddRange(ModeValues);
|
||||
@@ -726,7 +724,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
// Skip
|
||||
if (this[FlagStrings.Skip] == true)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(SkipValue))
|
||||
if (!string.IsNullOrEmpty(SkipValue))
|
||||
parameters.Add($"{FlagStrings.Skip}={SkipValue}");
|
||||
}
|
||||
|
||||
@@ -743,7 +741,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
#endregion
|
||||
|
||||
return string.Join(" ", parameters);
|
||||
return string.Join(" ", [.. parameters]);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -752,8 +750,8 @@ namespace MPF.Core.Modules.Redumper
|
||||
{
|
||||
return new Dictionary<string, List<string>>()
|
||||
{
|
||||
[CommandStrings.NONE] = new List<string>
|
||||
{
|
||||
[CommandStrings.NONE] =
|
||||
[
|
||||
// General
|
||||
FlagStrings.HelpLong,
|
||||
FlagStrings.HelpShort,
|
||||
@@ -799,7 +797,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
FlagStrings.Skip,
|
||||
FlagStrings.DumpReadSize,
|
||||
FlagStrings.OverreadLeadout,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -844,6 +842,12 @@ namespace MPF.Core.Modules.Redumper
|
||||
case MediaType.DVD:
|
||||
if (File.Exists($"{basePath}.log"))
|
||||
logFiles.Add($"{basePath}.log");
|
||||
if (File.Exists($"{basePath}.manufacturer"))
|
||||
logFiles.Add($"{basePath}.manufacturer");
|
||||
if (File.Exists($"{basePath}.1.manufacturer"))
|
||||
logFiles.Add($"{basePath}.1.manufacturer");
|
||||
if (File.Exists($"{basePath}.2.manufacturer"))
|
||||
logFiles.Add($"{basePath}.2.manufacturer");
|
||||
if (File.Exists($"{basePath}.physical"))
|
||||
logFiles.Add($"{basePath}.physical");
|
||||
if (File.Exists($"{basePath}.1.physical"))
|
||||
@@ -888,7 +892,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
{
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
|
||||
flags = new Dictionary<string, bool?>();
|
||||
flags = [];
|
||||
|
||||
// General
|
||||
DriveValue = null;
|
||||
@@ -937,18 +941,18 @@ namespace MPF.Core.Modules.Redumper
|
||||
case MediaType.CDROM:
|
||||
ModeValues = this.System switch
|
||||
{
|
||||
RedumpSystem.SuperAudioCD => new List<string> { CommandStrings.SACD },
|
||||
_ => new List<string> { CommandStrings.CD },
|
||||
RedumpSystem.SuperAudioCD => [CommandStrings.SACD],
|
||||
_ => [CommandStrings.CD],
|
||||
};
|
||||
break;
|
||||
case MediaType.DVD:
|
||||
ModeValues = new List<string> { CommandStrings.DVD };
|
||||
ModeValues = [CommandStrings.DVD];
|
||||
break;
|
||||
case MediaType.HDDVD: // TODO: Keep in sync if another command string shows up
|
||||
ModeValues = new List<string> { CommandStrings.DVD };
|
||||
ModeValues = [CommandStrings.DVD];
|
||||
break;
|
||||
case MediaType.BluRay:
|
||||
ModeValues = new List<string> { CommandStrings.BluRay };
|
||||
ModeValues = [CommandStrings.BluRay];
|
||||
break;
|
||||
default:
|
||||
BaseCommand = null;
|
||||
@@ -978,17 +982,17 @@ namespace MPF.Core.Modules.Redumper
|
||||
}
|
||||
|
||||
// Set the output paths
|
||||
if (!string.IsNullOrWhiteSpace(filename))
|
||||
if (!string.IsNullOrEmpty(filename))
|
||||
{
|
||||
var imagePath = Path.GetDirectoryName(filename);
|
||||
if (!string.IsNullOrWhiteSpace(imagePath))
|
||||
if (!string.IsNullOrEmpty(imagePath))
|
||||
{
|
||||
this[FlagStrings.ImagePath] = true;
|
||||
ImagePathValue = $"\"{imagePath}\"";
|
||||
}
|
||||
|
||||
string imageName = Path.GetFileNameWithoutExtension(filename);
|
||||
if (!string.IsNullOrWhiteSpace(imageName))
|
||||
if (!string.IsNullOrEmpty(imageName))
|
||||
{
|
||||
this[FlagStrings.ImageName] = true;
|
||||
ImageNameValue = $"\"{imageName}\"";
|
||||
@@ -1005,19 +1009,19 @@ namespace MPF.Core.Modules.Redumper
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
|
||||
// The string has to be valid by itself first
|
||||
if (string.IsNullOrWhiteSpace(parameters))
|
||||
if (string.IsNullOrEmpty(parameters))
|
||||
return false;
|
||||
|
||||
// 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();
|
||||
parameters = parameters!.Trim();
|
||||
List<string> parts = Regex.Matches(parameters, @"([a-zA-Z\-]*=)?[\""].+?[\""]|[^ ]+", RegexOptions.Compiled)
|
||||
.Cast<Match>()
|
||||
.Select(m => m.Value)
|
||||
.ToList();
|
||||
|
||||
// Setup the modes
|
||||
ModeValues = new List<string>();
|
||||
ModeValues = [];
|
||||
|
||||
// All modes should be cached separately
|
||||
int index = 0;
|
||||
@@ -1034,13 +1038,15 @@ namespace MPF.Core.Modules.Redumper
|
||||
case CommandStrings.BluRay:
|
||||
case CommandStrings.SACD:
|
||||
case CommandStrings.Dump:
|
||||
case CommandStrings.Protection:
|
||||
case CommandStrings.Refine:
|
||||
case CommandStrings.Split:
|
||||
case CommandStrings.Verify:
|
||||
case CommandStrings.DVDKey:
|
||||
case CommandStrings.DVDIsoKey:
|
||||
case CommandStrings.Protection:
|
||||
case CommandStrings.Split:
|
||||
case CommandStrings.Hash:
|
||||
case CommandStrings.Info:
|
||||
case CommandStrings.Skeleton:
|
||||
ModeValues.Add(part);
|
||||
break;
|
||||
|
||||
@@ -1083,7 +1089,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
// Drive
|
||||
stringValue = ProcessStringParameter(parts, FlagStrings.Drive, ref i);
|
||||
if (!string.IsNullOrWhiteSpace(stringValue))
|
||||
if (!string.IsNullOrEmpty(stringValue))
|
||||
DriveValue = stringValue;
|
||||
|
||||
// Speed
|
||||
@@ -1098,13 +1104,13 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
// Image Path
|
||||
stringValue = ProcessStringParameter(parts, FlagStrings.ImagePath, ref i);
|
||||
if (!string.IsNullOrWhiteSpace(stringValue))
|
||||
ImagePathValue = $"\"{stringValue.Trim('"')}\"";
|
||||
if (!string.IsNullOrEmpty(stringValue))
|
||||
ImagePathValue = $"\"{stringValue!.Trim('"')}\"";
|
||||
|
||||
// Image Name
|
||||
stringValue = ProcessStringParameter(parts, FlagStrings.ImageName, ref i);
|
||||
if (!string.IsNullOrWhiteSpace(stringValue))
|
||||
ImageNameValue = $"\"{stringValue.Trim('"')}\"";
|
||||
if (!string.IsNullOrEmpty(stringValue))
|
||||
ImageNameValue = $"\"{stringValue!.Trim('"')}\"";
|
||||
|
||||
// Overwrite
|
||||
ProcessFlagParameter(parts, FlagStrings.Overwrite, ref i);
|
||||
@@ -1115,7 +1121,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
// Drive Type
|
||||
stringValue = ProcessStringParameter(parts, FlagStrings.DriveType, ref i);
|
||||
if (!string.IsNullOrWhiteSpace(stringValue))
|
||||
if (!string.IsNullOrEmpty(stringValue))
|
||||
DriveTypeValue = stringValue;
|
||||
|
||||
// Drive Read Offset
|
||||
@@ -1135,12 +1141,12 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
// Drive Read Method
|
||||
stringValue = ProcessStringParameter(parts, FlagStrings.DriveReadMethod, ref i);
|
||||
if (!string.IsNullOrWhiteSpace(stringValue))
|
||||
if (!string.IsNullOrEmpty(stringValue))
|
||||
DriveReadMethodValue = stringValue;
|
||||
|
||||
// Drive Sector Order
|
||||
stringValue = ProcessStringParameter(parts, FlagStrings.DriveSectorOrder, ref i);
|
||||
if (!string.IsNullOrWhiteSpace(stringValue))
|
||||
if (!string.IsNullOrEmpty(stringValue))
|
||||
DriveSectorOrderValue = stringValue;
|
||||
|
||||
#endregion
|
||||
@@ -1218,12 +1224,12 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
// Skip
|
||||
stringValue = ProcessStringParameter(parts, FlagStrings.Skip, ref i);
|
||||
if (!string.IsNullOrWhiteSpace(stringValue))
|
||||
if (!string.IsNullOrEmpty(stringValue))
|
||||
SkipValue = stringValue;
|
||||
|
||||
// Skip
|
||||
intValue = ProcessInt32Parameter(parts, FlagStrings.DumpReadSize, ref i);
|
||||
if (!string.IsNullOrWhiteSpace(stringValue))
|
||||
if (!string.IsNullOrEmpty(stringValue))
|
||||
DumpReadSizeValue = intValue;
|
||||
|
||||
// Overread Leadout
|
||||
@@ -1233,7 +1239,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
}
|
||||
|
||||
// If the image name was not set, set it with a default value
|
||||
if (string.IsNullOrWhiteSpace(this.ImageNameValue))
|
||||
if (string.IsNullOrEmpty(this.ImageNameValue))
|
||||
this.ImageNameValue = "track";
|
||||
|
||||
return true;
|
||||
@@ -1264,7 +1270,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
// Now that we're at the relevant entries, read each line in and concatenate
|
||||
string? cueString = string.Empty, line = sr.ReadLine()?.Trim();
|
||||
while (!string.IsNullOrWhiteSpace(line))
|
||||
while (!string.IsNullOrEmpty(line))
|
||||
{
|
||||
cueString += line + "\n";
|
||||
line = sr.ReadLine()?.Trim();
|
||||
@@ -1346,7 +1352,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
if (line.StartsWith("current profile:"))
|
||||
{
|
||||
// current profile: <discType>
|
||||
discTypeOrBookType = line["current profile: ".Length..];
|
||||
discTypeOrBookType = line.Substring("current profile: ".Length);
|
||||
}
|
||||
|
||||
line = sr.ReadLine();
|
||||
@@ -1388,24 +1394,24 @@ namespace MPF.Core.Modules.Redumper
|
||||
{
|
||||
if (line.StartsWith("protection system type"))
|
||||
{
|
||||
copyrightProtectionSystemType = line["protection system type: ".Length..];
|
||||
copyrightProtectionSystemType = line.Substring("protection system type: ".Length);
|
||||
if (copyrightProtectionSystemType == "none" || copyrightProtectionSystemType == "<none>")
|
||||
copyrightProtectionSystemType = "No";
|
||||
}
|
||||
else if (line.StartsWith("region management information:"))
|
||||
{
|
||||
region = line["region management information: ".Length..];
|
||||
region = line.Substring("region management information: ".Length);
|
||||
}
|
||||
else if (line.StartsWith("disc key"))
|
||||
{
|
||||
decryptedDiscKey = line["disc key: ".Length..].Replace(':', ' ');
|
||||
decryptedDiscKey = line.Substring("disc key: ".Length).Replace(':', ' ');
|
||||
}
|
||||
else if (line.StartsWith("title keys"))
|
||||
{
|
||||
vobKeys = string.Empty;
|
||||
|
||||
line = sr.ReadLine()?.Trim();
|
||||
while (!string.IsNullOrWhiteSpace(line))
|
||||
while (!string.IsNullOrEmpty(line))
|
||||
{
|
||||
var match = Regex.Match(line, @"^(.*?): (.*?)$", RegexOptions.Compiled);
|
||||
if (match.Success)
|
||||
@@ -1482,7 +1488,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
break;
|
||||
|
||||
// REDUMP.ORG errors: <error count>
|
||||
string[] parts = line.Split(' ');
|
||||
string[] parts = line!.Split(' ');
|
||||
if (long.TryParse(parts[2], out long redump))
|
||||
return redump;
|
||||
else
|
||||
@@ -1590,24 +1596,24 @@ namespace MPF.Core.Modules.Redumper
|
||||
else if (line.StartsWith("layer break:"))
|
||||
{
|
||||
// layer break: <layerbreak>
|
||||
layerbreak1 = line["layer break: ".Length..].Trim();
|
||||
layerbreak1 = line.Substring("layer break: ".Length).Trim();
|
||||
}
|
||||
|
||||
// Multi-layer discs have the layer in the name
|
||||
else if (line.StartsWith("layer break (layer: 0):"))
|
||||
{
|
||||
// layer break (layer: 0): <layerbreak>
|
||||
layerbreak1 = line["layer break (layer: 0): ".Length..].Trim();
|
||||
layerbreak1 = line.Substring("layer break (layer: 0): ".Length).Trim();
|
||||
}
|
||||
else if (line.StartsWith("layer break (layer: 1):"))
|
||||
{
|
||||
// layer break (layer: 1): <layerbreak>
|
||||
layerbreak2 = line["layer break (layer: 1): ".Length..].Trim();
|
||||
layerbreak2 = line.Substring("layer break (layer: 1): ".Length).Trim();
|
||||
}
|
||||
else if (line.StartsWith("layer break (layer: 2):"))
|
||||
{
|
||||
// layer break (layer: 2): <layerbreak>
|
||||
layerbreak3 = line["layer break (layer: 2): ".Length..].Trim();
|
||||
layerbreak3 = line.Substring("layer break (layer: 2): ".Length).Trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1652,11 +1658,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
// Store the first session range
|
||||
if (line.Contains("session 1:"))
|
||||
firstSession = line["session 1: ".Length..].Trim();
|
||||
firstSession = line.Substring("session 1: ".Length).Trim();
|
||||
|
||||
// Store the secomd session range
|
||||
else if (line.Contains("session 2:"))
|
||||
secondSession = line["session 2: ".Length..].Trim();
|
||||
secondSession = line.Substring("session 2: ".Length).Trim();
|
||||
}
|
||||
|
||||
// If either is blank, we don't have multisession
|
||||
@@ -1878,7 +1884,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
{
|
||||
string? line = sr.ReadLine()?.TrimStart();
|
||||
if (line?.StartsWith("non-zero data sample range") == true)
|
||||
return line["non-zero data sample range: [".Length..].Trim().Split(' ')[0];
|
||||
return line.Substring("non-zero data sample range: [".Length).Trim().Split(' ')[0];
|
||||
}
|
||||
|
||||
// We couldn't detect it then
|
||||
@@ -1902,18 +1908,18 @@ namespace MPF.Core.Modules.Redumper
|
||||
serial = null; version = null; date = null;
|
||||
|
||||
// If the input header is null, we can't do a thing
|
||||
if (string.IsNullOrWhiteSpace(segaHeader))
|
||||
if (string.IsNullOrEmpty(segaHeader))
|
||||
return false;
|
||||
|
||||
// Now read it in cutting it into lines for easier parsing
|
||||
try
|
||||
{
|
||||
string[] header = segaHeader.Split('\n');
|
||||
string serialVersionLine = header[2][58..];
|
||||
string dateLine = header[3][58..];
|
||||
serial = serialVersionLine[..10].Trim();
|
||||
string[] header = segaHeader!.Split('\n');
|
||||
string serialVersionLine = header[2].Substring(58);
|
||||
string dateLine = header[3].Substring(58);
|
||||
serial = serialVersionLine.Substring(0, 10).Trim();
|
||||
version = serialVersionLine.Substring(10, 6).TrimStart('V', 'v');
|
||||
date = dateLine[..8];
|
||||
date = dateLine.Substring(0, 8);
|
||||
date = $"{date[0]}{date[1]}{date[2]}{date[3]}-{date[4]}{date[5]}-{date[6]}{date[7]}";
|
||||
return true;
|
||||
}
|
||||
@@ -2006,7 +2012,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
lines.Add(line);
|
||||
}
|
||||
|
||||
return string.Join("\n", lines).TrimEnd('\n');
|
||||
return string.Join("\n", [.. lines]).TrimEnd('\n');
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -2046,19 +2052,19 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
if (line.StartsWith("build date:"))
|
||||
{
|
||||
buildDate = line["build date: ".Length..].Trim();
|
||||
buildDate = line.Substring("build date: ".Length).Trim();
|
||||
}
|
||||
else if (line.StartsWith("serial:"))
|
||||
{
|
||||
serial = line["serial: ".Length..].Trim();
|
||||
serial = line.Substring("serial: ".Length).Trim();
|
||||
}
|
||||
else if (line.StartsWith("region:"))
|
||||
{
|
||||
region = line["region: ".Length..].Trim();
|
||||
region = line.Substring("region: ".Length).Trim();
|
||||
}
|
||||
else if (line.StartsWith("regions:"))
|
||||
{
|
||||
region = line["regions: ".Length..].Trim();
|
||||
region = line.Substring("regions: ".Length).Trim();
|
||||
}
|
||||
else if (line.StartsWith("header:"))
|
||||
{
|
||||
@@ -2103,7 +2109,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
{
|
||||
string? line = sr.ReadLine()?.TrimStart();
|
||||
if (line?.StartsWith("Universal Hash") == true)
|
||||
return line["Universal Hash (SHA-1): ".Length..].Trim();
|
||||
return line.Substring("Universal Hash (SHA-1): ".Length).Trim();
|
||||
}
|
||||
|
||||
// We couldn't detect it then
|
||||
@@ -2135,7 +2141,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
{
|
||||
string? line = sr.ReadLine()?.TrimStart();
|
||||
if (line?.StartsWith("disc write offset") == true)
|
||||
return line["disc write offset: ".Length..].Trim();
|
||||
return line.Substring("disc write offset: ".Length).Trim();
|
||||
}
|
||||
|
||||
// We couldn't detect it then
|
||||
@@ -2178,7 +2184,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
// Extract the version string
|
||||
var match = regex.Match(sr.ReadLine()?.Trim() ?? string.Empty);
|
||||
var version = match.Groups[1].Value;
|
||||
return string.IsNullOrWhiteSpace(version) ? null : version;
|
||||
return string.IsNullOrEmpty(version) ? null : version;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Hashing;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core.Modules.UmdImageCreator
|
||||
@@ -65,7 +66,7 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive? drive, bool includeArtifacts)
|
||||
{
|
||||
// Ensure that required sections exist
|
||||
info = SubmissionInfoTool.EnsureAllSections(info);
|
||||
info = Builder.EnsureAllSections(info);
|
||||
|
||||
// TODO: Determine if there's a UMDImageCreator version anywhere
|
||||
info.DumpingInfo!.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
@@ -92,7 +93,7 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
info.VersionAndEditions!.Version = umdversion ?? string.Empty;
|
||||
info.SizeAndChecksums!.Size = umdsize;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(umdlayer))
|
||||
if (!string.IsNullOrEmpty(umdlayer))
|
||||
info.SizeAndChecksums.Layerbreak = Int64.Parse(umdlayer ?? "-1");
|
||||
}
|
||||
|
||||
@@ -102,7 +103,7 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
info.Artifacts ??= new Dictionary<string, string>();
|
||||
info.Artifacts ??= [];
|
||||
|
||||
if (File.Exists(basePath + "_disc.txt"))
|
||||
info.Artifacts["disc"] = GetBase64(GetFullFile(basePath + "_disc.txt")) ?? string.Empty;
|
||||
@@ -203,7 +204,7 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
break;
|
||||
|
||||
if (line.StartsWith("TITLE") && title == null)
|
||||
title = line["TITLE: ".Length..];
|
||||
title = line.Substring("TITLE: ".Length);
|
||||
else if (line.StartsWith("DISC_VERSION") && umdversion == null)
|
||||
umdversion = line.Split(' ')[1];
|
||||
else if (line.StartsWith("pspUmdTypes"))
|
||||
|
||||
@@ -4,8 +4,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using BinaryObjectScanner;
|
||||
using BinaryObjectScanner.Protection;
|
||||
using psxt001z;
|
||||
|
||||
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'.
|
||||
@@ -21,13 +19,14 @@ namespace MPF.Core
|
||||
/// <param name="options">Options object that determines what to scan</param>
|
||||
/// <param name="progress">Optional progress callback</param>
|
||||
/// <returns>Set of all detected copy protections with an optional error string</returns>
|
||||
public static async Task<(Dictionary<string, List<string>>?, string?)> RunProtectionScanOnPath(string path, Data.Options options, IProgress<ProtectionProgress>? progress = null)
|
||||
public static async Task<(Dictionary<string, List<string>>?, string?)> RunProtectionScanOnPath(string path, Data.Options options, IProgress<BinaryObjectScanner.ProtectionProgress>? progress = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var found = await Task.Run(() =>
|
||||
#if NET40
|
||||
var found = await Task.Factory.StartNew(() =>
|
||||
{
|
||||
var scanner = new Scanner(
|
||||
var scanner = new BinaryObjectScanner.Scanner(
|
||||
options.ScanArchivesForProtection,
|
||||
scanContents: true, // Hardcoded value to avoid issues
|
||||
scanGameEngines: false, // Hardcoded value to avoid issues
|
||||
@@ -38,14 +37,37 @@ namespace MPF.Core
|
||||
|
||||
return scanner.GetProtections(path);
|
||||
});
|
||||
#else
|
||||
var found = await Task.Run(() =>
|
||||
{
|
||||
var scanner = new BinaryObjectScanner.Scanner(
|
||||
options.ScanArchivesForProtection,
|
||||
scanContents: true, // Hardcoded value to avoid issues
|
||||
scanGameEngines: false, // Hardcoded value to avoid issues
|
||||
options.ScanPackersForProtection,
|
||||
scanPaths: true, // Hardcoded value to avoid issues
|
||||
options.IncludeDebugProtectionInformation,
|
||||
progress);
|
||||
|
||||
return scanner.GetProtections(path);
|
||||
});
|
||||
#endif
|
||||
|
||||
// If nothing was returned, return
|
||||
if (found == null || !found.Any())
|
||||
#if NET20 || NET35
|
||||
if (found == null || found.Count == 0)
|
||||
#else
|
||||
if (found == null || found.IsEmpty)
|
||||
#endif
|
||||
return (null, null);
|
||||
|
||||
// Filter out any empty protections
|
||||
var filteredProtections = found
|
||||
.Where(kvp => kvp.Value != null && kvp.Value.Any())
|
||||
#if NET20 || NET35
|
||||
.Where(kvp => kvp.Value != null && kvp.Value.Count > 0)
|
||||
#else
|
||||
.Where(kvp => kvp.Value != null && !kvp.Value.IsEmpty)
|
||||
#endif
|
||||
.ToDictionary(
|
||||
kvp => kvp.Key,
|
||||
kvp => kvp.Value.OrderBy(s => s).ToList());
|
||||
@@ -78,7 +100,7 @@ namespace MPF.Core
|
||||
|
||||
// Sanitize and join protections for writing
|
||||
string protectionString = SanitizeFoundProtections(orderedDistinctProtections);
|
||||
if (string.IsNullOrWhiteSpace(protectionString))
|
||||
if (string.IsNullOrEmpty(protectionString))
|
||||
return "None found [OMIT FROM SUBMISSION]";
|
||||
|
||||
return protectionString;
|
||||
@@ -95,18 +117,19 @@ namespace MPF.Core
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return false;
|
||||
|
||||
return await Task.Run(() =>
|
||||
#if NET40
|
||||
return await Task.Factory.StartNew(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var antiModchip = new PSXAntiModchip();
|
||||
var antiModchip = new BinaryObjectScanner.Protection.PSXAntiModchip();
|
||||
foreach (string file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] fileContent = File.ReadAllBytes(file);
|
||||
var protection = antiModchip.CheckContents(file, fileContent, false);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
return true;
|
||||
}
|
||||
catch { }
|
||||
@@ -116,6 +139,33 @@ namespace MPF.Core
|
||||
|
||||
return false;
|
||||
});
|
||||
#else
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var antiModchip = new BinaryObjectScanner.Protection.PSXAntiModchip();
|
||||
#if NET20 || NET35
|
||||
foreach (string file in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
|
||||
#else
|
||||
foreach (string file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories))
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] fileContent = File.ReadAllBytes(file);
|
||||
var protection = antiModchip.CheckContents(file, fileContent, false);
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
return true;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return false;
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -129,7 +179,7 @@ namespace MPF.Core
|
||||
if (!File.Exists(sub))
|
||||
return null;
|
||||
|
||||
return LibCrypt.CheckSubfile(sub);
|
||||
return LibCrypt.DetectLibCrypt([sub]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -142,9 +192,15 @@ namespace MPF.Core
|
||||
if (foundProtections.Any(p => p.StartsWith("[Exception opening file")))
|
||||
{
|
||||
foundProtections = foundProtections.Where(p => !p.StartsWith("[Exception opening file"));
|
||||
#if NET20 || NET35 || NET40 || NET452 || NET462
|
||||
var tempList = new List<string> { "Exception occurred while scanning [RESCAN NEEDED]" };
|
||||
tempList.AddRange(foundProtections);
|
||||
foundProtections = tempList.OrderBy(p => p);
|
||||
#else
|
||||
foundProtections = foundProtections
|
||||
.Prepend("Exception occurred while scanning [RESCAN NEEDED]")
|
||||
.OrderBy(p => p);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ActiveMARK
|
||||
@@ -225,7 +281,16 @@ namespace MPF.Core
|
||||
.Where(p => p != "Cactus Data Shield 300 (Confirm presence of other CDS-300 files)");
|
||||
|
||||
if (foundProtections.Any(p => !p.StartsWith("SafeDisc")))
|
||||
{
|
||||
#if NET20 || NET35 || NET40 || NET452 || NET462
|
||||
var tempList = new List<string>();
|
||||
tempList.AddRange(foundProtections);
|
||||
tempList.Add("Cactus Data Shield 300");
|
||||
foundProtections = tempList;
|
||||
#else
|
||||
foundProtections = foundProtections.Append("Cactus Data Shield 300");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// SafeDisc
|
||||
@@ -327,7 +392,7 @@ namespace MPF.Core
|
||||
if (foundProtections.Any(p => p == "XCP") && foundProtections.Any(p => p.StartsWith("XCP") && p.Length > "XCP".Length))
|
||||
foundProtections = foundProtections.Where(p => p != "XCP");
|
||||
|
||||
return string.Join(", ", foundProtections);
|
||||
return string.Join(", ", foundProtections.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||
using BinaryObjectScanner;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Modules;
|
||||
using MPF.Core.UI.ComboBoxItems;
|
||||
using MPF.Core.Utilities;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
@@ -495,14 +496,14 @@ namespace MPF.Core.UI.ViewModels
|
||||
_options = OptionsLoader.LoadFromConfig();
|
||||
|
||||
// Added to clear warnings, all are set externally
|
||||
_drives = new List<Drive>();
|
||||
_driveSpeeds = new List<int>();
|
||||
_internalPrograms = new List<Element<InternalProgram>>();
|
||||
_drives = [];
|
||||
_driveSpeeds = [];
|
||||
_internalPrograms = [];
|
||||
_outputPath = string.Empty;
|
||||
_parameters = string.Empty;
|
||||
_startStopButtonText = string.Empty;
|
||||
_status = string.Empty;
|
||||
_systems = new List<RedumpSystemComboBoxItem>();
|
||||
_systems = [];
|
||||
|
||||
OptionsMenuItemEnabled = true;
|
||||
SystemTypeComboBoxEnabled = true;
|
||||
@@ -517,9 +518,9 @@ namespace MPF.Core.UI.ViewModels
|
||||
EnableParametersCheckBoxEnabled = true;
|
||||
LogPanelExpanded = _options.OpenLogWindowAtStartup;
|
||||
|
||||
MediaTypes = new List<Element<MediaType>>();
|
||||
MediaTypes = [];
|
||||
Systems = RedumpSystemComboBoxItem.GenerateElements().ToList();
|
||||
InternalPrograms = new List<Element<InternalProgram>>();
|
||||
InternalPrograms = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -585,7 +586,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
|
||||
if (Drives.Count > 0)
|
||||
{
|
||||
VerboseLogLn($"Found {Drives.Count} drives: {string.Join(", ", Drives.Select(d => d.Name))}");
|
||||
VerboseLogLn($"Found {Drives.Count} drives: {string.Join(", ", Drives.Select(d => d.Name).ToArray())}");
|
||||
|
||||
// Check for the last selected drive, if possible
|
||||
int index = -1;
|
||||
@@ -764,7 +765,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
{
|
||||
SchemaVersion = 1,
|
||||
FullyMatchedID = 3,
|
||||
PartiallyMatchedIDs = new List<int> { 0, 1, 2, 3 },
|
||||
PartiallyMatchedIDs = [0, 1, 2, 3],
|
||||
Added = DateTime.UtcNow,
|
||||
LastModified = DateTime.UtcNow,
|
||||
|
||||
@@ -778,8 +779,8 @@ namespace MPF.Core.UI.ViewModels
|
||||
DiscTitle = "Install Disc",
|
||||
Category = DiscCategory.Games,
|
||||
Region = Region.World,
|
||||
Languages = new Language?[] { Language.English, Language.Spanish, Language.French },
|
||||
LanguageSelection = new LanguageSelection?[] { LanguageSelection.BiosSettings },
|
||||
Languages = [Language.English, Language.Spanish, Language.French],
|
||||
LanguageSelection = [LanguageSelection.BiosSettings],
|
||||
Serial = "Disc Serial",
|
||||
Layer0MasteringRing = "L0 Mastering Ring",
|
||||
Layer0MasteringSID = "L0 Mastering SID",
|
||||
@@ -817,7 +818,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
{
|
||||
Version = "Original",
|
||||
VersionDatfile = "Alt",
|
||||
CommonEditions = new string[] { "Taikenban" },
|
||||
CommonEditions = ["Taikenban"],
|
||||
OtherEditions = "Rerelease",
|
||||
},
|
||||
|
||||
@@ -855,7 +856,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
DumpersAndStatus = new DumpersAndStatusSection()
|
||||
{
|
||||
Status = DumpStatus.TwoOrMoreGreen,
|
||||
Dumpers = new string[] { "Dumper1", "Dumper2" },
|
||||
Dumpers = ["Dumper1", "Dumper2"],
|
||||
OtherDumpers = "Dumper3",
|
||||
},
|
||||
|
||||
@@ -863,7 +864,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
{
|
||||
ClrMameProData = "Datfile",
|
||||
Cuesheet = "Cuesheet",
|
||||
CommonWriteOffsets = new int[] { 0, 12, -12 },
|
||||
CommonWriteOffsets = [0, 12, -12],
|
||||
OtherWriteOffsets = "-2",
|
||||
},
|
||||
|
||||
@@ -1325,7 +1326,11 @@ namespace MPF.Core.UI.ViewModels
|
||||
directory = Path.GetDirectoryName(directory);
|
||||
|
||||
if (directory != null && label != null)
|
||||
#if NET20 || NET35
|
||||
this.OutputPath = Path.Combine(Path.Combine(directory, label), filename);
|
||||
#else
|
||||
this.OutputPath = Path.Combine(directory, label, filename);
|
||||
#endif
|
||||
else
|
||||
this.OutputPath = filename;
|
||||
}
|
||||
@@ -1348,7 +1353,11 @@ namespace MPF.Core.UI.ViewModels
|
||||
directory = Path.GetDirectoryName(directory);
|
||||
|
||||
if (directory != null && label != null)
|
||||
#if NET20 || NET35
|
||||
this.OutputPath = Path.Combine(Path.Combine(directory, label), filename);
|
||||
#else
|
||||
this.OutputPath = Path.Combine(directory, label, filename);
|
||||
#endif
|
||||
else
|
||||
this.OutputPath = filename;
|
||||
}
|
||||
@@ -1410,7 +1419,11 @@ namespace MPF.Core.UI.ViewModels
|
||||
/// <summary>
|
||||
/// Scan and show copy protection for the current disc
|
||||
/// </summary>
|
||||
#if NET40
|
||||
public (string?, string?) ScanAndShowProtection()
|
||||
#else
|
||||
public async Task<(string?, string?)> ScanAndShowProtection()
|
||||
#endif
|
||||
{
|
||||
// Determine current environment, just in case
|
||||
_environment ??= DetermineEnvironment();
|
||||
@@ -1430,7 +1443,13 @@ namespace MPF.Core.UI.ViewModels
|
||||
|
||||
var progress = new Progress<ProtectionProgress>();
|
||||
progress.ProgressChanged += ProgressUpdated;
|
||||
#if NET40
|
||||
var protectionTask = Protection.RunProtectionScanOnPath(this.CurrentDrive.Name, this.Options, progress);
|
||||
protectionTask.Wait();
|
||||
var (protections, error) = protectionTask.Result;
|
||||
#else
|
||||
var (protections, error) = await Protection.RunProtectionScanOnPath(this.CurrentDrive.Name, this.Options, progress);
|
||||
#endif
|
||||
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
|
||||
@@ -1494,7 +1513,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
{
|
||||
// Set the drive speed list that's appropriate
|
||||
this.DriveSpeeds = (List<int>)Interface.GetSpeedsForMediaType(CurrentMediaType);
|
||||
VerboseLogLn($"Supported media speeds: {string.Join(", ", this.DriveSpeeds)}");
|
||||
VerboseLogLn($"Supported media speeds: {string.Join(", ", this.DriveSpeeds.Select(ds => ds.ToString()).ToArray())}");
|
||||
|
||||
// Set the selected speed
|
||||
int speed = (CurrentMediaType) switch
|
||||
@@ -1592,7 +1611,11 @@ namespace MPF.Core.UI.ViewModels
|
||||
_environment.ReportStatus += ProgressUpdated;
|
||||
|
||||
// Run the program with the parameters
|
||||
#if NET40
|
||||
Result result = _environment.Run(resultProgress);
|
||||
#else
|
||||
Result result = await _environment.Run(resultProgress);
|
||||
#endif
|
||||
|
||||
// If we didn't execute a dumping command we cannot get submission output
|
||||
if (_environment.Parameters?.IsDumpingCommand() != true)
|
||||
@@ -1668,7 +1691,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
private bool ValidateBeforeDumping()
|
||||
{
|
||||
// Validate that we have an output path of any sort
|
||||
if (string.IsNullOrWhiteSpace(_environment?.OutputPath))
|
||||
if (string.IsNullOrEmpty(_environment?.OutputPath))
|
||||
{
|
||||
if (_displayUserMessage != null)
|
||||
_ = _displayUserMessage("Missing Path", "No output path was provided so dumping cannot continue.", 1, false);
|
||||
@@ -1677,10 +1700,10 @@ namespace MPF.Core.UI.ViewModels
|
||||
}
|
||||
|
||||
// Validate that the user explicitly wants an inactive drive to be considered for dumping
|
||||
if (_environment.Drive?.MarkedActive != true && _displayUserMessage != null)
|
||||
if (_environment?.Drive?.MarkedActive != true && _displayUserMessage != null)
|
||||
{
|
||||
string message = "The currently selected drive does not appear to contain a disc! "
|
||||
+ (!_environment.System.DetectedByWindows() ? $"This is normal for {_environment.System.LongName()} as the discs may not be readable on Windows. " : string.Empty)
|
||||
+ (!_environment!.System.DetectedByWindows() ? $"This is normal for {_environment.System.LongName()} as the discs may not be readable on Windows. " : string.Empty)
|
||||
+ "Do you want to continue?";
|
||||
|
||||
bool? mbresult = _displayUserMessage("No Disc Detected", message, 2, false);
|
||||
@@ -1692,11 +1715,11 @@ namespace MPF.Core.UI.ViewModels
|
||||
}
|
||||
|
||||
// Pre-split the output path
|
||||
var outputDirectory = Path.GetDirectoryName(_environment.OutputPath);
|
||||
var outputDirectory = Path.GetDirectoryName(_environment!.OutputPath);
|
||||
string outputFilename = Path.GetFileName(_environment.OutputPath);
|
||||
|
||||
// If a complete dump already exists
|
||||
(bool foundFiles, List<string> _) = InfoTool.FoundAllFiles(outputDirectory, outputFilename, _environment.Parameters, true);
|
||||
(bool foundFiles, List<string> _) = _environment.Parameters.FoundAllFiles(outputDirectory, outputFilename, true);
|
||||
if (foundFiles && _displayUserMessage != null)
|
||||
{
|
||||
bool? mbresult = _displayUserMessage("Overwrite?", "A complete dump already exists! Are you sure you want to overwrite?", 2, true);
|
||||
@@ -1710,7 +1733,7 @@ namespace MPF.Core.UI.ViewModels
|
||||
// Validate that at least some space exists
|
||||
// TODO: Tie this to the size of the disc, type of disc, etc.
|
||||
string fullPath;
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
fullPath = Path.GetFullPath(_environment.OutputPath);
|
||||
else
|
||||
fullPath = Path.GetFullPath(outputDirectory);
|
||||
@@ -1730,19 +1753,28 @@ namespace MPF.Core.UI.ViewModels
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Progress Reporting
|
||||
|
||||
/// <summary>
|
||||
/// Handler for Result ProgressChanged event
|
||||
/// </summary>
|
||||
#if NET20 || NET35 || NET40
|
||||
private void ProgressUpdated(object? sender, BaseParameters.StringEventArgs value)
|
||||
#else
|
||||
private void ProgressUpdated(object? sender, string value)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
value.Value ??= string.Empty;
|
||||
LogLn(value.Value);
|
||||
#else
|
||||
value ??= string.Empty;
|
||||
LogLn(value);
|
||||
#endif
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ using SabreTools.RedumpLib.Web;
|
||||
|
||||
namespace MPF.Core.UI.ViewModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public class OptionsViewModel : INotifyPropertyChanged
|
||||
{
|
||||
#region Fields
|
||||
@@ -56,7 +59,15 @@ namespace MPF.Core.UI.ViewModels
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// Constructor for pure view model
|
||||
/// </summary>
|
||||
public OptionsViewModel()
|
||||
{
|
||||
Options = new Options();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for in-code
|
||||
/// </summary>
|
||||
public OptionsViewModel(Options baseOptions)
|
||||
{
|
||||
@@ -81,9 +92,19 @@ namespace MPF.Core.UI.ViewModels
|
||||
/// <summary>
|
||||
/// Test Redump login credentials
|
||||
/// </summary>
|
||||
#if NET40
|
||||
public static Task<(bool?, string?)> TestRedumpLogin(string username, string password)
|
||||
#else
|
||||
public static async Task<(bool?, string?)> TestRedumpLogin(string username, string password)
|
||||
#endif
|
||||
{
|
||||
#if NET40
|
||||
return Task.Factory.StartNew(() => RedumpWebClient.ValidateCredentials(username, password));
|
||||
#elif NETFRAMEWORK
|
||||
return await Task.Run(() => RedumpWebClient.ValidateCredentials(username, password));
|
||||
#else
|
||||
return await RedumpHttpClient.ValidateCredentials(username, password);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -8,33 +8,6 @@ namespace MPF.Core.Utilities
|
||||
{
|
||||
public static class EnumExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Determine if a system is okay if it's not detected by Windows
|
||||
/// </summary>
|
||||
/// <param name="system">RedumpSystem value to check</param>
|
||||
/// <returns>True if Windows show see a disc when dumping, false otherwise</returns>
|
||||
public static bool DetectedByWindows(this RedumpSystem? system)
|
||||
{
|
||||
return system switch
|
||||
{
|
||||
RedumpSystem.AmericanLaserGames3DO
|
||||
or RedumpSystem.AppleMacintosh
|
||||
or RedumpSystem.Atari3DO
|
||||
or RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem
|
||||
or RedumpSystem.NewJatreCDi
|
||||
or RedumpSystem.NintendoGameCube
|
||||
or RedumpSystem.NintendoWii
|
||||
or RedumpSystem.NintendoWiiU
|
||||
or RedumpSystem.PhilipsCDi
|
||||
or RedumpSystem.PhilipsCDiDigitalVideo
|
||||
or RedumpSystem.Panasonic3DOInteractiveMultiplayer
|
||||
or RedumpSystem.PanasonicM2
|
||||
or RedumpSystem.PioneerLaserActive
|
||||
or RedumpSystem.SuperAudioCD => false,
|
||||
_ => true,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the media supports drive speeds
|
||||
/// </summary>
|
||||
@@ -55,69 +28,6 @@ namespace MPF.Core.Utilities
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a system has reversed ringcodes
|
||||
/// </summary>
|
||||
/// <param name="system">RedumpSystem value to check</param>
|
||||
/// <returns>True if the system has reversed ringcodes, false otherwise</returns>
|
||||
public static bool HasReversedRingcodes(this RedumpSystem? system)
|
||||
{
|
||||
return system switch
|
||||
{
|
||||
RedumpSystem.SonyPlayStation2
|
||||
or RedumpSystem.SonyPlayStation3
|
||||
or RedumpSystem.SonyPlayStation4
|
||||
or RedumpSystem.SonyPlayStation5
|
||||
or RedumpSystem.SonyPlayStationPortable => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a system is considered audio-only
|
||||
/// </summary>
|
||||
/// <param name="system">RedumpSystem value to check</param>
|
||||
/// <returns>True if the system is audio-only, false otherwise</returns>
|
||||
/// <remarks>
|
||||
/// Philips CD-i should NOT be in this list. It's being included until there's a
|
||||
/// reasonable distinction between CD-i and CD-i ready on the database side.
|
||||
/// </remarks>
|
||||
public static bool IsAudio(this RedumpSystem? system)
|
||||
{
|
||||
return system switch
|
||||
{
|
||||
RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem
|
||||
or RedumpSystem.AudioCD
|
||||
or RedumpSystem.DVDAudio
|
||||
or RedumpSystem.HasbroiONEducationalGamingSystem
|
||||
or RedumpSystem.HasbroVideoNow
|
||||
or RedumpSystem.HasbroVideoNowColor
|
||||
or RedumpSystem.HasbroVideoNowJr
|
||||
or RedumpSystem.HasbroVideoNowXP
|
||||
or RedumpSystem.PhilipsCDi
|
||||
or RedumpSystem.PlayStationGameSharkUpdates
|
||||
or RedumpSystem.SuperAudioCD => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a system is considered XGD
|
||||
/// </summary>
|
||||
/// <param name="system">RedumpSystem value to check</param>
|
||||
/// <returns>True if the system is XGD, false otherwise</returns>
|
||||
public static bool IsXGD(this RedumpSystem? system)
|
||||
{
|
||||
return system switch
|
||||
{
|
||||
RedumpSystem.MicrosoftXbox
|
||||
or RedumpSystem.MicrosoftXbox360
|
||||
or RedumpSystem.MicrosoftXboxOne
|
||||
or RedumpSystem.MicrosoftXboxSeriesXS => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all programs with their short usable names
|
||||
/// </summary>
|
||||
@@ -127,7 +37,7 @@ namespace MPF.Core.Utilities
|
||||
|
||||
foreach (var val in Enum.GetValues(typeof(InternalProgram)))
|
||||
{
|
||||
if (((InternalProgram)val) == InternalProgram.NONE)
|
||||
if (((InternalProgram)val!) == InternalProgram.NONE)
|
||||
continue;
|
||||
|
||||
programs.Add($"{((InternalProgram?)val).LongName()}");
|
||||
|
||||
@@ -14,7 +14,13 @@ namespace MPF.Core.Utilities
|
||||
/// <param name="reader">TextReader representing the input</param>
|
||||
/// <param name="baseClass">Invoking class, passed on to the event handler</param>
|
||||
/// <param name="handler">Event handler to be invoked to write to log</param>
|
||||
#if NET20 || NET35
|
||||
public static async Task OutputToLog(TextReader reader, object baseClass, EventHandler<Modules.BaseParameters.StringEventArgs>? handler)
|
||||
#elif NET40
|
||||
public static void OutputToLog(TextReader reader, object baseClass, EventHandler<Modules.BaseParameters.StringEventArgs>? handler)
|
||||
#else
|
||||
public static async Task OutputToLog(TextReader reader, object baseClass, EventHandler<string>? handler)
|
||||
#endif
|
||||
{
|
||||
// Initialize the required variables
|
||||
char[] buffer = new char[256];
|
||||
@@ -26,7 +32,15 @@ namespace MPF.Core.Utilities
|
||||
while (true)
|
||||
{
|
||||
// Try to read the next chunk of characters
|
||||
#if NET20 || NET35
|
||||
read = await Task.Run(() => reader.Read(buffer, 0, buffer.Length));
|
||||
#elif NET40
|
||||
var readTask = Task.Factory.StartNew(() => reader.Read(buffer, 0, buffer.Length));
|
||||
readTask.Wait();
|
||||
read = readTask.Result;
|
||||
#else
|
||||
read = await reader.ReadAsync(buffer, 0, buffer.Length);
|
||||
#endif
|
||||
if (read == 0)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
@@ -37,22 +51,38 @@ namespace MPF.Core.Utilities
|
||||
string line = new(buffer, 0, read);
|
||||
|
||||
// If we have no newline characters, store in the string builder
|
||||
#if NETFRAMEWORK
|
||||
if (!line.Contains("\r") && !line.Contains("\n"))
|
||||
#else
|
||||
if (!line.Contains('\r') && !line.Contains('\n'))
|
||||
#endif
|
||||
sb.Append(line);
|
||||
|
||||
// If we have a newline, append and log
|
||||
#if NETFRAMEWORK
|
||||
else if (line.Contains("\n") || line.Contains("\r\n"))
|
||||
#else
|
||||
else if (line.Contains('\n') || line.Contains("\r\n"))
|
||||
#endif
|
||||
ProcessNewLines(sb, line, baseClass, handler);
|
||||
|
||||
// If we have a carriage return only, append and log first and last instances
|
||||
#if NETFRAMEWORK
|
||||
else if (line.Contains("\r"))
|
||||
#else
|
||||
else if (line.Contains('\r'))
|
||||
#endif
|
||||
ProcessCarriageReturns(sb, line, baseClass, handler);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
finally
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
handler?.Invoke(baseClass, new Modules.BaseParameters.StringEventArgs { Value = sb.ToString() });
|
||||
#else
|
||||
handler?.Invoke(baseClass, sb.ToString());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,14 +93,22 @@ namespace MPF.Core.Utilities
|
||||
/// <param name="line">Current line to process</param>
|
||||
/// <param name="baseClass">Invoking class, passed on to the event handler</param>
|
||||
/// <param name="handler">Event handler to be invoked to write to log</param>
|
||||
#if NET20 || NET35 || NET40
|
||||
private static void ProcessNewLines(StringBuilder sb, string line, object baseClass, EventHandler<Modules.BaseParameters.StringEventArgs>? handler)
|
||||
#else
|
||||
private static void ProcessNewLines(StringBuilder sb, string line, object baseClass, EventHandler<string>? handler)
|
||||
#endif
|
||||
{
|
||||
line = line.Replace("\r\n", "\n");
|
||||
var split = line.Split('\n');
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
// If the chunk contains a carriage return, handle it like a separate line
|
||||
#if NETFRAMEWORK
|
||||
if (split[i].Contains("\r"))
|
||||
#else
|
||||
if (split[i].Contains('\r'))
|
||||
#endif
|
||||
{
|
||||
ProcessCarriageReturns(sb, split[i], baseClass, handler);
|
||||
continue;
|
||||
@@ -80,8 +118,13 @@ namespace MPF.Core.Utilities
|
||||
if (i == 0)
|
||||
{
|
||||
sb.Append(split[i]);
|
||||
#if NET20 || NET35 || NET40
|
||||
handler?.Invoke(baseClass, new Modules.BaseParameters.StringEventArgs { Value = sb.ToString() });
|
||||
sb = new();
|
||||
#else
|
||||
handler?.Invoke(baseClass, sb.ToString());
|
||||
sb.Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
// For the last item, just append so it's dealt with the next time
|
||||
@@ -93,7 +136,11 @@ namespace MPF.Core.Utilities
|
||||
// For everything else, directly write out
|
||||
else
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
handler?.Invoke(baseClass, new Modules.BaseParameters.StringEventArgs { Value = split[i] });
|
||||
#else
|
||||
handler?.Invoke(baseClass, split[i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,17 +152,26 @@ namespace MPF.Core.Utilities
|
||||
/// <param name="line">Current line to process</param>
|
||||
/// <param name="baseClass">Invoking class, passed on to the event handler</param>
|
||||
/// <param name="handler">Event handler to be invoked to write to log</param>
|
||||
#if NET20 || NET35 || NET40
|
||||
private static void ProcessCarriageReturns(StringBuilder sb, string line, object baseClass, EventHandler<Modules.BaseParameters.StringEventArgs>? handler)
|
||||
#else
|
||||
private static void ProcessCarriageReturns(StringBuilder sb, string line, object baseClass, EventHandler<string>? handler)
|
||||
#endif
|
||||
{
|
||||
var split = line.Split('\r');
|
||||
|
||||
// Append and log the first
|
||||
sb.Append(split[0]);
|
||||
#if NET20 || NET35 || NET40
|
||||
handler?.Invoke(baseClass, new Modules.BaseParameters.StringEventArgs { Value = sb.ToString() });
|
||||
sb = new();
|
||||
#else
|
||||
handler?.Invoke(baseClass, sb.ToString());
|
||||
sb.Clear();
|
||||
#endif
|
||||
|
||||
// Append the last
|
||||
sb.Clear();
|
||||
sb.Append($"\r{split[^1]}");
|
||||
sb.Append($"\r{split[split.Length - 1]}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.IO;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using Newtonsoft.Json;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core.Utilities
|
||||
@@ -177,12 +178,12 @@ namespace MPF.Core.Utilities
|
||||
else if (args[startIndex].StartsWith("-l=") || args[startIndex].StartsWith("--load-seed="))
|
||||
{
|
||||
string seedInfo = args[startIndex].Split('=')[1];
|
||||
info = SubmissionInfoTool.CreateFromFile(seedInfo);
|
||||
info = Builder.CreateFromFile(seedInfo);
|
||||
}
|
||||
else if (args[startIndex] == "-l" || args[startIndex] == "--load-seed")
|
||||
{
|
||||
string seedInfo = args[startIndex + 1];
|
||||
info = SubmissionInfoTool.CreateFromFile(seedInfo);
|
||||
info = Builder.CreateFromFile(seedInfo);
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
@@ -218,8 +219,8 @@ namespace MPF.Core.Utilities
|
||||
}
|
||||
|
||||
// Now deal with the complex options
|
||||
options.ScanForProtection = scan && !string.IsNullOrWhiteSpace(parsedPath);
|
||||
options.OutputSeparateProtectionFile = scan && protectFile && !string.IsNullOrWhiteSpace(parsedPath);
|
||||
options.ScanForProtection = scan && !string.IsNullOrEmpty(parsedPath);
|
||||
options.OutputSeparateProtectionFile = scan && protectFile && !string.IsNullOrEmpty(parsedPath);
|
||||
|
||||
return (options, info, parsedPath, startIndex);
|
||||
}
|
||||
@@ -247,7 +248,7 @@ namespace MPF.Core.Utilities
|
||||
return supportedArguments;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Configuration
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using MPF.Core.Data;
|
||||
using Newtonsoft.Json.Linq;
|
||||
@@ -189,7 +190,7 @@ namespace MPF.Core.Utilities
|
||||
|
||||
// Get the latest tag from GitHub
|
||||
var (tag, url) = GetRemoteVersionAndUrl();
|
||||
bool different = version != tag;
|
||||
bool different = version != tag && tag != null;
|
||||
|
||||
string message = $"Local version: {version}"
|
||||
+ $"{Environment.NewLine}Remote version: {tag}"
|
||||
@@ -230,13 +231,21 @@ namespace MPF.Core.Utilities
|
||||
/// </summary>
|
||||
private static (string? tag, string? url) GetRemoteVersionAndUrl()
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
// Not supported in .NET Frameworks 2.0, 3.5, or 4.0
|
||||
return (null, null);
|
||||
#else
|
||||
using var hc = new System.Net.Http.HttpClient();
|
||||
#if NET452
|
||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
|
||||
#endif
|
||||
|
||||
// TODO: Figure out a better way than having this hardcoded...
|
||||
string url = "https://api.github.com/repos/SabreTools/MPF/releases/latest";
|
||||
var message = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, url);
|
||||
message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0");
|
||||
var latestReleaseJsonString = hc.Send(message)?.Content?.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
var latestReleaseJsonString = hc.SendAsync(message)?.ConfigureAwait(false).GetAwaiter().GetResult()
|
||||
.Content?.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
if (latestReleaseJsonString == null)
|
||||
return (null, null);
|
||||
|
||||
@@ -248,6 +257,7 @@ namespace MPF.Core.Utilities
|
||||
var releaseUrl = latestReleaseJson["html_url"]?.ToString();
|
||||
|
||||
return (latestTag, releaseUrl);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -15,12 +15,12 @@ namespace MPF.Test.Core.Converters
|
||||
/// <summary>
|
||||
/// DiscType values that map to InternalDriveType
|
||||
/// </summary>
|
||||
private static readonly DriveType[] _mappableDriveTypes = new DriveType[]
|
||||
{
|
||||
private static readonly DriveType[] _mappableDriveTypes =
|
||||
[
|
||||
DriveType.CDRom,
|
||||
DriveType.Fixed,
|
||||
DriveType.Removable,
|
||||
};
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Check that every supported DriveType maps to an InternalDriveType
|
||||
@@ -49,9 +49,9 @@ namespace MPF.Test.Core.Converters
|
||||
foreach (DriveType driveType in Enum.GetValues(typeof(DriveType)))
|
||||
{
|
||||
if (_mappableDriveTypes.Contains(driveType))
|
||||
testData.Add(new object?[] { driveType, false });
|
||||
testData.Add([driveType, false]);
|
||||
else
|
||||
testData.Add(new object?[] { driveType, true });
|
||||
testData.Add([driveType, true]);
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -84,7 +84,7 @@ namespace MPF.Test.Core.Converters
|
||||
var testData = new List<object?[]>() { new object?[] { null } };
|
||||
foreach (InternalProgram? internalProgram in Enum.GetValues(typeof(InternalProgram)))
|
||||
{
|
||||
testData.Add(new object?[] { internalProgram });
|
||||
testData.Add([internalProgram]);
|
||||
}
|
||||
|
||||
return testData;
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace MPF.Test.Core.Utilities
|
||||
/// <summary>
|
||||
/// MediaType values that support drive speeds
|
||||
/// </summary>
|
||||
private static readonly MediaType?[] _supportDriveSpeeds = new MediaType?[]
|
||||
{
|
||||
private static readonly MediaType?[] _supportDriveSpeeds =
|
||||
[
|
||||
MediaType.CDROM,
|
||||
MediaType.DVD,
|
||||
MediaType.GDROM,
|
||||
@@ -21,13 +21,13 @@ namespace MPF.Test.Core.Utilities
|
||||
MediaType.BluRay,
|
||||
MediaType.NintendoGameCubeGameDisc,
|
||||
MediaType.NintendoWiiOpticalDisc,
|
||||
};
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// RedumpSystem values that are considered Audio
|
||||
/// </summary>
|
||||
private static readonly RedumpSystem?[] _audioSystems = new RedumpSystem?[]
|
||||
{
|
||||
private static readonly RedumpSystem?[] _audioSystems =
|
||||
[
|
||||
RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem,
|
||||
RedumpSystem.AudioCD,
|
||||
RedumpSystem.DVDAudio,
|
||||
@@ -39,40 +39,41 @@ namespace MPF.Test.Core.Utilities
|
||||
RedumpSystem.PlayStationGameSharkUpdates,
|
||||
RedumpSystem.PhilipsCDi,
|
||||
RedumpSystem.SuperAudioCD,
|
||||
};
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// RedumpSystem values that are considered markers
|
||||
/// </summary>
|
||||
private static readonly RedumpSystem?[] _markerSystems = new RedumpSystem?[]
|
||||
{
|
||||
private static readonly RedumpSystem?[] _markerSystems =
|
||||
[
|
||||
RedumpSystem.MarkerArcadeEnd,
|
||||
RedumpSystem.MarkerComputerEnd,
|
||||
RedumpSystem.MarkerDiscBasedConsoleEnd,
|
||||
RedumpSystem.MarkerOtherEnd,
|
||||
};
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// RedumpSystem values that are have reversed ringcodes
|
||||
/// </summary>
|
||||
private static readonly RedumpSystem?[] _reverseRingcodeSystems = new RedumpSystem?[]
|
||||
{
|
||||
private static readonly RedumpSystem?[] _reverseRingcodeSystems =
|
||||
[
|
||||
RedumpSystem.SonyPlayStation2,
|
||||
RedumpSystem.SonyPlayStation3,
|
||||
RedumpSystem.SonyPlayStation4,
|
||||
RedumpSystem.SonyPlayStation5,
|
||||
RedumpSystem.SonyPlayStationPortable,
|
||||
};
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// RedumpSystem values that are considered XGD
|
||||
/// </summary>
|
||||
private static readonly RedumpSystem?[] _xgdSystems = new RedumpSystem?[]
|
||||
{
|
||||
private static readonly RedumpSystem?[] _xgdSystems =
|
||||
[
|
||||
RedumpSystem.MicrosoftXbox,
|
||||
RedumpSystem.MicrosoftXbox360,
|
||||
RedumpSystem.MicrosoftXboxOne,
|
||||
RedumpSystem.MicrosoftXboxSeriesXS,
|
||||
};
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Check that all optical media support drive speeds
|
||||
@@ -149,9 +150,9 @@ namespace MPF.Test.Core.Utilities
|
||||
foreach (MediaType mediaType in Enum.GetValues(typeof(MediaType)))
|
||||
{
|
||||
if (_supportDriveSpeeds.Contains(mediaType))
|
||||
testData.Add(new object?[] { mediaType, true });
|
||||
testData.Add([mediaType, true]);
|
||||
else
|
||||
testData.Add(new object?[] { mediaType, false });
|
||||
testData.Add([mediaType, false]);
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -167,9 +168,9 @@ namespace MPF.Test.Core.Utilities
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
if (_audioSystems.Contains(redumpSystem))
|
||||
testData.Add(new object?[] { redumpSystem, true });
|
||||
testData.Add([redumpSystem, true]);
|
||||
else
|
||||
testData.Add(new object?[] { redumpSystem, false });
|
||||
testData.Add([redumpSystem, false]);
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -185,9 +186,9 @@ namespace MPF.Test.Core.Utilities
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
if (_markerSystems.Contains(redumpSystem))
|
||||
testData.Add(new object?[] { redumpSystem, true });
|
||||
testData.Add([redumpSystem, true]);
|
||||
else
|
||||
testData.Add(new object?[] { redumpSystem, false });
|
||||
testData.Add([redumpSystem, false]);
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -203,9 +204,9 @@ namespace MPF.Test.Core.Utilities
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
if (_reverseRingcodeSystems.Contains(redumpSystem))
|
||||
testData.Add(new object?[] { redumpSystem, true });
|
||||
testData.Add([redumpSystem, true]);
|
||||
else
|
||||
testData.Add(new object?[] { redumpSystem, false });
|
||||
testData.Add([redumpSystem, false]);
|
||||
}
|
||||
|
||||
return testData;
|
||||
@@ -221,9 +222,9 @@ namespace MPF.Test.Core.Utilities
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
if (_xgdSystems.Contains(redumpSystem))
|
||||
testData.Add(new object?[] { redumpSystem, true });
|
||||
testData.Add([redumpSystem, true]);
|
||||
else
|
||||
testData.Add(new object?[] { redumpSystem, false });
|
||||
testData.Add([redumpSystem, false]);
|
||||
}
|
||||
|
||||
return testData;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MPF.Core;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
@@ -8,47 +9,6 @@ namespace MPF.Test.Library
|
||||
{
|
||||
public class InfoToolTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null, 0, 0, 0, 0, null)]
|
||||
[InlineData(null, 12345, 0, 0, 0, null)]
|
||||
[InlineData(null, 12345, 1, 0, 0, null)]
|
||||
[InlineData(null, 12345, 1, 2, 0, null)]
|
||||
[InlineData(null, 12345, 1, 2, 3, null)]
|
||||
[InlineData(MediaType.CDROM, 0, 0, 0, 0, "CD-ROM")]
|
||||
[InlineData(MediaType.CDROM, 12345, 0, 0, 0, "CD-ROM")]
|
||||
[InlineData(MediaType.CDROM, 12345, 1, 0, 0, "CD-ROM")]
|
||||
[InlineData(MediaType.CDROM, 12345, 1, 2, 0, "CD-ROM")]
|
||||
[InlineData(MediaType.CDROM, 12345, 1, 2, 3, "CD-ROM")]
|
||||
[InlineData(MediaType.DVD, 0, 0, 0, 0, "DVD-ROM-5")]
|
||||
[InlineData(MediaType.DVD, 12345, 0, 0, 0, "DVD-ROM-5")]
|
||||
[InlineData(MediaType.DVD, 12345, 1, 0, 0, "DVD-ROM-9")]
|
||||
[InlineData(MediaType.DVD, 12345, 1, 2, 0, "DVD-ROM-9")]
|
||||
[InlineData(MediaType.DVD, 12345, 1, 2, 3, "DVD-ROM-9")]
|
||||
[InlineData(MediaType.BluRay, 0, 0, 0, 0, "BD-ROM-25")]
|
||||
[InlineData(MediaType.BluRay, 12345, 0, 0, 0, "BD-ROM-25")]
|
||||
[InlineData(MediaType.BluRay, 26_843_531_857, 0, 0, 0, "BD-ROM-33")]
|
||||
[InlineData(MediaType.BluRay, 12345, 1, 0, 0, "BD-ROM-50")]
|
||||
[InlineData(MediaType.BluRay, 53_687_063_713, 1, 0, 0, "BD-ROM-66")]
|
||||
[InlineData(MediaType.BluRay, 12345, 1, 2, 0, "BD-ROM-100")]
|
||||
[InlineData(MediaType.BluRay, 12345, 1, 2, 3, "BD-ROM-128")]
|
||||
[InlineData(MediaType.UMD, 0, 0, 0, 0, "UMD-SL")]
|
||||
[InlineData(MediaType.UMD, 12345, 0, 0, 0, "UMD-SL")]
|
||||
[InlineData(MediaType.UMD, 12345, 1, 0, 0, "UMD-DL")]
|
||||
[InlineData(MediaType.UMD, 12345, 1, 2, 0, "UMD-DL")]
|
||||
[InlineData(MediaType.UMD, 12345, 1, 2, 3, "UMD-DL")]
|
||||
public void GetFixedMediaTypeTest(
|
||||
MediaType? mediaType,
|
||||
long size,
|
||||
long layerbreak,
|
||||
long layerbreak2,
|
||||
long layerbreak3,
|
||||
string? expected)
|
||||
{
|
||||
// TODO: Add tests around BDU
|
||||
var actual = InfoTool.GetFixedMediaType(mediaType, null, size, layerbreak, layerbreak2, layerbreak3);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "")]
|
||||
[InlineData(" ", "")]
|
||||
@@ -60,7 +20,7 @@ namespace MPF.Test.Library
|
||||
[InlineData("superhero\\blah&foo.bin", "superhero\\blah&foo.bin")]
|
||||
public void NormalizeOutputPathsTest(string? outputPath, string? expectedPath)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(expectedPath))
|
||||
if (!string.IsNullOrEmpty(expectedPath))
|
||||
expectedPath = Path.GetFullPath(expectedPath);
|
||||
|
||||
string actualPath = InfoTool.NormalizeOutputPaths(outputPath, true);
|
||||
@@ -90,7 +50,7 @@ namespace MPF.Test.Library
|
||||
};
|
||||
|
||||
// Process the special fields
|
||||
InfoTool.ProcessSpecialFields(info);
|
||||
Formatter.ProcessSpecialFields(info);
|
||||
|
||||
// Validate the basics
|
||||
Assert.NotNull(info.CommonDiscInfo.Comments);
|
||||
@@ -117,7 +77,7 @@ namespace MPF.Test.Library
|
||||
};
|
||||
|
||||
// Process the special fields
|
||||
InfoTool.ProcessSpecialFields(info);
|
||||
Formatter.ProcessSpecialFields(info);
|
||||
|
||||
// Validate
|
||||
Assert.Null(info.CommonDiscInfo);
|
||||
@@ -146,7 +106,7 @@ namespace MPF.Test.Library
|
||||
};
|
||||
|
||||
// Process the special fields
|
||||
InfoTool.ProcessSpecialFields(info);
|
||||
Formatter.ProcessSpecialFields(info);
|
||||
|
||||
// Validate the basics
|
||||
Assert.NotNull(info.CommonDiscInfo.Comments);
|
||||
@@ -180,7 +140,7 @@ namespace MPF.Test.Library
|
||||
};
|
||||
|
||||
// Process the special fields
|
||||
InfoTool.ProcessSpecialFields(info);
|
||||
Formatter.ProcessSpecialFields(info);
|
||||
|
||||
// Validate the basics
|
||||
Assert.NotNull(info.CommonDiscInfo.Comments);
|
||||
|
||||
@@ -11,11 +11,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsActiveMARKTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"ActiveMARK",
|
||||
"ActiveMARK 5",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("ActiveMARK 5", sanitized);
|
||||
@@ -24,11 +24,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsCactusDataShieldTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Cactus Data Shield 200",
|
||||
"Cactus Data Shield 200 (Build 3.0.100a)",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Cactus Data Shield 200 (Build 3.0.100a)", sanitized);
|
||||
@@ -37,11 +37,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsCDCheckTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Anything Else Protection",
|
||||
"Executable-Based CD Check",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Anything Else Protection", sanitized);
|
||||
@@ -50,11 +50,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsCDCopsTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"CD-Cops",
|
||||
"CD-Cops v1.2.0",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("CD-Cops v1.2.0", sanitized);
|
||||
@@ -63,11 +63,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsCDKeyTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Anything Else Protection",
|
||||
"CD-Key / Serial",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Anything Else Protection", sanitized);
|
||||
@@ -76,11 +76,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsEACdKeyTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"EA CdKey Registration Module",
|
||||
"EA CdKey Registration Module v1.2.0",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("EA CdKey Registration Module v1.2.0", sanitized);
|
||||
@@ -89,11 +89,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsEADRMTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"EA DRM Protection",
|
||||
"EA DRM Protection v1.2.0",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("EA DRM Protection v1.2.0", sanitized);
|
||||
@@ -102,11 +102,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsGFWLTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Games for Windows LIVE",
|
||||
"Games for Windows LIVE v1.2.0",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Games for Windows LIVE v1.2.0", sanitized);
|
||||
@@ -115,11 +115,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsGFWLZDPPTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Games for Windows LIVE",
|
||||
"Games for Windows LIVE Zero Day Piracy Protection",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Games for Windows LIVE, Games for Windows LIVE Zero Day Piracy Protection", sanitized);
|
||||
@@ -128,11 +128,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsImpulseReactorTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Impulse Reactor",
|
||||
"Impulse Reactor Core Module v1.2.0",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Impulse Reactor Core Module v1.2.0", sanitized);
|
||||
@@ -145,14 +145,14 @@ namespace MPF.Test.Library
|
||||
[InlineData(3)]
|
||||
public void SanitizeFoundProtectionsJoWoodXProtTest(int skip)
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"JoWood X-Prot 1.2.0.00",
|
||||
"JoWood X-Prot v2",
|
||||
"JoWood X-Prot v1.4+",
|
||||
"JoWood X-Prot v1.0-v1.3",
|
||||
"JoWood X-Prot",
|
||||
};
|
||||
];
|
||||
|
||||
// Safeguard for the future
|
||||
if (skip >= protections.Count)
|
||||
@@ -168,11 +168,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsOnlineRegistrationTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Anything Else Protection",
|
||||
"Executable-Based Online Registration",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Anything Else Protection", sanitized);
|
||||
@@ -185,14 +185,14 @@ namespace MPF.Test.Library
|
||||
[InlineData(3)]
|
||||
public void SanitizeFoundProtectionStarForceTest(int skip)
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"StarForce 1.20.000.000",
|
||||
"StarForce 5 [Protected Module]",
|
||||
"StarForce 5",
|
||||
"StarForce 3-5",
|
||||
"StarForce",
|
||||
};
|
||||
];
|
||||
|
||||
// Safeguard for the future
|
||||
if (skip >= protections.Count)
|
||||
@@ -208,11 +208,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsSysiphusTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Sysiphus",
|
||||
"Sysiphus v1.2.0",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Sysiphus v1.2.0", sanitized);
|
||||
@@ -221,11 +221,11 @@ namespace MPF.Test.Library
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectionsXCPTest()
|
||||
{
|
||||
List<string> protections = new()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"XCP",
|
||||
"XCP v1.2.0",
|
||||
};
|
||||
];
|
||||
|
||||
string sanitized = Protection.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("XCP v1.2.0", sanitized);
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0-windows;net8.0-windows</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -14,19 +17,19 @@
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.9.0-preview-23531-01" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0-preview-23531-01" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.2.0" />
|
||||
<PackageReference Include="xunit" Version="2.6.1" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.3.1" />
|
||||
<PackageReference Include="xunit" Version="2.6.2" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.5.0" />
|
||||
<PackageReference Include="xunit.assert" Version="2.6.1" />
|
||||
<PackageReference Include="xunit.core" Version="2.6.1" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.6.1" />
|
||||
<PackageReference Include="xunit.extensibility.execution" Version="2.6.1" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.6.1">
|
||||
<PackageReference Include="xunit.analyzers" Version="1.6.0" />
|
||||
<PackageReference Include="xunit.assert" Version="2.6.2" />
|
||||
<PackageReference Include="xunit.core" Version="2.6.2" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.6.2" />
|
||||
<PackageReference Include="xunit.extensibility.execution" Version="2.6.2" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.6.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -269,7 +269,7 @@ namespace MPF.Test.RedumpLib
|
||||
foreach (Language? language in fullLanguages)
|
||||
{
|
||||
var code = language.TwoLetterCode();
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
if (string.IsNullOrEmpty(code))
|
||||
continue;
|
||||
|
||||
// Throw if the code already exists
|
||||
@@ -296,7 +296,7 @@ namespace MPF.Test.RedumpLib
|
||||
foreach (Language? language in fullLanguages)
|
||||
{
|
||||
var code = language.ThreeLetterCode();
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
if (string.IsNullOrEmpty(code))
|
||||
continue;
|
||||
|
||||
// Throw if the code already exists
|
||||
@@ -323,7 +323,7 @@ namespace MPF.Test.RedumpLib
|
||||
foreach (Language? language in fullLanguages)
|
||||
{
|
||||
var code = language.ThreeLetterCodeAlt();
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
if (string.IsNullOrEmpty(code))
|
||||
continue;
|
||||
|
||||
// Throw if the code already exists
|
||||
@@ -492,7 +492,7 @@ namespace MPF.Test.RedumpLib
|
||||
foreach (Region? region in fullRegions)
|
||||
{
|
||||
var code = region.ShortName();
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
if (string.IsNullOrEmpty(code))
|
||||
continue;
|
||||
|
||||
// Throw if the code already exists
|
||||
|
||||
@@ -16,7 +16,12 @@ namespace MPF.UI.Core
|
||||
public static DoubleCollection SpeedsForDVDAsCollection { get; } = GetDoubleCollectionFromIntList(DVD);
|
||||
public static DoubleCollection SpeedsForHDDVDAsCollection { get; } = GetDoubleCollectionFromIntList(HDDVD);
|
||||
public static DoubleCollection SpeedsForBDAsCollection { get; } = GetDoubleCollectionFromIntList(BD);
|
||||
|
||||
#if NET20 || NET35 || NET40
|
||||
private static DoubleCollection GetDoubleCollectionFromIntList(IList<int> list)
|
||||
#else
|
||||
private static DoubleCollection GetDoubleCollectionFromIntList(IReadOnlyList<int> list)
|
||||
#endif
|
||||
=> new(list.Select(i => Convert.ToDouble(i)).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,9 @@
|
||||
WindowStartupLocation="CenterScreen"
|
||||
WindowStyle="None"
|
||||
ResizeMode="NoResize" SizeToContent="WidthAndHeight"
|
||||
TextOptions.TextFormattingMode="Display" TextOptions.TextRenderingMode="ClearType" UseLayoutRounding="True"
|
||||
Title="" MinHeight="155" MaxWidth="470" MinWidth="154"
|
||||
BorderBrush="DarkGray" BorderThickness="2">
|
||||
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome CaptionHeight="0" ResizeBorderThickness="0" />
|
||||
</WindowChrome.WindowChrome>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
|
||||
@@ -88,6 +88,21 @@ namespace WPFCustomMessageBox
|
||||
|
||||
internal CustomMessageBoxWindow(Window? owner, string? message, string? caption = null, MessageBoxButton? button = null, MessageBoxImage? image = null, bool removeTitleBarIcon = true)
|
||||
{
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
System.Windows.Media.TextOptions.SetTextFormattingMode(this, System.Windows.Media.TextFormattingMode.Display);
|
||||
System.Windows.Media.TextOptions.SetTextRenderingMode(this, System.Windows.Media.TextRenderingMode.ClearType);
|
||||
UseLayoutRounding = true;
|
||||
#endif
|
||||
|
||||
#if NET452_OR_GREATER || NETCOREAPP
|
||||
var chrome = new System.Windows.Shell.WindowChrome
|
||||
{
|
||||
CaptionHeight = 0,
|
||||
ResizeBorderThickness = new Thickness(0),
|
||||
};
|
||||
System.Windows.Shell.WindowChrome.SetWindowChrome(this, chrome);
|
||||
#endif
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
_removeTitleBarIcon = removeTitleBarIcon;
|
||||
|
||||
@@ -1,14 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0-windows;net8.0-windows</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net40;net452;net462;net472;net48;netcoreapp3.1;net5.0-windows;net6.0-windows;net7.0-windows;net8.0-windows</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.0.1</VersionPrefix>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<UseWPF>true</UseWPF>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2023</Copyright>
|
||||
<VersionPrefix>3.0.0</VersionPrefix>
|
||||
<Description>Common code for all MPF UI implementations</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2019-2023</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -21,7 +32,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.2.0" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -15,10 +15,7 @@
|
||||
<Window.Resources>
|
||||
<core:ElementConverter x:Key="ElementConverter" />
|
||||
</Window.Resources>
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome CaptionHeight="0" ResizeBorderThickness="0" />
|
||||
</WindowChrome.WindowChrome>
|
||||
|
||||
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical" Width="500" MaxHeight="650">
|
||||
<Grid Margin="0,10,0,0">
|
||||
|
||||
@@ -23,6 +23,16 @@ namespace MPF.UI.Core.Windows
|
||||
public DiscInformationWindow(Options options, SubmissionInfo? submissionInfo)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
#if NET452_OR_GREATER || NETCOREAPP
|
||||
var chrome = new System.Windows.Shell.WindowChrome
|
||||
{
|
||||
CaptionHeight = 0,
|
||||
ResizeBorderThickness = new Thickness(0),
|
||||
};
|
||||
System.Windows.Shell.WindowChrome.SetWindowChrome(this, chrome);
|
||||
#endif
|
||||
|
||||
DataContext = new DiscInformationViewModel(options, submissionInfo);
|
||||
DiscInformationViewModel.Load();
|
||||
|
||||
@@ -126,7 +136,7 @@ namespace MPF.UI.Core.Windows
|
||||
if (submissionInfo.PartiallyMatchedIDs == null)
|
||||
PartiallyMatchedIDs.Visibility = Visibility.Collapsed;
|
||||
else
|
||||
PartiallyMatchedIDs.Text = string.Join(", ", submissionInfo.PartiallyMatchedIDs);
|
||||
PartiallyMatchedIDs.Text = string.Join(", ", submissionInfo.PartiallyMatchedIDs.Select(i => i.ToString()).ToArray());
|
||||
if (submissionInfo.CopyProtection?.AntiModchip == null)
|
||||
AntiModchip.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo.TracksAndWriteOffsets?.OtherWriteOffsets == null)
|
||||
@@ -135,13 +145,13 @@ namespace MPF.UI.Core.Windows
|
||||
DMIHash.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo.EDC?.EDC == null)
|
||||
EDC.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.CommonDiscInfo?.ErrorsCount))
|
||||
if (string.IsNullOrEmpty(submissionInfo.CommonDiscInfo?.ErrorsCount))
|
||||
ErrorsCount.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.CommonDiscInfo?.EXEDateBuildDate))
|
||||
if (string.IsNullOrEmpty(submissionInfo.CommonDiscInfo?.EXEDateBuildDate))
|
||||
EXEDateBuildDate.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.Filename) != true)
|
||||
Filename.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.Header))
|
||||
if (string.IsNullOrEmpty(submissionInfo.Extras?.Header))
|
||||
Header.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.InternalName) != true)
|
||||
InternalName.Visibility = Visibility.Collapsed;
|
||||
@@ -151,21 +161,21 @@ namespace MPF.UI.Core.Windows
|
||||
Multisession.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo.CopyProtection?.LibCrypt == null)
|
||||
LibCrypt.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.CopyProtection?.LibCryptData))
|
||||
if (string.IsNullOrEmpty(submissionInfo.CopyProtection?.LibCryptData))
|
||||
LibCryptData.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.PFIHash) != true)
|
||||
PFIHash.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.PIC))
|
||||
if (string.IsNullOrEmpty(submissionInfo.Extras?.PIC))
|
||||
PIC.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.PVD))
|
||||
if (string.IsNullOrEmpty(submissionInfo.Extras?.PVD))
|
||||
PVD.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.RingNonZeroDataStart) != true)
|
||||
RingNonZeroDataStart.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.CopyProtection?.SecuROMData))
|
||||
if (string.IsNullOrEmpty(submissionInfo.CopyProtection?.SecuROMData))
|
||||
SecuROMData.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.SSHash) != true)
|
||||
SSHash.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrWhiteSpace(submissionInfo.Extras?.SecuritySectorRanges))
|
||||
if (string.IsNullOrEmpty(submissionInfo.Extras?.SecuritySectorRanges))
|
||||
SecuritySectorRanges.Visibility = Visibility.Collapsed;
|
||||
if (submissionInfo.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.SSVersion) != true)
|
||||
SSVersion.Visibility = Visibility.Collapsed;
|
||||
@@ -341,7 +351,7 @@ namespace MPF.UI.Core.Windows
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
<Window.Resources>
|
||||
<core:ElementConverter x:Key="ElementConverter" />
|
||||
</Window.Resources>
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome CaptionHeight="0" ResizeBorderThickness="0" />
|
||||
</WindowChrome.WindowChrome>
|
||||
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical">
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using MPF.Core;
|
||||
using MPF.Core.UI.ViewModels;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using WPFCustomMessageBox;
|
||||
using WinForms = System.Windows.Forms;
|
||||
@@ -20,7 +21,19 @@ namespace MPF.UI.Core.Windows
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public MainWindow() => InitializeComponent();
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
#if NET452_OR_GREATER || NETCOREAPP
|
||||
var chrome = new System.Windows.Shell.WindowChrome
|
||||
{
|
||||
CaptionHeight = 0,
|
||||
ResizeBorderThickness = new Thickness(0),
|
||||
};
|
||||
System.Windows.Shell.WindowChrome.SetWindowChrome(this, chrome);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MainWindow OnContentRendered event
|
||||
@@ -99,12 +112,12 @@ namespace MPF.UI.Core.Windows
|
||||
{
|
||||
// Get the current path, if possible
|
||||
string currentPath = MainViewModel.OutputPath;
|
||||
if (string.IsNullOrWhiteSpace(currentPath) && !string.IsNullOrWhiteSpace(MainViewModel.Options.DefaultOutputPath))
|
||||
if (string.IsNullOrEmpty(currentPath) && !string.IsNullOrEmpty(MainViewModel.Options.DefaultOutputPath))
|
||||
currentPath = Path.Combine(MainViewModel.Options.DefaultOutputPath, "track.bin");
|
||||
else if (string.IsNullOrWhiteSpace(currentPath))
|
||||
else if (string.IsNullOrEmpty(currentPath))
|
||||
currentPath = "track.bin";
|
||||
if (string.IsNullOrWhiteSpace(currentPath))
|
||||
currentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "track.bin");
|
||||
if (string.IsNullOrEmpty(currentPath))
|
||||
currentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory!, "track.bin");
|
||||
|
||||
// Get the full path
|
||||
currentPath = Path.GetFullPath(currentPath);
|
||||
@@ -137,7 +150,7 @@ namespace MPF.UI.Core.Windows
|
||||
(bool different, string message, var url) = MainViewModel.CheckForUpdates();
|
||||
|
||||
// If we have a new version, put it in the clipboard
|
||||
if (different)
|
||||
if (different && !string.IsNullOrEmpty(url))
|
||||
Clipboard.SetText(url);
|
||||
|
||||
if (showIfSame || different)
|
||||
@@ -185,7 +198,7 @@ namespace MPF.UI.Core.Windows
|
||||
{
|
||||
var submissionInfo = MainViewModel.CreateDebugSubmissionInfo();
|
||||
var result = ShowDiscInformationWindow(submissionInfo);
|
||||
InfoTool.ProcessSpecialFields(result.Item2);
|
||||
Formatter.ProcessSpecialFields(result.Item2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -315,9 +328,17 @@ namespace MPF.UI.Core.Windows
|
||||
/// <summary>
|
||||
/// Handler for CopyProtectScanButton Click event
|
||||
/// </summary>
|
||||
#if NET40
|
||||
public void CopyProtectScanButtonClick(object sender, RoutedEventArgs e)
|
||||
#else
|
||||
public async void CopyProtectScanButtonClick(object sender, RoutedEventArgs e)
|
||||
#endif
|
||||
{
|
||||
#if NET40
|
||||
var (output, error) = MainViewModel.ScanAndShowProtection();
|
||||
#else
|
||||
var (output, error) = await MainViewModel.ScanAndShowProtection();
|
||||
#endif
|
||||
|
||||
if (!MainViewModel.LogPanelExpanded)
|
||||
{
|
||||
|
||||
@@ -5,17 +5,18 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:core="clr-namespace:MPF.UI.Core"
|
||||
xmlns:coreWindows="clr-namespace:MPF.UI.Core.Windows"
|
||||
xmlns:viewModels="clr-namespace:MPF.Core.UI.ViewModels;assembly=MPF.Core"
|
||||
mc:Ignorable="d"
|
||||
Width="515.132" WindowStyle="None"
|
||||
WindowStartupLocation="CenterOwner" ResizeMode="CanMinimize" SizeToContent="Height"
|
||||
BorderBrush="DarkGray" BorderThickness="2">
|
||||
|
||||
<Window.DataContext>
|
||||
<viewModels:OptionsViewModel/>
|
||||
</Window.DataContext>
|
||||
<Window.Resources>
|
||||
<core:ElementConverter x:Key="ElementConverter" />
|
||||
</Window.Resources>
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome CaptionHeight="0" ResizeBorderThickness="0" />
|
||||
</WindowChrome.WindowChrome>
|
||||
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical">
|
||||
@@ -30,14 +31,8 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<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>
|
||||
<TextBlock.Inlines>
|
||||
<Run FontWeight="Bold" Text="{Binding Title, Mode=OneWay}"/>
|
||||
</TextBlock.Inlines>
|
||||
</TextBlock>
|
||||
</Label.Content>
|
||||
<Label Grid.Column="1" Grid.ColumnSpan="4" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" MouseDown="TitleMouseDown"
|
||||
Content="{Binding Path=Title, Mode=OneWay}" FontWeight="Bold">
|
||||
<Label.ContextMenu>
|
||||
<ContextMenu Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
|
||||
Foreground="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"
|
||||
@@ -311,28 +306,28 @@
|
||||
<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}}"
|
||||
Value="{Binding Options.PreferredDumpSpeedCD}" />
|
||||
<TextBox x:Name="DumpSpeedCDTextBox" Grid.Row="0" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" IsReadOnlyCaretVisible="False" VerticalAlignment="Center"
|
||||
<TextBox x:Name="DumpSpeedCDTextBox" Grid.Row="0" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" VerticalAlignment="Center"
|
||||
Text="{Binding ElementName=DumpSpeedCDSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}" Background="LightGray" Foreground="Gray"/>
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="DVD" />
|
||||
<Slider x:Name="DumpSpeedDVDSlider" Grid.Row="1" Grid.Column="1" Minimum="1" Maximum="24" IsSnapToTickEnabled="True" TickPlacement="BottomRight"
|
||||
Ticks="{Binding Source={x:Static core:Constants.SpeedsForDVDAsCollection}}"
|
||||
Value="{Binding Options.PreferredDumpSpeedDVD}" />
|
||||
<TextBox x:Name="DumpSpeedDVDTextBox" Grid.Row="1" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" IsReadOnlyCaretVisible="False" VerticalAlignment="Center"
|
||||
<TextBox x:Name="DumpSpeedDVDTextBox" Grid.Row="1" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" VerticalAlignment="Center"
|
||||
Text="{Binding ElementName=DumpSpeedDVDSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}" Background="LightGray" Foreground="Gray"/>
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="HD-DVD" />
|
||||
<Slider x:Name="DumpSpeedHDDVDSlider" Grid.Row="2" Grid.Column="1" Minimum="1" Maximum="24" IsSnapToTickEnabled="True" TickPlacement="BottomRight"
|
||||
Ticks="{Binding Source={x:Static core:Constants.SpeedsForHDDVDAsCollection}}"
|
||||
Value="{Binding Options.PreferredDumpSpeedHDDVD}" />
|
||||
<TextBox x:Name="DumpSpeedHDDVDTextBox" Grid.Row="2" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" IsReadOnlyCaretVisible="False" VerticalAlignment="Center"
|
||||
<TextBox x:Name="DumpSpeedHDDVDTextBox" Grid.Row="2" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" VerticalAlignment="Center"
|
||||
Text="{Binding ElementName=DumpSpeedHDDVDSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}" Background="LightGray" Foreground="Gray"/>
|
||||
|
||||
<Label Grid.Row="3" Grid.Column="0" Content="BD" />
|
||||
<Slider x:Name="DumpSpeedBDSlider" Grid.Row="3" Grid.Column="1" Minimum="1" Maximum="16" IsSnapToTickEnabled="True" TickPlacement="BottomRight"
|
||||
Ticks="{Binding Source={x:Static core:Constants.SpeedsForBDAsCollection}}"
|
||||
Value="{Binding Options.PreferredDumpSpeedBD}" />
|
||||
<TextBox x:Name="DumpSpeedBDTextBox" Grid.Row="3" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" IsReadOnlyCaretVisible="False" VerticalAlignment="Center"
|
||||
<TextBox x:Name="DumpSpeedBDTextBox" Grid.Row="3" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" VerticalAlignment="Center"
|
||||
Text="{Binding ElementName=DumpSpeedBDSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}" Background="LightGray" Foreground="Gray"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
@@ -25,6 +25,22 @@ namespace MPF.UI.Core.Windows
|
||||
public OptionsWindow(Options options)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
DumpSpeedCDTextBox.IsReadOnlyCaretVisible = false;
|
||||
DumpSpeedDVDTextBox.IsReadOnlyCaretVisible = false;
|
||||
DumpSpeedHDDVDTextBox.IsReadOnlyCaretVisible = false;
|
||||
DumpSpeedBDTextBox.IsReadOnlyCaretVisible = false;
|
||||
#endif
|
||||
|
||||
#if NET452_OR_GREATER || NETCOREAPP
|
||||
var chrome = new System.Windows.Shell.WindowChrome
|
||||
{
|
||||
CaptionHeight = 0,
|
||||
ResizeBorderThickness = new Thickness(0),
|
||||
};
|
||||
System.Windows.Shell.WindowChrome.SetWindowChrome(this, chrome);
|
||||
#endif
|
||||
DataContext = new OptionsViewModel(options);
|
||||
|
||||
// Set initial value for binding
|
||||
@@ -65,7 +81,7 @@ namespace MPF.UI.Core.Windows
|
||||
return;
|
||||
|
||||
// Strips button prefix to obtain the setting name
|
||||
string pathSettingName = button.Name[..button.Name.IndexOf("Button")];
|
||||
string pathSettingName = button.Name.Substring(0, button.Name.IndexOf("Button"));
|
||||
|
||||
// TODO: hack for now, then we'll see
|
||||
bool shouldBrowseForPath = pathSettingName == "DefaultOutputPath";
|
||||
@@ -149,7 +165,7 @@ namespace MPF.UI.Core.Windows
|
||||
/// </summary>
|
||||
private async Task ValidateRedumpCredentials()
|
||||
{
|
||||
(bool? success, string? message) = await MPF.Core.UI.ViewModels.OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password);
|
||||
(bool? success, string? message) = await OptionsViewModel.TestRedumpLogin(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password);
|
||||
|
||||
if (success == true)
|
||||
CustomMessageBox.Show(this, message, "Success", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
@@ -159,7 +175,7 @@ namespace MPF.UI.Core.Windows
|
||||
CustomMessageBox.Show(this, message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
@@ -198,7 +214,15 @@ namespace MPF.UI.Core.Windows
|
||||
/// <summary>
|
||||
/// Test Redump credentials for validity
|
||||
/// </summary>
|
||||
#if NET40
|
||||
private void OnRedumpTestClick(object sender, EventArgs e)
|
||||
{
|
||||
var validateTask = ValidateRedumpCredentials();
|
||||
validateTask.Wait();
|
||||
}
|
||||
#else
|
||||
private async void OnRedumpTestClick(object sender, EventArgs e) => await ValidateRedumpCredentials();
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
WindowStartupLocation="CenterOwner" ResizeMode="CanMinimize" SizeToContent="Height"
|
||||
BorderBrush="DarkGray" BorderThickness="2">
|
||||
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome CaptionHeight="0" ResizeBorderThickness="0" />
|
||||
</WindowChrome.WindowChrome>
|
||||
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Grid Margin="0,10,0,0">
|
||||
|
||||
@@ -5,6 +5,18 @@
|
||||
/// </summary>
|
||||
public partial class RingCodeGuideWindow : WindowBase
|
||||
{
|
||||
public RingCodeGuideWindow() => InitializeComponent();
|
||||
public RingCodeGuideWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
#if NET452_OR_GREATER || NETCOREAPP
|
||||
var chrome = new System.Windows.Shell.WindowChrome
|
||||
{
|
||||
CaptionHeight = 0,
|
||||
ResizeBorderThickness = new System.Windows.Thickness(0),
|
||||
};
|
||||
System.Windows.Shell.WindowChrome.SetWindowChrome(this, chrome);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
68
MPF/App.xaml
68
MPF/App.xaml
@@ -211,42 +211,18 @@
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
|
||||
<Themes:SystemDropShadowChrome x:Name="shadow" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=templateRoot}">
|
||||
<Border x:Name="dropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
|
||||
<ScrollViewer x:Name="DropDownScrollViewer">
|
||||
<Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
|
||||
<Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
|
||||
<Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}" Height="{Binding ActualHeight, ElementName=dropDownBorder}" Width="{Binding ActualWidth, ElementName=dropDownBorder}"/>
|
||||
</Canvas>
|
||||
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Themes:SystemDropShadowChrome>
|
||||
</Popup>
|
||||
<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom" />
|
||||
<ToggleButton x:Name="toggleButton" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{DynamicResource ComboBoxToggleButton}"/>
|
||||
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
|
||||
<Setter Property="Margin" TargetName="shadow" Value="0,0,5,5"/>
|
||||
<Setter Property="Color" TargetName="shadow" Value="#71000000"/>
|
||||
</Trigger>
|
||||
<Trigger Property="HasItems" Value="false">
|
||||
<Setter Property="Height" TargetName="dropDownBorder" Value="95"/>
|
||||
</Trigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsGrouping" Value="true"/>
|
||||
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
|
||||
<!--<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>--> <!-- Not supported in .NET Framework 3.5 or 4.0 -->
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
|
||||
</MultiTrigger>
|
||||
<Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false">
|
||||
<Setter Property="Canvas.Top" TargetName="opaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
|
||||
<Setter Property="Canvas.Left" TargetName="opaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
<SolidColorBrush x:Key="TextBox.Static.Background" Color="#FFFFFFFF"/>
|
||||
@@ -256,7 +232,7 @@
|
||||
<Setter Property="MinWidth" Value="0"/>
|
||||
<Setter Property="MinHeight" Value="0"/>
|
||||
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
|
||||
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
|
||||
<!--<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>--> <!-- Not supported in .NET Framework 3.5 -->
|
||||
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
@@ -272,20 +248,7 @@
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
|
||||
<Themes:SystemDropShadowChrome x:Name="shadow" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=templateRoot}">
|
||||
<Border x:Name="dropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
|
||||
<ScrollViewer x:Name="DropDownScrollViewer">
|
||||
<Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
|
||||
<Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
|
||||
<Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}" Height="{Binding ActualHeight, ElementName=dropDownBorder}" Width="{Binding ActualWidth, ElementName=dropDownBorder}"/>
|
||||
</Canvas>
|
||||
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Themes:SystemDropShadowChrome>
|
||||
</Popup>
|
||||
<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom" />
|
||||
<ToggleButton x:Name="toggleButton" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{DynamicResource ComboBoxToggleButton}"/>
|
||||
<Border x:Name="border" Background="{DynamicResource TextBox.Static.Background}" Margin="{TemplateBinding BorderThickness}">
|
||||
<TextBox x:Name="PART_EditableTextBox" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}" Margin="{TemplateBinding Padding}" Style="{DynamicResource ComboBoxEditableTextBox}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||
@@ -298,24 +261,13 @@
|
||||
<Trigger Property="IsKeyboardFocusWithin" Value="true">
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
</Trigger>
|
||||
<Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
|
||||
<Setter Property="Margin" TargetName="shadow" Value="0,0,5,5"/>
|
||||
<Setter Property="Color" TargetName="shadow" Value="#71000000"/>
|
||||
</Trigger>
|
||||
<Trigger Property="HasItems" Value="false">
|
||||
<Setter Property="Height" TargetName="dropDownBorder" Value="95"/>
|
||||
</Trigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsGrouping" Value="true"/>
|
||||
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
|
||||
<!--<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>--> <!-- Not supported in .NET Framework 3.5 or 4.0 -->
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
|
||||
</MultiTrigger>
|
||||
<Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false">
|
||||
<Setter Property="Canvas.Top" TargetName="opaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
|
||||
<Setter Property="Canvas.Left" TargetName="opaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
<Style x:Key="CustomComboBoxStyle" TargetType="{x:Type ComboBox}">
|
||||
@@ -328,7 +280,7 @@
|
||||
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
|
||||
<Setter Property="Padding" Value="6,3,5,3"/>
|
||||
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
|
||||
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
|
||||
<!--<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>--> <!-- Not supported in .NET Framework 3.5 -->
|
||||
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
|
||||
<Setter Property="Template" Value="{DynamicResource ComboBoxTemplate}"/>
|
||||
<Style.Triggers>
|
||||
@@ -384,7 +336,8 @@
|
||||
<Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Bottom">
|
||||
<Border x:Name="SubMenuBorder" BorderBrush="{DynamicResource MenuItem.SubMenu.Border}" BorderThickness="1" Background="{DynamicResource MenuItem.SubMenu.Background}" Padding="2">
|
||||
<ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
|
||||
<Grid RenderOptions.ClearTypeHint="Enabled">
|
||||
<!-- Grid RenderOptions.ClearTypeHint="Enabled">--> <!-- Not supported in .NET Framework 3.5 -->
|
||||
<Grid>
|
||||
<Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
|
||||
<Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=SubMenuBorder}" Height="{Binding ActualHeight, ElementName=SubMenuBorder}" Width="{Binding ActualWidth, ElementName=SubMenuBorder}"/>
|
||||
</Canvas>
|
||||
@@ -435,7 +388,8 @@
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ProgressBar}">
|
||||
<Grid x:Name="TemplateRoot">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<!-- Not supported in .NET Framework 3.5 -->
|
||||
<!--<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Determinate"/>
|
||||
<VisualState x:Name="Indeterminate">
|
||||
@@ -453,7 +407,7 @@
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</VisualStateManager.VisualStateGroups>-->
|
||||
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"/>
|
||||
<Rectangle x:Name="PART_Track"/>
|
||||
<Grid x:Name="PART_Indicator" ClipToBounds="true" HorizontalAlignment="Left">
|
||||
|
||||
185
MPF/App.xaml.cs
185
MPF/App.xaml.cs
@@ -1,7 +1,188 @@
|
||||
namespace MPF
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using Microsoft.Windows.Themes;
|
||||
|
||||
namespace MPF
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : System.Windows.Application { }
|
||||
public partial class App : Application
|
||||
{
|
||||
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
public App()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
AddDropShadowChrome("ComboBoxTemplate");
|
||||
AddDropShadowChrome("ComboBoxEditableTemplate");
|
||||
}
|
||||
|
||||
private void AddDropShadowChrome(string resourceName)
|
||||
{
|
||||
// Get the template resource
|
||||
if (Resources[resourceName] is not ControlTemplate controlTemplate)
|
||||
return;
|
||||
|
||||
// Get the popup
|
||||
if (controlTemplate.Resources["PART_Popup"] is not Popup popup)
|
||||
return;
|
||||
|
||||
// Create the various nested items
|
||||
var chrome = new SystemDropShadowChrome
|
||||
{
|
||||
Name = "shadow",
|
||||
Color = Colors.Transparent,
|
||||
};
|
||||
var border = new Border
|
||||
{
|
||||
Name = "dropDownBorder",
|
||||
BorderThickness = new Thickness(1),
|
||||
};
|
||||
var scrollViewer = new ScrollViewer { Name = "DropDownScrollViewer" };
|
||||
var grid = new Grid { Name = "grid" };
|
||||
RenderOptions.SetClearTypeHint(grid, ClearTypeHint.Enabled);
|
||||
var canvas = new Canvas
|
||||
{
|
||||
Name = "canvas",
|
||||
HorizontalAlignment = HorizontalAlignment.Left,
|
||||
Height = 0,
|
||||
VerticalAlignment = VerticalAlignment.Top,
|
||||
Width = 0,
|
||||
};
|
||||
var rectangle = new Rectangle { Name = "opaqueRect" };
|
||||
var itemsPresenter = new ItemsPresenter { Name = "ItemsPresenter" };
|
||||
KeyboardNavigation.SetDirectionalNavigation(itemsPresenter, KeyboardNavigationMode.Contained);
|
||||
|
||||
// Set the bindings
|
||||
BindingOperations.SetBinding(chrome, SystemDropShadowChrome.MaxHeightProperty, new Binding
|
||||
{
|
||||
Source = new TemplateBindingExtension(ComboBox.MaxDropDownHeightProperty),
|
||||
});
|
||||
BindingOperations.SetBinding(chrome, SystemDropShadowChrome.MinWidthProperty, new Binding
|
||||
{
|
||||
Source = ComboBox.ActualWidthProperty,
|
||||
ElementName = "templateRoot",
|
||||
});
|
||||
|
||||
BindingOperations.SetBinding(border, Border.BorderBrushProperty, new Binding
|
||||
{
|
||||
Source = new DynamicResourceExtension(new StaticResourceExtension(SystemColors.WindowFrameBrushKey)),
|
||||
});
|
||||
BindingOperations.SetBinding(border, Border.BackgroundProperty, new Binding
|
||||
{
|
||||
Source = new DynamicResourceExtension(new StaticResourceExtension(SystemColors.WindowBrushKey)),
|
||||
});
|
||||
|
||||
BindingOperations.SetBinding(rectangle, Rectangle.FillProperty, new Binding
|
||||
{
|
||||
Source = Border.BackgroundProperty,
|
||||
ElementName = "dropDownBorder",
|
||||
});
|
||||
BindingOperations.SetBinding(rectangle, Rectangle.HeightProperty, new Binding
|
||||
{
|
||||
Source = Border.ActualHeightProperty,
|
||||
ElementName = "dropDownBorder",
|
||||
});
|
||||
BindingOperations.SetBinding(rectangle, Rectangle.WidthProperty, new Binding
|
||||
{
|
||||
Source = Border.ActualWidthProperty,
|
||||
ElementName = "dropDownBorder",
|
||||
});
|
||||
|
||||
BindingOperations.SetBinding(itemsPresenter, ItemsPresenter.SnapsToDevicePixelsProperty, new Binding
|
||||
{
|
||||
Source = new TemplateBindingExtension(ComboBox.SnapsToDevicePixelsProperty),
|
||||
});
|
||||
|
||||
// Build the item tree
|
||||
canvas.Children.Add(rectangle);
|
||||
grid.Children.Add(canvas);
|
||||
grid.Children.Add(itemsPresenter);
|
||||
scrollViewer.Content = grid;
|
||||
border.Child = scrollViewer;
|
||||
chrome.Child = border;
|
||||
|
||||
// Add the tree to the popup
|
||||
popup.Child = chrome;
|
||||
|
||||
// Get the triggers
|
||||
var triggers = controlTemplate.Triggers;
|
||||
if (triggers == null)
|
||||
return;
|
||||
|
||||
// Create the new triggers
|
||||
var hasDropShadow = new Trigger
|
||||
{
|
||||
Property = Popup.HasDropShadowProperty,
|
||||
SourceName = "PART_Popup",
|
||||
Value = "true",
|
||||
};
|
||||
var hasItems = new Trigger
|
||||
{
|
||||
Property = ComboBox.HasItemsProperty,
|
||||
Value = "false",
|
||||
};
|
||||
var canContentScroll = new Trigger
|
||||
{
|
||||
Property = ScrollViewer.CanContentScrollProperty,
|
||||
SourceName = "DropDownScrollViewer",
|
||||
Value = "false",
|
||||
};
|
||||
|
||||
// Create and add the setters
|
||||
hasDropShadow.Setters.Add(new Setter
|
||||
{
|
||||
Property = SystemDropShadowChrome.MarginProperty,
|
||||
TargetName = "shadow",
|
||||
Value = "0,0,5,5",
|
||||
});
|
||||
hasDropShadow.Setters.Add(new Setter
|
||||
{
|
||||
Property = SystemDropShadowChrome.ColorProperty,
|
||||
TargetName = "shadow",
|
||||
Value = "#71000000",
|
||||
});
|
||||
|
||||
hasItems.Setters.Add(new Setter
|
||||
{
|
||||
Property = Border.HeightProperty,
|
||||
TargetName = "dropDownBorder",
|
||||
Value = "95",
|
||||
});
|
||||
|
||||
canContentScroll.Setters.Add(new Setter
|
||||
{
|
||||
Property = Canvas.TopProperty,
|
||||
TargetName = "opaqueRect",
|
||||
Value = new Binding
|
||||
{
|
||||
Source = ScrollViewer.VerticalOffsetProperty,
|
||||
ElementName = "DropDownScrollViewer",
|
||||
},
|
||||
});
|
||||
canContentScroll.Setters.Add(new Setter
|
||||
{
|
||||
Property = Canvas.LeftProperty,
|
||||
TargetName = "opaqueRect",
|
||||
Value = new Binding
|
||||
{
|
||||
Source = ScrollViewer.HorizontalOffsetProperty,
|
||||
ElementName = "DropDownScrollViewer",
|
||||
},
|
||||
});
|
||||
|
||||
// Add the new triggers
|
||||
triggers.Add(hasDropShadow);
|
||||
triggers.Add(hasItems);
|
||||
triggers.Add(canContentScroll);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,43 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0-windows;net8.0-windows</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net40;net452;net462;net472;net48;netcoreapp3.1;net5.0-windows;net6.0-windows;net7.0-windows;net8.0-windows</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<ApplicationIcon>Images\Icon.ico</ApplicationIcon>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.0.1</VersionPrefix>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<UseWPF>true</UseWPF>
|
||||
<Nullable>enable</Nullable>
|
||||
<ApplicationIcon>Images\Icon.ico</ApplicationIcon>
|
||||
<Title>MPF</Title>
|
||||
<Description>Frontend for various dumping programs</Description>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2023</Copyright>
|
||||
<VersionPrefix>3.0.0</VersionPrefix>
|
||||
<InternalsVisibleTo>MPF.Test</InternalsVisibleTo>
|
||||
<Description>Frontend for various dumping programs</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2019-2023</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Special handling for Aero2 on non-Framework .NET -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`)) OR $(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`))">
|
||||
<ReferenceWpfAeroTheme>false</ReferenceWpfAeroTheme>
|
||||
<ReferenceWpfAero2Theme>true</ReferenceWpfAero2Theme>
|
||||
<ReferenceWpfAeroLiteTheme>false</ReferenceWpfAeroLiteTheme>
|
||||
<ReferenceWpfClassicTheme>false</ReferenceWpfClassicTheme>
|
||||
<ReferenceWpfLunaTheme>false</ReferenceWpfLunaTheme>
|
||||
<ReferenceWpfRoyaleTheme>false</ReferenceWpfRoyaleTheme>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="MPF.Test" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\Icon.ico" />
|
||||
</ItemGroup>
|
||||
@@ -25,15 +47,55 @@
|
||||
<ProjectReference Include="..\MPF.UI.Core\MPF.UI.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net4`))">
|
||||
<Reference Include="PresentationFramework.Aero" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`)) OR $(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`))">
|
||||
<Reference Include="PresentationFramework.Aero2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BinaryObjectScanner" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="3.0.0" GeneratePathProperty="true">
|
||||
<PackageReference Include="BinaryObjectScanner" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="3.0.2" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.2.0" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="$(PkgBinaryObjectScanner)\content\**" PackagePath="contentFiles\any\any;content" CopyToOutputDirectory="Always" PackageCopyToOutput="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<!-- Special handling for Aero2 on non-Framework .NET -->
|
||||
<Target Name="SelectWpfThemeAssembly" AfterTargets="ResolveAssemblyReferences" Condition="'$(ReferenceWpfAeroTheme)' == 'true' Or
 '$(ReferenceWpfAero2Theme)' == 'true' Or
 '$(ReferenceWpfAeroLiteTheme)' == 'true' Or
 '$(ReferenceWpfClassicTheme)' == 'true' Or 
 '$(ReferenceWpfLunaTheme)' == 'true' Or
 '$(ReferenceWpfRoyaleTheme)' == 'true'">
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`)) OR $(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`))">
|
||||
<_WpfThemeAssemblies Include="@(ReferencePath)" Condition="'%(ReferencePath.NuGetPackageId)'=='Microsoft.WindowsDesktop.App.Ref' And 
 '%(ReferencePath.FileName)'=='PresentationFramework.Aero'">
|
||||
<Aliases Condition="'$(WpfAeroThemeAliases)'!=''">$(WpfAeroThemeAliases)</Aliases>
|
||||
</_WpfThemeAssemblies>
|
||||
|
||||
<_WpfThemeAssemblies Include="@(ReferencePath)" Condition="'%(ReferencePath.NuGetPackageId)'=='Microsoft.WindowsDesktop.App.Ref' And 
 '%(ReferencePath.FileName)'=='PresentationFramework.Aero2'">
|
||||
<Aliases Condition="'$(WpfAero2ThemeAliases)'!=''">$(WpfAero2ThemeAliases)</Aliases>
|
||||
</_WpfThemeAssemblies>
|
||||
|
||||
<_WpfThemeAssemblies Include="@(ReferencePath)" Condition="'%(ReferencePath.NuGetPackageId)'=='Microsoft.WindowsDesktop.App.Ref' And 
 '%(ReferencePath.FileName)'=='PresentationFramework.AeroLite'">
|
||||
<Aliases Condition="'$(WpfAeroLiteThemeAliases)'!=''">$(WpfAeroLiteThemeAliases)</Aliases>
|
||||
</_WpfThemeAssemblies>
|
||||
|
||||
<_WpfThemeAssemblies Include="@(ReferencePath)" Condition="'%(ReferencePath.NuGetPackageId)'=='Microsoft.WindowsDesktop.App.Ref' And 
 '%(ReferencePath.FileName)'=='PresentationFramework.Classic'">
|
||||
<Aliases Condition="'$(WpfClassicThemeAliases)'!=''">$(WpfClassicThemeAliases)</Aliases>
|
||||
</_WpfThemeAssemblies>
|
||||
|
||||
<_WpfThemeAssemblies Include="@(ReferencePath)" Condition="'%(ReferencePath.NuGetPackageId)'=='Microsoft.WindowsDesktop.App.Ref' And 
 '%(ReferencePath.FileName)'=='PresentationFramework.Luna'">
|
||||
<Aliases Condition="'$(WpfLunaThemeAliases)'!=''">$(WpfLunaThemeAliases)</Aliases>
|
||||
</_WpfThemeAssemblies>
|
||||
|
||||
<_WpfThemeAssemblies Include="@(ReferencePath)" Condition="'%(ReferencePath.NuGetPackageId)'=='Microsoft.WindowsDesktop.App.Ref' And 
 '%(ReferencePath.FileName)'=='PresentationFramework.Royale'">
|
||||
<Aliases Condition="'$(WpfRoyaleThemeAliases)'!=''">$(WpfRoyaleThemeAliases)</Aliases>
|
||||
</_WpfThemeAssemblies>
|
||||
|
||||
<ReferencePath Remove="@(_WpfThemeAssemblies)" />
|
||||
<ReferencePath Include="@(_WpfThemeAssemblies)" Condition="('%(_WpfThemeAssemblies.FileName)'=='PresentationFramework.Aero' And '$(ReferenceWpfAeroTheme)'=='true') Or 
 ('%(_WpfThemeAssemblies.FileName)'=='PresentationFramework.Aero2' And '$(ReferenceWpfAero2Theme)'=='true') Or 
 ('%(_WpfThemeAssemblies.FileName)'=='PresentationFramework.AeroLite' And '$(ReferenceWpfAeroLiteTheme)'=='true') Or 
 ('%(_WpfThemeAssemblies.FileName)'=='PresentationFramework.Classic' And '$(ReferenceWpfClassicTheme)'=='true') Or 
 ('%(_WpfThemeAssemblies.FileName)'=='PresentationFramework.Luna' And '$(ReferenceWpfLunaTheme)'=='true') Or
 ('%(_WpfThemeAssemblies.FileName)'=='PresentationFramework.Royale' And '$(ReferenceWpfRoyaleTheme)'=='true')" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -1,5 +1,5 @@
|
||||
# version format
|
||||
version: 3.0.0-{build}
|
||||
version: 3.0.1-{build}
|
||||
|
||||
# pull request template
|
||||
pull_requests:
|
||||
@@ -48,8 +48,8 @@ after_build:
|
||||
- 7z e DiscImageCreator_20230606.zip -oMPF\bin\Debug\net8.0-windows\win-x64\publish\Programs\Creator Release_ANSI\*
|
||||
|
||||
# Redumper
|
||||
- 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\net8.0-windows\win-x64\publish\Programs\Redumper redumper-2023.11.01_build247-win64\bin\*
|
||||
- ps: appveyor DownloadFile https://github.com/superg/redumper/releases/download/build_268/redumper-2023.11.27_build268-win64.zip
|
||||
- 7z e redumper-2023.11.27_build268-win64.zip -oMPF\bin\Debug\net8.0-windows\win-x64\publish\Programs\Redumper redumper-2023.11.27_build268-win64\bin\*
|
||||
|
||||
# Create MPF Debug archives
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\MPF\bin\Debug\net8.0-windows\win-x64\publish\
|
||||
|
||||
Reference in New Issue
Block a user