mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-02-05 21:34:02 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5510b5d19d | ||
|
|
d0f0ade757 | ||
|
|
26b03d8256 | ||
|
|
97f685512a | ||
|
|
0f790869d8 | ||
|
|
608edeb630 | ||
|
|
56066877b1 | ||
|
|
a530f271d0 | ||
|
|
327fd68f04 | ||
|
|
f12d48861f | ||
|
|
5a613be9bf | ||
|
|
226031f3bd | ||
|
|
e5edf43624 | ||
|
|
f2019b7ac4 | ||
|
|
0efb6d08e7 | ||
|
|
7ed1717f56 |
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.AACS;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.BDPlus;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.BFPK;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.CFB;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.InstallShieldCabinet;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.LinearExecutable;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.MSDOS;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.MicrosoftCabinet;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.MoPaQ;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.N3DS;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.NewExecutable;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.Nitro;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.PFF;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.PlayJ;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.PlayJ;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.PortableExecutable;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.Quantum;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.ArchiveDotOrg;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.AttractMode;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.AttractMode;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.ClrMamePro;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.ClrMamePro;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.DosCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.DosCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.EverdriveSMDB;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.EverdriveSMDB;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.Hashfile;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.Hashfile;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.Listrom;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.Listrom;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.Listxml;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.Listxml;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.OfflineList;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.OfflineList;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.OpenMSX;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.OpenMSX;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.RomCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.RomCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.SeparatedValue;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.SeparatedValue;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.SoftwareList;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using SabreTools.Models.SoftwareList;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
|
||||
60
Extensions.NewExecutable.cs
Normal file
60
Extensions.NewExecutable.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using SabreTools.Models.NewExecutable;
|
||||
|
||||
namespace SabreTools.Serialization
|
||||
{
|
||||
public static partial class Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Determine if a resource type information entry is an integer or offset
|
||||
/// </summary>
|
||||
/// <param name="entry">Resource type information entry to check</param>
|
||||
/// <returns>True if the entry is an integer type, false if an offset, null on error</returns>
|
||||
public static bool? IsIntegerType(this ResourceTypeInformationEntry entry)
|
||||
{
|
||||
// We can't do anything with an invalid entry
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
// If the highest order bit is set, it's an integer type
|
||||
return (entry.TypeID & 0x8000) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a resource type resource entry is an integer or offset
|
||||
/// </summary>
|
||||
/// <param name="entry">Resource type resource entry to check</param>
|
||||
/// <returns>True if the entry is an integer type, false if an offset, null on error</returns>
|
||||
public static bool? IsIntegerType(this ResourceTypeResourceEntry entry)
|
||||
{
|
||||
// We can't do anything with an invalid entry
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
// If the highest order bit is set, it's an integer type
|
||||
return (entry.ResourceID & 0x8000) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the segment entry type for an entry table bundle
|
||||
/// </summary>
|
||||
/// <param name="entry">Entry table bundle to check</param>
|
||||
/// <returns>SegmentEntryType corresponding to the type</returns>
|
||||
public static SegmentEntryType GetEntryType(this EntryTableBundle entry)
|
||||
{
|
||||
// We can't do anything with an invalid entry
|
||||
if (entry == null)
|
||||
return SegmentEntryType.Unused;
|
||||
|
||||
// Determine the entry type based on segment indicator
|
||||
if (entry.SegmentIndicator == 0x00)
|
||||
return SegmentEntryType.Unused;
|
||||
else if (entry.SegmentIndicator >= 0x01 && entry.SegmentIndicator <= 0xFE)
|
||||
return SegmentEntryType.FixedSegment;
|
||||
else if (entry.SegmentIndicator == 0xFF)
|
||||
return SegmentEntryType.MoveableSegment;
|
||||
|
||||
// We should never get here
|
||||
return SegmentEntryType.Unused;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,70 +5,12 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.Models.PortableExecutable;
|
||||
|
||||
namespace SabreTools.Serialization
|
||||
{
|
||||
public static class Extensions
|
||||
public static partial class Extensions
|
||||
{
|
||||
#region New Executable
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a resource type information entry is an integer or offset
|
||||
/// </summary>
|
||||
/// <param name="entry">Resource type information entry to check</param>
|
||||
/// <returns>True if the entry is an integer type, false if an offset, null on error</returns>
|
||||
public static bool? IsIntegerType(this Models.NewExecutable.ResourceTypeInformationEntry entry)
|
||||
{
|
||||
// We can't do anything with an invalid entry
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
// If the highest order bit is set, it's an integer type
|
||||
return (entry.TypeID & 0x8000) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a resource type resource entry is an integer or offset
|
||||
/// </summary>
|
||||
/// <param name="entry">Resource type resource entry to check</param>
|
||||
/// <returns>True if the entry is an integer type, false if an offset, null on error</returns>
|
||||
public static bool? IsIntegerType(this Models.NewExecutable.ResourceTypeResourceEntry entry)
|
||||
{
|
||||
// We can't do anything with an invalid entry
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
// If the highest order bit is set, it's an integer type
|
||||
return (entry.ResourceID & 0x8000) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the segment entry type for an entry table bundle
|
||||
/// </summary>
|
||||
/// <param name="entry">Entry table bundle to check</param>
|
||||
/// <returns>SegmentEntryType corresponding to the type</returns>
|
||||
public static Models.NewExecutable.SegmentEntryType GetEntryType(this Models.NewExecutable.EntryTableBundle entry)
|
||||
{
|
||||
// We can't do anything with an invalid entry
|
||||
if (entry == null)
|
||||
return Models.NewExecutable.SegmentEntryType.Unused;
|
||||
|
||||
// Determine the entry type based on segment indicator
|
||||
if (entry.SegmentIndicator == 0x00)
|
||||
return Models.NewExecutable.SegmentEntryType.Unused;
|
||||
else if (entry.SegmentIndicator >= 0x01 && entry.SegmentIndicator <= 0xFE)
|
||||
return Models.NewExecutable.SegmentEntryType.FixedSegment;
|
||||
else if (entry.SegmentIndicator == 0xFF)
|
||||
return Models.NewExecutable.SegmentEntryType.MoveableSegment;
|
||||
|
||||
// We should never get here
|
||||
return Models.NewExecutable.SegmentEntryType.Unused;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Portable Executable
|
||||
|
||||
/// <summary>
|
||||
/// Convert a relative virtual address to a physical one
|
||||
/// </summary>
|
||||
@@ -76,9 +18,9 @@ namespace SabreTools.Serialization
|
||||
/// <param name="sections">Array of sections to check against</param>
|
||||
/// <returns>Physical address, 0 on error</returns>
|
||||
#if NET48
|
||||
public static uint ConvertVirtualAddress(this uint rva, Models.PortableExecutable.SectionHeader[] sections)
|
||||
public static uint ConvertVirtualAddress(this uint rva, SectionHeader[] sections)
|
||||
#else
|
||||
public static uint ConvertVirtualAddress(this uint rva, Models.PortableExecutable.SectionHeader?[] sections)
|
||||
public static uint ConvertVirtualAddress(this uint rva, SectionHeader?[]? sections)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid section table, we can't do anything
|
||||
@@ -130,7 +72,11 @@ namespace SabreTools.Serialization
|
||||
/// <param name="rva">Relative virtual address to convert</param>
|
||||
/// <param name="sections">Array of sections to check against</param>
|
||||
/// <returns>Section index, null on error</returns>
|
||||
public static int ContainingSectionIndex(this uint rva, Models.PortableExecutable.SectionHeader[] sections)
|
||||
#if NET48
|
||||
public static int ContainingSectionIndex(this uint rva, SectionHeader[] sections)
|
||||
#else
|
||||
public static int ContainingSectionIndex(this uint rva, SectionHeader?[]? sections)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid section table, we can't do anything
|
||||
if (sections == null || sections.Length == 0)
|
||||
@@ -144,15 +90,15 @@ namespace SabreTools.Serialization
|
||||
for (int i = 0; i < sections.Length; i++)
|
||||
{
|
||||
// If the section is invalid, just skip it
|
||||
if (sections[i] == null)
|
||||
var section = sections[i];
|
||||
if (section == null)
|
||||
continue;
|
||||
|
||||
// If the section "starts" at 0, just skip it
|
||||
if (sections[i].PointerToRawData == 0)
|
||||
if (section.PointerToRawData == 0)
|
||||
continue;
|
||||
|
||||
// Attempt to derive the physical address from the current section
|
||||
var section = sections[i];
|
||||
if (rva >= section.VirtualAddress && section.VirtualSize != 0 && rva <= section.VirtualAddress + section.VirtualSize)
|
||||
return i;
|
||||
else if (rva >= section.VirtualAddress && section.SizeOfRawData != 0 && rva <= section.VirtualAddress + section.SizeOfRawData)
|
||||
@@ -169,9 +115,9 @@ namespace SabreTools.Serialization
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>A filled SecuROM AddD overlay data on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Models.PortableExecutable.SecuROMAddD AsSecuROMAddD(this byte[] data, ref int offset)
|
||||
public static SecuROMAddD AsSecuROMAddD(this byte[] data, ref int offset)
|
||||
#else
|
||||
public static Models.PortableExecutable.SecuROMAddD? AsSecuROMAddD(this byte[]? data, ref int offset)
|
||||
public static SecuROMAddD? AsSecuROMAddD(this byte[]? data, ref int offset)
|
||||
#endif
|
||||
{
|
||||
// If we have data that's invalid, we can't do anything
|
||||
@@ -179,7 +125,7 @@ namespace SabreTools.Serialization
|
||||
return null;
|
||||
|
||||
// Read in the table
|
||||
var addD = new Models.PortableExecutable.SecuROMAddD();
|
||||
var addD = new SecuROMAddD();
|
||||
|
||||
addD.Signature = data.ReadUInt32(ref offset);
|
||||
if (addD.Signature != 0x44646441)
|
||||
@@ -205,10 +151,10 @@ namespace SabreTools.Serialization
|
||||
|
||||
addD.Unknown14h = data.ReadBytes(ref offset, bytesToRead);
|
||||
|
||||
addD.Entries = new Models.PortableExecutable.SecuROMAddDEntry[addD.EntryCount];
|
||||
addD.Entries = new SecuROMAddDEntry[addD.EntryCount];
|
||||
for (int i = 0; i < addD.EntryCount; i++)
|
||||
{
|
||||
var addDEntry = new Models.PortableExecutable.SecuROMAddDEntry();
|
||||
var addDEntry = new SecuROMAddDEntry();
|
||||
|
||||
addDEntry.PhysicalOffset = data.ReadUInt32(ref offset);
|
||||
addDEntry.Length = data.ReadUInt32(ref offset);
|
||||
@@ -236,16 +182,16 @@ namespace SabreTools.Serialization
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>A filled NB10 Program Database on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Models.PortableExecutable.NB10ProgramDatabase AsNB10ProgramDatabase(this byte[] data, ref int offset)
|
||||
public static NB10ProgramDatabase AsNB10ProgramDatabase(this byte[] data, ref int offset)
|
||||
#else
|
||||
public static Models.PortableExecutable.NB10ProgramDatabase? AsNB10ProgramDatabase(this byte[] data, ref int offset)
|
||||
public static NB10ProgramDatabase? AsNB10ProgramDatabase(this byte[] data, ref int offset)
|
||||
#endif
|
||||
{
|
||||
// If we have data that's invalid, we can't do anything
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
var nb10ProgramDatabase = new Models.PortableExecutable.NB10ProgramDatabase();
|
||||
var nb10ProgramDatabase = new NB10ProgramDatabase();
|
||||
|
||||
nb10ProgramDatabase.Signature = data.ReadUInt32(ref offset);
|
||||
if (nb10ProgramDatabase.Signature != 0x3031424E)
|
||||
@@ -266,16 +212,16 @@ namespace SabreTools.Serialization
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>A filled RSDS Program Database on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Models.PortableExecutable.RSDSProgramDatabase AsRSDSProgramDatabase(this byte[] data, ref int offset)
|
||||
public static RSDSProgramDatabase AsRSDSProgramDatabase(this byte[] data, ref int offset)
|
||||
#else
|
||||
public static Models.PortableExecutable.RSDSProgramDatabase? AsRSDSProgramDatabase(this byte[]? data, ref int offset)
|
||||
public static RSDSProgramDatabase? AsRSDSProgramDatabase(this byte[]? data, ref int offset)
|
||||
#endif
|
||||
{
|
||||
// If we have data that's invalid, we can't do anything
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
var rsdsProgramDatabase = new Models.PortableExecutable.RSDSProgramDatabase();
|
||||
var rsdsProgramDatabase = new RSDSProgramDatabase();
|
||||
|
||||
rsdsProgramDatabase.Signature = data.ReadUInt32(ref offset);
|
||||
if (rsdsProgramDatabase.Signature != 0x53445352)
|
||||
@@ -302,9 +248,9 @@ namespace SabreTools.Serialization
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>A filled resource header on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Models.PortableExecutable.ResourceHeader AsResourceHeader(this byte[] data, ref int offset)
|
||||
public static ResourceHeader AsResourceHeader(this byte[] data, ref int offset)
|
||||
#else
|
||||
public static Models.PortableExecutable.ResourceHeader? AsResourceHeader(this byte[]? data, ref int offset)
|
||||
public static ResourceHeader? AsResourceHeader(this byte[]? data, ref int offset)
|
||||
#endif
|
||||
{
|
||||
// If we have data that's invalid, we can't do anything
|
||||
@@ -312,13 +258,13 @@ namespace SabreTools.Serialization
|
||||
return null;
|
||||
|
||||
// Read in the table
|
||||
var header = new Models.PortableExecutable.ResourceHeader();
|
||||
var header = new ResourceHeader();
|
||||
header.DataSize = data.ReadUInt32(ref offset);
|
||||
header.HeaderSize = data.ReadUInt32(ref offset);
|
||||
header.ResourceType = (Models.PortableExecutable.ResourceType)data.ReadUInt32(ref offset); // TODO: Could be a string too
|
||||
header.ResourceType = (ResourceType)data.ReadUInt32(ref offset); // TODO: Could be a string too
|
||||
header.Name = data.ReadUInt32(ref offset); // TODO: Could be a string too
|
||||
header.DataVersion = data.ReadUInt32(ref offset);
|
||||
header.MemoryFlags = (Models.PortableExecutable.MemoryFlags)data.ReadUInt16(ref offset);
|
||||
header.MemoryFlags = (MemoryFlags)data.ReadUInt16(ref offset);
|
||||
header.LanguageId = data.ReadUInt16(ref offset);
|
||||
header.Version = data.ReadUInt32(ref offset);
|
||||
header.Characteristics = data.ReadUInt32(ref offset);
|
||||
@@ -332,9 +278,9 @@ namespace SabreTools.Serialization
|
||||
/// <param name="entry">Resource data entry to parse into an accelerator table resource</param>
|
||||
/// <returns>A filled accelerator table resource on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Models.PortableExecutable.AcceleratorTableEntry[] AsAcceleratorTableResource(this Models.PortableExecutable.ResourceDataEntry entry)
|
||||
public static AcceleratorTableEntry[] AsAcceleratorTableResource(this ResourceDataEntry entry)
|
||||
#else
|
||||
public static Models.PortableExecutable.AcceleratorTableEntry[]? AsAcceleratorTableResource(this Models.PortableExecutable.ResourceDataEntry? entry)
|
||||
public static AcceleratorTableEntry[]? AsAcceleratorTableResource(this ResourceDataEntry? entry)
|
||||
#endif
|
||||
{
|
||||
// If we have data that's invalid for this resource type, we can't do anything
|
||||
@@ -348,14 +294,14 @@ namespace SabreTools.Serialization
|
||||
int offset = 0;
|
||||
|
||||
// Create the output object
|
||||
var table = new Models.PortableExecutable.AcceleratorTableEntry[count];
|
||||
var table = new AcceleratorTableEntry[count];
|
||||
|
||||
// Read in the table
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var acceleratorTableEntry = new Models.PortableExecutable.AcceleratorTableEntry();
|
||||
var acceleratorTableEntry = new AcceleratorTableEntry();
|
||||
|
||||
acceleratorTableEntry.Flags = (Models.PortableExecutable.AcceleratorTableFlags)entry.Data.ReadUInt16(ref offset);
|
||||
acceleratorTableEntry.Flags = (AcceleratorTableFlags)entry.Data.ReadUInt16(ref offset);
|
||||
acceleratorTableEntry.Ansi = entry.Data.ReadUInt16(ref offset);
|
||||
acceleratorTableEntry.Id = entry.Data.ReadUInt16(ref offset);
|
||||
acceleratorTableEntry.Padding = entry.Data.ReadUInt16(ref offset);
|
||||
@@ -372,9 +318,9 @@ namespace SabreTools.Serialization
|
||||
/// <param name="entry">Resource data entry to parse into a side-by-side assembly manifest</param>
|
||||
/// <returns>A filled side-by-side assembly manifest on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Models.PortableExecutable.AssemblyManifest AsAssemblyManifest(this Models.PortableExecutable.ResourceDataEntry entry)
|
||||
public static AssemblyManifest AsAssemblyManifest(this ResourceDataEntry entry)
|
||||
#else
|
||||
public static Models.PortableExecutable.AssemblyManifest? AsAssemblyManifest(this Models.PortableExecutable.ResourceDataEntry? entry)
|
||||
public static AssemblyManifest? AsAssemblyManifest(this ResourceDataEntry? entry)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid entry, just skip
|
||||
@@ -383,8 +329,8 @@ namespace SabreTools.Serialization
|
||||
|
||||
try
|
||||
{
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(Models.PortableExecutable.AssemblyManifest));
|
||||
return serializer.Deserialize(new MemoryStream(entry.Data)) as Models.PortableExecutable.AssemblyManifest;
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(AssemblyManifest));
|
||||
return serializer.Deserialize(new MemoryStream(entry.Data)) as AssemblyManifest;
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -398,9 +344,9 @@ namespace SabreTools.Serialization
|
||||
/// <param name="entry">Resource data entry to parse into a dialog box</param>
|
||||
/// <returns>A filled dialog box on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Models.PortableExecutable.DialogBoxResource AsDialogBox(this Models.PortableExecutable.ResourceDataEntry entry)
|
||||
public static DialogBoxResource AsDialogBox(this ResourceDataEntry entry)
|
||||
#else
|
||||
public static Models.PortableExecutable.DialogBoxResource? AsDialogBox(this Models.PortableExecutable.ResourceDataEntry? entry)
|
||||
public static DialogBoxResource? AsDialogBox(this ResourceDataEntry? entry)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid entry, just skip
|
||||
@@ -411,7 +357,7 @@ namespace SabreTools.Serialization
|
||||
int offset = 0;
|
||||
|
||||
// Create the output object
|
||||
var dialogBoxResource = new Models.PortableExecutable.DialogBoxResource();
|
||||
var dialogBoxResource = new DialogBoxResource();
|
||||
|
||||
// Try to read the signature for an extended dialog box template
|
||||
int signatureOffset = sizeof(ushort);
|
||||
@@ -420,13 +366,13 @@ namespace SabreTools.Serialization
|
||||
{
|
||||
#region Extended dialog template
|
||||
|
||||
var dialogTemplateExtended = new Models.PortableExecutable.DialogTemplateExtended();
|
||||
var dialogTemplateExtended = new DialogTemplateExtended();
|
||||
|
||||
dialogTemplateExtended.Version = entry.Data.ReadUInt16(ref offset);
|
||||
dialogTemplateExtended.Signature = entry.Data.ReadUInt16(ref offset);
|
||||
dialogTemplateExtended.HelpID = entry.Data.ReadUInt32(ref offset);
|
||||
dialogTemplateExtended.ExtendedStyle = (Models.PortableExecutable.ExtendedWindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogTemplateExtended.Style = (Models.PortableExecutable.WindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogTemplateExtended.ExtendedStyle = (ExtendedWindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogTemplateExtended.Style = (WindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogTemplateExtended.DialogItems = entry.Data.ReadUInt16(ref offset);
|
||||
dialogTemplateExtended.PositionX = entry.Data.ReadInt16(ref offset);
|
||||
dialogTemplateExtended.PositionY = entry.Data.ReadInt16(ref offset);
|
||||
@@ -535,7 +481,7 @@ namespace SabreTools.Serialization
|
||||
#region Point size and typeface
|
||||
|
||||
// Only if DS_SETFONT is set are the values here used
|
||||
if (dialogTemplateExtended.Style.HasFlag(Models.PortableExecutable.WindowStyles.DS_SETFONT))
|
||||
if (dialogTemplateExtended.Style.HasFlag(WindowStyles.DS_SETFONT))
|
||||
{
|
||||
dialogTemplateExtended.PointSize = entry.Data.ReadUInt16(ref offset);
|
||||
dialogTemplateExtended.Weight = entry.Data.ReadUInt16(ref offset);
|
||||
@@ -559,15 +505,15 @@ namespace SabreTools.Serialization
|
||||
|
||||
#region Extended dialog item templates
|
||||
|
||||
var dialogItemExtendedTemplates = new List<Models.PortableExecutable.DialogItemTemplateExtended>();
|
||||
var dialogItemExtendedTemplates = new List<DialogItemTemplateExtended>();
|
||||
|
||||
for (int i = 0; i < dialogTemplateExtended.DialogItems; i++)
|
||||
{
|
||||
var dialogItemTemplate = new Models.PortableExecutable.DialogItemTemplateExtended();
|
||||
var dialogItemTemplate = new DialogItemTemplateExtended();
|
||||
|
||||
dialogItemTemplate.HelpID = entry.Data.ReadUInt32(ref offset);
|
||||
dialogItemTemplate.ExtendedStyle = (Models.PortableExecutable.ExtendedWindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogItemTemplate.Style = (Models.PortableExecutable.WindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogItemTemplate.ExtendedStyle = (ExtendedWindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogItemTemplate.Style = (WindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogItemTemplate.PositionX = entry.Data.ReadInt16(ref offset);
|
||||
dialogItemTemplate.PositionY = entry.Data.ReadInt16(ref offset);
|
||||
dialogItemTemplate.WidthX = entry.Data.ReadInt16(ref offset);
|
||||
@@ -587,7 +533,7 @@ namespace SabreTools.Serialization
|
||||
_ = entry.Data.ReadUInt16(ref offset);
|
||||
|
||||
// Read the ordinal
|
||||
dialogItemTemplate.ClassResourceOrdinal = (Models.PortableExecutable.DialogItemTemplateOrdinal)entry.Data.ReadUInt16(ref offset);
|
||||
dialogItemTemplate.ClassResourceOrdinal = (DialogItemTemplateOrdinal)entry.Data.ReadUInt16(ref offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -665,10 +611,10 @@ namespace SabreTools.Serialization
|
||||
{
|
||||
#region Dialog template
|
||||
|
||||
var dialogTemplate = new Models.PortableExecutable.DialogTemplate();
|
||||
var dialogTemplate = new DialogTemplate();
|
||||
|
||||
dialogTemplate.Style = (Models.PortableExecutable.WindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogTemplate.ExtendedStyle = (Models.PortableExecutable.ExtendedWindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogTemplate.Style = (WindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogTemplate.ExtendedStyle = (ExtendedWindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogTemplate.ItemCount = entry.Data.ReadUInt16(ref offset);
|
||||
dialogTemplate.PositionX = entry.Data.ReadInt16(ref offset);
|
||||
dialogTemplate.PositionY = entry.Data.ReadInt16(ref offset);
|
||||
@@ -777,7 +723,7 @@ namespace SabreTools.Serialization
|
||||
#region Point size and typeface
|
||||
|
||||
// Only if DS_SETFONT is set are the values here used
|
||||
if (dialogTemplate.Style.HasFlag(Models.PortableExecutable.WindowStyles.DS_SETFONT))
|
||||
if (dialogTemplate.Style.HasFlag(WindowStyles.DS_SETFONT))
|
||||
{
|
||||
dialogTemplate.PointSizeValue = entry.Data.ReadUInt16(ref offset);
|
||||
|
||||
@@ -800,14 +746,14 @@ namespace SabreTools.Serialization
|
||||
|
||||
#region Dialog item templates
|
||||
|
||||
var dialogItemTemplates = new List<Models.PortableExecutable.DialogItemTemplate>();
|
||||
var dialogItemTemplates = new List<DialogItemTemplate>();
|
||||
|
||||
for (int i = 0; i < dialogTemplate.ItemCount; i++)
|
||||
{
|
||||
var dialogItemTemplate = new Models.PortableExecutable.DialogItemTemplate();
|
||||
var dialogItemTemplate = new DialogItemTemplate();
|
||||
|
||||
dialogItemTemplate.Style = (Models.PortableExecutable.WindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogItemTemplate.ExtendedStyle = (Models.PortableExecutable.ExtendedWindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogItemTemplate.Style = (WindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogItemTemplate.ExtendedStyle = (ExtendedWindowStyles)entry.Data.ReadUInt32(ref offset);
|
||||
dialogItemTemplate.PositionX = entry.Data.ReadInt16(ref offset);
|
||||
dialogItemTemplate.PositionY = entry.Data.ReadInt16(ref offset);
|
||||
dialogItemTemplate.WidthX = entry.Data.ReadInt16(ref offset);
|
||||
@@ -827,7 +773,7 @@ namespace SabreTools.Serialization
|
||||
_ = entry.Data.ReadUInt16(ref offset);
|
||||
|
||||
// Read the ordinal
|
||||
dialogItemTemplate.ClassResourceOrdinal = (Models.PortableExecutable.DialogItemTemplateOrdinal)entry.Data.ReadUInt16(ref offset);
|
||||
dialogItemTemplate.ClassResourceOrdinal = (DialogItemTemplateOrdinal)entry.Data.ReadUInt16(ref offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -911,9 +857,9 @@ namespace SabreTools.Serialization
|
||||
/// <param name="entry">Resource data entry to parse into a font group</param>
|
||||
/// <returns>A filled font group on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Models.PortableExecutable.FontGroupHeader AsFontGroup(this Models.PortableExecutable.ResourceDataEntry entry)
|
||||
public static FontGroupHeader AsFontGroup(this ResourceDataEntry entry)
|
||||
#else
|
||||
public static Models.PortableExecutable.FontGroupHeader? AsFontGroup(this Models.PortableExecutable.ResourceDataEntry? entry)
|
||||
public static FontGroupHeader? AsFontGroup(this ResourceDataEntry? entry)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid entry, just skip
|
||||
@@ -924,19 +870,19 @@ namespace SabreTools.Serialization
|
||||
int offset = 0;
|
||||
|
||||
// Create the output object
|
||||
var fontGroupHeader = new Models.PortableExecutable.FontGroupHeader();
|
||||
var fontGroupHeader = new FontGroupHeader();
|
||||
|
||||
fontGroupHeader.NumberOfFonts = entry.Data.ReadUInt16(ref offset);
|
||||
if (fontGroupHeader.NumberOfFonts > 0)
|
||||
{
|
||||
fontGroupHeader.DE = new Models.PortableExecutable.DirEntry[fontGroupHeader.NumberOfFonts];
|
||||
fontGroupHeader.DE = new DirEntry[fontGroupHeader.NumberOfFonts];
|
||||
for (int i = 0; i < fontGroupHeader.NumberOfFonts; i++)
|
||||
{
|
||||
var dirEntry = new Models.PortableExecutable.DirEntry();
|
||||
var dirEntry = new DirEntry();
|
||||
|
||||
dirEntry.FontOrdinal = entry.Data.ReadUInt16(ref offset);
|
||||
|
||||
dirEntry.Entry = new Models.PortableExecutable.FontDirEntry();
|
||||
dirEntry.Entry = new FontDirEntry();
|
||||
dirEntry.Entry.Version = entry.Data.ReadUInt16(ref offset);
|
||||
dirEntry.Entry.Size = entry.Data.ReadUInt32(ref offset);
|
||||
dirEntry.Entry.Copyright = entry.Data.ReadBytes(ref offset, 60);
|
||||
@@ -984,9 +930,9 @@ namespace SabreTools.Serialization
|
||||
/// <param name="entry">Resource data entry to parse into a menu</param>
|
||||
/// <returns>A filled menu on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Models.PortableExecutable.MenuResource AsMenu(this Models.PortableExecutable.ResourceDataEntry entry)
|
||||
public static MenuResource AsMenu(this ResourceDataEntry entry)
|
||||
#else
|
||||
public static Models.PortableExecutable.MenuResource? AsMenu(this Models.PortableExecutable.ResourceDataEntry? entry)
|
||||
public static MenuResource? AsMenu(this ResourceDataEntry? entry)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid entry, just skip
|
||||
@@ -997,7 +943,7 @@ namespace SabreTools.Serialization
|
||||
int offset = 0;
|
||||
|
||||
// Create the output object
|
||||
var menuResource = new Models.PortableExecutable.MenuResource();
|
||||
var menuResource = new MenuResource();
|
||||
|
||||
// Try to read the version for an extended header
|
||||
int versionOffset = 0;
|
||||
@@ -1006,7 +952,7 @@ namespace SabreTools.Serialization
|
||||
{
|
||||
#region Extended menu header
|
||||
|
||||
var menuHeaderExtended = new Models.PortableExecutable.MenuHeaderExtended();
|
||||
var menuHeaderExtended = new MenuHeaderExtended();
|
||||
|
||||
menuHeaderExtended.Version = entry.Data.ReadUInt16(ref offset);
|
||||
menuHeaderExtended.Offset = entry.Data.ReadUInt16(ref offset);
|
||||
@@ -1018,7 +964,7 @@ namespace SabreTools.Serialization
|
||||
|
||||
#region Extended dialog item templates
|
||||
|
||||
var extendedMenuItems = new List<Models.PortableExecutable.MenuItemExtended>();
|
||||
var extendedMenuItems = new List<MenuItemExtended>();
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
@@ -1026,12 +972,12 @@ namespace SabreTools.Serialization
|
||||
|
||||
while (offset < entry.Data.Length)
|
||||
{
|
||||
var extendedMenuItem = new Models.PortableExecutable.MenuItemExtended();
|
||||
var extendedMenuItem = new MenuItemExtended();
|
||||
|
||||
extendedMenuItem.ItemType = (Models.PortableExecutable.MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
extendedMenuItem.State = (Models.PortableExecutable.MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
extendedMenuItem.ItemType = (MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
extendedMenuItem.State = (MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
extendedMenuItem.ID = entry.Data.ReadUInt32(ref offset);
|
||||
extendedMenuItem.Flags = (Models.PortableExecutable.MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
extendedMenuItem.Flags = (MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
extendedMenuItem.MenuText = entry.Data.ReadString(ref offset, Encoding.Unicode);
|
||||
|
||||
// Align to the DWORD boundary if we're not at the end
|
||||
@@ -1053,7 +999,7 @@ namespace SabreTools.Serialization
|
||||
{
|
||||
#region Menu header
|
||||
|
||||
var menuHeader = new Models.PortableExecutable.MenuHeader();
|
||||
var menuHeader = new MenuHeader();
|
||||
|
||||
menuHeader.Version = entry.Data.ReadUInt16(ref offset);
|
||||
menuHeader.HeaderSize = entry.Data.ReadUInt16(ref offset);
|
||||
@@ -1064,26 +1010,26 @@ namespace SabreTools.Serialization
|
||||
|
||||
#region Menu items
|
||||
|
||||
var menuItems = new List<Models.PortableExecutable.MenuItem>();
|
||||
var menuItems = new List<MenuItem>();
|
||||
|
||||
while (offset < entry.Data.Length)
|
||||
{
|
||||
var menuItem = new Models.PortableExecutable.MenuItem();
|
||||
var menuItem = new MenuItem();
|
||||
|
||||
// Determine if this is a popup
|
||||
int flagsOffset = offset;
|
||||
var initialFlags = (Models.PortableExecutable.MenuFlags)entry.Data.ReadUInt16(ref flagsOffset);
|
||||
if (initialFlags.HasFlag(Models.PortableExecutable.MenuFlags.MF_POPUP))
|
||||
var initialFlags = (MenuFlags)entry.Data.ReadUInt16(ref flagsOffset);
|
||||
if (initialFlags.HasFlag(MenuFlags.MF_POPUP))
|
||||
{
|
||||
menuItem.PopupItemType = (Models.PortableExecutable.MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
menuItem.PopupState = (Models.PortableExecutable.MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
menuItem.PopupItemType = (MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
menuItem.PopupState = (MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
menuItem.PopupID = entry.Data.ReadUInt32(ref offset);
|
||||
menuItem.PopupResInfo = (Models.PortableExecutable.MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
menuItem.PopupResInfo = (MenuFlags)entry.Data.ReadUInt32(ref offset);
|
||||
menuItem.PopupMenuText = entry.Data.ReadString(ref offset, Encoding.Unicode);
|
||||
}
|
||||
else
|
||||
{
|
||||
menuItem.NormalResInfo = (Models.PortableExecutable.MenuFlags)entry.Data.ReadUInt16(ref offset);
|
||||
menuItem.NormalResInfo = (MenuFlags)entry.Data.ReadUInt16(ref offset);
|
||||
menuItem.NormalMenuText = entry.Data.ReadString(ref offset, Encoding.Unicode);
|
||||
}
|
||||
|
||||
@@ -1111,9 +1057,9 @@ namespace SabreTools.Serialization
|
||||
/// <param name="entry">Resource data entry to parse into a message table resource</param>
|
||||
/// <returns>A filled message table resource on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Models.PortableExecutable.MessageResourceData AsMessageResourceData(this Models.PortableExecutable.ResourceDataEntry entry)
|
||||
public static MessageResourceData AsMessageResourceData(this ResourceDataEntry entry)
|
||||
#else
|
||||
public static Models.PortableExecutable.MessageResourceData? AsMessageResourceData(this Models.PortableExecutable.ResourceDataEntry? entry)
|
||||
public static MessageResourceData? AsMessageResourceData(this ResourceDataEntry? entry)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid entry, just skip
|
||||
@@ -1124,17 +1070,17 @@ namespace SabreTools.Serialization
|
||||
int offset = 0;
|
||||
|
||||
// Create the output object
|
||||
var messageResourceData = new Models.PortableExecutable.MessageResourceData();
|
||||
var messageResourceData = new MessageResourceData();
|
||||
|
||||
// Message resource blocks
|
||||
messageResourceData.NumberOfBlocks = entry.Data.ReadUInt32(ref offset);
|
||||
if (messageResourceData.NumberOfBlocks > 0)
|
||||
{
|
||||
var messageResourceBlocks = new List<Models.PortableExecutable.MessageResourceBlock>();
|
||||
var messageResourceBlocks = new List<MessageResourceBlock>();
|
||||
|
||||
for (int i = 0; i < messageResourceData.NumberOfBlocks; i++)
|
||||
{
|
||||
var messageResourceBlock = new Models.PortableExecutable.MessageResourceBlock();
|
||||
var messageResourceBlock = new MessageResourceBlock();
|
||||
|
||||
messageResourceBlock.LowId = entry.Data.ReadUInt32(ref offset);
|
||||
messageResourceBlock.HighId = entry.Data.ReadUInt32(ref offset);
|
||||
@@ -1150,9 +1096,9 @@ namespace SabreTools.Serialization
|
||||
if (messageResourceData.Blocks != null && messageResourceData.Blocks.Length != 0)
|
||||
{
|
||||
#if NET48
|
||||
var messageResourceEntries = new Dictionary<uint, Models.PortableExecutable.MessageResourceEntry>();
|
||||
var messageResourceEntries = new Dictionary<uint, MessageResourceEntry>();
|
||||
#else
|
||||
var messageResourceEntries = new Dictionary<uint, Models.PortableExecutable.MessageResourceEntry?>();
|
||||
var messageResourceEntries = new Dictionary<uint, MessageResourceEntry?>();
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < messageResourceData.Blocks.Length; i++)
|
||||
@@ -1165,7 +1111,7 @@ namespace SabreTools.Serialization
|
||||
|
||||
for (uint j = messageResourceBlock.LowId; j <= messageResourceBlock.HighId; j++)
|
||||
{
|
||||
var messageResourceEntry = new Models.PortableExecutable.MessageResourceEntry();
|
||||
var messageResourceEntry = new MessageResourceEntry();
|
||||
|
||||
messageResourceEntry.Length = entry.Data.ReadUInt16(ref offset);
|
||||
messageResourceEntry.Flags = entry.Data.ReadUInt16(ref offset);
|
||||
@@ -1195,9 +1141,9 @@ namespace SabreTools.Serialization
|
||||
/// <param name="entry">Resource data entry to parse into a string table resource</param>
|
||||
/// <returns>A filled string table resource on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Dictionary<int, string> AsStringTable(this Models.PortableExecutable.ResourceDataEntry entry)
|
||||
public static Dictionary<int, string> AsStringTable(this ResourceDataEntry entry)
|
||||
#else
|
||||
public static Dictionary<int, string?>? AsStringTable(this Models.PortableExecutable.ResourceDataEntry? entry)
|
||||
public static Dictionary<int, string?>? AsStringTable(this ResourceDataEntry? entry)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid entry, just skip
|
||||
@@ -1246,9 +1192,9 @@ namespace SabreTools.Serialization
|
||||
/// <param name="entry">Resource data entry to parse into a version info resource</param>
|
||||
/// <returns>A filled version info resource on success, null on error</returns>
|
||||
#if NET48
|
||||
public static Models.PortableExecutable.VersionInfo AsVersionInfo(this Models.PortableExecutable.ResourceDataEntry entry)
|
||||
public static VersionInfo AsVersionInfo(this ResourceDataEntry entry)
|
||||
#else
|
||||
public static Models.PortableExecutable.VersionInfo? AsVersionInfo(this Models.PortableExecutable.ResourceDataEntry? entry)
|
||||
public static VersionInfo? AsVersionInfo(this ResourceDataEntry? entry)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid entry, just skip
|
||||
@@ -1259,11 +1205,11 @@ namespace SabreTools.Serialization
|
||||
int offset = 0;
|
||||
|
||||
// Create the output object
|
||||
var versionInfo = new Models.PortableExecutable.VersionInfo();
|
||||
var versionInfo = new VersionInfo();
|
||||
|
||||
versionInfo.Length = entry.Data.ReadUInt16(ref offset);
|
||||
versionInfo.ValueLength = entry.Data.ReadUInt16(ref offset);
|
||||
versionInfo.ResourceType = (Models.PortableExecutable.VersionResourceType)entry.Data.ReadUInt16(ref offset);
|
||||
versionInfo.ResourceType = (VersionResourceType)entry.Data.ReadUInt16(ref offset);
|
||||
versionInfo.Key = entry.Data.ReadString(ref offset, Encoding.Unicode);
|
||||
if (versionInfo.Key != "VS_VERSION_INFO")
|
||||
return null;
|
||||
@@ -1274,7 +1220,7 @@ namespace SabreTools.Serialization
|
||||
// Read fixed file info
|
||||
if (versionInfo.ValueLength > 0)
|
||||
{
|
||||
var fixedFileInfo = new Models.PortableExecutable.FixedFileInfo();
|
||||
var fixedFileInfo = new FixedFileInfo();
|
||||
fixedFileInfo.Signature = entry.Data.ReadUInt32(ref offset);
|
||||
if (fixedFileInfo.Signature != 0xFEEF04BD)
|
||||
return null;
|
||||
@@ -1285,10 +1231,10 @@ namespace SabreTools.Serialization
|
||||
fixedFileInfo.ProductVersionMS = entry.Data.ReadUInt32(ref offset);
|
||||
fixedFileInfo.ProductVersionLS = entry.Data.ReadUInt32(ref offset);
|
||||
fixedFileInfo.FileFlagsMask = entry.Data.ReadUInt32(ref offset);
|
||||
fixedFileInfo.FileFlags = (Models.PortableExecutable.FixedFileInfoFlags)(entry.Data.ReadUInt32(ref offset) & fixedFileInfo.FileFlagsMask);
|
||||
fixedFileInfo.FileOS = (Models.PortableExecutable.FixedFileInfoOS)entry.Data.ReadUInt32(ref offset);
|
||||
fixedFileInfo.FileType = (Models.PortableExecutable.FixedFileInfoFileType)entry.Data.ReadUInt32(ref offset);
|
||||
fixedFileInfo.FileSubtype = (Models.PortableExecutable.FixedFileInfoFileSubtype)entry.Data.ReadUInt32(ref offset);
|
||||
fixedFileInfo.FileFlags = (FixedFileInfoFlags)(entry.Data.ReadUInt32(ref offset) & fixedFileInfo.FileFlagsMask);
|
||||
fixedFileInfo.FileOS = (FixedFileInfoOS)entry.Data.ReadUInt32(ref offset);
|
||||
fixedFileInfo.FileType = (FixedFileInfoFileType)entry.Data.ReadUInt32(ref offset);
|
||||
fixedFileInfo.FileSubtype = (FixedFileInfoFileSubtype)entry.Data.ReadUInt32(ref offset);
|
||||
fixedFileInfo.FileDateMS = entry.Data.ReadUInt32(ref offset);
|
||||
fixedFileInfo.FileDateLS = entry.Data.ReadUInt32(ref offset);
|
||||
versionInfo.Value = fixedFileInfo;
|
||||
@@ -1361,19 +1307,19 @@ namespace SabreTools.Serialization
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>A filled string file info resource on success, null on error</returns>
|
||||
#if NET48
|
||||
private static Models.PortableExecutable.StringFileInfo AsStringFileInfo(byte[] data, ref int offset)
|
||||
private static StringFileInfo AsStringFileInfo(byte[] data, ref int offset)
|
||||
#else
|
||||
private static Models.PortableExecutable.StringFileInfo? AsStringFileInfo(byte[] data, ref int offset)
|
||||
private static StringFileInfo? AsStringFileInfo(byte[] data, ref int offset)
|
||||
#endif
|
||||
{
|
||||
var stringFileInfo = new Models.PortableExecutable.StringFileInfo();
|
||||
var stringFileInfo = new StringFileInfo();
|
||||
|
||||
// Cache the initial offset
|
||||
int currentOffset = offset;
|
||||
|
||||
stringFileInfo.Length = data.ReadUInt16(ref offset);
|
||||
stringFileInfo.ValueLength = data.ReadUInt16(ref offset);
|
||||
stringFileInfo.ResourceType = (Models.PortableExecutable.VersionResourceType)data.ReadUInt16(ref offset);
|
||||
stringFileInfo.ResourceType = (VersionResourceType)data.ReadUInt16(ref offset);
|
||||
stringFileInfo.Key = data.ReadString(ref offset, Encoding.Unicode);
|
||||
if (stringFileInfo.Key != "StringFileInfo")
|
||||
{
|
||||
@@ -1388,14 +1334,14 @@ namespace SabreTools.Serialization
|
||||
stringFileInfo.Padding = data.ReadByte(ref offset);
|
||||
}
|
||||
|
||||
var stringFileInfoChildren = new List<Models.PortableExecutable.StringTable>();
|
||||
var stringFileInfoChildren = new List<StringTable>();
|
||||
while ((offset - currentOffset) < stringFileInfo.Length)
|
||||
{
|
||||
var stringTable = new Models.PortableExecutable.StringTable();
|
||||
var stringTable = new StringTable();
|
||||
|
||||
stringTable.Length = data.ReadUInt16(ref offset);
|
||||
stringTable.ValueLength = data.ReadUInt16(ref offset);
|
||||
stringTable.ResourceType = (Models.PortableExecutable.VersionResourceType)data.ReadUInt16(ref offset);
|
||||
stringTable.ResourceType = (VersionResourceType)data.ReadUInt16(ref offset);
|
||||
stringTable.Key = data.ReadString(ref offset, Encoding.Unicode);
|
||||
|
||||
// Align to the DWORD boundary if we're not at the end
|
||||
@@ -1405,14 +1351,14 @@ namespace SabreTools.Serialization
|
||||
stringTable.Padding = data.ReadByte(ref offset);
|
||||
}
|
||||
|
||||
var stringTableChildren = new List<Models.PortableExecutable.StringData>();
|
||||
var stringTableChildren = new List<StringData>();
|
||||
while ((offset - currentOffset) < stringTable.Length)
|
||||
{
|
||||
var stringData = new Models.PortableExecutable.StringData();
|
||||
var stringData = new StringData();
|
||||
|
||||
stringData.Length = data.ReadUInt16(ref offset);
|
||||
stringData.ValueLength = data.ReadUInt16(ref offset);
|
||||
stringData.ResourceType = (Models.PortableExecutable.VersionResourceType)data.ReadUInt16(ref offset);
|
||||
stringData.ResourceType = (VersionResourceType)data.ReadUInt16(ref offset);
|
||||
stringData.Key = data.ReadString(ref offset, Encoding.Unicode);
|
||||
|
||||
// Align to the DWORD boundary if we're not at the end
|
||||
@@ -1460,19 +1406,19 @@ namespace SabreTools.Serialization
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>A filled var file info resource on success, null on error</returns>
|
||||
#if NET48
|
||||
private static Models.PortableExecutable.VarFileInfo AsVarFileInfo(byte[] data, ref int offset)
|
||||
private static VarFileInfo AsVarFileInfo(byte[] data, ref int offset)
|
||||
#else
|
||||
private static Models.PortableExecutable.VarFileInfo? AsVarFileInfo(byte[] data, ref int offset)
|
||||
private static VarFileInfo? AsVarFileInfo(byte[] data, ref int offset)
|
||||
#endif
|
||||
{
|
||||
var varFileInfo = new Models.PortableExecutable.VarFileInfo();
|
||||
var varFileInfo = new VarFileInfo();
|
||||
|
||||
// Cache the initial offset
|
||||
int initialOffset = offset;
|
||||
|
||||
varFileInfo.Length = data.ReadUInt16(ref offset);
|
||||
varFileInfo.ValueLength = data.ReadUInt16(ref offset);
|
||||
varFileInfo.ResourceType = (Models.PortableExecutable.VersionResourceType)data.ReadUInt16(ref offset);
|
||||
varFileInfo.ResourceType = (VersionResourceType)data.ReadUInt16(ref offset);
|
||||
varFileInfo.Key = data.ReadString(ref offset, Encoding.Unicode);
|
||||
if (varFileInfo.Key != "VarFileInfo")
|
||||
return null;
|
||||
@@ -1484,14 +1430,14 @@ namespace SabreTools.Serialization
|
||||
varFileInfo.Padding = data.ReadByte(ref offset);
|
||||
}
|
||||
|
||||
var varFileInfoChildren = new List<Models.PortableExecutable.VarData>();
|
||||
var varFileInfoChildren = new List<VarData>();
|
||||
while ((offset - initialOffset) < varFileInfo.Length)
|
||||
{
|
||||
var varData = new Models.PortableExecutable.VarData();
|
||||
var varData = new VarData();
|
||||
|
||||
varData.Length = data.ReadUInt16(ref offset);
|
||||
varData.ValueLength = data.ReadUInt16(ref offset);
|
||||
varData.ResourceType = (Models.PortableExecutable.VersionResourceType)data.ReadUInt16(ref offset);
|
||||
varData.ResourceType = (VersionResourceType)data.ReadUInt16(ref offset);
|
||||
varData.Key = data.ReadString(ref offset, Encoding.Unicode);
|
||||
if (varData.Key != "Translation")
|
||||
{
|
||||
@@ -1527,7 +1473,5 @@ namespace SabreTools.Serialization
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.AttractMode;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.AttractMode;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.ClrMamePro;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
@@ -6,14 +7,21 @@ namespace SabreTools.Serialization.Files
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public MetadataFile Deserialize(string path)
|
||||
public MetadataFile Deserialize(string path) => Deserialize(path, true);
|
||||
#else
|
||||
public MetadataFile? Deserialize(string? path)
|
||||
public MetadataFile? Deserialize(string? path) => Deserialize(path, true);
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public MetadataFile Deserialize(string path, bool quotes)
|
||||
#else
|
||||
public MetadataFile? Deserialize(string? path, bool quotes)
|
||||
#endif
|
||||
{
|
||||
using (var stream = PathProcessor.OpenStream(path))
|
||||
{
|
||||
return new Streams.ClrMamePro().Deserialize(stream);
|
||||
return new Streams.ClrMamePro().Deserialize(stream, quotes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SabreTools.Models.ClrMamePro;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
626
Files/CueSheet.Deserializer.cs
Normal file
626
Files/CueSheet.Deserializer.cs
Normal file
@@ -0,0 +1,626 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using SabreTools.Models.CueSheets;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class CueSheet : IFileSerializer<Models.CueSheets.CueSheet>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public Models.CueSheets.CueSheet Deserialize(string path)
|
||||
#else
|
||||
public Models.CueSheets.CueSheet? Deserialize(string? path)
|
||||
#endif
|
||||
{
|
||||
// Check that the file exists
|
||||
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
|
||||
return null;
|
||||
|
||||
// Check the extension
|
||||
string ext = Path.GetExtension(path).TrimStart('.');
|
||||
if (!string.Equals(ext, "cue", StringComparison.OrdinalIgnoreCase)
|
||||
&& !string.Equals(ext, "txt", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create the holding objects
|
||||
var cueSheet = new Models.CueSheets.CueSheet();
|
||||
var cueFiles = new List<CueFile>();
|
||||
|
||||
// Open the file and begin reading
|
||||
string[] cueLines = File.ReadAllLines(path);
|
||||
for (int i = 0; i < cueLines.Length; i++)
|
||||
{
|
||||
string line = cueLines[i].Trim();
|
||||
|
||||
// http://stackoverflow.com/questions/554013/regular-expression-to-split-on-spaces-unless-in-quotes
|
||||
string[] splitLine = Regex
|
||||
.Matches(line, @"[^\s""]+|""[^""]*""")
|
||||
.Cast<Match>()
|
||||
.Select(m => m.Groups[0].Value)
|
||||
.ToArray();
|
||||
|
||||
// If we have an empty line, we skip
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
|
||||
switch (splitLine[0])
|
||||
{
|
||||
// Read comments
|
||||
case "REM":
|
||||
// We ignore all comments for now
|
||||
break;
|
||||
|
||||
// Read MCN
|
||||
case "CATALOG":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"CATALOG line malformed: {line}");
|
||||
|
||||
cueSheet.Catalog = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read external CD-Text file path
|
||||
case "CDTEXTFILE":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"CDTEXTFILE line malformed: {line}");
|
||||
|
||||
cueSheet.CdTextFile = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced performer
|
||||
case "PERFORMER":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"PERFORMER line malformed: {line}");
|
||||
|
||||
cueSheet.Performer = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced songwriter
|
||||
case "SONGWRITER":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"SONGWRITER line malformed: {line}");
|
||||
|
||||
cueSheet.Songwriter = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced title
|
||||
case "TITLE":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"TITLE line malformed: {line}");
|
||||
|
||||
cueSheet.Title = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read file information
|
||||
case "FILE":
|
||||
if (splitLine.Length < 3)
|
||||
throw new FormatException($"FILE line malformed: {line}");
|
||||
|
||||
var file = CreateCueFile(splitLine[1], splitLine[2], cueLines, ref i);
|
||||
if (file == default)
|
||||
throw new FormatException($"FILE line malformed: {line}");
|
||||
|
||||
cueFiles.Add(file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cueSheet.Files = cueFiles.ToArray();
|
||||
return cueSheet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill a FILE from an array of lines
|
||||
/// </summary>
|
||||
/// <param name="fileName">File name to set</param>
|
||||
/// <param name="fileType">File type to set</param>
|
||||
/// <param name="cueLines">Lines array to pull from</param>
|
||||
/// <param name="i">Reference to index in array</param>
|
||||
#if NET48
|
||||
private static CueFile CreateCueFile(string fileName, string fileType, string[] cueLines, ref int i)
|
||||
#else
|
||||
private static CueFile? CreateCueFile(string fileName, string fileType, string[]? cueLines, ref int i)
|
||||
#endif
|
||||
{
|
||||
// Check the required parameters
|
||||
if (cueLines == null)
|
||||
throw new ArgumentNullException(nameof(cueLines));
|
||||
else if (i < 0 || i > cueLines.Length)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
// Create the holding objects
|
||||
var cueFile = new CueFile();
|
||||
var cueTracks = new List<CueTrack>();
|
||||
|
||||
// Set the current fields
|
||||
cueFile.FileName = fileName.Trim('"');
|
||||
cueFile.FileType = GetFileType(fileType);
|
||||
|
||||
// Increment to start
|
||||
i++;
|
||||
|
||||
for (; i < cueLines.Length; i++)
|
||||
{
|
||||
string line = cueLines[i].Trim();
|
||||
string[] splitLine = line.Split(' ');
|
||||
|
||||
// If we have an empty line, we skip
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
|
||||
switch (splitLine[0])
|
||||
{
|
||||
// Read comments
|
||||
case "REM":
|
||||
// We ignore all comments for now
|
||||
break;
|
||||
|
||||
// Read track information
|
||||
case "TRACK":
|
||||
if (splitLine.Length < 3)
|
||||
throw new FormatException($"TRACK line malformed: {line}");
|
||||
|
||||
var track = CreateCueTrack(splitLine[1], splitLine[2], cueLines, ref i);
|
||||
if (track == default)
|
||||
throw new FormatException($"TRACK line malformed: {line}");
|
||||
|
||||
cueTracks.Add(track);
|
||||
break;
|
||||
|
||||
// Default means return
|
||||
default:
|
||||
i--;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
cueFile.Tracks = cueTracks.ToArray();
|
||||
return cueFile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill a TRACK from an array of lines
|
||||
/// </summary>
|
||||
/// <param name="number">Number to set</param>
|
||||
/// <param name="dataType">Data type to set</param>
|
||||
/// <param name="cueLines">Lines array to pull from</param>
|
||||
/// <param name="i">Reference to index in array</param>
|
||||
#if NET48
|
||||
private static CueTrack CreateCueTrack(string number, string dataType, string[] cueLines, ref int i)
|
||||
#else
|
||||
private static CueTrack? CreateCueTrack(string number, string dataType, string[]? cueLines, ref int i)
|
||||
#endif
|
||||
{
|
||||
// Check the required parameters
|
||||
if (cueLines == null)
|
||||
throw new ArgumentNullException(nameof(cueLines));
|
||||
else if (i < 0 || i > cueLines.Length)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
// Set the current fields
|
||||
if (!int.TryParse(number, out int parsedNumber))
|
||||
throw new ArgumentException($"Number was not a number: {number}");
|
||||
else if (parsedNumber < 1 || parsedNumber > 99)
|
||||
throw new IndexOutOfRangeException($"Index must be between 1 and 99: {parsedNumber}");
|
||||
|
||||
// Create the holding objects
|
||||
var cueTrack = new CueTrack();
|
||||
var cueIndices = new List<CueIndex>();
|
||||
|
||||
cueTrack.Number = parsedNumber;
|
||||
cueTrack.DataType = GetDataType(dataType);
|
||||
|
||||
// Increment to start
|
||||
i++;
|
||||
|
||||
for (; i < cueLines.Length; i++)
|
||||
{
|
||||
string line = cueLines[i].Trim();
|
||||
string[] splitLine = line.Split(' ');
|
||||
|
||||
// If we have an empty line, we skip
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
|
||||
switch (splitLine[0])
|
||||
{
|
||||
// Read comments
|
||||
case "REM":
|
||||
// We ignore all comments for now
|
||||
break;
|
||||
|
||||
// Read flag information
|
||||
case "FLAGS":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"FLAGS line malformed: {line}");
|
||||
|
||||
cueTrack.Flags = GetFlags(splitLine);
|
||||
break;
|
||||
|
||||
// Read International Standard Recording Code
|
||||
case "ISRC":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"ISRC line malformed: {line}");
|
||||
|
||||
cueTrack.ISRC = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced performer
|
||||
case "PERFORMER":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"PERFORMER line malformed: {line}");
|
||||
|
||||
cueTrack.Performer = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced songwriter
|
||||
case "SONGWRITER":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"SONGWRITER line malformed: {line}");
|
||||
|
||||
cueTrack.Songwriter = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced title
|
||||
case "TITLE":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"TITLE line malformed: {line}");
|
||||
|
||||
cueTrack.Title = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read pregap information
|
||||
case "PREGAP":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"PREGAP line malformed: {line}");
|
||||
|
||||
var pregap = CreatePreGap(splitLine[1]);
|
||||
if (pregap == default)
|
||||
throw new FormatException($"PREGAP line malformed: {line}");
|
||||
|
||||
cueTrack.PreGap = pregap;
|
||||
break;
|
||||
|
||||
// Read index information
|
||||
case "INDEX":
|
||||
if (splitLine.Length < 3)
|
||||
throw new FormatException($"INDEX line malformed: {line}");
|
||||
|
||||
var index = CreateCueIndex(splitLine[1], splitLine[2]);
|
||||
if (index == default)
|
||||
throw new FormatException($"INDEX line malformed: {line}");
|
||||
|
||||
cueIndices.Add(index);
|
||||
break;
|
||||
|
||||
// Read postgap information
|
||||
case "POSTGAP":
|
||||
if (splitLine.Length < 2)
|
||||
throw new FormatException($"POSTGAP line malformed: {line}");
|
||||
|
||||
var postgap = CreatePostGap(splitLine[1]);
|
||||
if (postgap == default)
|
||||
throw new FormatException($"POSTGAP line malformed: {line}");
|
||||
|
||||
cueTrack.PostGap = postgap;
|
||||
break;
|
||||
|
||||
// Default means return
|
||||
default:
|
||||
i--;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
cueTrack.Indices = cueIndices.ToArray();
|
||||
return cueTrack;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a PREGAP from a mm:ss:ff length
|
||||
/// </summary>
|
||||
/// <param name="length">String to get length information from</param>
|
||||
#if NET48
|
||||
private static PreGap CreatePreGap(string length)
|
||||
#else
|
||||
private static PreGap CreatePreGap(string? length)
|
||||
#endif
|
||||
{
|
||||
// Ignore empty lines
|
||||
if (string.IsNullOrWhiteSpace(length))
|
||||
throw new ArgumentException("Length was null or whitespace");
|
||||
|
||||
// Ignore lines that don't contain the correct information
|
||||
if (length.Length != 8 || length.Count(c => c == ':') != 2)
|
||||
throw new FormatException($"Length was not in a recognized format: {length}");
|
||||
|
||||
// Split the line
|
||||
string[] splitLength = length.Split(':');
|
||||
if (splitLength.Length != 3)
|
||||
throw new FormatException($"Length was not in a recognized format: {length}");
|
||||
|
||||
// Parse the lengths
|
||||
int[] lengthSegments = new int[3];
|
||||
|
||||
// Minutes
|
||||
if (!int.TryParse(splitLength[0], out lengthSegments[0]))
|
||||
throw new FormatException($"Minutes segment was not a number: {splitLength[0]}");
|
||||
else if (lengthSegments[0] < 0)
|
||||
throw new IndexOutOfRangeException($"Minutes segment must be 0 or greater: {lengthSegments[0]}");
|
||||
|
||||
// Seconds
|
||||
if (!int.TryParse(splitLength[1], out lengthSegments[1]))
|
||||
throw new FormatException($"Seconds segment was not a number: {splitLength[1]}");
|
||||
else if (lengthSegments[1] < 0 || lengthSegments[1] > 60)
|
||||
throw new IndexOutOfRangeException($"Seconds segment must be between 0 and 60: {lengthSegments[1]}");
|
||||
|
||||
// Frames
|
||||
if (!int.TryParse(splitLength[2], out lengthSegments[2]))
|
||||
throw new FormatException($"Frames segment was not a number: {splitLength[2]}");
|
||||
else if (lengthSegments[2] < 0 || lengthSegments[2] > 75)
|
||||
throw new IndexOutOfRangeException($"Frames segment must be between 0 and 75: {lengthSegments[2]}");
|
||||
|
||||
// Set the values
|
||||
var preGap = new PreGap
|
||||
{
|
||||
Minutes = lengthSegments[0],
|
||||
Seconds = lengthSegments[1],
|
||||
Frames = lengthSegments[2],
|
||||
};
|
||||
return preGap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill a INDEX from an array of lines
|
||||
/// </summary>
|
||||
/// <param name="index">Index to set</param>
|
||||
/// <param name="startTime">Start time to set</param>
|
||||
#if NET48
|
||||
private static CueIndex CreateCueIndex(string index, string startTime)
|
||||
#else
|
||||
private static CueIndex CreateCueIndex(string? index, string? startTime)
|
||||
#endif
|
||||
{
|
||||
// Set the current fields
|
||||
if (!int.TryParse(index, out int parsedIndex))
|
||||
throw new ArgumentException($"Index was not a number: {index}");
|
||||
else if (parsedIndex < 0 || parsedIndex > 99)
|
||||
throw new IndexOutOfRangeException($"Index must be between 0 and 99: {parsedIndex}");
|
||||
|
||||
// Ignore empty lines
|
||||
if (string.IsNullOrWhiteSpace(startTime))
|
||||
throw new ArgumentException("Start time was null or whitespace");
|
||||
|
||||
// Ignore lines that don't contain the correct information
|
||||
if (startTime.Length != 8 || startTime.Count(c => c == ':') != 2)
|
||||
throw new FormatException($"Start time was not in a recognized format: {startTime}");
|
||||
|
||||
// Split the line
|
||||
string[] splitTime = startTime.Split(':');
|
||||
if (splitTime.Length != 3)
|
||||
throw new FormatException($"Start time was not in a recognized format: {startTime}");
|
||||
|
||||
// Parse the lengths
|
||||
int[] lengthSegments = new int[3];
|
||||
|
||||
// Minutes
|
||||
if (!int.TryParse(splitTime[0], out lengthSegments[0]))
|
||||
throw new FormatException($"Minutes segment was not a number: {splitTime[0]}");
|
||||
else if (lengthSegments[0] < 0)
|
||||
throw new IndexOutOfRangeException($"Minutes segment must be 0 or greater: {lengthSegments[0]}");
|
||||
|
||||
// Seconds
|
||||
if (!int.TryParse(splitTime[1], out lengthSegments[1]))
|
||||
throw new FormatException($"Seconds segment was not a number: {splitTime[1]}");
|
||||
else if (lengthSegments[1] < 0 || lengthSegments[1] > 60)
|
||||
throw new IndexOutOfRangeException($"Seconds segment must be between 0 and 60: {lengthSegments[1]}");
|
||||
|
||||
// Frames
|
||||
if (!int.TryParse(splitTime[2], out lengthSegments[2]))
|
||||
throw new FormatException($"Frames segment was not a number: {splitTime[2]}");
|
||||
else if (lengthSegments[2] < 0 || lengthSegments[2] > 75)
|
||||
throw new IndexOutOfRangeException($"Frames segment must be between 0 and 75: {lengthSegments[2]}");
|
||||
|
||||
// Set the values
|
||||
var cueIndex = new CueIndex
|
||||
{
|
||||
Index = parsedIndex,
|
||||
Minutes = lengthSegments[0],
|
||||
Seconds = lengthSegments[1],
|
||||
Frames = lengthSegments[2],
|
||||
};
|
||||
return cueIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a POSTGAP from a mm:ss:ff length
|
||||
/// </summary>
|
||||
/// <param name="length">String to get length information from</param>
|
||||
#if NET48
|
||||
private static PostGap CreatePostGap(string length)
|
||||
#else
|
||||
private static PostGap CreatePostGap(string? length)
|
||||
#endif
|
||||
{
|
||||
// Ignore empty lines
|
||||
if (string.IsNullOrWhiteSpace(length))
|
||||
throw new ArgumentException("Length was null or whitespace");
|
||||
|
||||
// Ignore lines that don't contain the correct information
|
||||
if (length.Length != 8 || length.Count(c => c == ':') != 2)
|
||||
throw new FormatException($"Length was not in a recognized format: {length}");
|
||||
|
||||
// Split the line
|
||||
string[] splitLength = length.Split(':');
|
||||
if (splitLength.Length != 3)
|
||||
throw new FormatException($"Length was not in a recognized format: {length}");
|
||||
|
||||
// Parse the lengths
|
||||
int[] lengthSegments = new int[3];
|
||||
|
||||
// Minutes
|
||||
if (!int.TryParse(splitLength[0], out lengthSegments[0]))
|
||||
throw new FormatException($"Minutes segment was not a number: {splitLength[0]}");
|
||||
else if (lengthSegments[0] < 0)
|
||||
throw new IndexOutOfRangeException($"Minutes segment must be 0 or greater: {lengthSegments[0]}");
|
||||
|
||||
// Seconds
|
||||
if (!int.TryParse(splitLength[1], out lengthSegments[1]))
|
||||
throw new FormatException($"Seconds segment was not a number: {splitLength[1]}");
|
||||
else if (lengthSegments[1] < 0 || lengthSegments[1] > 60)
|
||||
throw new IndexOutOfRangeException($"Seconds segment must be between 0 and 60: {lengthSegments[1]}");
|
||||
|
||||
// Frames
|
||||
if (!int.TryParse(splitLength[2], out lengthSegments[2]))
|
||||
throw new FormatException($"Frames segment was not a number: {splitLength[2]}");
|
||||
else if (lengthSegments[2] < 0 || lengthSegments[2] > 75)
|
||||
throw new IndexOutOfRangeException($"Frames segment must be between 0 and 75: {lengthSegments[2]}");
|
||||
|
||||
// Set the values
|
||||
var postGap = new PostGap
|
||||
{
|
||||
Minutes = lengthSegments[0],
|
||||
Seconds = lengthSegments[1],
|
||||
Frames = lengthSegments[2],
|
||||
};
|
||||
return postGap;
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Get the file type from a given string
|
||||
/// </summary>
|
||||
/// <param name="fileType">String to get value from</param>
|
||||
/// <returns>CueFileType, if possible</returns>
|
||||
#if NET48
|
||||
private static CueFileType GetFileType(string fileType)
|
||||
#else
|
||||
private static CueFileType GetFileType(string? fileType)
|
||||
#endif
|
||||
{
|
||||
switch (fileType?.ToLowerInvariant())
|
||||
{
|
||||
case "binary":
|
||||
return CueFileType.BINARY;
|
||||
|
||||
case "motorola":
|
||||
return CueFileType.MOTOROLA;
|
||||
|
||||
case "aiff":
|
||||
return CueFileType.AIFF;
|
||||
|
||||
case "wave":
|
||||
return CueFileType.WAVE;
|
||||
|
||||
case "mp3":
|
||||
return CueFileType.MP3;
|
||||
|
||||
default:
|
||||
return CueFileType.BINARY;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the data type from a given string
|
||||
/// </summary>
|
||||
/// <param name="dataType">String to get value from</param>
|
||||
/// <returns>CueTrackDataType, if possible (default AUDIO)</returns>
|
||||
#if NET48
|
||||
private static CueTrackDataType GetDataType(string dataType)
|
||||
#else
|
||||
private static CueTrackDataType GetDataType(string? dataType)
|
||||
#endif
|
||||
{
|
||||
switch (dataType?.ToLowerInvariant())
|
||||
{
|
||||
case "audio":
|
||||
return CueTrackDataType.AUDIO;
|
||||
|
||||
case "cdg":
|
||||
return CueTrackDataType.CDG;
|
||||
|
||||
case "mode1/2048":
|
||||
return CueTrackDataType.MODE1_2048;
|
||||
|
||||
case "mode1/2352":
|
||||
return CueTrackDataType.MODE1_2352;
|
||||
|
||||
case "mode2/2336":
|
||||
return CueTrackDataType.MODE2_2336;
|
||||
|
||||
case "mode2/2352":
|
||||
return CueTrackDataType.MODE2_2352;
|
||||
|
||||
case "cdi/2336":
|
||||
return CueTrackDataType.CDI_2336;
|
||||
|
||||
case "cdi/2352":
|
||||
return CueTrackDataType.CDI_2352;
|
||||
|
||||
default:
|
||||
return CueTrackDataType.AUDIO;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the flag value for an array of strings
|
||||
/// </summary>
|
||||
/// <param name="flagStrings">Possible flags as strings</param>
|
||||
/// <returns>CueTrackFlag value representing the strings, if possible</returns>
|
||||
#if NET48
|
||||
private static CueTrackFlag GetFlags(string[] flagStrings)
|
||||
#else
|
||||
private static CueTrackFlag GetFlags(string?[]? flagStrings)
|
||||
#endif
|
||||
{
|
||||
CueTrackFlag flag = 0;
|
||||
if (flagStrings == null)
|
||||
return flag;
|
||||
|
||||
#if NET48
|
||||
foreach (string flagString in flagStrings)
|
||||
#else
|
||||
foreach (string? flagString in flagStrings)
|
||||
#endif
|
||||
{
|
||||
switch (flagString?.ToLowerInvariant())
|
||||
{
|
||||
case "flags":
|
||||
// No-op since this is the start of the line
|
||||
break;
|
||||
|
||||
case "dcp":
|
||||
flag |= CueTrackFlag.DCP;
|
||||
break;
|
||||
|
||||
case "4ch":
|
||||
flag |= CueTrackFlag.FourCH;
|
||||
break;
|
||||
|
||||
case "pre":
|
||||
flag |= CueTrackFlag.PRE;
|
||||
break;
|
||||
|
||||
case "scms":
|
||||
flag |= CueTrackFlag.SCMS;
|
||||
break;
|
||||
|
||||
case "data":
|
||||
flag |= CueTrackFlag.DATA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
31
Files/CueSheet.Serializer.cs
Normal file
31
Files/CueSheet.Serializer.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class CueSheet : IFileSerializer<Models.CueSheets.CueSheet>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public bool Serialize(Models.CueSheets.CueSheet obj, string path)
|
||||
#else
|
||||
public bool Serialize(Models.CueSheets.CueSheet? obj, string? path)
|
||||
#endif
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
return false;
|
||||
|
||||
using (var stream = new Streams.CueSheet().Serialize(obj))
|
||||
{
|
||||
if (stream == null)
|
||||
return false;
|
||||
|
||||
using (var fs = File.OpenWrite(path))
|
||||
{
|
||||
stream.CopyTo(fs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.DosCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.DosCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.EverdriveSMDB;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.EverdriveSMDB;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class Hashfile : IFileSerializer<Models.Hashfile.Hashfile>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public Models.Hashfile.Hashfile Deserialize(string path)
|
||||
public Models.Hashfile.Hashfile Deserialize(string path) => Deserialize(path, Hash.CRC);
|
||||
#else
|
||||
public Models.Hashfile.Hashfile? Deserialize(string? path)
|
||||
public Models.Hashfile.Hashfile? Deserialize(string? path) => Deserialize(path, Hash.CRC);
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public Models.Hashfile.Hashfile Deserialize(string path, Hash hash)
|
||||
#else
|
||||
public Models.Hashfile.Hashfile? Deserialize(string? path, Hash hash)
|
||||
#endif
|
||||
{
|
||||
using (var stream = PathProcessor.OpenStream(path))
|
||||
{
|
||||
return new Streams.Hashfile().Deserialize(stream);
|
||||
return new Streams.Hashfile().Deserialize(stream, hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,27 @@
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class Hashfile : IFileSerializer<Models.Hashfile.Hashfile>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public bool Serialize(Models.Hashfile.Hashfile obj, string path)
|
||||
public bool Serialize(Models.Hashfile.Hashfile obj, string path) => Serialize(obj, path, Hash.CRC);
|
||||
#else
|
||||
public bool Serialize(Models.Hashfile.Hashfile? obj, string? path)
|
||||
public bool Serialize(Models.Hashfile.Hashfile? obj, string? path) => Serialize(obj, path, Hash.CRC);
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public bool Serialize(Models.Hashfile.Hashfile obj, string path, Hash hash)
|
||||
#else
|
||||
public bool Serialize(Models.Hashfile.Hashfile? obj, string? path, Hash hash)
|
||||
#endif
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
return false;
|
||||
|
||||
using (var stream = new Streams.Hashfile().Serialize(obj))
|
||||
using (var stream = new Streams.Hashfile().Serialize(obj, hash))
|
||||
{
|
||||
if (stream == null)
|
||||
return false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.Listrom;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.Listrom;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
21
Files/PIC.Deserializer.cs
Normal file
21
Files/PIC.Deserializer.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using SabreTools.Models.PIC;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class PIC : IFileSerializer<DiscInformation>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public DiscInformation Deserialize(string path)
|
||||
#else
|
||||
public DiscInformation? Deserialize(string? path)
|
||||
#endif
|
||||
{
|
||||
using (var stream = PathProcessor.OpenStream(path))
|
||||
{
|
||||
return new Streams.PIC().Deserialize(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Files/PIC.Serializer.cs
Normal file
31
Files/PIC.Serializer.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using SabreTools.Models.PIC;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class PIC : IFileSerializer<DiscInformation>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public bool Serialize(DiscInformation obj, string path)
|
||||
#else
|
||||
public bool Serialize(DiscInformation? obj, string? path)
|
||||
#endif
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
return false;
|
||||
|
||||
using (var stream = new Streams.PIC().Serialize(obj))
|
||||
{
|
||||
if (stream == null)
|
||||
return false;
|
||||
|
||||
using (var fs = System.IO.File.OpenWrite(path))
|
||||
{
|
||||
stream.CopyTo(fs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.RomCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.RomCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.SeparatedValue;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
@@ -6,14 +7,21 @@ namespace SabreTools.Serialization.Files
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public MetadataFile Deserialize(string path)
|
||||
public MetadataFile Deserialize(string path) => Deserialize(path, ',');
|
||||
#else
|
||||
public MetadataFile? Deserialize(string? path)
|
||||
public MetadataFile? Deserialize(string? path) => Deserialize(path, ',');
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public MetadataFile Deserialize(string path, char delim)
|
||||
#else
|
||||
public MetadataFile? Deserialize(string? path, char delim)
|
||||
#endif
|
||||
{
|
||||
using (var stream = PathProcessor.OpenStream(path))
|
||||
{
|
||||
return new Streams.SeparatedValue().Deserialize(stream);
|
||||
return new Streams.SeparatedValue().Deserialize(stream, delim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SabreTools.Models.SeparatedValue;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
@@ -6,15 +7,22 @@ namespace SabreTools.Serialization.Files
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public bool Serialize(MetadataFile obj, string path)
|
||||
public bool Serialize(MetadataFile obj, string path) => Serialize(obj, path, ',');
|
||||
#else
|
||||
public bool Serialize(MetadataFile? obj, string? path)
|
||||
public bool Serialize(MetadataFile? obj, string? path) => Serialize(obj, path, ',');
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public bool Serialize(MetadataFile obj, string path, char delim)
|
||||
#else
|
||||
public bool Serialize(MetadataFile? obj, string? path, char delim)
|
||||
#endif
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
return false;
|
||||
|
||||
using (var stream = new Streams.SeparatedValue().Serialize(obj))
|
||||
using (var stream = new Streams.SeparatedValue().Serialize(obj, delim))
|
||||
{
|
||||
if (stream == null)
|
||||
return false;
|
||||
|
||||
216
Files/XMID.Deserializer.cs
Normal file
216
Files/XMID.Deserializer.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class XMID : IFileSerializer<Models.Xbox.XMID>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
/// <remarks>This treats the input path like a parseable string</remarks>
|
||||
#if NET48
|
||||
public Models.Xbox.XMID Deserialize(string path)
|
||||
#else
|
||||
public Models.Xbox.XMID? Deserialize(string? path)
|
||||
#endif
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
return null;
|
||||
|
||||
string xmid = path.TrimEnd('\0');
|
||||
if (string.IsNullOrWhiteSpace(xmid))
|
||||
return null;
|
||||
|
||||
return ParseXMID(xmid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an XGD2/3 XMID string
|
||||
/// </summary>
|
||||
/// <param name="xmidString">XMID string to attempt to parse</param>
|
||||
/// <returns>Filled XMID on success, null on error</returns>
|
||||
#if NET48
|
||||
private static Models.Xbox.XMID ParseXMID(string xmidString)
|
||||
#else
|
||||
private static Models.Xbox.XMID? ParseXMID(string? xmidString)
|
||||
#endif
|
||||
{
|
||||
if (xmidString == null || xmidString.Length != 8)
|
||||
return null;
|
||||
|
||||
var xmid = new Models.Xbox.XMID();
|
||||
|
||||
xmid.PublisherIdentifier = xmidString.Substring(0, 2);
|
||||
if (string.IsNullOrEmpty(PublisherName(xmid)))
|
||||
return null;
|
||||
|
||||
xmid.GameID = xmidString.Substring(2, 3);
|
||||
xmid.VersionNumber = xmidString.Substring(5, 2);
|
||||
xmid.RegionIdentifier = xmidString[7];
|
||||
if (InternalRegion(xmid) == null)
|
||||
return null;
|
||||
|
||||
return xmid;
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable name derived from the publisher identifier
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static string PublisherName(Models.Xbox.XMID xmid) => GetPublisher(xmid.PublisherIdentifier);
|
||||
#else
|
||||
public static string? PublisherName(Models.Xbox.XMID xmid) => GetPublisher(xmid.PublisherIdentifier);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Internally represented region
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static string InternalRegion(Models.Xbox.XMID xmid) => GetRegion(xmid.RegionIdentifier);
|
||||
#else
|
||||
public static string? InternalRegion(Models.Xbox.XMID xmid) => GetRegion(xmid.RegionIdentifier);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Get the full name of the publisher from the 2-character identifier
|
||||
/// </summary>
|
||||
/// <param name="publisherIdentifier">Case-sensitive 2-character identifier</param>
|
||||
/// <returns>Publisher name, if possible</returns>
|
||||
/// <see cref="https://xboxdevwiki.net/Xbe#Title_ID"/>
|
||||
#if NET48
|
||||
private static string GetPublisher(string publisherIdentifier)
|
||||
#else
|
||||
private static string? GetPublisher(string? publisherIdentifier)
|
||||
#endif
|
||||
{
|
||||
switch (publisherIdentifier)
|
||||
{
|
||||
case "AC": return "Acclaim Entertainment";
|
||||
case "AH": return "ARUSH Entertainment";
|
||||
case "AQ": return "Aqua System";
|
||||
case "AS": return "ASK";
|
||||
case "AT": return "Atlus";
|
||||
case "AV": return "Activision";
|
||||
case "AY": return "Aspyr Media";
|
||||
case "BA": return "Bandai";
|
||||
case "BL": return "Black Box";
|
||||
case "BM": return "BAM! Entertainment";
|
||||
case "BR": return "Broccoli Co.";
|
||||
case "BS": return "Bethesda Softworks";
|
||||
case "BU": return "Bunkasha Co.";
|
||||
case "BV": return "Buena Vista Games";
|
||||
case "BW": return "BBC Multimedia";
|
||||
case "BZ": return "Blizzard";
|
||||
case "CC": return "Capcom";
|
||||
case "CK": return "Kemco Corporation"; // TODO: Confirm
|
||||
case "CM": return "Codemasters";
|
||||
case "CV": return "Crave Entertainment";
|
||||
case "DC": return "DreamCatcher Interactive";
|
||||
case "DX": return "Davilex";
|
||||
case "EA": return "Electronic Arts (EA)";
|
||||
case "EC": return "Encore inc";
|
||||
case "EL": return "Enlight Software";
|
||||
case "EM": return "Empire Interactive";
|
||||
case "ES": return "Eidos Interactive";
|
||||
case "FI": return "Fox Interactive";
|
||||
case "FS": return "From Software";
|
||||
case "GE": return "Genki Co.";
|
||||
case "GV": return "Groove Games";
|
||||
case "HE": return "Tru Blu (Entertainment division of Home Entertainment Suppliers)";
|
||||
case "HP": return "Hip games";
|
||||
case "HU": return "Hudson Soft";
|
||||
case "HW": return "Highwaystar";
|
||||
case "IA": return "Mad Catz Interactive";
|
||||
case "IF": return "Idea Factory";
|
||||
case "IG": return "Infogrames";
|
||||
case "IL": return "Interlex Corporation";
|
||||
case "IM": return "Imagine Media";
|
||||
case "IO": return "Ignition Entertainment";
|
||||
case "IP": return "Interplay Entertainment";
|
||||
case "IX": return "InXile Entertainment"; // TODO: Confirm
|
||||
case "JA": return "Jaleco";
|
||||
case "JW": return "JoWooD";
|
||||
case "KB": return "Kemco"; // TODO: Confirm
|
||||
case "KI": return "Kids Station Inc."; // TODO: Confirm
|
||||
case "KN": return "Konami";
|
||||
case "KO": return "KOEI";
|
||||
case "KU": return "Kobi and / or GAE (formerly Global A Entertainment)"; // TODO: Confirm
|
||||
case "LA": return "LucasArts";
|
||||
case "LS": return "Black Bean Games (publishing arm of Leader S.p.A.)";
|
||||
case "MD": return "Metro3D";
|
||||
case "ME": return "Medix";
|
||||
case "MI": return "Microïds";
|
||||
case "MJ": return "Majesco Entertainment";
|
||||
case "MM": return "Myelin Media";
|
||||
case "MP": return "MediaQuest"; // TODO: Confirm
|
||||
case "MS": return "Microsoft Game Studios";
|
||||
case "MW": return "Midway Games";
|
||||
case "MX": return "Empire Interactive"; // TODO: Confirm
|
||||
case "NK": return "NewKidCo";
|
||||
case "NL": return "NovaLogic";
|
||||
case "NM": return "Namco";
|
||||
case "OX": return "Oxygen Interactive";
|
||||
case "PC": return "Playlogic Entertainment";
|
||||
case "PL": return "Phantagram Co., Ltd.";
|
||||
case "RA": return "Rage";
|
||||
case "SA": return "Sammy";
|
||||
case "SC": return "SCi Games";
|
||||
case "SE": return "SEGA";
|
||||
case "SN": return "SNK";
|
||||
case "SS": return "Simon & Schuster";
|
||||
case "SU": return "Success Corporation";
|
||||
case "SW": return "Swing! Deutschland";
|
||||
case "TA": return "Takara";
|
||||
case "TC": return "Tecmo";
|
||||
case "TD": return "The 3DO Company (or just 3DO)";
|
||||
case "TK": return "Takuyo";
|
||||
case "TM": return "TDK Mediactive";
|
||||
case "TQ": return "THQ";
|
||||
case "TS": return "Titus Interactive";
|
||||
case "TT": return "Take-Two Interactive Software";
|
||||
case "US": return "Ubisoft";
|
||||
case "VC": return "Victor Interactive Software";
|
||||
case "VN": return "Vivendi Universal (just took Interplays publishing rights)"; // TODO: Confirm
|
||||
case "VU": return "Vivendi Universal Games";
|
||||
case "VV": return "Vivendi Universal Games"; // TODO: Confirm
|
||||
case "WE": return "Wanadoo Edition";
|
||||
case "WR": return "Warner Bros. Interactive Entertainment"; // TODO: Confirm
|
||||
case "XI": return "XPEC Entertainment and Idea Factory";
|
||||
case "XK": return "Xbox kiosk disk?"; // TODO: Confirm
|
||||
case "XL": return "Xbox special bundled or live demo disk?"; // TODO: Confirm
|
||||
case "XM": return "Evolved Games"; // TODO: Confirm
|
||||
case "XP": return "XPEC Entertainment";
|
||||
case "XR": return "Panorama";
|
||||
case "YB": return "YBM Sisa (South-Korea)";
|
||||
case "ZD": return "Zushi Games (formerly Zoo Digital Publishing)";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the region based on the XGD serial character
|
||||
/// </summary>
|
||||
/// <param name="region">Character denoting the region</param>
|
||||
/// <returns>Region, if possible</returns>
|
||||
#if NET48
|
||||
private static string GetRegion(char region)
|
||||
#else
|
||||
private static string? GetRegion(char region)
|
||||
#endif
|
||||
{
|
||||
switch (region)
|
||||
{
|
||||
case 'W': return "World";
|
||||
case 'A': return "USA";
|
||||
case 'J': return "Japan / Asia";
|
||||
case 'E': return "Europe";
|
||||
case 'K': return "USA / Japan";
|
||||
case 'L': return "USA / Europe";
|
||||
case 'H': return "Japan / Europe";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
15
Files/XMID.Serializer.cs
Normal file
15
Files/XMID.Serializer.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class XMID : IFileSerializer<Models.Xbox.XMID>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public bool Serialize(Models.Xbox.XMID obj, string path) => throw new NotImplementedException();
|
||||
#else
|
||||
public bool Serialize(Models.Xbox.XMID? obj, string? path) => throw new NotImplementedException();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
275
Files/XeMID.Deserializer.cs
Normal file
275
Files/XeMID.Deserializer.cs
Normal file
@@ -0,0 +1,275 @@
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class XeMID : IFileSerializer<Models.Xbox.XeMID>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
/// <remarks>This treats the input path like a parseable string</remarks>
|
||||
#if NET48
|
||||
public Models.Xbox.XeMID Deserialize(string path)
|
||||
#else
|
||||
public Models.Xbox.XeMID? Deserialize(string? path)
|
||||
#endif
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
return null;
|
||||
|
||||
string xemid = path.TrimEnd('\0');
|
||||
if (string.IsNullOrWhiteSpace(xemid))
|
||||
return null;
|
||||
|
||||
return ParseXeMID(xemid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an XGD2/3 XeMID string
|
||||
/// </summary>
|
||||
/// <param name="xemidString">XeMID string to attempt to parse</param>
|
||||
/// <returns>Filled XeMID on success, null on error</returns>
|
||||
#if NET48
|
||||
private static Models.Xbox.XeMID ParseXeMID(string xemidString)
|
||||
#else
|
||||
private static Models.Xbox.XeMID? ParseXeMID(string? xemidString)
|
||||
#endif
|
||||
{
|
||||
if (xemidString == null
|
||||
|| (xemidString.Length != 13 && xemidString.Length != 14
|
||||
&& xemidString.Length != 21 && xemidString.Length != 22))
|
||||
return null;
|
||||
|
||||
var xemid = new Models.Xbox.XeMID();
|
||||
|
||||
xemid.PublisherIdentifier = xemidString.Substring(0, 2);
|
||||
if (string.IsNullOrEmpty(PublisherName(xemid)))
|
||||
return null;
|
||||
|
||||
xemid.PlatformIdentifier = xemidString[2];
|
||||
if (xemid.PlatformIdentifier != '2')
|
||||
return null;
|
||||
|
||||
xemid.GameID = xemidString.Substring(3, 3);
|
||||
xemid.SKU = xemidString.Substring(6, 2);
|
||||
xemid.RegionIdentifier = xemidString[8];
|
||||
if (InternalRegion(xemid) == null)
|
||||
return null;
|
||||
|
||||
if (xemidString.Length == 13 || xemidString.Length == 21)
|
||||
{
|
||||
xemid.BaseVersion = xemidString.Substring(9, 1);
|
||||
xemid.MediaSubtypeIdentifier = xemidString[10];
|
||||
if (string.IsNullOrEmpty(MediaSubtype(xemid)))
|
||||
return null;
|
||||
|
||||
xemid.DiscNumberIdentifier = xemidString.Substring(11, 2);
|
||||
}
|
||||
else if (xemidString.Length == 14 || xemidString.Length == 22)
|
||||
{
|
||||
xemid.BaseVersion = xemidString.Substring(9, 2);
|
||||
xemid.MediaSubtypeIdentifier = xemidString[11];
|
||||
if (string.IsNullOrEmpty(MediaSubtype(xemid)))
|
||||
return null;
|
||||
|
||||
xemid.DiscNumberIdentifier = xemidString.Substring(12, 2);
|
||||
}
|
||||
|
||||
if (xemidString.Length == 21)
|
||||
xemid.CertificationSubmissionIdentifier = xemidString.Substring(13);
|
||||
else if (xemidString.Length == 22)
|
||||
xemid.CertificationSubmissionIdentifier = xemidString.Substring(14);
|
||||
|
||||
return xemid;
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable name derived from the publisher identifier
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static string PublisherName(Models.Xbox.XeMID xemid) => GetPublisher(xemid.PublisherIdentifier);
|
||||
#else
|
||||
public static string? PublisherName(Models.Xbox.XeMID xemid) => GetPublisher(xemid.PublisherIdentifier);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Internally represented region
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static string InternalRegion(Models.Xbox.XeMID xemid) => GetRegion(xemid.RegionIdentifier);
|
||||
#else
|
||||
public static string? InternalRegion(Models.Xbox.XeMID xemid) => GetRegion(xemid.RegionIdentifier);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable subtype derived from the media identifier
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static string MediaSubtype(Models.Xbox.XeMID xemid) => GetMediaSubtype(xemid.MediaSubtypeIdentifier);
|
||||
#else
|
||||
public static string? MediaSubtype(Models.Xbox.XeMID xemid) => GetMediaSubtype(xemid.MediaSubtypeIdentifier);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Determine the XGD type based on the XGD2/3 media type identifier character
|
||||
/// </summary>
|
||||
/// <param name="mediaTypeIdentifier">Character denoting the media type</param>
|
||||
/// <returns>Media subtype as a string, if possible</returns>
|
||||
#if NET48
|
||||
private static string GetMediaSubtype(char mediaTypeIdentifier)
|
||||
#else
|
||||
private static string? GetMediaSubtype(char mediaTypeIdentifier)
|
||||
#endif
|
||||
{
|
||||
switch (mediaTypeIdentifier)
|
||||
{
|
||||
case 'F': return "XGD3";
|
||||
case 'X': return "XGD2";
|
||||
case 'Z': return "Games on Demand / Marketplace Demo";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the full name of the publisher from the 2-character identifier
|
||||
/// </summary>
|
||||
/// <param name="publisherIdentifier">Case-sensitive 2-character identifier</param>
|
||||
/// <returns>Publisher name, if possible</returns>
|
||||
/// <see cref="https://xboxdevwiki.net/Xbe#Title_ID"/>
|
||||
#if NET48
|
||||
private static string GetPublisher(string publisherIdentifier)
|
||||
#else
|
||||
private static string? GetPublisher(string? publisherIdentifier)
|
||||
#endif
|
||||
{
|
||||
switch (publisherIdentifier)
|
||||
{
|
||||
case "AC": return "Acclaim Entertainment";
|
||||
case "AH": return "ARUSH Entertainment";
|
||||
case "AQ": return "Aqua System";
|
||||
case "AS": return "ASK";
|
||||
case "AT": return "Atlus";
|
||||
case "AV": return "Activision";
|
||||
case "AY": return "Aspyr Media";
|
||||
case "BA": return "Bandai";
|
||||
case "BL": return "Black Box";
|
||||
case "BM": return "BAM! Entertainment";
|
||||
case "BR": return "Broccoli Co.";
|
||||
case "BS": return "Bethesda Softworks";
|
||||
case "BU": return "Bunkasha Co.";
|
||||
case "BV": return "Buena Vista Games";
|
||||
case "BW": return "BBC Multimedia";
|
||||
case "BZ": return "Blizzard";
|
||||
case "CC": return "Capcom";
|
||||
case "CK": return "Kemco Corporation"; // TODO: Confirm
|
||||
case "CM": return "Codemasters";
|
||||
case "CV": return "Crave Entertainment";
|
||||
case "DC": return "DreamCatcher Interactive";
|
||||
case "DX": return "Davilex";
|
||||
case "EA": return "Electronic Arts (EA)";
|
||||
case "EC": return "Encore inc";
|
||||
case "EL": return "Enlight Software";
|
||||
case "EM": return "Empire Interactive";
|
||||
case "ES": return "Eidos Interactive";
|
||||
case "FI": return "Fox Interactive";
|
||||
case "FS": return "From Software";
|
||||
case "GE": return "Genki Co.";
|
||||
case "GV": return "Groove Games";
|
||||
case "HE": return "Tru Blu (Entertainment division of Home Entertainment Suppliers)";
|
||||
case "HP": return "Hip games";
|
||||
case "HU": return "Hudson Soft";
|
||||
case "HW": return "Highwaystar";
|
||||
case "IA": return "Mad Catz Interactive";
|
||||
case "IF": return "Idea Factory";
|
||||
case "IG": return "Infogrames";
|
||||
case "IL": return "Interlex Corporation";
|
||||
case "IM": return "Imagine Media";
|
||||
case "IO": return "Ignition Entertainment";
|
||||
case "IP": return "Interplay Entertainment";
|
||||
case "IX": return "InXile Entertainment"; // TODO: Confirm
|
||||
case "JA": return "Jaleco";
|
||||
case "JW": return "JoWooD";
|
||||
case "KB": return "Kemco"; // TODO: Confirm
|
||||
case "KI": return "Kids Station Inc."; // TODO: Confirm
|
||||
case "KN": return "Konami";
|
||||
case "KO": return "KOEI";
|
||||
case "KU": return "Kobi and / or GAE (formerly Global A Entertainment)"; // TODO: Confirm
|
||||
case "LA": return "LucasArts";
|
||||
case "LS": return "Black Bean Games (publishing arm of Leader S.p.A.)";
|
||||
case "MD": return "Metro3D";
|
||||
case "ME": return "Medix";
|
||||
case "MI": return "Microïds";
|
||||
case "MJ": return "Majesco Entertainment";
|
||||
case "MM": return "Myelin Media";
|
||||
case "MP": return "MediaQuest"; // TODO: Confirm
|
||||
case "MS": return "Microsoft Game Studios";
|
||||
case "MW": return "Midway Games";
|
||||
case "MX": return "Empire Interactive"; // TODO: Confirm
|
||||
case "NK": return "NewKidCo";
|
||||
case "NL": return "NovaLogic";
|
||||
case "NM": return "Namco";
|
||||
case "OX": return "Oxygen Interactive";
|
||||
case "PC": return "Playlogic Entertainment";
|
||||
case "PL": return "Phantagram Co., Ltd.";
|
||||
case "RA": return "Rage";
|
||||
case "SA": return "Sammy";
|
||||
case "SC": return "SCi Games";
|
||||
case "SE": return "SEGA";
|
||||
case "SN": return "SNK";
|
||||
case "SS": return "Simon & Schuster";
|
||||
case "SU": return "Success Corporation";
|
||||
case "SW": return "Swing! Deutschland";
|
||||
case "TA": return "Takara";
|
||||
case "TC": return "Tecmo";
|
||||
case "TD": return "The 3DO Company (or just 3DO)";
|
||||
case "TK": return "Takuyo";
|
||||
case "TM": return "TDK Mediactive";
|
||||
case "TQ": return "THQ";
|
||||
case "TS": return "Titus Interactive";
|
||||
case "TT": return "Take-Two Interactive Software";
|
||||
case "US": return "Ubisoft";
|
||||
case "VC": return "Victor Interactive Software";
|
||||
case "VN": return "Vivendi Universal (just took Interplays publishing rights)"; // TODO: Confirm
|
||||
case "VU": return "Vivendi Universal Games";
|
||||
case "VV": return "Vivendi Universal Games"; // TODO: Confirm
|
||||
case "WE": return "Wanadoo Edition";
|
||||
case "WR": return "Warner Bros. Interactive Entertainment"; // TODO: Confirm
|
||||
case "XI": return "XPEC Entertainment and Idea Factory";
|
||||
case "XK": return "Xbox kiosk disk?"; // TODO: Confirm
|
||||
case "XL": return "Xbox special bundled or live demo disk?"; // TODO: Confirm
|
||||
case "XM": return "Evolved Games"; // TODO: Confirm
|
||||
case "XP": return "XPEC Entertainment";
|
||||
case "XR": return "Panorama";
|
||||
case "YB": return "YBM Sisa (South-Korea)";
|
||||
case "ZD": return "Zushi Games (formerly Zoo Digital Publishing)";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the region based on the XGD serial character
|
||||
/// </summary>
|
||||
/// <param name="region">Character denoting the region</param>
|
||||
/// <returns>Region, if possible</returns>
|
||||
#if NET48
|
||||
private static string GetRegion(char region)
|
||||
#else
|
||||
private static string? GetRegion(char region)
|
||||
#endif
|
||||
{
|
||||
switch (region)
|
||||
{
|
||||
case 'W': return "World";
|
||||
case 'A': return "USA";
|
||||
case 'J': return "Japan / Asia";
|
||||
case 'E': return "Europe";
|
||||
case 'K': return "USA / Japan";
|
||||
case 'L': return "USA / Europe";
|
||||
case 'H': return "Japan / Europe";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
15
Files/XeMID.Serializer.cs
Normal file
15
Files/XeMID.Serializer.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class XeMID : IFileSerializer<Models.Xbox.XeMID>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public bool Serialize(Models.Xbox.XeMID obj, string path) => throw new NotImplementedException();
|
||||
#else
|
||||
public bool Serialize(Models.Xbox.XeMID? obj, string? path) => throw new NotImplementedException();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace SabreTools.Serialization
|
||||
namespace SabreTools.Serialization.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines how to serialize to and from byte arrays
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace SabreTools.Serialization
|
||||
namespace SabreTools.Serialization.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines how to serialize to and from files
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace SabreTools.Serialization
|
||||
namespace SabreTools.Serialization.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines how to serialize to and from models
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.IO;
|
||||
|
||||
namespace SabreTools.Serialization
|
||||
namespace SabreTools.Serialization.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines how to serialize to and from Streams
|
||||
17
Interfaces/IWrapper.cs
Normal file
17
Interfaces/IWrapper.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace SabreTools.Serialization.Interfaces
|
||||
{
|
||||
public interface IWrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// Get a human-readable description of the wrapper
|
||||
/// </summary>
|
||||
string Description();
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Export the item information as JSON
|
||||
/// </summary>
|
||||
string ExportJSON();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
22
README.MD
22
README.MD
@@ -1,3 +1,25 @@
|
||||
# SabreTools.Serialization
|
||||
|
||||
This library comprises of serializers that both read and write from files and streams to the dedicated models as well as convert to and from the common internal models. This library is partially used by the current parsing and writing code but none of the internal model serialization is used.
|
||||
|
||||
Find the link to the Nuget package [here](https://www.nuget.org/packages/SabreTools.Serialization).
|
||||
|
||||
## `SabreTools.Serialization.Bytes`
|
||||
|
||||
This namespace comprises of deserializers that take byte arrays to convert into models.
|
||||
|
||||
## `SabreTools.Serialization.CrossModel`
|
||||
|
||||
This namespace comprises of serializers and deserializers that convert models to other common ones. This is mainly used for metadata files converting to and from a common, `Dictionary`-based model.
|
||||
|
||||
## `SabreTools.Serialization.Files`
|
||||
|
||||
This namespace comprises of serializers and deserializers that can convert to and from files on disk. Most of the serializers are symmetric, but this is not guaranteed. Unimplemented methods will throw `NotImplementedException`.
|
||||
|
||||
## `SabreTools.Serialization.Streams`
|
||||
|
||||
This namespace comprises of serializers and deserializers that can convert to and from any type of stream. Most of the serializers are symmetric, but this is not guaranteed. Unimplemented methods will throw `NotImplementedException`.
|
||||
|
||||
## `SabreTools.Serialization.Wrappers`
|
||||
|
||||
This namespace comrpises of wrapping classes that include keeping a reference to the source of each serializable model. Some of the wrappers may also include what are referred to as "extension properties", which are generated properties derived from either parts of the model or the underlying source.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net48;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Version>1.1.0</Version>
|
||||
<Version>1.1.5</Version>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
|
||||
<!-- Package Properties -->
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.IO" Version="1.1.1" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.1.1" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.Models.AACS;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SabreTools.Models.AACS;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using SabreTools.IO.Readers;
|
||||
using SabreTools.Models.AttractMode;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using SabreTools.IO.Writers;
|
||||
using SabreTools.Models.AttractMode;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.Models.BDPlus;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
using static SabreTools.Models.BDPlus.Constants;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SabreTools.Models.BDPlus;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.Models.BFPK;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
using static SabreTools.Models.BFPK.Constants;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SabreTools.Models.BFPK;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user