Compare commits

..

84 Commits
2.2 ... 2.3

Author SHA1 Message Date
Matt Nadareski
87400793eb Bump version to 2.3 2022-02-05 13:45:06 -08:00
Matt Nadareski
45f79d95b1 Adjust paths for DIC just before dumping (fixes #358) 2022-02-04 20:46:56 -08:00
Matt Nadareski
c8a4a61028 Normalize PS1/PS2 executable names 2022-02-03 22:28:14 -08:00
Matt Nadareski
44091981b2 Check explicitly for no matches on Redump pull (fixes #357) 2022-02-03 15:43:17 -08:00
Matt Nadareski
d3352643fc Ensure drive is not null for volume labels (fixes #356) 2022-02-02 20:05:15 -08:00
Matt Nadareski
114c7fb38a Make error clearer if something is unsupported in Check 2022-02-02 19:59:53 -08:00
Matt Nadareski
dc7da708dc Add alternate pseudo-tag for Playable Demos 2022-02-02 12:54:08 -08:00
Matt Nadareski
72e56aa1c7 Ensure Games pseudo-tag is multi-line 2022-02-02 12:50:32 -08:00
Matt Nadareski
99ceab07ad Ensure version only pulled if one doesn't exist (fixes #355) 2022-02-01 20:54:26 -08:00
Matt Nadareski
c0f6c072ce Read longer string for Saturn internal serial 2022-02-01 20:51:33 -08:00
Matt Nadareski
e039124f6c Add verification reminders for pulled tags 2022-02-01 13:04:28 -08:00
Matt Nadareski
c96e4a4c7a Add another hand-formatted version of SS tag 2022-01-31 10:50:53 -08:00
Matt Nadareski
622a08acf3 Update changelog 2022-01-31 09:49:07 -08:00
Matt Nadareski
f44b6bf0d0 Slightly rename UK and USA regions for UI 2022-01-31 09:47:42 -08:00
Matt Nadareski
a6d75e15ea Check for $SystemUpdate folder for X360 discs 2022-01-30 20:51:47 -08:00
Matt Nadareski
a02f03c4cb Move internal serial before volume label 2022-01-30 15:57:12 -08:00
Matt Nadareski
d48f5132fb Add another hand-formatted version of SS tag 2022-01-28 23:12:25 -08:00
Matt Nadareski
ed4ac24efa Add Sierra ID to list of pseudo-tags 2022-01-28 09:24:37 -08:00
Matt Nadareski
9f3b8a7c2c Adjust long names for some languages 2022-01-27 21:40:23 -08:00
Matt Nadareski
612d4bb1f5 Fix incorrect region two-letter code 2022-01-27 21:25:58 -08:00
Matt Nadareski
b58a50d246 Disable unnecessary cuesheet parsing 2022-01-27 20:49:32 -08:00
Matt Nadareski
af83811d57 Fix parsing of non-tag tags again 2022-01-27 17:17:42 -08:00
Matt Nadareski
66835fe6ab Fix non-tag tag shortnames 2022-01-27 16:27:40 -08:00
Matt Nadareski
34cc1d33c6 Hook up additional Xbox field to disc info window 2022-01-27 16:04:14 -08:00
Matt Nadareski
a42d14e3b8 Fix incorrect language three-letter code 2022-01-27 15:39:09 -08:00
Matt Nadareski
87aa165edf Add more non-tag support; rearrange info window 2022-01-27 13:35:47 -08:00
Matt Nadareski
d217d62007 Start supporting ordered tags and non-tags 2022-01-27 12:13:17 -08:00
Matt Nadareski
27bcc0d40a Better helper method organization 2022-01-27 10:58:40 -08:00
Matt Nadareski
e1df075cde Make site code formatting helper method 2022-01-27 10:51:27 -08:00
Matt Nadareski
8358692e8d Ensure ordering in output site tags 2022-01-27 10:45:48 -08:00
Matt Nadareski
e1fae01dab Add support for all ISO region codes 2022-01-26 23:29:06 -08:00
Matt Nadareski
d206ab140a Add support for all ISO language codes 2022-01-26 21:38:11 -08:00
Matt Nadareski
9d8722ab17 Try to delete old log archive before writing (fixes #348) 2022-01-26 09:51:37 -08:00
Matt Nadareski
c4fa40c403 Sync with Redump region and language selection (fixes #349) 2022-01-26 09:41:34 -08:00
Matt Nadareski
1d0b06bfbe Use volume label in checks, not formatted version 2022-01-20 13:20:15 -08:00
Matt Nadareski
2cdf473dcb Be smarter about volume labels 2022-01-20 13:15:53 -08:00
Matt Nadareski
1af9e2c2da Conditionally pull region from Redump 2022-01-14 16:30:20 -08:00
Matt Nadareski
9a1815fa1e Differentiate XMID and XeMID 2022-01-14 13:06:11 -08:00
Matt Nadareski
f601961c49 Fix crash on invalid parameters 2022-01-13 10:25:57 -08:00
Matt Nadareski
406acd34c5 Fix Sega CD internal serial reading 2022-01-09 22:38:22 -08:00
Matt Nadareski
31cdcbbc25 Reformat Saturn internal date (fixes #346) 2022-01-09 14:44:55 -08:00
Matt Nadareski
2215ce71c9 Make protection read-only field multiline 2022-01-07 21:41:49 -08:00
Matt Nadareski
1872fbb1c8 Fix incorrect header check 2022-01-07 20:57:47 -08:00
Matt Nadareski
d99f912ac2 Add hidden debug option for "ShowDebugViewMenuItem" (fixes #334) 2022-01-07 13:25:46 -08:00
Matt Nadareski
00a76fb648 Only include booleans if the value is true 2022-01-07 12:49:10 -08:00
Matt Nadareski
187e951a47 Fix IsReadOnly 2022-01-07 09:04:12 -08:00
Matt Nadareski
c0b9b27aae Adjust width ratios for disc info window 2022-01-06 22:19:06 -08:00
Matt Nadareski
b76bb17396 Convert postgap and VCD fields to checkboxes 2022-01-06 21:51:20 -08:00
Matt Nadareski
2efa6d3623 Fix scrolling issues in disc info window 2022-01-06 21:31:46 -08:00
Matt Nadareski
3972ce633d Changed IsEnabled to IsReadOnly 2022-01-06 21:30:47 -08:00
Matt Nadareski
0dc7901393 Further disc info window tweaks 2022-01-06 17:08:45 -08:00
Matt Nadareski
a25ba6eaa5 Add tab setting (fixes #303) 2022-01-06 15:25:25 -08:00
Matt Nadareski
4ea48dfe57 Tweak minimalized layout a bit more 2022-01-06 14:57:38 -08:00
Matt Nadareski
8f7ad8b2ee Unban newly opened consoles 2022-01-06 10:23:07 -08:00
Matt Nadareski
3b9800df07 Add <tab> processing 2022-01-04 21:28:51 -08:00
Matt Nadareski
4c80d3234e Logically group more things in disc info window 2022-01-04 21:19:46 -08:00
Matt Nadareski
9e4af1d66b Remove Enter/Escape registration on disc info window 2022-01-04 11:13:17 -08:00
Matt Nadareski
73555df2ea Omit volume label for "Audio CD" (fixes #343) 2022-01-03 21:26:54 -08:00
Matt Nadareski
3ca78604fd Fix InfoTool tests 2022-01-02 22:01:21 -08:00
Matt Nadareski
0138046923 Add newlines for mutliline special fields 2022-01-02 21:54:49 -08:00
Matt Nadareski
2129184209 Add missing continue statement 2022-01-02 13:58:58 -08:00
Matt Nadareski
dd2116f8a6 Fix newline skipping 2022-01-01 22:24:03 -08:00
Matt Nadareski
814c2d9149 Force scroll visibility, tweak text sizes again 2022-01-01 21:42:05 -08:00
Matt Nadareski
b3f7276044 Skip unnecessary newlines in parsing 2022-01-01 21:36:39 -08:00
Matt Nadareski
ad88aa980b Tweak more Disc Info window formatting 2022-01-01 21:13:35 -08:00
Matt Nadareski
aca55e9203 Handle pulled linebreaks better, again 2022-01-01 20:46:44 -08:00
Matt Nadareski
cc3330bb27 Skip anti-modchip string in some cases 2022-01-01 20:42:52 -08:00
Matt Nadareski
1370909db7 Handle pulled linebreaks better (fixes #342) 2022-01-01 14:18:14 -08:00
Matt Nadareski
08cc0c394b Sanitize filename after check (fixes #341) 2022-01-01 14:16:58 -08:00
Matt Nadareski
cb6692aea3 Add even more safety to clone 2022-01-01 13:58:33 -08:00
Matt Nadareski
b3badb3a55 Add first attempt 2-layer ringcode guide 2021-12-31 14:21:14 -08:00
Matt Nadareski
cbf73901d3 Add model for 2-layer ringcode guide 2021-12-31 13:54:31 -08:00
Matt Nadareski
4822e45d58 Ensure all fields are read-only on read-only tab 2021-12-30 22:21:33 -08:00
Matt Nadareski
1d930d36bf Be smarter about showing update checks 2021-12-30 21:00:01 -08:00
Matt Nadareski
9effcc403d Allow internal serial and volume label to be hidden 2021-12-30 20:56:55 -08:00
Matt Nadareski
05dcc039bd Tweak new disc information fields and tabs 2021-12-30 20:48:32 -08:00
Matt Nadareski
cb08656abc Add horizontal scroll to user input 2021-12-30 20:45:15 -08:00
Matt Nadareski
69b22fc736 Show most read-only fields in new tab (fixes #301) 2021-12-30 17:27:08 -08:00
Matt Nadareski
bf857f6ce7 Fix CSSKey log handling (fixes #333) 2021-12-30 15:47:44 -08:00
Matt Nadareski
7ebf2378b3 Try to handle multi-line fields during parsing 2021-12-30 15:36:58 -08:00
Matt Nadareski
aec25dab37 Clean up default handling of fields 2021-12-30 15:23:17 -08:00
Matt Nadareski
e11969780d Add new tabs for special site information 2021-12-30 14:52:49 -08:00
Matt Nadareski
02c98b1547 Add internal structure for special site codes 2021-12-30 13:00:55 -08:00
Matt Nadareski
c864589478 Start overhauling Redump information pulling, again 2021-12-30 11:09:37 -08:00
39 changed files with 5083 additions and 956 deletions

View File

@@ -1,3 +1,87 @@
### 2.3 (2022-02-05)
- Start overhauling Redump information pulling, again
- Add internal structure for special site codes
- Add new tabs for special site information
- Clean up default handling of fields
- Try to handle multi-line fields during parsing
- Fix CSSKey log handling
- Show most read-only fields in new tab
- Add horizontal scroll to user input
- Tweak new disc information fields and tabs
- Allow internal serial and volume label to be hidden
- Be smarter about showing update checks
- Ensure all fields are read-only on read-only tab
- Add model for 2-layer ringcode guide
- Add first attempt 2-layer ringcode guide
- Add even more safety to clone
- Sanitize filename after check
- Handle pulled linebreaks better
- Skip anti-modchip string in some cases
- Handle pulled linebreaks better, again
- Tweak more Disc Info window formatting
- Skip unnecessary newlines in parsing
- Force scroll visibility, tweak text sizes again
- Fix newline skipping
- Add missing continue statement
- Add newlines for mutliline special fields
- Omit volume label for "Audio CD"
- Remove Enter/Escape registration on disc info window
- Logically group more things in disc info window
- Remove tab key from disc info window
- Add `<tab>` processing
- Unban newly opened consoles
- Tweak minimalized layout a bit more
- Add tab setting
- Further disc info window tweaks
- Changed IsEnabled to IsReadOnly
- Fix scrolling issues in disc info window
- Convert postgap and VCD fields to checkboxes
- Adjust width ratios for disc info window
- Fix IsReadOnly
- Only include booleans if the value is true
- Add hidden debug option for "ShowDebugViewMenuItem"
- Fix incorrect header check
- Make protection read-only field multiline
- Reformat Saturn internal date
- Fix Sega CD internal serial reading
- Fix crash on invalid parameters
- Differentiate XMID and XeMID
- Conditionally pull region from Redump
- Be smarter about volume labels
- Use volume label in checks, not formatted version
- Sync with Redump region and language selection
- Try to delete old log archive before writing
- Add support for all ISO language codes
- Add support for all ISO region codes
- Ensure ordering in output site tags
- Make site code formatting helper method
- Better helper method organization
- Start supporting ordered tags and non-tags
- Add more non-tag support; rearrange info window
- Fix incorrect language three-letter code
- Hook up additional Xbox field to disc info window
- Fix non-tag tag shortnames
- Fix parsing of non-tag tags again
- Disable unnecessary cuesheet parsing
- Fix incorrect region two-letter code
- Adjust long names for some languages
- Add Sierra ID to list of pseudo-tags
- Add another hand-formatted version of SS tag
- Move internal serial before volume label
- Check for $SystemUpdate folder for X360 discs
- Slightly rename UK and USA regions for UI
- Add another hand-formatted version of SS tag
- Add verification reminders for pulled tags
- Read longer string for Saturn internal serial
- Ensure version only pulled if one doesn't exist
- Ensure Games pseudo-tag is multi-line
- Add alternate pseudo-tag for Playable Demos
- Make error clearer if something is unsupported in Check
- Ensure drive is not null for volume labels
- Check explicitly for no matches on Redump pull
- Normalize PS1/PS2 executable names
- Adjust paths for DIC just before dumping
### 2.2 (2021-12-30)
- Fix Saturn header finding
- Add Pocket PC support

View File

@@ -10,7 +10,7 @@
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
<Copyright>Copyright (c)2019-2021</Copyright>
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
<Version>2.2</Version>
<Version>2.3</Version>
<AssemblyVersion>$(Version)</AssemblyVersion>
<FileVersion>$(Version)</FileVersion>
<IncludeSource>true</IncludeSource>

View File

@@ -100,12 +100,7 @@ namespace MPF.Core.Data
public const string PlayStationEDCField = "EDC";
public const string PlayStationAntiModchipField = "Anti-modchip";
public const string PlayStationLibCryptField = "LibCrypt";
public const string XBOXDMIHash = "DMI";
public const string XBOXPFIHash = "PFI";
public const string XBOXSSHash = "SS";
public const string XBOXSSRanges = "Security Sector Ranges";
public const string XBOXSSVersion = "Security Sector Version";
public const string XBOXXeMID = "XeMID";
// Default values

View File

@@ -268,58 +268,24 @@ namespace MPF.Core.Data
if (this.InternalDriveType != Data.InternalDriveType.Optical)
return RedumpSystem.IBMPCcompatible;
// Audio CD
if (this.FormattedVolumeLabel.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
{
return RedumpSystem.AudioCD;
}
// Check volume labels first
RedumpSystem? systemFromLabel = GetRedumpSystemFromVolumeLabel();
if (systemFromLabel != null)
return systemFromLabel;
// BD-Video
if (Directory.Exists(Path.Combine(drivePath, "BDMV")))
{
// Technically BD-Audio has this as well, but it's hard to split that out right now
return RedumpSystem.BDVideo;
}
#region Consoles
// DVD-Audio
// Microsoft Xbox 360
try
{
if (Directory.Exists(Path.Combine(drivePath, "AUDIO_TS"))
&& Directory.EnumerateFiles(Path.Combine(drivePath, "AUDIO_TS")).Any())
if (Directory.Exists(Path.Combine(drivePath, "$SystemUpdate"))
&& Directory.EnumerateFiles(Path.Combine(drivePath, "$SystemUpdate")).Any())
{
return RedumpSystem.DVDAudio;
return RedumpSystem.MicrosoftXbox360;
}
}
catch { }
// DVD-Video and Xbox
try
{
if (Directory.Exists(Path.Combine(drivePath, "VIDEO_TS"))
&& Directory.EnumerateFiles(Path.Combine(drivePath, "VIDEO_TS")).Any())
{
// TODO: Maybe add video track hashes to compare for Xbox and X360?
if (this.FormattedVolumeLabel.StartsWith("SEP13011042", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.MicrosoftXbox;
return RedumpSystem.DVDVideo;
}
}
catch { }
// HD-DVD-Video
try
{
if (Directory.Exists(Path.Combine(drivePath, "HVDVD_TS"))
&& Directory.EnumerateFiles(Path.Combine(drivePath, "HVDVD_TS")).Any())
{
return RedumpSystem.HDDVDVideo;
}
}
catch
{
}
// Sega Dreamcast
if (File.Exists(Path.Combine(drivePath, "IP.BIN")))
{
@@ -364,30 +330,51 @@ namespace MPF.Core.Data
return RedumpSystem.SonyPlayStation;
}
// Sony PlayStation 3
if (this.FormattedVolumeLabel.Equals("PS3VOLUME", StringComparison.OrdinalIgnoreCase))
{
return RedumpSystem.SonyPlayStation3;
}
// Sony PlayStation 4
if (this.FormattedVolumeLabel.Equals("PS4VOLUME", StringComparison.OrdinalIgnoreCase))
{
return RedumpSystem.SonyPlayStation4;
}
// Sony PlayStation 5
if (this.FormattedVolumeLabel.Equals("PS5VOLUME", StringComparison.OrdinalIgnoreCase))
{
return RedumpSystem.SonyPlayStation5;
}
// V.Tech V.Flash / V.Smile Pro
if (File.Exists(Path.Combine(drivePath, "0SYSTEM")))
{
return RedumpSystem.VTechVFlashVSmilePro;
}
#endregion
#region Video Formats
// BD-Video
if (Directory.Exists(Path.Combine(drivePath, "BDMV")))
{
// Technically BD-Audio has this as well, but it's hard to split that out right now
return RedumpSystem.BDVideo;
}
// DVD-Audio and DVD-Video
try
{
if (Directory.Exists(Path.Combine(drivePath, "AUDIO_TS"))
&& Directory.EnumerateFiles(Path.Combine(drivePath, "AUDIO_TS")).Any())
{
return RedumpSystem.DVDAudio;
}
else if (Directory.Exists(Path.Combine(drivePath, "VIDEO_TS"))
&& Directory.EnumerateFiles(Path.Combine(drivePath, "VIDEO_TS")).Any())
{
return RedumpSystem.DVDVideo;
}
}
catch { }
// HD-DVD-Video
try
{
if (Directory.Exists(Path.Combine(drivePath, "HVDVD_TS"))
&& Directory.EnumerateFiles(Path.Combine(drivePath, "HVDVD_TS")).Any())
{
return RedumpSystem.HDDVDVideo;
}
}
catch { }
// VCD
try
{
@@ -399,10 +386,59 @@ namespace MPF.Core.Data
}
catch { }
#endregion
// Default return
return defaultValue;
}
/// <summary>
/// Get the current system from the drive volume label
/// </summary>
/// <returns>The system based on volume label, null if none detected</returns>
public RedumpSystem? GetRedumpSystemFromVolumeLabel()
{
// If the volume label is empty, we can't do anything
if (string.IsNullOrWhiteSpace(this.VolumeLabel))
return null;
// Audio CD
if (this.VolumeLabel.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.AudioCD;
// Microsoft Xbox
if (this.VolumeLabel.Equals("SEP13011042", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.MicrosoftXbox;
else if (this.VolumeLabel.Equals("SEP13011042072", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.MicrosoftXbox;
// Microsoft Xbox 360
if (this.VolumeLabel.Equals("XBOX360", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.MicrosoftXbox360;
else if (this.VolumeLabel.Equals("XGD2DVD_NTSC", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.MicrosoftXbox360;
// Microsoft Xbox 360 - Too overly broad even if a lot of discs use this
//if (this.VolumeLabel.Equals("CD_ROM", StringComparison.OrdinalIgnoreCase))
// return RedumpSystem.MicrosoftXbox360; // Also for Xbox One?
//if (this.VolumeLabel.Equals("DVD_ROM", StringComparison.OrdinalIgnoreCase))
// return RedumpSystem.MicrosoftXbox360;
// Sony PlayStation 3
if (this.VolumeLabel.Equals("PS3VOLUME", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.SonyPlayStation3;
// Sony PlayStation 4
if (this.VolumeLabel.Equals("PS4VOLUME", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.SonyPlayStation4;
// Sony PlayStation 5
if (this.VolumeLabel.Equals("PS5VOLUME", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.SonyPlayStation5;
return null;
}
/// <summary>
/// Read a sector with a specified size from the drive
/// </summary>

View File

@@ -104,6 +104,16 @@ namespace MPF.Core.Data
}
}
/// <summary>
/// Default output path for dumps
/// </summary>
/// <remarks>This is a hidden setting</remarks>
public bool ShowDebugViewMenuItem
{
get { return GetBooleanSetting(_settings, "ShowDebugViewMenuItem", false); }
set { _settings["ShowDebugViewMenuItem"] = value.ToString(); }
}
#endregion
#region Dumping Speeds
@@ -269,6 +279,15 @@ namespace MPF.Core.Data
set { _settings["PromptForDiscInformation"] = value.ToString(); }
}
/// <summary>
/// Enable tabs in all input fields
/// </summary>
public bool EnableTabsInInputFields
{
get { return GetBooleanSetting(_settings, "EnableTabsInInputFields", false); }
set { _settings["EnableTabsInInputFields"] = value.ToString(); }
}
/// <summary>
/// Show disc eject reminder before the disc information window is shown
/// </summary>

View File

@@ -6,7 +6,7 @@ namespace MPF.Core.Data
/// Contains information specific to an XGD disc
/// </summary>
/// <remarks>
/// XGD1 XeMID Format Information:
/// XGD1 XMID Format Information:
///
/// AABBBCCD
/// - AA => The two-ASCII-character publisher identifier (see GetPublisher for details)
@@ -37,9 +37,9 @@ namespace MPF.Core.Data
public bool Initialized { get; private set; }
/// <summary>
/// Raw XeMID string that all other information is derived from
/// Raw XMID/XeMID string that all other information is derived from
/// </summary>
public string XeMID { get; private set; }
public string XMID { get; private set; }
/// <summary>
/// 2-character publisher identifier
@@ -112,27 +112,27 @@ namespace MPF.Core.Data
#endregion
/// <summary>
/// Populate a set of XGD information from a Master ID (XeMID) string
/// Populate a set of XGD information from a Master ID (XMID/XeMID) string
/// </summary>
/// <param name="xemid">XeMID string representing the DMI information</param>
/// <param name="xmid">XMID/XeMID string representing the DMI information</param>
/// <param name="validate">True if value validation should be performed, false otherwise</param>
public XgdInfo(string xemid, bool validate = false)
public XgdInfo(string xmid, bool validate = false)
{
this.Initialized = false;
if (string.IsNullOrWhiteSpace(xemid))
if (string.IsNullOrWhiteSpace(xmid))
return;
this.XeMID = xemid.TrimEnd('\0');
if (string.IsNullOrWhiteSpace(this.XeMID))
this.XMID = xmid.TrimEnd('\0');
if (string.IsNullOrWhiteSpace(this.XMID))
return;
// XGD1 information is 8 characters
if (this.XeMID.Length == 8)
this.Initialized = ParseXGD1XeMID(this.XeMID, validate);
if (this.XMID.Length == 8)
this.Initialized = ParseXGD1XMID(this.XMID, validate);
// XGD2/3 information is semi-variable length
else if (this.XeMID.Length == 13 || this.XeMID.Length == 14 || this.XeMID.Length == 21 || this.XeMID.Length == 22)
this.Initialized = ParseXGD23XeMID(this.XeMID, validate);
else if (this.XMID.Length == 13 || this.XMID.Length == 14 || this.XMID.Length == 21 || this.XMID.Length == 22)
this.Initialized = ParseXGD23XeMID(this.XMID, validate);
}
/// <summary>
@@ -191,23 +191,23 @@ namespace MPF.Core.Data
}
/// <summary>
/// Parse an XGD1 XeMID string
/// Parse an XGD1 XMID string
/// </summary>
/// <param name="xemid">XeMID string to attempt to parse</param>
/// <param name="xmid">XMID string to attempt to parse</param>
/// <param name="validate">True if value validation should be performed, false otherwise</param>
/// <returns>True if the XeMID could be parsed, false otherwise</returns>
private bool ParseXGD1XeMID(string xemid, bool validate)
/// <returns>True if the XMID could be parsed, false otherwise</returns>
private bool ParseXGD1XMID(string xmid, bool validate)
{
if (xemid == null || xemid.Length != 8)
if (xmid == null || xmid.Length != 8)
return false;
this.PublisherIdentifier = xemid.Substring(0, 2);
this.PublisherIdentifier = xmid.Substring(0, 2);
if (validate && string.IsNullOrEmpty(this.PublisherName))
return false;
this.GameID = xemid.Substring(2, 3);
this.SKU = xemid.Substring(5, 2);
this.RegionIdentifier = xemid[7];
this.GameID = xmid.Substring(2, 3);
this.SKU = xmid.Substring(5, 2);
this.RegionIdentifier = xmid[7];
if (validate && this.InternalRegion == null)
return false;
@@ -408,7 +408,7 @@ namespace MPF.Core.Data
switch (region)
{
case 'W': return Region.World;
case 'A': return Region.USA;
case 'A': return Region.UnitedStatesOfAmerica;
case 'J': return Region.JapanAsia;
case 'E': return Region.Europe;
case 'K': return Region.USAJapan;

View File

@@ -6,7 +6,7 @@
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
<Copyright>Copyright (c)2019-2021</Copyright>
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
<Version>2.2</Version>
<Version>2.3</Version>
<AssemblyVersion>$(Version)</AssemblyVersion>
<FileVersion>$(Version)</FileVersion>
<IncludeSource>true</IncludeSource>

View File

@@ -6,7 +6,7 @@
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
<Copyright>Copyright (c)2019-2021</Copyright>
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
<Version>2.2</Version>
<Version>2.3</Version>
<AssemblyVersion>$(Version)</AssemblyVersion>
<FileVersion>$(Version)</FileVersion>
<IncludeSource>true</IncludeSource>

View File

@@ -118,6 +118,28 @@ namespace MPF.Library
#region Public Functionality
/// <summary>
/// Adjust output paths if we're using DiscImageCreator
/// </summary>
public void AdjustPathsForDiscImageCreator()
{
// Only DiscImageCreator has issues with paths
if (this.Parameters.InternalProgram != InternalProgram.DiscImageCreator)
return;
// Replace all instances in the output directory
this.OutputDirectory = this.OutputDirectory.Replace('.', '_');
// Currently, only periods in directories matter
// Leave the following code commented in case filename handling breaks again
// Replace all instances in the output filename, except the extension
//string tempFilename = Path.GetFileNameWithoutExtension(this.OutputFilename)
// .Replace('.', '_');
//string tempExtension = Path.GetExtension(this.OutputFilename)?.TrimStart('.');
//this.OutputFilename = $"{tempFilename}.{tempExtension}";
}
/// <summary>
/// Set the parameters object based on the internal program and parameters string
/// </summary>
@@ -330,6 +352,11 @@ namespace MPF.Library
resultProgress?.Report(Result.Success("Disc information skipped!"));
}
// Process special fields for site codes
resultProgress?.Report(Result.Success("Processing site codes..."));
InfoTool.ProcessSpecialFields(submissionInfo);
resultProgress?.Report(Result.Success("Processing complete!"));
// Format the information for the text output
resultProgress?.Report(Result.Success("Formatting information..."));
List<string> formattedValues = InfoTool.FormatOutputData(submissionInfo);

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
<Copyright>Copyright (c)2019-2021</Copyright>
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
<Version>2.2</Version>
<Version>2.3</Version>
<AssemblyVersion>$(Version)</AssemblyVersion>
<FileVersion>$(Version)</FileVersion>
<IncludeSource>true</IncludeSource>

View File

@@ -183,7 +183,8 @@ namespace MPF.Modules.Aaru
break;
default:
return (false, missingFiles); // TODO: Figure out more formats
missingFiles.Add("Media and system combination not supported for Aaru");
break;
}
return (!missingFiles.Any(), missingFiles);
@@ -274,7 +275,8 @@ namespace MPF.Modules.Aaru
case RedumpSystem.KonamiPython2:
if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out Region? pythonTwoRegion, out string pythonTwoDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {pythonTwoSerial}\n";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = pythonTwoSerial ?? string.Empty;
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? pythonTwoRegion;
info.CommonDiscInfo.EXEDateBuildDate = pythonTwoDate;
}
@@ -283,12 +285,12 @@ namespace MPF.Modules.Aaru
break;
case RedumpSystem.MicrosoftXbox:
if (GetXgdAuxInfo(sidecar, out string dmihash, out string pfihash, out string sshash, out string ss, out string ssver))
if (GetXgdAuxInfo(sidecar, out string xgd1DMIHash, out string xgd1PFIHash, out string xgd1SSHash, out string ss, out string xgd1SSVer))
{
info.CommonDiscInfo.Comments += $"{Template.XBOXDMIHash}: {dmihash ?? ""}\n" +
$"{Template.XBOXPFIHash}: {pfihash ?? ""}\n" +
$"{Template.XBOXSSHash}: {sshash ?? ""}\n" +
$"{Template.XBOXSSVersion}: {ssver ?? ""}\n";
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd1DMIHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd1PFIHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd1SSHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd1SSVer;
info.Extras.SecuritySectorRanges = ss ?? "";
}
@@ -302,12 +304,12 @@ namespace MPF.Modules.Aaru
break;
case RedumpSystem.MicrosoftXbox360:
if (GetXgdAuxInfo(sidecar, out string dmi360hash, out string pfi360hash, out string ss360hash, out string ss360, out string ssver360))
if (GetXgdAuxInfo(sidecar, out string xgd23DMIHash, out string xgd23PFIHash, out string xgd23SSHash, out string ss360, out string xgd23SSVer))
{
info.CommonDiscInfo.Comments += $"{Template.XBOXDMIHash}: {dmi360hash ?? ""}\n" +
$"{Template.XBOXPFIHash}: {pfi360hash ?? ""}\n" +
$"{Template.XBOXSSHash}: {ss360hash ?? ""}\n" +
$"{Template.XBOXSSVersion}: {ssver360 ?? ""}\n";
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd23DMIHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd23PFIHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd23SSHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd23SSVer;
info.Extras.SecuritySectorRanges = ss360 ?? "";
}
@@ -322,7 +324,8 @@ namespace MPF.Modules.Aaru
case RedumpSystem.SonyPlayStation:
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out Region? playstationRegion, out string playstationDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {playstationSerial}\n";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationSerial ?? string.Empty;
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion;
info.CommonDiscInfo.EXEDateBuildDate = playstationDate;
}
@@ -332,7 +335,8 @@ namespace MPF.Modules.Aaru
case RedumpSystem.SonyPlayStation2:
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out Region? playstationTwoRegion, out string playstationTwoDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {playstationTwoSerial}\n";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationTwoSerial ?? string.Empty;
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationTwoRegion;
info.CommonDiscInfo.EXEDateBuildDate = playstationTwoDate;
}

View File

@@ -1176,11 +1176,18 @@ namespace MPF.Modules
if (!string.IsNullOrEmpty(bootValue))
{
var match = Regex.Match(bootValue, @"cdrom.?:\\?(.*)");
if (match != null && match.Groups.Count > 1)
if (match.Groups.Count > 1)
{
exeName = match.Groups[1].Value;
exeName = exeName.Split(';')[0];
serial = exeName.Replace('_', '-').Replace(".", string.Empty);
// EXE name may have a trailing `;` after
// EXE name should always be in all caps
exeName = match.Groups[1].Value
.Split(';')[0]
.ToUpperInvariant();
// Serial is most of the EXE name normalized
serial = exeName
.Replace('_', '-')
.Replace(".", string.Empty);
}
}
@@ -1353,9 +1360,9 @@ namespace MPF.Modules
case 'C': return Region.China;
case 'E': return Region.Europe;
case 'J': return Region.JapanKorea;
case 'K': return Region.Korea;
case 'K': return Region.SouthKorea;
case 'P': return Region.Japan;
case 'U': return Region.USA;
case 'U': return Region.UnitedStatesOfAmerica;
}
}

View File

@@ -50,7 +50,8 @@ namespace MPF.Modules.CleanRip
break;
default:
return (false, missingFiles);
missingFiles.Add("Media and system combination not supported for CleanRip");
break;
}
return (!missingFiles.Any(), missingFiles);
@@ -245,7 +246,7 @@ namespace MPF.Modules.CleanRip
region = Region.Germany;
break;
case 'E':
region = Region.USA;
region = Region.UnitedStatesOfAmerica;
break;
case 'F':
region = Region.France;
@@ -257,7 +258,7 @@ namespace MPF.Modules.CleanRip
region = Region.Japan;
break;
case 'K':
region = Region.Korea;
region = Region.SouthKorea;
break;
case 'L':
region = Region.Europe; // Japanese import to Europe
@@ -266,22 +267,22 @@ namespace MPF.Modules.CleanRip
region = Region.Europe; // American import to Europe
break;
case 'N':
region = Region.USA; // Japanese import to USA
region = Region.UnitedStatesOfAmerica; // Japanese import to USA
break;
case 'P':
region = Region.Europe;
break;
case 'R':
region = Region.Russia;
region = Region.RussianFederation;
break;
case 'S':
region = Region.Spain;
break;
case 'Q':
region = Region.Korea; // Korea with Japanese language
region = Region.SouthKorea; // Korea with Japanese language
break;
case 'T':
region = Region.Korea; // Korea with English language
region = Region.SouthKorea; // Korea with English language
break;
case 'X':
region = null; // Not a real region code

View File

@@ -90,7 +90,8 @@ namespace MPF.Modules.DD
case RedumpSystem.KonamiPython2:
if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out Region? pythonTwoRegion, out string pythonTwoDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {pythonTwoSerial}\n";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = pythonTwoSerial ?? string.Empty;
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? pythonTwoRegion;
info.CommonDiscInfo.EXEDateBuildDate = pythonTwoDate;
}
@@ -101,7 +102,8 @@ namespace MPF.Modules.DD
case RedumpSystem.SonyPlayStation:
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out Region? playstationRegion, out string playstationDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {playstationSerial}\n";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationSerial ?? string.Empty;
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion;
info.CommonDiscInfo.EXEDateBuildDate = playstationDate;
}
@@ -111,7 +113,8 @@ namespace MPF.Modules.DD
case RedumpSystem.SonyPlayStation2:
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out Region? playstationTwoRegion, out string playstationTwoDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {playstationTwoSerial}\n";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationTwoSerial ?? string.Empty;
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationTwoRegion;
info.CommonDiscInfo.EXEDateBuildDate = playstationTwoDate;
}

View File

@@ -346,7 +346,8 @@ namespace MPF.Modules.DiscImageCreator
break;
default:
return (false, missingFiles);
missingFiles.Add("Media and system combination not supported for DiscImageCreator");
break;
}
return (!missingFiles.Any(), missingFiles);
@@ -384,7 +385,7 @@ namespace MPF.Modules.DiscImageCreator
}
info.TracksAndWriteOffsets.Cuesheet = GetFullFile(basePath + ".cue") ?? "";
var cueSheet = new CueSheet(basePath + ".cue"); // TODO: Do something with this
//var cueSheet = new CueSheet(basePath + ".cue"); // TODO: Do something with this
// Audio CDs "all have an offset of 0" and should not be included
if (System != RedumpSystem.AudioCD)
@@ -463,7 +464,8 @@ namespace MPF.Modules.DiscImageCreator
case RedumpSystem.KonamiPython2:
if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out Region? pythonTwoRegion, out string pythonTwoDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {pythonTwoSerial}\n";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = pythonTwoSerial ?? string.Empty;
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? pythonTwoRegion;
info.CommonDiscInfo.EXEDateBuildDate = pythonTwoDate;
}
@@ -472,29 +474,45 @@ namespace MPF.Modules.DiscImageCreator
break;
case RedumpSystem.MicrosoftXbox:
case RedumpSystem.MicrosoftXbox360:
string xgdXeMID = string.Empty;
if (this.System == RedumpSystem.MicrosoftXbox)
xgdXeMID = GetXGD1XeMID(Path.Combine(outputDirectory, "DMI.bin"));
else if (this.System == RedumpSystem.MicrosoftXbox360)
xgdXeMID = GetXGD23XeMID(Path.Combine(outputDirectory, "DMI.bin"));
XgdInfo xgdInfo = new XgdInfo(xgdXeMID);
if (xgdInfo?.Initialized == true)
string xgd1XMID = GetXGD1XMID(Path.Combine(outputDirectory, "DMI.bin"));
XgdInfo xgd1Info = new XgdInfo(xgd1XMID);
if (xgd1Info?.Initialized == true)
{
info.CommonDiscInfo.Comments += $"{Template.XBOXXeMID}: {xgdInfo.XeMID ?? ""}\n";
info.CommonDiscInfo.Serial = xgdInfo.GetSerial() ?? "";
info.VersionAndEditions.Version = xgdInfo.GetVersion() ?? "";
info.CommonDiscInfo.Region = xgdInfo.InternalRegion;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.XMID] = xgd1Info.XMID;
info.CommonDiscInfo.Serial = xgd1Info.GetSerial() ?? "";
info.VersionAndEditions.Version = xgd1Info.GetVersion() ?? "";
info.CommonDiscInfo.Region = xgd1Info.InternalRegion;
}
if (GetXGDAuxInfo(basePath + "_disc.txt", out string xgdDMIHash, out string xgdPFIHash, out string xgdSSHash, out string xgdSS, out string xgdSSVer))
if (GetXGDAuxInfo(basePath + "_disc.txt", out string xgd1DMIHash, out string xgd1PFIHash, out string xgd1SSHash, out string xgd1SS, out string xgd1SSVer))
{
info.CommonDiscInfo.Comments += $"{Template.XBOXDMIHash}: {xgdDMIHash ?? ""}\n" +
$"{Template.XBOXPFIHash}: {xgdPFIHash ?? ""}\n" +
$"{Template.XBOXSSHash}: {xgdSSHash ?? ""}\n" +
$"{Template.XBOXSSVersion}: {xgdSSVer ?? ""}\n";
info.Extras.SecuritySectorRanges = xgdSS ?? "";
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd1DMIHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd1PFIHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd1SSHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd1SSVer;
info.Extras.SecuritySectorRanges = xgd1SS ?? "";
}
break;
case RedumpSystem.MicrosoftXbox360:
string xgd23XeMID = GetXGD23XeMID(Path.Combine(outputDirectory, "DMI.bin"));
XgdInfo xgd23Info = new XgdInfo(xgd23XeMID);
if (xgd23Info?.Initialized == true)
{
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.XeMID] = xgd23Info.XMID;
info.CommonDiscInfo.Serial = xgd23Info.GetSerial() ?? "";
info.VersionAndEditions.Version = xgd23Info.GetVersion() ?? "";
info.CommonDiscInfo.Region = xgd23Info.InternalRegion;
}
if (GetXGDAuxInfo(basePath + "_disc.txt", out string xgd23DMIHash, out string xgd23PFIHash, out string xgd23SSHash, out string xgd23SS, out string xgd23SSVer))
{
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd23DMIHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd23PFIHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd23SSHash;
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd23SSVer;
info.Extras.SecuritySectorRanges = xgd23SS ?? "";
}
break;
@@ -510,7 +528,8 @@ namespace MPF.Modules.DiscImageCreator
if (GetGDROMBuildInfo(info.Extras.Header, out string gdSerial, out string gdVersion, out string gdDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {gdSerial ?? ""}";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = gdSerial ?? string.Empty;
info.VersionAndEditions.Version = gdVersion ?? "";
info.CommonDiscInfo.EXEDateBuildDate = gdDate ?? "";
}
@@ -527,7 +546,8 @@ namespace MPF.Modules.DiscImageCreator
if (GetSegaCDBuildInfo(info.Extras.Header, out string scdSerial, out string fixedDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {scdSerial ?? ""}";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = scdSerial ?? string.Empty;
info.CommonDiscInfo.EXEDateBuildDate = fixedDate ?? "";
}
@@ -544,7 +564,8 @@ namespace MPF.Modules.DiscImageCreator
if (GetGDROMBuildInfo(info.Extras.Header, out string gdSerial, out string gdVersion, out string gdDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {gdSerial ?? ""}";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = gdSerial ?? string.Empty;
info.VersionAndEditions.Version = gdVersion ?? "";
info.CommonDiscInfo.EXEDateBuildDate = gdDate ?? "";
}
@@ -563,7 +584,8 @@ namespace MPF.Modules.DiscImageCreator
if (GetGDROMBuildInfo(info.Extras.Header, out string gdSerial, out string gdVersion, out string gdDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {gdSerial ?? ""}";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = gdSerial ?? string.Empty;
info.VersionAndEditions.Version = gdVersion ?? "";
info.CommonDiscInfo.EXEDateBuildDate = gdDate ?? "";
}
@@ -582,7 +604,8 @@ namespace MPF.Modules.DiscImageCreator
if (GetGDROMBuildInfo(info.Extras.Header, out string gdSerial, out string gdVersion, out string gdDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {gdSerial ?? ""}";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = gdSerial ?? string.Empty;
info.VersionAndEditions.Version = gdVersion ?? "";
info.CommonDiscInfo.EXEDateBuildDate = gdDate ?? "";
}
@@ -601,7 +624,8 @@ namespace MPF.Modules.DiscImageCreator
if (GetGDROMBuildInfo(info.Extras.Header, out string gdSerial, out string gdVersion, out string gdDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {gdSerial ?? ""}";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = gdSerial ?? string.Empty;
info.VersionAndEditions.Version = gdVersion ?? "";
info.CommonDiscInfo.EXEDateBuildDate = gdDate ?? "";
}
@@ -618,7 +642,8 @@ namespace MPF.Modules.DiscImageCreator
if (GetSaturnBuildInfo(info.Extras.Header, out string saturnSerial, out string saturnVersion, out string buildDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {saturnSerial ?? ""}";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = saturnSerial ?? string.Empty;
info.VersionAndEditions.Version = saturnVersion ?? "";
info.CommonDiscInfo.EXEDateBuildDate = buildDate ?? "";
}
@@ -628,7 +653,8 @@ namespace MPF.Modules.DiscImageCreator
case RedumpSystem.SonyPlayStation:
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out Region? playstationRegion, out string playstationDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {playstationSerial ?? ""}\n";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationSerial ?? string.Empty;
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion;
info.CommonDiscInfo.EXEDateBuildDate = playstationDate;
}
@@ -652,7 +678,8 @@ namespace MPF.Modules.DiscImageCreator
case RedumpSystem.SonyPlayStation2:
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out Region? playstationTwoRegion, out string playstationTwoDate))
{
info.CommonDiscInfo.Comments += $"{Constants.InternalSerialNameCommentField} {playstationTwoSerial}\n";
// Ensure internal serial is pulled from local data
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationTwoSerial ?? string.Empty;
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationTwoRegion;
info.CommonDiscInfo.EXEDateBuildDate = playstationTwoDate;
}
@@ -680,6 +707,8 @@ namespace MPF.Modules.DiscImageCreator
info.Artifacts["ccd"] = GetBase64(GetFullFile(basePath + ".ccd"));
if (File.Exists(basePath + "_cmd.txt")) // TODO: Figure out how to read in the timestamp-named file
info.Artifacts["cmd"] = GetBase64(GetFullFile(basePath + "_cmd.txt"));
if (File.Exists(basePath + "_CSSKey.txt"))
info.Artifacts["csskey"] = GetBase64(GetFullFile(basePath + "_CSSKey.txt"));
if (File.Exists(basePath + ".cue"))
info.Artifacts["cue"] = GetBase64(GetFullFile(basePath + ".cue"));
if (File.Exists(basePath + ".dat"))
@@ -1424,8 +1453,6 @@ namespace MPF.Modules.DiscImageCreator
logFiles.Add(cmdPath);
if (File.Exists($"{basePath}_cmd.txt"))
logFiles.Add($"{basePath}_cmd.txt");
if (File.Exists($"{basePath}_CSSKey.txt"))
logFiles.Add($"{basePath}_CSSKey.txt");
if (File.Exists($"{basePath}.dat"))
logFiles.Add($"{basePath}.dat");
if (File.Exists($"{basePath}.sub"))
@@ -1470,6 +1497,8 @@ namespace MPF.Modules.DiscImageCreator
logFiles.Add(cmdPath);
if (File.Exists($"{basePath}_cmd.txt"))
logFiles.Add($"{basePath}_cmd.txt");
if (File.Exists($"{basePath}_CSSKey.txt"))
logFiles.Add($"{basePath}_CSSKey.txt");
if (File.Exists($"{basePath}.dat"))
logFiles.Add($"{basePath}.dat");
if (File.Exists($"{basePath}_disc.txt"))
@@ -2899,9 +2928,10 @@ namespace MPF.Modules.DiscImageCreator
string[] header = segaHeader.Split('\n');
string serialVersionLine = header[2].Substring(58);
string dateLine = header[3].Substring(58);
serial = serialVersionLine.Substring(0, 8);
serial = serialVersionLine.Substring(0, 10).Trim();
version = serialVersionLine.Substring(10, 6).TrimStart('V', 'v');
date = dateLine.Substring(0, 8);
date = $"{date[0]}{date[1]}{date[2]}{date[3]}-{date[4]}{date[5]}-{date[6]}{date[7]}";
return true;
}
catch
@@ -2931,7 +2961,7 @@ namespace MPF.Modules.DiscImageCreator
string[] header = segaHeader.Split('\n');
string serialVersionLine = header[8].Substring(58);
string dateLine = header[1].Substring(58);
serial = serialVersionLine.Substring(3, 7);
serial = serialVersionLine.Substring(3, 8).TrimEnd('-', ' ');
date = dateLine.Substring(8).Trim();
// Properly format the date string, if possible
@@ -3165,11 +3195,11 @@ namespace MPF.Modules.DiscImageCreator
}
/// <summary>
/// Get the XGD1 Master ID (XeMID) information
/// Get the XGD1 Master ID (XMID) information
/// </summary>
/// <param name="dmi">DMI.bin file location</param>
/// <returns>String representation of the XGD1 DMI information, empty string on error</returns>
private static string GetXGD1XeMID(string dmi)
private static string GetXGD1XMID(string dmi)
{
if (!File.Exists(dmi))
return string.Empty;

View File

@@ -6,7 +6,7 @@
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
<Copyright>Copyright (c)2019-2021</Copyright>
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
<Version>2.2</Version>
<Version>2.3</Version>
<AssemblyVersion>$(Version)</AssemblyVersion>
<FileVersion>$(Version)</FileVersion>
<IncludeSource>true</IncludeSource>

View File

@@ -52,7 +52,8 @@ namespace MPF.Modules.UmdImageCreator
break;
default:
return (false, missingFiles);
missingFiles.Add("Media and system combination not supported for UmdImageCreator");
break;
}
return (!missingFiles.Any(), missingFiles);

View File

@@ -1,4 +1,5 @@
using MPF.Library;
using System.Collections.Generic;
using MPF.Library;
using RedumpLib.Data;
using Xunit;
@@ -61,5 +62,135 @@ namespace MPF.Test.Library
Assert.Equal(expectedOutputDirectory, actualOutputDirectory);
Assert.Equal(expectedOutputFilename, actualOutputFilename);
}
[Fact]
public void ProcessSpecialFieldsCompleteTest()
{
// Create a new SubmissionInfo object
SubmissionInfo info = new SubmissionInfo()
{
CommonDiscInfo = new CommonDiscInfoSection()
{
Comments = "This is a comments line\n[T:ISBN] ISBN Value",
CommentsSpecialFields = new Dictionary<SiteCode?, string>()
{
[SiteCode.VolumeLabel] = "VOLUME_LABEL",
},
Contents = "This is a contents line\n[T:GF] Game Footage",
ContentsSpecialFields = new Dictionary<SiteCode?, string>()
{
[SiteCode.Patches] = "1.04 patch",
},
}
};
// Process the special fields
InfoTool.ProcessSpecialFields(info);
// Validate the basics
Assert.NotNull(info.CommonDiscInfo.Comments);
Assert.Null(info.CommonDiscInfo.CommentsSpecialFields);
Assert.NotNull(info.CommonDiscInfo.Contents);
Assert.Null(info.CommonDiscInfo.ContentsSpecialFields);
// Split the values
string[] splitComments = info.CommonDiscInfo.Comments.Split('\n');
string[] splitContents = info.CommonDiscInfo.Contents.Split('\n');
// Validate the lines
Assert.Equal(3, splitComments.Length);
Assert.Equal(5, splitContents.Length);
}
[Fact]
public void ProcessSpecialFieldsNullObjectTest()
{
// Create a new SubmissionInfo object
SubmissionInfo info = new SubmissionInfo()
{
CommonDiscInfo = null,
};
// Process the special fields
InfoTool.ProcessSpecialFields(info);
// Validate
Assert.Null(info.CommonDiscInfo);
}
[Fact]
public void ProcessSpecialFieldsNullCommentsContentsTest()
{
// Create a new SubmissionInfo object
SubmissionInfo info = new SubmissionInfo()
{
CommonDiscInfo = new CommonDiscInfoSection()
{
Comments = null,
CommentsSpecialFields = new Dictionary<SiteCode?, string>()
{
[SiteCode.VolumeLabel] = "VOLUME_LABEL",
},
Contents = null,
ContentsSpecialFields = new Dictionary<SiteCode?, string>()
{
[SiteCode.Patches] = "1.04 patch",
},
}
};
// Process the special fields
InfoTool.ProcessSpecialFields(info);
// Validate the basics
Assert.NotNull(info.CommonDiscInfo.Comments);
Assert.Null(info.CommonDiscInfo.CommentsSpecialFields);
Assert.NotNull(info.CommonDiscInfo.Contents);
Assert.Null(info.CommonDiscInfo.ContentsSpecialFields);
// Split the values
string[] splitComments = info.CommonDiscInfo.Comments.Split('\n');
string[] splitContents = info.CommonDiscInfo.Contents.Split('\n');
// Validate the lines
Assert.Single(splitComments);
Assert.Equal(2, splitContents.Length);
}
[Fact]
public void ProcessSpecialFieldsNullDictionariesTest()
{
// Create a new SubmissionInfo object
SubmissionInfo info = new SubmissionInfo()
{
CommonDiscInfo = new CommonDiscInfoSection()
{
Comments = "This is a comments line\n[T:ISBN] ISBN Value",
CommentsSpecialFields = null,
Contents = "This is a contents line\n[T:GF] Game Footage",
ContentsSpecialFields = null,
}
};
// Process the special fields
InfoTool.ProcessSpecialFields(info);
// Validate the basics
Assert.NotNull(info.CommonDiscInfo.Comments);
Assert.Null(info.CommonDiscInfo.CommentsSpecialFields);
Assert.NotNull(info.CommonDiscInfo.Contents);
Assert.Null(info.CommonDiscInfo.ContentsSpecialFields);
// Split the values
string[] splitComments = info.CommonDiscInfo.Comments.Split('\n');
string[] splitContents = info.CommonDiscInfo.Contents.Split('\n');
// Validate the lines
Assert.Equal(2, splitComments.Length);
Assert.Equal(2, splitContents.Length);
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using RedumpLib.Data;
using Xunit;
@@ -250,6 +251,87 @@ namespace MPF.Test.RedumpLib
Assert.NotNull(actual);
}
/// <summary>
/// Ensure that every Language that has an ISO 639-1 code is unique
/// </summary>
[Fact]
public void LanguageNoDuplicateTwoLetterCodeTest()
{
var fullLanguages = Enum.GetValues(typeof(Language)).Cast<Language?>().ToList();
var filteredLanguages = new Dictionary<string, Language?>();
int totalCount = 0;
foreach (Language? language in fullLanguages)
{
string code = language.TwoLetterCode();
if (string.IsNullOrWhiteSpace(code))
continue;
// Throw if the code already exists
if (filteredLanguages.ContainsKey(code))
throw new DuplicateNameException($"Code {code} already in dictionary");
filteredLanguages[code] = language;
totalCount++;
}
Assert.Equal(totalCount, filteredLanguages.Count);
}
/// <summary>
/// Ensure that every Language that has a standard/bibliographic ISO 639-2 code is unique
/// </summary>
[Fact]
public void LanguageNoDuplicateThreeLetterCodeTest()
{
var fullLanguages = Enum.GetValues(typeof(Language)).Cast<Language?>().ToList();
var filteredLanguages = new Dictionary<string, Language?>();
int totalCount = 0;
foreach (Language? language in fullLanguages)
{
string code = language.ThreeLetterCode();
if (string.IsNullOrWhiteSpace(code))
continue;
// Throw if the code already exists
if (filteredLanguages.ContainsKey(code))
throw new DuplicateNameException($"Code {code} already in dictionary");
filteredLanguages[code] = language;
totalCount++;
}
Assert.Equal(totalCount, filteredLanguages.Count);
}
/// <summary>
/// Ensure that every Language that has a terminology ISO 639-2 code is unique
/// </summary>
[Fact]
public void LanguageNoDuplicateThreeLetterCodeAltTest()
{
var fullLanguages = Enum.GetValues(typeof(Language)).Cast<Language?>().ToList();
var filteredLanguages = new Dictionary<string, Language?>();
int totalCount = 0;
foreach (Language? language in fullLanguages)
{
string code = language.ThreeLetterCodeAlt();
if (string.IsNullOrWhiteSpace(code))
continue;
// Throw if the code already exists
if (filteredLanguages.ContainsKey(code))
throw new DuplicateNameException($"Code {code} already in dictionary");
filteredLanguages[code] = language;
totalCount++;
}
Assert.Equal(totalCount, filteredLanguages.Count);
}
/// <summary>
/// Generate a test set of Language values
/// </summary>
@@ -392,6 +474,33 @@ namespace MPF.Test.RedumpLib
Assert.NotNull(actual);
}
/// <summary>
/// Ensure that every Language that has an ISO 639-1 code is unique
/// </summary>
[Fact]
public void RegionNoDuplicateShortNameTest()
{
var fullRegions = Enum.GetValues(typeof(Region)).Cast<Region?>().ToList();
var filteredRegions = new Dictionary<string, Region?>();
int totalCount = 0;
foreach (Region? region in fullRegions)
{
string code = region.ShortName();
if (string.IsNullOrWhiteSpace(code))
continue;
// Throw if the code already exists
if (filteredRegions.ContainsKey(code))
throw new DuplicateNameException($"Code {code} already in dictionary");
filteredRegions[code] = region;
totalCount++;
}
Assert.Equal(totalCount, filteredRegions.Count);
}
/// <summary>
/// Generate a test set of Region values
/// </summary>
@@ -409,6 +518,59 @@ namespace MPF.Test.RedumpLib
#endregion
#region Site Code
/// <summary>
/// Check that every SiteCode has a long name provided
/// </summary>
/// <param name="siteCode">SiteCode value to check</param>
/// <param name="expectNull">True to expect a null value, false otherwise</param>
[Theory]
[MemberData(nameof(GenerateSiteCodeTestData))]
public void SiteCodeLongNameTest(SiteCode? siteCode, bool expectNull)
{
string actual = siteCode.LongName();
if (expectNull)
Assert.Null(actual);
else
Assert.NotNull(actual);
}
/// <summary>
/// Check that every SiteCode has a short name provided
/// </summary>
/// <param name="siteCode">SiteCode value to check</param>
/// <param name="expectNull">True to expect a null value, false otherwise</param>
[Theory]
[MemberData(nameof(GenerateSiteCodeTestData))]
public void SiteCodeShortNameTest(SiteCode? siteCode, bool expectNull)
{
string actual = siteCode.ShortName();
if (expectNull)
Assert.Null(actual);
else
Assert.NotNull(actual);
}
/// <summary>
/// Generate a test set of SiteCode values
/// </summary>
/// <returns>MemberData-compatible list of SiteCode values</returns>
public static List<object[]> GenerateSiteCodeTestData()
{
var testData = new List<object[]>() { new object[] { null, true } };
foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode)))
{
testData.Add(new object[] { siteCode, false });
}
return testData;
}
#endregion
#region System
/// <summary>

View File

@@ -79,8 +79,16 @@ namespace MPF.Test.RedumpLib
Barcode = "UPC Barcode",
EXEDateBuildDate = "19xx-xx-xx",
ErrorsCount = "0",
Comments = "[T:ISBN] ISBN\r\nComment data",
Contents = "Demos:\r\n- Game Demo 1",
Comments = "Comment data line 1\r\nComment data line 2",
CommentsSpecialFields = new Dictionary<SiteCode?, string>()
{
[SiteCode.ISBN] = "ISBN",
},
Contents = "Special contents 1\r\nSpecial contents 2",
ContentsSpecialFields = new Dictionary<SiteCode?, string>()
{
[SiteCode.PlayableDemos] = "Game Demo 1",
},
},
VersionAndEditions = new VersionAndEditionsSection()

View File

Before

Width:  |  Height:  |  Size: 423 KiB

After

Width:  |  Height:  |  Size: 423 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -13,7 +13,7 @@
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
<Copyright>Copyright (c)2019-2021</Copyright>
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
<Version>2.2</Version>
<Version>2.3</Version>
<AssemblyVersion>$(Version)</AssemblyVersion>
<FileVersion>$(Version)</FileVersion>
<IncludeSource>true</IncludeSource>
@@ -41,9 +41,14 @@
<Content Include="$(PkgBurnOutSharp)\content\**" PackagePath="contentFiles\any\any;content" CopyToOutputDirectory="Always" PackageCopyToOutput="true" />
</ItemGroup>
<ItemGroup>
<None Remove="Images\ring-code-guide-2-layer.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Images\Icon.ico" />
<Resource Include="Images\ring-code-guide.png" />
<Resource Include="Images\ring-code-guide-2-layer.png" />
<Resource Include="Images\ring-code-guide-1-layer.png" />
</ItemGroup>
<ItemGroup>

View File

@@ -6,7 +6,7 @@
d:DesignHeight="450" d:DesignWidth="800" x:Name="userInput">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="0.75*" />
<ColumnDefinition Width="1.25*" />
</Grid.ColumnDefinitions>
@@ -22,7 +22,9 @@
AcceptsTab="{Binding ElementName=userInput, Path=Tab}"
AcceptsReturn="{Binding ElementName=userInput, Path=Enter}"
TextWrapping="{Binding ElementName=userInput, Path=TextWrapping}"
IsReadOnly="{Binding ElementName=userInput, Path=IsReadOnly}"
VerticalContentAlignment="{Binding ElementName=userInput, Path=VerticalContentAlignmentValue}"
VerticalScrollBarVisibility="{Binding ElementName=userInput, Path=ScrollBarVisibility}"/>
HorizontalScrollBarVisibility="{Binding ElementName=userInput, Path=HorizontalScrollBarVisibility}"
VerticalScrollBarVisibility="{Binding ElementName=userInput, Path=VerticalScrollBarVisibility}"/>
</Grid>
</UserControl>

View File

@@ -28,11 +28,17 @@ namespace MPF.UserControls
public static readonly DependencyProperty TextWrappingProperty =
DependencyProperty.Register("TextWrapping", typeof(TextWrapping), typeof(UserInput));
public static readonly DependencyProperty IsReadOnlyProperty =
DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(UserInput));
public static readonly DependencyProperty VerticalContentAlignmentValueProperty =
DependencyProperty.Register("VerticalContentAlignmentValue", typeof(VerticalAlignment), typeof(UserInput));
public static readonly DependencyProperty ScrollBarVisibilityProperty =
DependencyProperty.Register("ScrollBarVisibility", typeof(ScrollBarVisibility), typeof(UserInput));
public static readonly DependencyProperty HorizontalScrollBarVisibilityProperty =
DependencyProperty.Register("HorizontalScrollBarVisibility", typeof(ScrollBarVisibility), typeof(UserInput));
public static readonly DependencyProperty VerticalScrollBarVisibilityProperty =
DependencyProperty.Register("VerticalScrollBarVisibility", typeof(ScrollBarVisibility), typeof(UserInput));
#endregion
@@ -74,16 +80,28 @@ namespace MPF.UserControls
set => SetValue(TextWrappingProperty, value);
}
public bool IsReadOnly
{
get => (bool)GetValue(IsReadOnlyProperty);
set => SetValue(IsReadOnlyProperty, value);
}
public VerticalAlignment VerticalContentAlignmentValue
{
get => (VerticalAlignment)GetValue(VerticalContentAlignmentValueProperty);
set => SetValue(VerticalContentAlignmentValueProperty, value);
}
public ScrollBarVisibility ScrollBarVisibility
public ScrollBarVisibility HorizontalScrollBarVisibility
{
get => (ScrollBarVisibility)GetValue(ScrollBarVisibilityProperty);
set => SetValue(ScrollBarVisibilityProperty, value);
get => (ScrollBarVisibility)GetValue(HorizontalScrollBarVisibilityProperty);
set => SetValue(HorizontalScrollBarVisibilityProperty, value);
}
public ScrollBarVisibility VerticalScrollBarVisibility
{
get => (ScrollBarVisibility)GetValue(VerticalScrollBarVisibilityProperty);
set => SetValue(VerticalScrollBarVisibilityProperty, value);
}
#endregion
@@ -96,8 +114,10 @@ namespace MPF.UserControls
Tab = false;
Enter = false;
TextWrapping = TextWrapping.NoWrap;
IsReadOnly = false;
VerticalContentAlignmentValue = VerticalAlignment.Center;
ScrollBarVisibility = ScrollBarVisibility.Auto;
HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
InitializeComponent();
}

View File

@@ -67,16 +67,379 @@ namespace MPF.GUI.ViewModels
#region Helpers
/// <summary>
/// Enable tab entry on supported fields
/// </summary>
private void EnableTabsInInputFields()
{
// Additional Information
Parent.CommentsTextBox.Tab = true;
Parent.GeneralContent.Tab = true;
Parent.ExtrasTextBox.Tab = true;
Parent.GameFootageTextBox.Tab = true;
Parent.NetYarozeGamesTextBox.Tab = true;
Parent.PatchesTextBox.Tab = true;
Parent.PlayableDemosTextBox.Tab = true;
Parent.RollingDemosTextBox.Tab = true;
Parent.SavegamesTextBox.Tab = true;
Parent.TechDemosTextBox.Tab = true;
// L0
Parent.L0MasteringRing.Tab = true;
Parent.L0MasteringSID.Tab = true;
Parent.L0Toolstamp.Tab = true;
Parent.L0MouldSID.Tab = true;
Parent.L0AdditionalMould.Tab = true;
// L1
Parent.L1MasteringRing.Tab = true;
Parent.L1MasteringSID.Tab = true;
Parent.L1Toolstamp.Tab = true;
Parent.L1MouldSID.Tab = true;
Parent.L1AdditionalMould.Tab = true;
// L2
Parent.L2MasteringRing.Tab = true;
Parent.L2MasteringSID.Tab = true;
Parent.L2Toolstamp.Tab = true;
// L3
Parent.L3MasteringRing.Tab = true;
Parent.L3MasteringSID.Tab = true;
Parent.L3Toolstamp.Tab = true;
}
/// <summary>
/// Hide any optional, read-only fields if they don't have a value
/// </summary>
private void HideReadOnlyFields()
{
if (SubmissionInfo?.MatchedIDs == null)
Parent.MatchedIDs.Visibility = Visibility.Collapsed;
else
Parent.MatchedIDs.Text = string.Join(", ", SubmissionInfo.MatchedIDs);
if (SubmissionInfo?.CopyProtection?.AntiModchip == null)
Parent.AntiModchip.Visibility = Visibility.Collapsed;
else
Parent.AntiModchip.Text = SubmissionInfo.CopyProtection.AntiModchip.LongName();
if (SubmissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.DMIHash) != true)
Parent.DMIHash.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(SubmissionInfo?.CommonDiscInfo?.ErrorsCount))
Parent.ErrorsCount.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(SubmissionInfo?.CommonDiscInfo?.EXEDateBuildDate))
Parent.EXEDateBuildDate.Visibility = Visibility.Collapsed;
if (SubmissionInfo?.EDC?.EDC == null)
Parent.EDC.Visibility = Visibility.Collapsed;
else
Parent.EDC.Text = SubmissionInfo.EDC.EDC.LongName();
if (string.IsNullOrWhiteSpace(SubmissionInfo?.Extras?.Header))
Parent.Header.Visibility = Visibility.Collapsed;
if (SubmissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.InternalSerialName) != true)
Parent.InternalSerialName.Visibility = Visibility.Collapsed;
if (SubmissionInfo?.CopyProtection?.LibCrypt == null)
Parent.LibCrypt.Visibility = Visibility.Collapsed;
else
Parent.LibCrypt.Text = SubmissionInfo.CopyProtection.LibCrypt.LongName();
if (string.IsNullOrWhiteSpace(SubmissionInfo?.CopyProtection?.LibCryptData))
Parent.LibCryptData.Visibility = Visibility.Collapsed;
if (SubmissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.PFIHash) != true)
Parent.PFIHash.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(SubmissionInfo?.Extras?.PIC))
Parent.PIC.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(SubmissionInfo?.CopyProtection?.Protection))
Parent.Protection.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(SubmissionInfo?.Extras?.PVD))
Parent.PVD.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(SubmissionInfo?.CopyProtection?.SecuROMData))
Parent.SecuROMData.Visibility = Visibility.Collapsed;
if (SubmissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.SSHash) != true)
Parent.SSHash.Visibility = Visibility.Collapsed;
if (string.IsNullOrWhiteSpace(SubmissionInfo?.Extras?.SecuritySectorRanges))
Parent.SecuritySectorRanges.Visibility = Visibility.Collapsed;
if (SubmissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.SSVersion) != true)
Parent.SSVersion.Visibility = Visibility.Collapsed;
if (SubmissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.VolumeLabel) != true)
Parent.VolumeLabel.Visibility = Visibility.Collapsed;
if (SubmissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.XeMID) != true)
Parent.XeMID.Visibility = Visibility.Collapsed;
if (SubmissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.XMID) != true)
Parent.XMID.Visibility = Visibility.Collapsed;
}
/// <summary>
/// Manipulate fields based on the current disc
/// </summary>
private void ManipulateFields()
{
// Enable tabs in all fields, if required
if (App.Options.EnableTabsInInputFields)
EnableTabsInInputFields();
// Hide read-only fields that don't have values set
HideReadOnlyFields();
// Different media types mean different fields available
UpdateFromDiscType();
// Different systems mean different fields available
UpdateFromSystemType();
}
/// <summary>
/// Load the current contents of the base SubmissionInfo to the UI
/// </summary>
private void Load()
{
Parent.CategoryComboBox.SelectedIndex = Categories.FindIndex(r => r == SubmissionInfo.CommonDiscInfo.Category);
Parent.RegionComboBox.SelectedIndex = Regions.FindIndex(r => r == SubmissionInfo.CommonDiscInfo.Region);
if (SubmissionInfo.CommonDiscInfo.Languages != null)
Languages.ForEach(l => l.IsChecked = SubmissionInfo.CommonDiscInfo.Languages.Contains(l));
if (SubmissionInfo.CommonDiscInfo.LanguageSelection != null)
LanguageSelections.ForEach(ls => ls.IsChecked = SubmissionInfo.CommonDiscInfo.LanguageSelection.Contains(ls));
// TODO: Figure out if this can be automatically mapped instead
// Comment Fields
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields != null)
{
// Additional Information
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.AlternativeTitle))
Parent.AlternativeTitleTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.AlternativeTitle];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.AlternativeForeignTitle))
Parent.AlternativeForeignTitleTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.AlternativeForeignTitle];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.Genre))
Parent.GenreTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.Genre];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.PostgapType))
Parent.PostgapTypeCheckBox.IsChecked = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.PostgapType] != null;
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.Series))
Parent.SeriesTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.Series];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.VCD))
Parent.VCDCheckBox.IsChecked = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.VCD] != null;
// Physical Identifiers
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.BBFCRegistrationNumber))
Parent.BBFCRegistrationNumberTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.BBFCRegistrationNumber];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.DiscHologramID))
Parent.DiscHologramIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.DiscHologramID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.DNASDiscID))
Parent.DNASDiscIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.DNASDiscID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.ISBN))
Parent.ISBNTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.ISBN];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.ISSN))
Parent.ISSNTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.ISSN];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.PPN))
Parent.PPNTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.PPN];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.VFCCode))
Parent.VFCCodeTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.VFCCode];
// Publisher Identifiers
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.AcclaimID))
Parent.AcclaimIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.AcclaimID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.ActivisionID))
Parent.ActivisionIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.ActivisionID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.BandaiID))
Parent.BandaiIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.BandaiID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.ElectronicArtsID))
Parent.ElectronicArtsIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.ElectronicArtsID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.FoxInteractiveID))
Parent.FoxInteractiveIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.FoxInteractiveID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.GTInteractiveID))
Parent.GTInteractiveIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.GTInteractiveID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.JASRACID))
Parent.JASRACIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.JASRACID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.KingRecordsID))
Parent.KingRecordsIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.KingRecordsID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.KoeiID))
Parent.KoeiIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.KoeiID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.KonamiID))
Parent.KonamiIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.KonamiID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.LucasArtsID))
Parent.LucasArtsIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.LucasArtsID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.MicrosoftID))
Parent.MicrosoftIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.MicrosoftID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.NaganoID))
Parent.NaganoIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.NaganoID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.NamcoID))
Parent.NamcoIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.NamcoID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.NipponIchiSoftwareID))
Parent.NipponIchiSoftwareIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.NipponIchiSoftwareID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.OriginID))
Parent.OriginIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.OriginID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.PonyCanyonID))
Parent.PonyCanyonIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.PonyCanyonID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.SegaID))
Parent.SegaIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.SegaID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.SelenID))
Parent.SelenIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.SelenID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.SierraID))
Parent.SierraIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.SierraID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.TaitoID))
Parent.TaitoIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.TaitoID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.UbisoftID))
Parent.UbisoftIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.UbisoftID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.ValveID))
Parent.ValveIDTextBox.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.ValveID];
// Read-Only Information
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.DMIHash))
Parent.DMIHash.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.InternalSerialName))
Parent.InternalSerialName.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.PFIHash))
Parent.PFIHash.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.SSHash))
Parent.SSHash.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.SSVersion))
Parent.SSVersion.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.VolumeLabel))
Parent.VolumeLabel.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.VolumeLabel];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.XeMID))
Parent.XeMID.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.XeMID];
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.XMID))
Parent.XMID.Text = SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.XMID];
}
// Content Fields
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields != null)
{
// Games
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields.ContainsKey(SiteCode.Games))
Parent.GamesTextBox.Text = SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.Games];
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields.ContainsKey(SiteCode.NetYarozeGames))
Parent.NetYarozeGamesTextBox.Text = SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.NetYarozeGames];
// Demos
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields.ContainsKey(SiteCode.PlayableDemos))
Parent.PlayableDemosTextBox.Text = SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.PlayableDemos];
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields.ContainsKey(SiteCode.RollingDemos))
Parent.RollingDemosTextBox.Text = SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.RollingDemos];
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields.ContainsKey(SiteCode.TechDemos))
Parent.TechDemosTextBox.Text = SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.TechDemos];
// Video
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields.ContainsKey(SiteCode.GameFootage))
Parent.GameFootageTextBox.Text = SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.GameFootage];
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields.ContainsKey(SiteCode.Videos))
Parent.VideosTextBox.Text = SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.Videos];
// Miscellaneous
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields.ContainsKey(SiteCode.Patches))
Parent.PatchesTextBox.Text = SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.Patches];
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields.ContainsKey(SiteCode.Savegames))
Parent.SavegamesTextBox.Text = SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.Savegames];
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields.ContainsKey(SiteCode.Extras))
Parent.ExtrasTextBox.Text = SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.Extras];
}
}
/// <summary>
/// Save the current contents of the UI to the base SubmissionInfo
/// </summary>
public void Save()
{
SubmissionInfo.CommonDiscInfo.Category = (Parent.CategoryComboBox.SelectedItem as Element<DiscCategory>)?.Value ?? DiscCategory.Games;
SubmissionInfo.CommonDiscInfo.Region = (Parent.RegionComboBox.SelectedItem as Element<Region>)?.Value ?? Region.World;
SubmissionInfo.CommonDiscInfo.Languages = Languages.Where(l => l.IsChecked).Select(l => l?.Value).ToArray();
if (!SubmissionInfo.CommonDiscInfo.Languages.Any())
SubmissionInfo.CommonDiscInfo.Languages = new Language?[] { null };
SubmissionInfo.CommonDiscInfo.LanguageSelection = LanguageSelections.Where(ls => ls.IsChecked).Select(ls => ls?.Value).ToArray();
// TODO: Figure out if this can be automatically mapped instead
// Initialize the dictionaries, if needed
if (SubmissionInfo.CommonDiscInfo.CommentsSpecialFields == null)
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
if (SubmissionInfo.CommonDiscInfo.ContentsSpecialFields == null)
SubmissionInfo.CommonDiscInfo.ContentsSpecialFields = new Dictionary<SiteCode?, string>();
#region Comment Fields
// Additional Information
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.AlternativeTitle] = Parent.AlternativeTitleTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.AlternativeForeignTitle] = Parent.AlternativeForeignTitleTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.Genre] = Parent.GenreTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.PostgapType] = Parent.PostgapTypeCheckBox.IsChecked?.ToString();
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.Series] = Parent.SeriesTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.VCD] = Parent.VCDCheckBox.IsChecked?.ToString();
// Physical Identifiers
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.BBFCRegistrationNumber] = Parent.BBFCRegistrationNumberTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.DiscHologramID] = Parent.DiscHologramIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.DNASDiscID] = Parent.DNASDiscIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.ISBN] = Parent.ISBNTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.ISSN] = Parent.ISSNTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.PPN] = Parent.PPNTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.VFCCode] = Parent.VFCCodeTextBox.Text;
// Publisher Identifiers
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.AcclaimID] = Parent.AcclaimIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.ActivisionID] = Parent.ActivisionIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.BandaiID] = Parent.BandaiIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.ElectronicArtsID] = Parent.ElectronicArtsIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.FoxInteractiveID] = Parent.FoxInteractiveIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.GTInteractiveID] = Parent.GTInteractiveIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.JASRACID] = Parent.JASRACIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.KingRecordsID] = Parent.KingRecordsIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.KoeiID] = Parent.KoeiIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.KonamiID] = Parent.KonamiIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.LucasArtsID] = Parent.LucasArtsIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.MicrosoftID] = Parent.MicrosoftIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.NaganoID] = Parent.NaganoIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.NamcoID] = Parent.NamcoIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.NipponIchiSoftwareID] = Parent.NipponIchiSoftwareIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.OriginID] = Parent.OriginIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.PonyCanyonID] = Parent.PonyCanyonIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.SegaID] = Parent.SegaIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.SelenID] = Parent.SelenIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.SierraID] = Parent.SierraIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.TaitoID] = Parent.TaitoIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.UbisoftID] = Parent.UbisoftIDTextBox.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.ValveID] = Parent.ValveIDTextBox.Text;
// Read-Only Information
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = Parent.DMIHash.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = Parent.InternalSerialName.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = Parent.PFIHash.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = Parent.SSHash.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = Parent.SSVersion.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.VolumeLabel] = Parent.VolumeLabel.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.XeMID] = Parent.XeMID.Text;
SubmissionInfo.CommonDiscInfo.CommentsSpecialFields[SiteCode.XMID] = Parent.XMID.Text;
#endregion
#region Content Fields
// Games
SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.Games] = Parent.GamesTextBox.Text;
SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.NetYarozeGames] = Parent.NetYarozeGamesTextBox.Text;
// Demos
SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.PlayableDemos] = Parent.PlayableDemosTextBox.Text;
SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.RollingDemos] = Parent.RollingDemosTextBox.Text;
SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.TechDemos] = Parent.TechDemosTextBox.Text;
// Video
SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.GameFootage] = Parent.GameFootageTextBox.Text;
SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.Videos] = Parent.VideosTextBox.Text;
// Miscellaneous
SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.Patches] = Parent.PatchesTextBox.Text;
SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.Savegames] = Parent.SavegamesTextBox.Text;
SubmissionInfo.CommonDiscInfo.ContentsSpecialFields[SiteCode.Extras] = Parent.ExtrasTextBox.Text;
#endregion
}
/// <summary>
/// Update visible fields and sections based on the media type
/// </summary>
private void UpdateFromDiscType()
{
// Sony-printed discs have layers in the opposite order
var system = SubmissionInfo?.CommonDiscInfo?.System;
bool reverseOrder = system.HasReversedRingcodes();
// Different media types mean different fields available
switch (SubmissionInfo?.CommonDiscInfo?.Media)
{
case DiscType.CD:
@@ -207,8 +570,14 @@ namespace MPF.GUI.ViewModels
Parent.L3Info.Visibility = Visibility.Collapsed;
break;
}
}
// Different systems mean different fields available
/// <summary>
/// Update visible fields and sections based on the system type
/// </summary>
private void UpdateFromSystemType()
{
var system = SubmissionInfo?.CommonDiscInfo?.System;
switch (system)
{
case RedumpSystem.SonyPlayStation2:
@@ -217,32 +586,6 @@ namespace MPF.GUI.ViewModels
}
}
/// <summary>
/// Load the current contents of the base SubmissionInfo to the UI
/// </summary>
private void Load()
{
Parent.CategoryComboBox.SelectedIndex = Categories.FindIndex(r => r == SubmissionInfo.CommonDiscInfo.Category);
Parent.RegionComboBox.SelectedIndex = Regions.FindIndex(r => r == SubmissionInfo.CommonDiscInfo.Region);
if (SubmissionInfo.CommonDiscInfo.Languages != null)
Languages.ForEach(l => l.IsChecked = SubmissionInfo.CommonDiscInfo.Languages.Contains(l));
if (SubmissionInfo.CommonDiscInfo.LanguageSelection != null)
LanguageSelections.ForEach(ls => ls.IsChecked = SubmissionInfo.CommonDiscInfo.LanguageSelection.Contains(ls));
}
/// <summary>
/// Save the current contents of the UI to the base SubmissionInfo
/// </summary>
public void Save()
{
SubmissionInfo.CommonDiscInfo.Category = (Parent.CategoryComboBox.SelectedItem as Element<DiscCategory>)?.Value ?? DiscCategory.Games;
SubmissionInfo.CommonDiscInfo.Region = (Parent.RegionComboBox.SelectedItem as Element<Region>)?.Value ?? Region.World;
SubmissionInfo.CommonDiscInfo.Languages = Languages.Where(l => l.IsChecked).Select(l => l?.Value).ToArray();
if (!SubmissionInfo.CommonDiscInfo.Languages.Any())
SubmissionInfo.CommonDiscInfo.Languages = new Language?[] { null };
SubmissionInfo.CommonDiscInfo.LanguageSelection = LanguageSelections.Where(ls => ls.IsChecked).Select(ls => ls?.Value).ToArray();
}
#endregion
#region Event Handlers

View File

@@ -81,12 +81,16 @@ namespace MPF.GUI.ViewModels
// Add the click handlers to the UI
AddEventHandlers();
// Display the debug option in the menu, if necessary
if (App.Options.ShowDebugViewMenuItem)
App.Instance.DebugViewMenuItem.Visibility = Visibility.Visible;
// Finish initializing the rest of the values
InitializeUIValues(removeEventHandlers: false, rescanDrives: true);
// Check for updates, if necessary
if (App.Options.CheckForUpdatesOnStartup)
CheckForUpdates();
CheckForUpdates(showIfSame: false);
}
#region Population
@@ -209,7 +213,8 @@ namespace MPF.GUI.ViewModels
/// <summary>
/// Check for available updates
/// </summary>
public void CheckForUpdates()
/// <param name="showIfSame">True to show the box even if it's the same, false to only show if it's different</param>
public void CheckForUpdates(bool showIfSame)
{
(bool different, string message, string url) = Tools.CheckForNewVersion();
@@ -221,7 +226,8 @@ namespace MPF.GUI.ViewModels
if (url == null)
message = "An exception occurred while checking for versions, please try again later. See the log window for more details.";
CustomMessageBox.Show(App.Instance, message, "Version Update Check", MessageBoxButton.OK, different ? MessageBoxImage.Exclamation : MessageBoxImage.Information);
if (showIfSame || different)
CustomMessageBox.Show(App.Instance, message, "Version Update Check", MessageBoxButton.OK, different ? MessageBoxImage.Exclamation : MessageBoxImage.Information);
}
/// <summary>
@@ -257,6 +263,138 @@ namespace MPF.GUI.ViewModels
CustomMessageBox.Show(App.Instance, aboutText, "About", MessageBoxButton.OK, MessageBoxImage.Information);
}
/// <summary>
/// Build a dummy SubmissionInfo and display it for testing
/// </summary>
public void ShowDebugDiscInfoWindow()
{
var submissionInfo = new SubmissionInfo()
{
SchemaVersion = 1,
MatchedIDs = new List<int> { 0, 1, 2, 3 },
Added = DateTime.UtcNow,
LastModified = DateTime.UtcNow,
CommonDiscInfo = new CommonDiscInfoSection()
{
System = RedumpSystem.IBMPCcompatible,
Media = DiscType.BD50,
Title = "Game Title",
ForeignTitleNonLatin = "Foreign Game Title",
DiscNumberLetter = "1",
DiscTitle = "Install Disc",
Category = DiscCategory.Games,
Region = Region.World,
Languages = new Language?[] { Language.English, Language.Spanish, Language.French },
LanguageSelection = new LanguageSelection?[] { LanguageSelection.BiosSettings },
Serial = "Disc Serial",
Layer0MasteringRing = "L0 Mastering Ring",
Layer0MasteringSID = "L0 Mastering SID",
Layer0ToolstampMasteringCode = "L0 Toolstamp",
Layer0MouldSID = "L0 Mould SID",
Layer0AdditionalMould = "L0 Additional Mould",
Layer1MasteringRing = "L1 Mastering Ring",
Layer1MasteringSID = "L1 Mastering SID",
Layer1ToolstampMasteringCode = "L1 Toolstamp",
Layer1MouldSID = "L1 Mould SID",
Layer1AdditionalMould = "L1 Additional Mould",
Layer2MasteringRing = "L2 Mastering Ring",
Layer2MasteringSID = "L2 Mastering SID",
Layer2ToolstampMasteringCode = "L2 Toolstamp",
Layer3MasteringRing = "L3 Mastering Ring",
Layer3MasteringSID = "L3 Mastering SID",
Layer3ToolstampMasteringCode = "L3 Toolstamp",
RingWriteOffset = "+12",
Barcode = "UPC Barcode",
EXEDateBuildDate = "19xx-xx-xx",
ErrorsCount = "0",
Comments = "Comment data line 1\r\nComment data line 2",
CommentsSpecialFields = new Dictionary<SiteCode?, string>()
{
[SiteCode.ISBN] = "ISBN",
},
Contents = "Special contents 1\r\nSpecial contents 2",
ContentsSpecialFields = new Dictionary<SiteCode?, string>()
{
[SiteCode.PlayableDemos] = "Game Demo 1",
},
},
VersionAndEditions = new VersionAndEditionsSection()
{
Version = "Original",
VersionDatfile = "Alt",
CommonEditions = new string[] { "Taikenban" },
OtherEditions = "Rerelease",
},
EDC = new EDCSection()
{
EDC = YesNo.Yes,
},
ParentCloneRelationship = new ParentCloneRelationshipSection()
{
ParentID = "12345",
RegionalParent = false,
},
Extras = new ExtrasSection()
{
PVD = "PVD with a stupidly long line and nothing else but a little more\nPVD with a stupidly long line and nothing else but a little more\nPVD with a stupidly long line and nothing else but a little more\nPVD with a stupidly long line and nothing else but a little more\nPVD with a stupidly long line and nothing else but a little more\nPVD with a stupidly long line and nothing else but a little more\n",
DiscKey = "Disc key",
DiscID = "Disc ID",
PIC = "PIC",
Header = "Header",
BCA = "BCA",
SecuritySectorRanges = "SSv1 Ranges",
},
CopyProtection = new CopyProtectionSection()
{
AntiModchip = YesNo.Yes,
LibCrypt = YesNo.No,
LibCryptData = "LibCrypt data",
Protection = "List of protections",
SecuROMData = "SecuROM data",
},
DumpersAndStatus = new DumpersAndStatusSection()
{
Status = DumpStatus.TwoOrMoHumanReadablesGreen,
Dumpers = new string[] { "Dumper1", "Dumper2" },
OtherDumpers = "Dumper3",
},
TracksAndWriteOffsets = new TracksAndWriteOffsetsSection()
{
ClrMameProData = "Datfile",
Cuesheet = "Cuesheet",
CommonWriteOffsets = new int[] { 0, 12, -12 },
OtherWriteOffsets = "-2",
},
SizeAndChecksums = new SizeAndChecksumsSection()
{
Layerbreak = 0,
Layerbreak2 = 1,
Layerbreak3 = 2,
Size = 12345,
CRC32 = "CRC32",
MD5 = "MD5",
SHA1 = "SHA1",
},
Artifacts = new Dictionary<string, string>()
{
["Sample Artifact"] = "Sample Data",
},
};
var result = ShowDiscInformationWindow(submissionInfo);
InfoTool.ProcessSpecialFields(result.Item2);
}
/// <summary>
/// Show the Options window
/// </summary>
@@ -403,6 +541,7 @@ namespace MPF.GUI.ViewModels
App.Instance.AboutMenuItem.Click += AboutClick;
App.Instance.AppExitMenuItem.Click += AppExitClick;
App.Instance.CheckForUpdatesMenuItem.Click += CheckForUpdatesClick;
App.Instance.DebugViewMenuItem.Click += DebugViewClick;
App.Instance.OptionsMenuItem.Click += OptionsMenuItemClick;
// User Area Click
@@ -859,10 +998,15 @@ namespace MPF.GUI.ViewModels
if (Env.Parameters == null)
return;
int driveIndex = Drives.Select(d => d.Letter).ToList().IndexOf(Env.Parameters.InputPath[0]);
if (driveIndex > -1)
App.Instance.DriveLetterComboBox.SelectedIndex = driveIndex;
// Catch this in case there's an input path issue
try
{
int driveIndex = Drives.Select(d => d.Letter).ToList().IndexOf(Env.Parameters.InputPath[0]);
if (driveIndex > -1)
App.Instance.DriveLetterComboBox.SelectedIndex = driveIndex;
}
catch { }
int driveSpeed = Env.Parameters.Speed ?? -1;
if (driveSpeed > 0)
App.Instance.DriveSpeedComboBox.SelectedValue = driveSpeed;
@@ -1058,6 +1202,9 @@ namespace MPF.GUI.ViewModels
// One last check to determine environment, just in case
Env = DetermineEnvironment();
// Run path adjustments for DiscImageCreator
Env.AdjustPathsForDiscImageCreator();
// If still in custom parameter mode, check that users meant to continue or not
if (App.Instance.EnableParametersCheckBox.IsChecked == true)
{
@@ -1247,7 +1394,13 @@ namespace MPF.GUI.ViewModels
/// Handler for CheckForUpdatesMenuItem Click event
/// </summary>
private void CheckForUpdatesClick(object sender, RoutedEventArgs e) =>
CheckForUpdates();
CheckForUpdates(showIfSame: true);
/// <summary>
/// Handler for DebugViewMenuItem Click event
/// </summary>
private void DebugViewClick(object sender, RoutedEventArgs e) =>
ShowDebugDiscInfoWindow();
/// <summary>
/// Handler for OptionsMenuItem Click event

View File

@@ -15,7 +15,7 @@
</WindowChrome.WindowChrome>
<Grid>
<StackPanel Orientation="Vertical" Width="500">
<StackPanel Orientation="Vertical" Width="500" MaxHeight="650">
<Grid Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25"/>
@@ -67,128 +67,324 @@
Foreground="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"
Style="{DynamicResource CustomTabControlStyle}">
<TabItem x:Name="CommonInfo" Header="Common Info" Style="{DynamicResource CustomTabItemStyle}">
<StackPanel Orientation="Vertical">
<Expander Margin="5" Padding="5" BorderThickness="1" BorderBrush="LightGray" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Common Disc Information" IsExpanded="True">
<StackPanel Orientation="Vertical">
<controls:UserInput Label="Title" Text="{Binding SubmissionInfo.CommonDiscInfo.Title, Mode=TwoWay}"/>
<controls:UserInput Label="Foreign Title (Non-Latin)" Text="{Binding SubmissionInfo.CommonDiscInfo.ForeignTitleNonLatin, Mode=TwoWay}"/>
<controls:UserInput Label="Disc Number / Letter" Text="{Binding SubmissionInfo.CommonDiscInfo.DiscNumberLetter, Mode=TwoWay}"/>
<controls:UserInput Label="Disc Title" Text="{Binding SubmissionInfo.CommonDiscInfo.DiscTitle, Mode=TwoWay}"/>
<ScrollViewer CanContentScroll="False" VerticalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MaxHeight="500">
<StackPanel Orientation="Vertical">
<GroupBox Header="Common Disc Information" Margin="5" Padding="5" BorderThickness="1" BorderBrush="LightGray"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel Orientation="Vertical">
<controls:UserInput Label="Title"
Text="{Binding SubmissionInfo.CommonDiscInfo.Title, Mode=TwoWay}"/>
<controls:UserInput x:Name="AlternativeTitleTextBox" Label="Alternative Title"/>
<controls:UserInput Label="Foreign Title (Non-Latin)"
Text="{Binding SubmissionInfo.CommonDiscInfo.ForeignTitleNonLatin, Mode=TwoWay}"/>
<controls:UserInput x:Name="AlternativeForeignTitleTextBox" Label="Alternative Foreign Title"/>
<controls:UserInput Label="Disc Number / Letter"
Text="{Binding SubmissionInfo.CommonDiscInfo.DiscNumberLetter, Mode=TwoWay}"/>
<controls:UserInput Label="Disc Title"
Text="{Binding SubmissionInfo.CommonDiscInfo.DiscTitle, Mode=TwoWay}"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1.25*" />
</Grid.ColumnDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.75*" />
<ColumnDefinition Width="1.25*" />
</Grid.ColumnDefinitions>
<Label x:Name="CategoryLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Category" />
<ComboBox x:Name="CategoryComboBox" Grid.Row="0" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ItemsSource="{Binding Categories}"
Style="{DynamicResource CustomComboBoxStyle}" />
</Grid>
<Label x:Name="CategoryLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Category" />
<ComboBox x:Name="CategoryComboBox" Grid.Row="0" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ItemsSource="{Binding Categories}"
Style="{DynamicResource CustomComboBoxStyle}" />
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1.25*" />
</Grid.ColumnDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.75*" />
<ColumnDefinition Width="1.25*" />
</Grid.ColumnDefinitions>
<Label x:Name="RegionLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Region" />
<ComboBox x:Name="RegionComboBox" Grid.Row="0" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ItemsSource="{Binding Regions}"
Style="{DynamicResource CustomComboBoxStyle}" />
</Grid>
<Label x:Name="RegionLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Region" />
<ComboBox x:Name="RegionComboBox" Grid.Row="0" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ItemsSource="{Binding Regions}"
Style="{DynamicResource CustomComboBoxStyle}" />
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1.25*" />
</Grid.ColumnDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.75*" />
<ColumnDefinition Width="1.25*" />
</Grid.ColumnDefinitions>
<Label x:Name="LanguagesLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Languages" />
<ComboBox x:Name="LanguagesComboBox" Grid.Row="0" Grid.Column="1" Height="24" HorizontalAlignment="Stretch" ItemsSource="{Binding Languages}"
SelectedIndex="0" Style="{DynamicResource CustomComboBoxStyle}">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
<Label x:Name="LanguagesLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Languages" />
<ComboBox x:Name="LanguagesComboBox" Grid.Row="0" Grid.Column="1" Height="24" HorizontalAlignment="Stretch" ItemsSource="{Binding Languages}"
SelectedIndex="0" Style="{DynamicResource CustomComboBoxStyle}">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
<Grid x:Name="LanguageSelectionGrid" Visibility="Collapsed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1.25*" />
</Grid.ColumnDefinitions>
<Grid x:Name="LanguageSelectionGrid" Visibility="Collapsed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.75*" />
<ColumnDefinition Width="1.25*" />
</Grid.ColumnDefinitions>
<Label x:Name="LanguageSelectionLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Language Selection Via" />
<ComboBox x:Name="LanguageSelectionComboBox" Grid.Row="0" Grid.Column="1" Height="24" HorizontalAlignment="Stretch" ItemsSource="{Binding LanguageSelections}"
SelectedIndex="0" Style="{DynamicResource CustomComboBoxStyle}">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
<Label x:Name="LanguageSelectionLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Language Selection Via" />
<ComboBox x:Name="LanguageSelectionComboBox" Grid.Row="0" Grid.Column="1" Height="24" HorizontalAlignment="Stretch" ItemsSource="{Binding LanguageSelections}"
SelectedIndex="0" Style="{DynamicResource CustomComboBoxStyle}">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
<controls:UserInput Label="Serial" Text="{Binding SubmissionInfo.CommonDiscInfo.Serial, Mode=TwoWay}"/>
<controls:UserInput Label="Barcode" Text="{Binding SubmissionInfo.CommonDiscInfo.Barcode, Mode=TwoWay}"/>
<controls:UserInput Label="Comments" Text="{Binding SubmissionInfo.CommonDiscInfo.Comments, Mode=TwoWay}" TextHeight="50" Tab="True" Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top" />
<controls:UserInput Label="Contents" Text="{Binding SubmissionInfo.CommonDiscInfo.Contents, Mode=TwoWay}" TextHeight="50" Tab="True" Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
</StackPanel>
</Expander>
<Expander Margin="5" Padding="5" BorderThickness="1" BorderBrush="LightGray" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Version and Editions" IsExpanded="True">
<StackPanel Orientation="Vertical">
<controls:UserInput Label="Version" Text="{Binding SubmissionInfo.VersionAndEditions.Version, Mode=TwoWay}"/>
<controls:UserInput Label="Edition" Text="{Binding SubmissionInfo.VersionAndEditions.OtherEditions, Mode=TwoWay}"/>
</StackPanel>
</Expander>
</StackPanel>
<controls:UserInput Label="Serial" Text="{Binding SubmissionInfo.CommonDiscInfo.Serial, Mode=TwoWay}"/>
<controls:UserInput Label="Barcode" Text="{Binding SubmissionInfo.CommonDiscInfo.Barcode, Mode=TwoWay}"/>
</StackPanel>
</GroupBox>
<GroupBox Header="Version and Editions" Margin="5" Padding="5" BorderThickness="1" BorderBrush="LightGray"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel Orientation="Vertical">
<controls:UserInput Label="Version" Text="{Binding SubmissionInfo.VersionAndEditions.Version, Mode=TwoWay}"/>
<controls:UserInput Label="Edition" Text="{Binding SubmissionInfo.VersionAndEditions.OtherEditions, Mode=TwoWay}"/>
</StackPanel>
</GroupBox>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem x:Name="L0Info" Header="Data/L0 Info" Style="{DynamicResource CustomTabItemStyle}">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="L0MasteringRing" Label="Data/L0 Mastering Ring" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer0MasteringRing, Mode=TwoWay}" Tab="True"/>
<controls:UserInput x:Name="L0MasteringSID" Label="Data/L0 Mastering SID" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer0MasteringSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L0Toolstamp" Label="Data/L0 Toolstamp/Mastering Code" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer0ToolstampMasteringCode, Mode=TwoWay}"/>
<controls:UserInput x:Name="L0MouldSID" Label="Data/L0 Mould SID" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer0MouldSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L0AdditionalMould" Label="Data/L0 Additional Mould" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer0AdditionalMould, Mode=TwoWay}"/>
</StackPanel>
<TabItem Header="Additional Info" Style="{DynamicResource CustomTabItemStyle}">
<ScrollViewer CanContentScroll="False" VerticalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MaxHeight="500">
<StackPanel Orientation="Vertical">
<GroupBox Header="Extras" Margin="5" Padding="5" BorderThickness="1" BorderBrush="LightGray"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="CommentsTextBox" Label="Comments"
Text="{Binding SubmissionInfo.CommonDiscInfo.Comments, Mode=TwoWay}" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top" />
<controls:UserInput x:Name="GenreTextBox" Label="Genre"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.75*" />
<ColumnDefinition Width="1.25*" />
</Grid.ColumnDefinitions>
<Label/>
<CheckBox Grid.Column="1" x:Name="PostgapTypeCheckBox" Content="Postgap type (Form 2)" Margin="0,4"/>
</Grid>
<controls:UserInput x:Name="SeriesTextBox" Label="Series"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.75*" />
<ColumnDefinition Width="1.25*" />
</Grid.ColumnDefinitions>
<Label/>
<CheckBox Grid.Column="1" x:Name="VCDCheckBox" Content="V-CD" Margin="0,4"/>
</Grid>
</StackPanel>
</GroupBox>
<GroupBox Header="Physical Identifiers" Margin="5" Padding="5" BorderThickness="1" BorderBrush="LightGray"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="BBFCRegistrationNumberTextBox" Label="BBFC Reg. No."/>
<controls:UserInput x:Name="DiscHologramIDTextBox" Label="Disc Hologram ID"/>
<controls:UserInput x:Name="DNASDiscIDTextBox" Label="DNAS Disc ID"/>
<controls:UserInput x:Name="ISBNTextBox" Label="ISBN"/>
<controls:UserInput x:Name="ISSNTextBox" Label="ISSN"/>
<controls:UserInput x:Name="PPNTextBox" Label="PPN"/>
<controls:UserInput x:Name="VFCCodeTextBox" Label="VFC code"/>
</StackPanel>
</GroupBox>
<GroupBox Header="Publisher Identifiers" Margin="5" Padding="5" BorderThickness="1" BorderBrush="LightGray"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="AcclaimIDTextBox" Label="Acclaim ID"/>
<controls:UserInput x:Name="ActivisionIDTextBox" Label="Activision ID"/>
<controls:UserInput x:Name="BandaiIDTextBox" Label="Bandai ID"/>
<controls:UserInput x:Name="ElectronicArtsIDTextBox" Label="Electronic Arts ID"/>
<controls:UserInput x:Name="FoxInteractiveIDTextBox" Label="Fox Interactive ID"/>
<controls:UserInput x:Name="GTInteractiveIDTextBox" Label="GT Interactive ID"/>
<controls:UserInput x:Name="JASRACIDTextBox" Label="JASRAC ID"/>
<controls:UserInput x:Name="KingRecordsIDTextBox" Label="King Records ID"/>
<controls:UserInput x:Name="KoeiIDTextBox" Label="Koei ID"/>
<controls:UserInput x:Name="KonamiIDTextBox" Label="Konami ID"/>
<controls:UserInput x:Name="LucasArtsIDTextBox" Label="LucasArts ID"/>
<controls:UserInput x:Name="MicrosoftIDTextBox" Label="Microsoft ID"/>
<controls:UserInput x:Name="NaganoIDTextBox" Label="Nagano ID"/>
<controls:UserInput x:Name="NamcoIDTextBox" Label="Namco ID"/>
<controls:UserInput x:Name="NipponIchiSoftwareIDTextBox" Label="Nippon Ichi Software ID"/>
<controls:UserInput x:Name="OriginIDTextBox" Label="Origin ID"/>
<controls:UserInput x:Name="PonyCanyonIDTextBox" Label="Pony Canyon ID"/>
<controls:UserInput x:Name="SegaIDTextBox" Label="Sega ID"/>
<controls:UserInput x:Name="SelenIDTextBox" Label="Selen ID"/>
<controls:UserInput x:Name="SierraIDTextBox" Label="Sierra ID"/>
<controls:UserInput x:Name="TaitoIDTextBox" Label="Taito ID"/>
<controls:UserInput x:Name="UbisoftIDTextBox" Label="Ubisoft ID"/>
<controls:UserInput x:Name="ValveIDTextBox" Label="Valve ID"/>
</StackPanel>
</GroupBox>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem x:Name="L1Info" Header="Label/L1 Info" Style="{DynamicResource CustomTabItemStyle}">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="L1MasteringRing" Label="Label/L1 Mastering Ring" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer1MasteringRing, Mode=TwoWay}" Tab="True"/>
<controls:UserInput x:Name="L1MasteringSID" Label="Label/L1 Mastering SID" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer1MasteringSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L1Toolstamp" Label="Label/L1 Toolstamp/Mastering Code" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer1ToolstampMasteringCode, Mode=TwoWay}"/>
<controls:UserInput x:Name="L1MouldSID" Label="Label/L1 Mould SID" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer1MouldSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L1AdditionalMould" Label="Label/L1 Additional Mould" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer1AdditionalMould, Mode=TwoWay}"/>
</StackPanel>
<TabItem Header="Contents" Style="{DynamicResource CustomTabItemStyle}">
<ScrollViewer CanContentScroll="False" VerticalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MaxHeight="500">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="GeneralContent" Label="General"
Text="{Binding SubmissionInfo.CommonDiscInfo.Contents, Mode=TwoWay}" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
<!-- Games -->
<controls:UserInput x:Name="GamesTextBox" Label="Games" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
<controls:UserInput x:Name="NetYarozeGamesTextBox" Label="Net Yaroze Games" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
<!-- Demos -->
<controls:UserInput x:Name="PlayableDemosTextBox" Label="Playable Demos" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
<controls:UserInput x:Name="RollingDemosTextBox" Label="Rolling Demos" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
<controls:UserInput x:Name="TechDemosTextBox" Label="Tech Demos" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
<!-- Video -->
<controls:UserInput x:Name="GameFootageTextBox" Label="Game Footage" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
<controls:UserInput x:Name="VideosTextBox" Label="Videos" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
<!-- Miscellaneous -->
<controls:UserInput x:Name="PatchesTextBox" Label="Patches" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
<controls:UserInput x:Name="SavegamesTextBox" Label="Savegames" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
<controls:UserInput x:Name="ExtrasTextBox" Label="Extras" TextHeight="50"
Enter="True" TextWrapping="Wrap" VerticalContentAlignmentValue="Top"/>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem x:Name="L2Info" Header="L2 Info" Visibility="Collapsed" Style="{DynamicResource CustomTabItemStyle}">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="L2MasteringRing" Label="L2 Mastering Ring" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer2MasteringRing, Mode=TwoWay}" Tab="True"/>
<controls:UserInput x:Name="L2MasteringSID" Label="L2 Mastering SID" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer2MasteringSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L2Toolstamp" Label="L2 Toolstamp/Mastering Code" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer2ToolstampMasteringCode, Mode=TwoWay}"/>
</StackPanel>
<TabItem Header="Ringcodes" Style="{DynamicResource CustomTabItemStyle}">
<ScrollViewer CanContentScroll="False" VerticalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MaxHeight="500">
<StackPanel Orientation="Vertical">
<GroupBox x:Name="L0Info" Header="Data/L0 Info" Margin="5" Padding="5" BorderThickness="1" BorderBrush="LightGray"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="L0MasteringRing" Label="Data/L0 Mastering Ring"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer0MasteringRing, Mode=TwoWay}"/>
<controls:UserInput x:Name="L0MasteringSID" Label="Data/L0 Mastering SID"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer0MasteringSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L0Toolstamp" Label="Data/L0 Toolstamp/Mastering Code"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer0ToolstampMasteringCode, Mode=TwoWay}"/>
<controls:UserInput x:Name="L0MouldSID" Label="Data/L0 Mould SID"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer0MouldSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L0AdditionalMould" Label="Data/L0 Additional Mould"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer0AdditionalMould, Mode=TwoWay}"/>
</StackPanel>
</GroupBox>
<GroupBox x:Name="L1Info" Header="Label/L1 Info" Margin="5" Padding="5" BorderThickness="1" BorderBrush="LightGray"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="L1MasteringRing" Label="Label/L1 Mastering Ring"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer1MasteringRing, Mode=TwoWay}"/>
<controls:UserInput x:Name="L1MasteringSID" Label="Label/L1 Mastering SID"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer1MasteringSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L1Toolstamp" Label="Label/L1 Toolstamp/Mastering Code"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer1ToolstampMasteringCode, Mode=TwoWay}"/>
<controls:UserInput x:Name="L1MouldSID" Label="Label/L1 Mould SID"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer1MouldSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L1AdditionalMould" Label="Label/L1 Additional Mould"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer1AdditionalMould, Mode=TwoWay}"/>
</StackPanel>
</GroupBox>
<GroupBox x:Name="L2Info" Header="L2 Info" Visibility="Collapsed" Margin="5" Padding="5" BorderThickness="1" BorderBrush="LightGray"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="L2MasteringRing" Label="L2 Mastering Ring"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer2MasteringRing, Mode=TwoWay}"/>
<controls:UserInput x:Name="L2MasteringSID" Label="L2 Mastering SID"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer2MasteringSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L2Toolstamp" Label="L2 Toolstamp/Mastering Code"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer2ToolstampMasteringCode, Mode=TwoWay}"/>
</StackPanel>
</GroupBox>
<GroupBox x:Name="L3Info" Header="L3 Info" Visibility="Collapsed" Margin="5" Padding="5" BorderThickness="1" BorderBrush="LightGray"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="L3MasteringRing" Label="L3 Mastering Ring"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer3MasteringRing, Mode=TwoWay}"/>
<controls:UserInput x:Name="L3MasteringSID" Label="L3 Mastering SID"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer3MasteringSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L3Toolstamp" Label="L3 Toolstamp/Mastering Code"
Text="{Binding SubmissionInfo.CommonDiscInfo.Layer3ToolstampMasteringCode, Mode=TwoWay}"/>
</StackPanel>
</GroupBox>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem x:Name="L3Info" Header="L3 Info" Visibility="Collapsed" Style="{DynamicResource CustomTabItemStyle}">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="L3MasteringRing" Label="L3 Mastering Ring" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer3MasteringRing, Mode=TwoWay}" Tab="True"/>
<controls:UserInput x:Name="L3MasteringSID" Label="L3 Mastering SID" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer3MasteringSID, Mode=TwoWay}"/>
<controls:UserInput x:Name="L3Toolstamp" Label="L3 Toolstamp/Mastering Code" Text="{Binding SubmissionInfo.CommonDiscInfo.Layer3ToolstampMasteringCode, Mode=TwoWay}"/>
</StackPanel>
<TabItem Header="Read-Only Info" Style="{DynamicResource CustomTabItemStyle}">
<ScrollViewer CanContentScroll="False" VerticalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MaxHeight="500">
<StackPanel Orientation="Vertical">
<controls:UserInput x:Name="MatchedIDs" Label="Matched ID(s)" IsReadOnly="True"/>
<controls:UserInput x:Name="AntiModchip" Label="Anti-Modchip" IsReadOnly="True"/>
<controls:UserInput x:Name="DMIHash" Label="DMI Hash" IsReadOnly="True"/>
<controls:UserInput x:Name="EDC" Label="EDC" IsReadOnly="True"/>
<controls:UserInput x:Name="ErrorsCount" Label="Error(s) Count" IsReadOnly="True"
Text="{Binding SubmissionInfo.CommonDiscInfo.ErrorsCount, Mode=TwoWay}"/>
<controls:UserInput x:Name="EXEDateBuildDate" Label="EXE/Build Date" IsReadOnly="True"
Text="{Binding SubmissionInfo.CommonDiscInfo.EXEDateBuildDate, Mode=TwoWay}"/>
<controls:UserInput x:Name="Header" Label="Header" IsReadOnly="True"
Text="{Binding SubmissionInfo.Extras.Header, Mode=TwoWay}" TextHeight="75" TextWrapping="NoWrap"
VerticalContentAlignmentValue="Top" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"/>
<controls:UserInput x:Name="InternalSerialName" Label="Internal Serial" IsReadOnly="True"/>
<controls:UserInput x:Name="LibCrypt" Label="LibCrypt" IsReadOnly="True"/>
<controls:UserInput x:Name="LibCryptData" Label="LibCrypt Data" IsReadOnly="True"
Text="{Binding SubmissionInfo.CopyProtection.LibCryptData, Mode=TwoWay}" TextHeight="75" TextWrapping="NoWrap"
VerticalContentAlignmentValue="Top" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"/>
<controls:UserInput x:Name="PFIHash" Label="PFI Hash" IsReadOnly="True"/>
<controls:UserInput x:Name="PIC" Label="PIC" IsReadOnly="True"
Text="{Binding SubmissionInfo.Extras.PIC, Mode=TwoWay}" TextHeight="75" TextWrapping="NoWrap"
VerticalContentAlignmentValue="Top" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"/>
<controls:UserInput x:Name="Protection" Label="Protection" IsReadOnly="True"
Text="{Binding SubmissionInfo.CopyProtection.Protection, Mode=TwoWay}" TextHeight="75" TextWrapping="Wrap"
VerticalContentAlignmentValue="Top" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"/>
<controls:UserInput x:Name="PVD" Label="PVD" IsReadOnly="True"
Text="{Binding SubmissionInfo.Extras.PVD, Mode=TwoWay}" TextHeight="75" TextWrapping="NoWrap"
VerticalContentAlignmentValue="Top" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"/>
<controls:UserInput x:Name="SecuROMData" Label="SecuROM Data" IsReadOnly="True"
Text="{Binding SubmissionInfo.CopyProtection.SecuROMData, Mode=TwoWay}" TextHeight="75" TextWrapping="NoWrap"
VerticalContentAlignmentValue="Top" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"/>
<controls:UserInput x:Name="SSHash" Label="Security Sector Hash" IsReadOnly="True"/>
<controls:UserInput x:Name="SecuritySectorRanges" Label="Security Sector Ranges" IsReadOnly="True"
Text="{Binding SubmissionInfo.Extras.SecuritySectorRanges, Mode=TwoWay}" TextHeight="75" TextWrapping="NoWrap"
VerticalContentAlignmentValue="Top" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"/>
<controls:UserInput x:Name="SSVersion" Label="Security Sector Version" IsReadOnly="True"/>
<controls:UserInput x:Name="VolumeLabel" Label="Volume Label" IsReadOnly="True"/>
<controls:UserInput x:Name="XeMID" Label="XeMID" IsReadOnly="True"/>
<controls:UserInput x:Name="XMID" Label="XMID" IsReadOnly="True"/>
<!-- TODO: Add track/checksum data once there's a reasonable way to do so -->
</StackPanel>
</ScrollViewer>
</TabItem>
</TabControl>
<!-- Accept / Cancel -->
<GroupBox Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<UniformGrid Columns="3" Margin="5,5,5,5" Height="28">
<Button Name="AcceptButton" Height="25" Width="80" IsDefault="True" Content="Accept"
<Button Name="AcceptButton" Height="25" Width="80" Content="Accept"
Style="{DynamicResource CustomButtonStyle}" />
<Button Name="CancelButton" Height="25" Width="80" IsCancel="True" Content="Cancel"
<Button Name="CancelButton" Height="25" Width="80" Content="Cancel"
Style="{DynamicResource CustomButtonStyle}" />
<Button Name="RingCodeGuideButton" Grid.Column="2" Height="25" Width="120" Content="Ring Code Guide"
Style="{DynamicResource CustomButtonStyle}" />

View File

@@ -53,6 +53,10 @@
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
Foreground="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"
Template="{DynamicResource CustomMenuItemTemplate}" />
<MenuItem x:Name="DebugViewMenuItem" Header="_Debug Info Window" HorizontalAlignment="Left" Width="185"
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
Foreground="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"
Template="{DynamicResource CustomMenuItemTemplate}" Visibility="Collapsed" />
</MenuItem>
<MenuItem x:Name="HelpMenuItem" Header="_Help"
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"

View File

@@ -172,6 +172,11 @@
ToolTip="Enable showing the disc information output after dumping" Margin="0,4"
/>
<CheckBox VerticalAlignment="Center" Content="Enable Tab Input"
IsChecked="{Binding Options.EnableTabsInInputFields}"
ToolTip="Enable entering tabs in supported input fields instead of tab navigation" Margin="0,4"
/>
<CheckBox VerticalAlignment="Center" Content="Show Eject Reminder"
IsChecked="{Binding Options.ShowDiscEjectReminder}"
ToolTip="Enable showing the disc eject reminder after information is gathered" Margin="0,4"
@@ -179,7 +184,7 @@
<CheckBox VerticalAlignment="Center" Content="Add Placeholders"
IsChecked="{Binding Options.AddPlaceholders}"
ToolTip="Enable adding placeholder text in the submissioninfo output for required and optional fields" Margin="0,4"
ToolTip="Enable adding placeholder text in the output for required and optional fields" Margin="0,4"
/>
<CheckBox VerticalAlignment="Center" Content="Output Submission JSON"

View File

@@ -39,10 +39,12 @@
<MenuItem Header="Minimize" Click="MinimizeButtonClick" Width="185"
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
Foreground="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"
BorderBrush="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
Template="{DynamicResource CustomMenuItemTemplate}"/>
<MenuItem Header="Close" Click="CloseButtonClick" Width="185"
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
Foreground="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"
BorderBrush="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
Template="{DynamicResource CustomMenuItemTemplate}"/>
</ContextMenu>
</Label.ContextMenu>
@@ -61,44 +63,96 @@
</Button>
</Grid>
</Grid>
<Grid Margin="5,5,5,5">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TabControl Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
Foreground="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"
Style="{DynamicResource CustomTabControlStyle}">
<TabItem Header="1-Layer Ringcode" Style="{DynamicResource CustomTabItemStyle}">
<Grid Margin="5,5,5,5">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Grid.Row="0" Source="/Images/ring-code-guide.png"
HorizontalAlignment="Center" Stretch="Fill" Width="500" Height="500"
RenderOptions.BitmapScalingMode="HighQuality" />
<Label Grid.Row="1">
<Label.Content>
<TextBlock><Bold Foreground="Red">1. Mastering Ring:</Bold> Sony DADC&lt;tab&gt;A0100368905-0101&lt;tab&gt;15</TextBlock>
</Label.Content>
</Label>
<Label Grid.Row="2">
<Label.Content>
<TextBlock><Bold Foreground="Green">2. Mastering SID:</Bold> IFPI L553</TextBlock>
</Label.Content>
</Label>
<Label Grid.Row="3">
<Label.Content>
<TextBlock><Bold Foreground="Purple">3. Toolstamp/Mastering Code:</Bold> A2</TextBlock>
</Label.Content>
</Label>
<Label Grid.Row="4">
<Label.Content>
<TextBlock><Bold Foreground="LightBlue">4. Mould SID:</Bold> IFPI 94V1</TextBlock>
</Label.Content>
</Label>
</Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="/Images/ring-code-guide-1-layer.png"
HorizontalAlignment="Center" Stretch="Fill" Width="500" Height="500"
RenderOptions.BitmapScalingMode="HighQuality" />
<Label Grid.Row="1">
<Label.Content>
<TextBlock><Bold Foreground="Red">1. Mastering Ring:</Bold> Sony DADC&lt;tab&gt;A0100368905-0101&lt;tab&gt;15</TextBlock>
</Label.Content>
</Label>
<Label Grid.Row="2">
<Label.Content>
<TextBlock><Bold Foreground="Green">2. Mastering SID:</Bold> IFPI L553</TextBlock>
</Label.Content>
</Label>
<Label Grid.Row="3">
<Label.Content>
<TextBlock><Bold Foreground="Purple">3. Toolstamp/Mastering Code:</Bold> A2</TextBlock>
</Label.Content>
</Label>
<Label Grid.Row="4">
<Label.Content>
<TextBlock><Bold Foreground="LightBlue">4. Mould SID:</Bold> IFPI 94V1</TextBlock>
</Label.Content>
</Label>
</Grid>
</TabItem>
<TabItem Header="2-Layer Ringcode" Style="{DynamicResource CustomTabItemStyle}">
<Grid Margin="5,5,5,5">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="/Images/ring-code-guide-2-layer.png"
HorizontalAlignment="Center" Stretch="Fill" Width="475" Height="500"
RenderOptions.BitmapScalingMode="HighQuality" />
<Label Grid.Row="1">
<Label.Content>
<TextBlock><Bold Foreground="Red">1. Outer Mastering Ring:</Bold> IM01501A-L1&lt;tab&gt;03 +&lt;tab&gt;+</TextBlock>
</Label.Content>
</Label>
<Label Grid.Row="2">
<Label.Content>
<TextBlock><Bold Foreground="Green">2. Inner Mastering Ring:</Bold> IM01501A-L0&lt;tab&gt;03 +&lt;tab&gt;+</TextBlock>
</Label.Content>
</Label>
<Label Grid.Row="3">
<Label.Content>
<TextBlock><Bold Foreground="Purple">3. Outer Mastering SID:</Bold> IFPI LB48</TextBlock>
</Label.Content>
</Label>
<Label Grid.Row="4">
<Label.Content>
<TextBlock><Bold Foreground="LightBlue">4. Inner Mastering SID:</Bold> IFPI LB48</TextBlock>
</Label.Content>
</Label>
<Label Grid.Row="5">
<Label.Content>
<TextBlock><Bold>Note:</Bold> See the 1-Layer guide for more details on additional fields</TextBlock>
</Label.Content>
</Label>
</Grid>
</TabItem>
</TabControl>
</StackPanel>
</Grid>
</windows:WindowBase>

View File

@@ -0,0 +1,26 @@
namespace RedumpLib.Attributes
{
/// <summary>
/// Attribute specifc to Language values
/// </summary>
/// <remarks>
/// Some languages have multiple proper names. Should all be supported?
/// </remarks>
public class LanguageAttribute : HumanReadableAttribute
{
/// <summary>
/// ISO 639-1 Code
/// </summary>
public string TwoLetterCode { get; set; } = null;
/// <summary>
/// ISO 639-2 Code (Standard or Bibliographic)
/// </summary>
public string ThreeLetterCode { get; set; } = null;
/// <summary>
/// ISO 639-2 Code (Terminology)
/// </summary>
public string ThreeLetterCodeAlt { get; set; } = null;
}
}

View File

@@ -4,101 +4,6 @@ namespace RedumpLib.Data
{
public static class Constants
{
#region Comment Field Tags
// TODO: Make this into a proper enum with LongName and ShortName
public const string AcclaimIDCommentField = "[T:ACC]";
public const string AcclaimIDCommentString = "<b>Acclaim ID</b>:";
public const string ActivisionIDCommentField = "[T:ACT]";
public const string ActivisionIDCommentString = "<b>Activision ID</b>:";
public const string AlternativeTitleCommentField = "[T:ALT]";
public const string AlternativeTitleCommentString = "<b>Alternative Title</b>:";
public const string AlternativeForeignTitleCommentField = "[T:ALTF]";
public const string AlternativeForeignTitleCommentString = "<b>Alternative Foreign Title</b>:";
public const string BandaiIDCommentField = "[T:BID]";
public const string BandaiIDCommentString = "<b>Bandai ID</b>:";
public const string BBFCRegistrationNumberCommentField = "[T:BBFC]";
public const string BBFCRegistrationNumberCommentString = "<b>BBFC Reg. No.</b>:";
public const string DNASDiscIDCommentField = "[T:DNAS]";
public const string DNASDiscIDCommentString = "<b>DNAS Disc ID</b>:";
public const string ElectronicArtsIDCommentField = "[T:EAID]";
public const string ElectronicArtsIDCommentString = "<b>Electronic Arts ID</b>:";
public const string ExtrasCommentField = "[T:X]";
public const string ExtrasCommentString = "<b>Extras</b>:";
public const string FoxInteractiveIDCommentField = "[T:FIID]";
public const string FoxInteractiveIDCommentString = "<b>Fox Interactive ID</b>:";
public const string GameFootageCommentField = "[T:GF]";
public const string GameFootageCommentString = "<b>Game Footage</b>:";
public const string GenreCommentField = "[T:G]";
public const string GenreCommentString = "<b>Genre</b>:";
public const string GTInteractiveIDCommentField = "[T:GTID]";
public const string GTInteractiveIDCommentString = "<b>GT Interactive ID</b>:";
public const string InternalSerialNameCommentField = "[T:ISN]";
public const string InternalSerialNameCommentString = "<b>Internal Serial</b>:";
public const string ISBNCommentField = "[T:ISBN]";
public const string ISBNCommentString = "<b>ISBN</b>:";
public const string ISSNCommentField = "[T:ISSN]";
public const string ISSNCommentString = "<b>ISSN</b>:";
public const string JASRACIDCommentField = "[T:JID]";
public const string JASRACIDCommentString = "<b>JASRAC ID</b>:";
public const string KingRecordsIDCommentField = "[T:KIRZ]";
public const string KingRecordsIDCommentString = "<b>King Records ID</b>:";
public const string KoeiIDCommentField = "[T:KOEI]";
public const string KoeiIDCommentString = "<b>Koei ID</b>:";
public const string KonamiIDCommentField = "[T:KID]";
public const string KonamiIDCommentString = "<b>Konami ID</b>:";
public const string LucasArtsIDCommentField = "[T:LAID]";
public const string LucasArtsIDCommentString = "<b>Lucas Arts ID</b>:";
public const string NaganoIDCommentField = "[T:NGID]";
public const string NaganoIDCommentString = "<b>Nagano ID</b>:";
public const string NamcoIDCommentField = "[T:NID]";
public const string NamcoIDCommentString = "<b>Namco ID</b>:";
public const string NetYarozeGamesCommentField = "[T:NYG]";
public const string NetYarozeGamesCommentSring = "Net Yaroze Games</b>:";
public const string NipponIchiSoftwareIDCommentField = "[T:NPS]";
public const string NipponIchiSoftwareIDCommentString = "<b>Nippon Ichi Software ID</b>:";
public const string OriginIDCommentField = "[T:OID]";
public const string OriginIDCommentString = "<b>Origin ID</b>:";
public const string PatchesCommentField = "[T:P]";
public const string PatchesCommentString = "<b>Patches</b>:";
public const string PlayableDemosCommentField = "[T:PD]";
public const string PlayableDemosCommentString = "<b>Playable Demos</b>:";
public const string PonyCanyonIDCommentField = "[T:PCID]";
public const string PonyCanyonIDCommentString = "<b>Pony Canyon ID</b>:";
public const string PostgapTypeCommentField = "[T:PT2]";
public const string PostgapTypeCommentString = "<b>Postgap type</b>: Form 2";
public const string PPNCommentField = "[T:PPN]";
public const string PPNCommentString = "<b>PPN</b>:";
public const string RollingDemosCommentField = "[T:RD]";
public const string RollingDemosCommentString = "<b>Rolling Demos</b>:";
public const string SavegamesCommentField = "[T:SG]";
public const string SavegamesCommentString = "<b>Savegames</b>:";
public const string SegaIDCommentField = "[T:SID]";
public const string SegaIDCommentString = "<b>Sega ID</b>:";
public const string SelenIDCommentField = "[T:SNID]";
public const string SelenIDCommentString = "<b>Selen ID</b>:";
public const string SeriesCommentField = "[T:S]";
public const string SeriesCommentString = "<b>Series</b>:";
public const string TaitoIDCommentField = "[T:TID]";
public const string TaitoIDCommentString = "<b>Taito ID</b>:";
public const string TechDemosCommentField = "[T:TD]";
public const string TechDemosCommentString = "<b>Tech Demos</b>:";
public const string UbisoftIDCommentField = "[T:UID]";
public const string UbisoftIDCommentString = "<b>Ubisoft ID</b>:";
public const string ValveIDCommentField = "[T:VID]";
public const string ValveIDCommentString = "<b>Valve ID</b>:";
public const string VFCCodeCommentField = "[T:VFC]";
public const string VGCCodeCommentString = "<b>VFC code</b>:";
public const string VideosCommentField = "[T:V]";
public const string VideosCommentString = "<b>Videos</b>:";
public const string VolumeLabelCommentField = "[T:VOL]";
public const string VolumeLabelCommentString = "<b>Volume Label</b>:";
public const string VCDCommentField = "[T:VCD]";
public const string VCDCommentString = "<b>V-CD</b>";
#endregion
// TODO: Add RegexOptions.Compiled
#region Regular Expressions

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,6 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using RedumpLib.Attributes;
namespace RedumpLib.Data
@@ -909,7 +911,23 @@ namespace RedumpLib.Data
/// </summary>
/// <param name="language"></param>
/// <returns></returns>
public static string ShortName(this Language? language) => AttributeHelper<Language?>.GetAttribute(language)?.ShortName;
public static string ShortName(this Language? language)
{
// Some languages need to use the alternate code instead
switch (language)
{
case Language.Albanian:
case Language.Armenian:
case Language.Icelandic:
case Language.Macedonian:
case Language.Romanian:
case Language.Slovak:
return language.ThreeLetterCodeAlt();
default:
return language.ThreeLetterCode();
}
}
/// <summary>
/// Get the Language enum value for a given string
@@ -918,103 +936,56 @@ namespace RedumpLib.Data
/// <returns>Language represented by the string, if possible</returns>
public static Language? ToLanguage(string lang)
{
switch (lang)
{
case "afr":
return Language.Afrikaans;
case "sqi":
return Language.Albanian;
case "ara":
return Language.Arabic;
case "baq":
return Language.Basque;
case "bul":
return Language.Bulgarian;
case "cat":
return Language.Catalan;
case "chi":
return Language.Chinese;
case "hrv":
return Language.Croatian;
case "cze":
return Language.Czech;
case "dan":
return Language.Danish;
case "dut":
return Language.Dutch;
case "eng":
return Language.English;
case "est":
return Language.Estonian;
case "fin":
return Language.Finnish;
case "fre":
return Language.French;
case "gla":
return Language.Gaelic;
case "ger":
return Language.German;
case "gre":
return Language.Greek;
case "heb":
return Language.Hebrew;
case "hin":
return Language.Hindi;
case "hun":
return Language.Hungarian;
case "ind":
return Language.Indonesian;
case "isl":
return Language.Icelandic;
case "ita":
return Language.Italian;
case "jap":
return Language.Japanese;
case "kor":
return Language.Korean;
case "lat":
return Language.Latin;
case "lav":
return Language.Latvian;
case "lit":
return Language.Lithuanian;
case "mkd":
return Language.Macedonian;
case "nor":
return Language.Norwegian;
case "pol":
return Language.Polish;
case "por":
return Language.Portuguese;
case "pan":
return Language.Punjabi;
case "ron":
return Language.Romanian;
case "rus":
return Language.Russian;
case "srp":
return Language.Serbian;
case "slk":
return Language.Slovak;
case "slv":
return Language.Slovenian;
case "spa":
return Language.Spanish;
case "swe":
return Language.Swedish;
case "tam":
return Language.Tamil;
case "tha":
return Language.Thai;
case "tur":
return Language.Turkish;
case "ukr":
return Language.Ukrainian;
default:
return null;
}
var languages = Enum.GetValues(typeof(Language)).Cast<Language?>().ToList();
// Check ISO 639-1 codes
Dictionary<string, Language?> languageMapping = languages
.Where(l => l.TwoLetterCode() != null)
.ToDictionary(l => l.TwoLetterCode(), l => l);
if (languageMapping.ContainsKey(lang))
return languageMapping[lang];
// Check standard ISO 639-2 codes
languageMapping = languages
.Where(l => l.ThreeLetterCode() != null)
.ToDictionary(l => l.ThreeLetterCode(), l => l);
if (languageMapping.ContainsKey(lang))
return languageMapping[lang];
// Check alternate ISO 639-2 codes
languageMapping = languages
.Where(l => l.ThreeLetterCodeAlt() != null)
.ToDictionary(l => l.ThreeLetterCodeAlt(), l => l);
if (languageMapping.ContainsKey(lang))
return languageMapping[lang];
return null;
}
/// <summary>
/// Get the ISO 639-2 code for each known language
/// </summary>
/// <param name="language"></param>
/// <returns></returns>
public static string ThreeLetterCode(this Language? language) => ((LanguageAttribute)AttributeHelper<Language?>.GetAttribute(language))?.ThreeLetterCode;
/// <summary>
/// Get the ISO 639-2 alternate code for each known language
/// </summary>
/// <param name="language"></param>
/// <returns></returns>
public static string ThreeLetterCodeAlt(this Language? language) => ((LanguageAttribute)AttributeHelper<Language?>.GetAttribute(language))?.ThreeLetterCodeAlt;
/// <summary>
/// Get the ISO 639-1 code for each known language
/// </summary>
/// <param name="language"></param>
/// <returns></returns>
public static string TwoLetterCode(this Language? language) => ((LanguageAttribute)AttributeHelper<Language?>.GetAttribute(language))?.TwoLetterCode;
#endregion
#region Language Selection
@@ -1069,171 +1040,40 @@ namespace RedumpLib.Data
/// <returns>Region represented by the string, if possible</returns>
public static Region? ToRegion(string region)
{
switch (region)
{
case "Ar":
return Region.Argentina;
case "A":
return Region.Asia;
case "A,E":
return Region.AsiaEurope;
case "A,U":
return Region.AsiaUSA;
case "Au":
return Region.Australia;
case "Au,G":
return Region.AustraliaGermany;
case "Au,Nz":
return Region.AustraliaNewZealand;
case "At":
return Region.Austria;
case "At,Ch":
return Region.AustriaSwitzerland;
case "Be":
return Region.Belgium;
case "Be,N":
return Region.BelgiumNetherlands;
case "B":
return Region.Brazil;
case "Bg":
return Region.Bulgaria;
case "Ca":
return Region.Canada;
case "C":
return Region.China;
case "Hr":
return Region.Croatia;
case "Cz":
return Region.Czech;
case "Dk":
return Region.Denmark;
case "Ee":
return Region.Estonia;
case "E":
return Region.Europe;
case "E,A":
return Region.EuropeAsia;
case "E,Au":
return Region.EuropeAustralia;
case "E,Ca":
return Region.EuropeCanada;
case "E,G":
return Region.EuropeGermany;
case "Ex":
return Region.Export;
case "Fi":
return Region.Finland;
case "F":
return Region.France;
case "F,S":
return Region.FranceSpain;
case "G":
return Region.Germany;
case "GC":
return Region.GreaterChina;
case "Gr":
return Region.Greece;
case "H":
return Region.Hungary;
case "Is":
return Region.Iceland;
case "In":
return Region.India;
case "Ie":
return Region.Ireland;
case "Il":
return Region.Israel;
case "I":
return Region.Italy;
case "J":
return Region.Japan;
case "J,A":
return Region.JapanAsia;
case "J,E":
return Region.JapanEurope;
case "J,K":
return Region.JapanKorea;
case "J,U":
return Region.JapanUSA;
case "K":
return Region.Korea;
case "LAm":
return Region.LatinAmerica;
case "Lt":
return Region.Lithuania;
case "N":
return Region.Netherlands;
case "Nz":
return Region.NewZealand;
case "No":
return Region.Norway;
case "P":
return Region.Poland;
case "Pt":
return Region.Portugal;
case "Ro":
return Region.Romania;
case "R":
return Region.Russia;
case "Sca":
return Region.Scandinavia;
case "Rs":
return Region.Serbia;
case "Sg":
return Region.Singapore;
case "Sk":
return Region.Slovakia;
case "Za":
return Region.SouthAfrica;
case "S":
return Region.Spain;
case "S,Pt":
return Region.SpainPortugal;
case "Sw":
return Region.Sweden;
case "Ch":
return Region.Switzerland;
case "Tw":
return Region.Taiwan;
case "Th":
return Region.Thailand;
case "Tr":
return Region.Turkey;
case "Ae":
return Region.UnitedArabEmirates;
case "Uk":
return Region.UK;
case "Uk,Au":
return Region.UKAustralia;
case "Ue":
return Region.Ukraine;
case "U":
return Region.USA;
case "U,A":
return Region.USAAsia;
case "U,Au":
return Region.USAAustralia;
case "U,B":
return Region.USABrazil;
case "U,Ca":
return Region.USACanada;
case "U,E":
return Region.USAEurope;
case "U,G":
return Region.USAGermany;
case "U,J":
return Region.USAJapan;
case "U,K":
return Region.USAKorea;
case "W":
return Region.World;
default:
return null;
}
region = region.ToLowerInvariant();
var regions = Enum.GetValues(typeof(Region)).Cast<Region?>().ToList();
// Check ISO 3166-1 alpha-2 codes
Dictionary<string, Region?> regionMapping = regions
.Where(r => r.ShortName() != null)
.ToDictionary(r => r.ShortName().ToLowerInvariant(), r => r);
if (regionMapping.ContainsKey(region))
return regionMapping[region];
return null;
}
#endregion
#region Site Code
/// <summary>
/// Get the HTML version for each known site code
/// </summary>
/// <param name="siteCode"></param>
/// <returns></returns>
public static string LongName(this SiteCode? siteCode) => AttributeHelper<SiteCode?>.GetAttribute(siteCode)?.LongName;
/// <summary>
/// Get the short tag for each known site code
/// </summary>
/// <param name="siteCode"></param>
/// <returns></returns>
public static string ShortName(this SiteCode? siteCode) => AttributeHelper<SiteCode?>.GetAttribute(siteCode)?.ShortName;
#endregion
#region System
/// <summary>

View File

@@ -79,7 +79,7 @@ namespace RedumpLib.Data
DumpersAndStatus = this.DumpersAndStatus?.Clone() as DumpersAndStatusSection,
TracksAndWriteOffsets = this.TracksAndWriteOffsets?.Clone() as TracksAndWriteOffsetsSection,
SizeAndChecksums = this.SizeAndChecksums?.Clone() as SizeAndChecksumsSection,
Artifacts = this.Artifacts.ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
Artifacts = this.Artifacts?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
};
}
}
@@ -211,9 +211,15 @@ namespace RedumpLib.Data
[JsonProperty(PropertyName = "d_comments", NullValueHandling = NullValueHandling.Ignore)]
public string Comments { get; set; }
[JsonIgnore]
public Dictionary<SiteCode?, string> CommentsSpecialFields { get; set; }
[JsonProperty(PropertyName = "d_contents", NullValueHandling = NullValueHandling.Ignore)]
public string Contents { get; set; }
[JsonIgnore]
public Dictionary<SiteCode?, string> ContentsSpecialFields { get; set; }
public object Clone()
{
return new CommonDiscInfoSection
@@ -254,7 +260,9 @@ namespace RedumpLib.Data
EXEDateBuildDate = this.EXEDateBuildDate,
ErrorsCount = this.ErrorsCount,
Comments = this.Comments,
CommentsSpecialFields = this.CommentsSpecialFields?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
Contents = this.Contents,
ContentsSpecialFields = this.ContentsSpecialFields?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
};
}
}

View File

@@ -30,7 +30,7 @@ namespace RedumpLib.Web
public string GetLastFilename()
{
// If the response headers are null or empty
if (ResponseHeaders == null || ResponseHeaders.Count != 0)
if (ResponseHeaders == null || ResponseHeaders.Count == 0)
return null;
// If we don't have the response header we care about

View File

@@ -1,5 +1,5 @@
# version format
version: 2.2-{build}
version: 2.3-{build}
# pull request template
pull_requests: